"""Power C object file (.o/.obj) reader/writer. u16 code_len; code u16 n_reloc; u16 off[n] (u16 at off+1 is code-relative, += load base) u16 n_def; {name\0 u8 kind u16 off} u16 n_ref; {name\0 u16 kind u16 site} kind 0=abs16 1=hi 2=lo 4=abs+1 (site = opcode offset) u16 n_res; {name\0 u16 size} """ import struct class Obj: def __init__(s): s.code=bytearray(); s.reloc=[]; s.defs=[]; s.refs=[]; s.res=[] @staticmethod def parse(data): o=Obj(); p=0 def u16(): nonlocal p v=data[p]|data[p+1]<<8; p+=2; return v def name(): nonlocal p e=data.index(0,p); n=bytes(data[p:e]); p=e+1; return n n=u16(); o.code=bytearray(data[p:p+n]); p+=n k=u16(); o.reloc=[u16() for _ in range(k)] k=u16() for _ in range(k): nm=name(); kind=data[p]; p+=1; off=u16(); o.defs.append([nm,kind,off]) k=u16() for _ in range(k): nm=name(); kind=u16(); off=u16(); o.refs.append([nm,kind,off]) k=u16() for _ in range(k): nm=name(); sz=u16(); o.res.append([nm,sz]) o.trailing=bytes(data[p:]) return o def build(o): out=bytearray() def u16(v): out.extend((v&255,v>>8&255)) u16(len(o.code)); out+=o.code u16(len(o.reloc)); [u16(x) for x in o.reloc] u16(len(o.defs)) for nm,kind,off in o.defs: out+=nm+b'\0'+bytes([kind]); u16(off) u16(len(o.refs)) for nm,kind,off in o.refs: out+=nm+b'\0'; u16(kind); u16(off) u16(len(o.res)) for nm,sz in o.res: out+=nm+b'\0'; u16(sz) out+=o.trailing return bytes(out) def pn(b): return ''.join(chr(c) if 32<=c<127 else '<%02x>'%c for c in b) if __name__=='__main__': import sys for f in sys.argv[1:]: d=open(f,'rb').read(); o=Obj.parse(d) assert o.build()==d,'roundtrip mismatch '+f print(f,'code',len(o.code),'reloc',len(o.reloc),'defs',[(pn(a),b,hex(c)) for a,b,c in o.defs],'refs',len(o.refs),'res',o.res,'trail',len(o.trailing))