|
- """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))
|