2021-02-17 21:20:30 +00:00
|
|
|
import argparse
|
|
|
|
import struct
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import obj_pb2
|
|
|
|
|
2021-02-19 05:27:20 +00:00
|
|
|
CRT0_FILE = '/home/paulmathieu/vhdl/tools/crt0.o'
|
2021-02-17 21:20:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
def parse_objs(objs):
|
|
|
|
sections = []
|
|
|
|
relocs = []
|
|
|
|
|
|
|
|
for obj in objs:
|
|
|
|
of = obj_pb2.ObjFile()
|
|
|
|
of.ParseFromString(obj.read())
|
|
|
|
sections += of.sections
|
|
|
|
relocs += of.relocs
|
|
|
|
|
|
|
|
return sections, relocs
|
|
|
|
|
|
|
|
|
|
|
|
def map_sections(sections):
|
|
|
|
secmap = []
|
|
|
|
|
|
|
|
addr = 0
|
|
|
|
|
|
|
|
# _start goes first
|
|
|
|
for sec in sections:
|
|
|
|
if sec.name == '_start':
|
|
|
|
secmap.append((addr, sec))
|
|
|
|
addr += len(sec.text)
|
|
|
|
sections.remove(sec)
|
|
|
|
break
|
|
|
|
assert secmap, "could not find symbol _start :/"
|
|
|
|
|
|
|
|
for sec in sections:
|
|
|
|
secmap.append((addr, sec))
|
|
|
|
addr += len(sec.text)
|
|
|
|
|
|
|
|
return secmap
|
|
|
|
|
|
|
|
|
|
|
|
def do_relocs(secmap, relocs):
|
|
|
|
namemap = {s[1].name: s for s in secmap}
|
|
|
|
for reloc in relocs:
|
|
|
|
assert reloc.section in namemap
|
|
|
|
assert reloc.target in namemap
|
|
|
|
_, sec = namemap[reloc.section]
|
|
|
|
# the reloc hex should look like /e.ff0000/
|
|
|
|
buff = bytearray(sec.text)
|
|
|
|
target_addr = namemap[reloc.target][0]
|
|
|
|
reg = buff[reloc.offset] & 0xf
|
|
|
|
buff[reloc.offset+0:reloc.offset+4] = [
|
2021-02-23 04:35:09 +00:00
|
|
|
0xe0 | reg, (target_addr >> 0) & 0xff,
|
2021-02-17 21:20:30 +00:00
|
|
|
0x90 | reg, (target_addr >> 8) & 0xff,
|
|
|
|
]
|
|
|
|
sec.text = bytes(buff)
|
|
|
|
|
|
|
|
|
|
|
|
def dump(secmap):
|
|
|
|
out = bytearray()
|
|
|
|
for _, sec in secmap:
|
|
|
|
out += sec.text
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
def parse_args():
|
|
|
|
parser = argparse.ArgumentParser(description='Assemble.')
|
|
|
|
parser.add_argument('--debug', action='store_true',
|
|
|
|
help='print debug info')
|
|
|
|
parser.add_argument('objfiles', metavar='O', nargs='+',
|
|
|
|
type=argparse.FileType('rb'),
|
|
|
|
help='input file (default: stdin)')
|
|
|
|
parser.add_argument('--output', '-o', type=argparse.FileType('wb'),
|
|
|
|
default=sys.stdout.buffer, help='output file')
|
|
|
|
parser.add_argument('--vhdl', action='store_true',
|
|
|
|
help='vhdl output')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
args = parse_args()
|
|
|
|
|
|
|
|
with open(CRT0_FILE, 'rb') as crt0:
|
|
|
|
sections, relocs = parse_objs(args.objfiles + [crt0])
|
|
|
|
|
|
|
|
sectionmap = map_sections(sections)
|
|
|
|
do_relocs(sectionmap, relocs)
|
|
|
|
text = dump(sectionmap)
|
|
|
|
|
|
|
|
if args.vhdl:
|
|
|
|
args.output.write(',\n'.join(f'x"{x:04x}"' for x in
|
|
|
|
struct.unpack(f'>{len(text) // 2}H', text)).encode())
|
|
|
|
else:
|
|
|
|
args.output.write(text)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|