from pathlib import Path
import subprocess,hashlib,json
from unicorn import *
from unicorn.arm_const import *
import unicorn
p=Path(__file__).resolve().parent
o=p/'it_hook_repro.o';binary=p/'it_hook_repro.bin'
subprocess.run(['arm-none-eabi-as','-mcpu=cortex-m4','-mthumb',str(p/'it_hook_repro.S'),'-o',str(o)],check=True)
subprocess.run(['arm-none-eabi-objcopy','-O','binary',str(o),str(binary)],check=True);o.unlink()
rows=[]
for mode in ['none','global-no-op','peripheral-only']:
 u=Uc(UC_ARCH_ARM,UC_MODE_THUMB|UC_MODE_MCLASS);u.ctl_set_cpu_model(UC_CPU_ARM_CORTEX_M4)
 u.mem_map(0x8000000,4096);u.mem_map(0x20000000,4096);u.mem_map(0x40020000,4096);u.mem_write(0x8000000,binary.read_bytes())
 u.reg_write(UC_ARM_REG_R2,19);u.reg_write(UC_ARM_REG_R3,2589);u.reg_write(UC_ARM_REG_R4,0x20000000);u.reg_write(UC_ARM_REG_R7,0);u.reg_write(UC_ARM_REG_LR,0x8000ff1)
 trace=[];events=[]
 u.hook_add(UC_HOOK_CODE,lambda uc,addr,size,data:trace.append({'pc':hex(addr),'xpsr':hex(uc.reg_read(UC_ARM_REG_XPSR))}))
 def write(uc,access,address,size,value,data):events.append(hex(address))
 if mode=='global-no-op':u.hook_add(UC_HOOK_MEM_WRITE,write)
 if mode=='peripheral-only':u.hook_add(UC_HOOK_MEM_WRITE,write,begin=0x40020004,end=0x40020004)
 u.emu_start(0x8000001,0x8000ff0,count=200);r=u.reg_read(UC_ARM_REG_R0);assert r==(0 if mode=='global-no-op' else 1)
 rows.append({'hook':mode,'input_cycles':2589,'input_us':19,'expected_semantic_return':1,'observed_return':r,'write_events':events,'trace':trace})
out={'status':'GLOBAL_MEMORY_HOOK_DEFECT_REPRODUCED_BOUNDED_HOOK_AVOIDS_TRIGGER','unicorn':unicorn.__version__,'source_sha256':hashlib.sha256((p/'it_hook_repro.S').read_bytes()).hexdigest(),'binary_sha256':hashlib.sha256(binary.read_bytes()).hexdigest(),'cases':rows,'firmware_changes_required':False,'physical_validation':False}
(p/'it_hook_repro_receipt_A81.json').write_text(json.dumps(out,indent=2)+'\n');print(out['status'])
