Mercurial > lcfOS
diff python/ppci/linker.py @ 336:d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
author | Windel Bouwman |
---|---|
date | Wed, 19 Feb 2014 22:32:15 +0100 |
parents | 582a1aaa3983 |
children | b4882ff0ed06 |
line wrap: on
line diff
--- a/python/ppci/linker.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/linker.py Wed Feb 19 22:32:15 2014 +0100 @@ -22,19 +22,71 @@ @reloc('lit_add_8') -class LitAdd8: - def apply(self): - pass +def apply_lit8(reloc, sym, section, reloc_value): + assert sym.value % 4 == 0 + offset = (sym.value - (align(reloc_value + 2, 4))) + assert offset in range(0, 1024, 4), str(offset)+str( self.dst.sections) + rel8 = offset >> 2 + section.data[reloc.offset] = rel8 + + +@reloc('wrap_new11') +def apply_wrap_new11(reloc, sym, section, reloc_value): + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-2048, 2046, 2) + imm11 = wrap_negative(offset >> 1, 11) + section.data[reloc.offset] = (imm11 & 0xff) + section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7 + + +@reloc('rel8') +def apply_rel8(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-256, 254, 2), str(offset) + str(reloc) + imm8 = wrap_negative(offset >> 1, 8) + section.data[reloc.offset] = imm8 + + +@reloc('bl_imm11_imm10') +def apply_bl_imm11(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-16777216, 16777214, 2), str(offset) + imm32 = wrap_negative(offset >> 1, 32) + imm11 = imm32 & 0x7FF + imm10 = (imm32 >> 11) & 0x3FF + s = (imm32 >> 24) & 0x1 + section.data[reloc.offset + 2] = imm11 & 0xFF + section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 + section.data[reloc.offset] = imm10 & 0xff + section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2) + +@reloc('b_imm11_imm6') +def apply_b_imm11_imm6(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-1048576, 1048574, 2), str(offset) + imm32 = wrap_negative(offset >> 1, 32) + imm11 = imm32 & 0x7FF + imm6 = (imm32 >> 11) & 0x3F + s = (imm32 >> 24) & 0x1 + section.data[reloc.offset + 2] = imm11 & 0xFF + section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 + section.data[reloc.offset] |= imm6 + section.data[reloc.offset + 1] |= (s << 2) class Linker: - def set_symbol(self, sym): - self.dst.add_symbol(sym.name, sym.value, sym.section) - - def link(self, objs): + """ Merges the sections of several object files and + performs relocation """ + def link(self, objs, layout={}): # Create new object file to store output: self.dst = ObjectFile() - self.dst.get_section('code').address = 0x08000000 + + # Create sections with address: + for section_name, address in layout.items(): + self.dst.get_section(section_name).address = address # First copy all sections into output sections: for iobj in objs: @@ -42,19 +94,26 @@ # Merge sections: for in_s in iobj.sections.values(): out_s = self.dst.get_section(in_s.name) - offsets[in_s.name] = out_s.address + out_s.Size + # TODO: align section in other way: + while out_s.Size % 4 != 0: + out_s.add_data(bytes([0])) + + # Add new section: + offsets[in_s.name] = out_s.Size out_s.add_data(in_s.data) - # TODO: align section + # Merge symbols: for sym in iobj.symbols.values(): - self.set_symbol(sym) + out_s = self.dst.get_section(sym.section) + value = offsets[sym.section] + out_s.address + sym.value + self.dst.add_symbol(sym.name, value, sym.section) # Merge relocations: for reloc in iobj.relocations: - self.dst.add_relocation(reloc.sym, reloc.offset, reloc.typ, reloc.section) + offset = offsets[reloc.section] + reloc.offset + self.dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) - # Check that there are no more unresolved symbols: # Perform relocations: for reloc in self.dst.relocations: # Lookup symbol: @@ -64,48 +123,12 @@ # patch up: section = self.dst.get_section(reloc.section) - if reloc.typ == 'lit_add_8': - assert sym.value % 4 == 0 - offset = (sym.value - (align(reloc.offset + 2, 4))) - assert offset in range(0, 1024, 4) - rel8 = offset >> 2 - section.data[reloc.offset] = rel8 - elif reloc.typ == 'wrap_new11': - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-2048, 2046, 2) - imm11 = wrap_negative(offset >> 1, 11) - section.data[reloc.offset] = (imm11 & 0xff) - section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7 - elif reloc.typ == 'rel8': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-256, 254, 2), str(offset) + str(reloc) - imm8 = wrap_negative(offset >> 1, 8) - section.data[reloc.offset] = imm8 - elif reloc.typ == 'bl_imm11_imm10': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-16777216, 16777214, 2), str(offset) - imm32 = wrap_negative(offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm10 = (imm32 >> 11) & 0x3FF - s = (imm32 >> 24) & 0x1 - section.data[reloc.offset + 2] = imm11 & 0xFF - section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 - section.data[reloc.offset] = imm10 & 0xff - section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2) - elif reloc.typ == 'b_imm11_imm6': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-1048576, 1048574, 2), str(offset) - imm32 = wrap_negative(offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm6 = (imm32 >> 11) & 0x3F - s = (imm32 >> 24) & 0x1 - section.data[reloc.offset + 2] = imm11 & 0xFF - section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 - section.data[reloc.offset] |= imm6 - section.data[reloc.offset + 1] |= (s << 2) + # Determine location in memory of reloc patchup position: + reloc_value = section.address + reloc.offset + + if reloc.typ in reloc_map: + f = reloc_map[reloc.typ] + f(reloc, sym, section, reloc_value) else: raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ))