Mercurial > lcfOS
diff python/ppci/linker.py @ 385:d056b552d3f4
Made better use of layout
author | Windel Bouwman |
---|---|
date | Thu, 01 May 2014 14:03:12 +0200 |
parents | 173e20a47fda |
children | 2a970e7270e2 |
line wrap: on
line diff
--- a/python/ppci/linker.py Sun Apr 27 17:50:25 2014 +0200 +++ b/python/ppci/linker.py Thu May 01 14:03:12 2014 +0200 @@ -1,161 +1,46 @@ import logging -import struct from .objectfile import ObjectFile from . import CompilerError -from .bitfun import encode_imm32 from .layout import Layout, Section -def align(x, m): - while ((x % m) != 0): - x = x + 1 - return x - -def wrap_negative(x, bits): - b = struct.unpack('<I', struct.pack('<i', x))[0] - mask = (1 << bits) - 1 - return b & mask - -reloc_map = {} - -def reloc(t): - def f(c): - reloc_map[t] = c - return f - - -@reloc('lit_add_8') -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) +class Linker: + """ Merges the sections of several object files and + performs relocation """ + def __init__(self, target): + self.logger = logging.getLogger('Linker') + self.target = target -@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) - -# ARM reloc!! -# TODO: move to target classes??? -@reloc('b_imm24') -def apply_b_imm24(reloc, sym, section, reloc_value): - assert sym.value % 4 == 0 - assert reloc_value % 4 == 0 - offset = (sym.value - (reloc_value + 8)) - rel24 = wrap_negative(offset >> 2, 24) - section.data[reloc.offset+2] = (rel24 >> 16) & 0xFF - section.data[reloc.offset+1] = (rel24 >> 8) & 0xFF - section.data[reloc.offset+0] = rel24 & 0xFF - - -@reloc('ldr_imm12') -def apply_ldr_imm12(reloc, sym, section, reloc_value): - assert sym.value % 4 == 0 - assert reloc_value % 4 == 0 - offset = (sym.value - (reloc_value + 8)) - U = 1 - if offset < 0: - offset = -offset - U = 0 - assert offset < 4096, str(sym) + str(section) + str(reloc) - section.data[reloc.offset+2] |= (U << 7) - section.data[reloc.offset+1] |= (offset >> 8) & 0xF - section.data[reloc.offset+0] = offset & 0xFF - -@reloc('adr_imm12') -def apply_adr_imm12(reloc, sym, section, reloc_value): - assert sym.value % 4 == 0 - assert reloc_value % 4 == 0 - offset = (sym.value - (reloc_value + 8)) - U = 2 - if offset < 0: - offset = -offset - U = 1 - assert offset < 4096 - offset = encode_imm32(offset) - section.data[reloc.offset+2] |= (U << 6) - section.data[reloc.offset+1] |= (offset >> 8) & 0xF - section.data[reloc.offset+0] = offset & 0xFF - -@reloc('absaddr32') -def apply_absaddr32(reloc, sym, section, reloc_value): - assert sym.value % 4 == 0 - assert reloc_value % 4 == 0 - offset = sym.value - section.data[reloc.offset+3] = (offset >> 24) & 0xFF - section.data[reloc.offset+2] = (offset >> 16) & 0xFF - section.data[reloc.offset+1] = (offset >> 8) & 0xFF - section.data[reloc.offset+0] = offset & 0xFF - - -class Linker: - """ Merges the sections of several object files and - performs relocation """ - def __init__(self): - self.logger = logging.getLogger('Linker') + def layout_sections(self, dst, layout): + """ Use the given layout to place sections into memories """ + # Create sections with address: + dst.images = {} + for mem in layout.memories: + cur_addr = mem.location + output_memory = bytearray() + for memory_input in mem.inputs: + if type(memory_input) is Section: + section = dst.get_section(memory_input.section_name) + section.address = cur_addr + cur_addr += section.Size + output_memory += section.data + # TODO: align sections + else: + print(memory_input) + dst.images[mem.name] = bytes(output_memory) def link(self, objs, layout): assert type(objs) is list assert type(layout) is Layout # Create new object file to store output: - self.dst = ObjectFile() - - # Create sections with address: - for mem in layout.mems: - for inp in mem.inputs: - if type(inp) is Section: - self.dst.get_section(inp.section_name).address = mem.location + dst = ObjectFile() # First copy all sections into output sections: for iobj in objs: offsets = {} # Merge sections: for in_s in iobj.sections.values(): - out_s = self.dst.get_section(in_s.name) + out_s = dst.get_section(in_s.name) # TODO: align section in other way: while out_s.Size % 4 != 0: out_s.add_data(bytes([0])) @@ -167,35 +52,39 @@ # Merge symbols: for sym in iobj.symbols.values(): - 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) + out_s = dst.get_section(sym.section) + value = offsets[sym.section] + sym.value + dst.add_symbol(sym.name, value, sym.section) self.logger.debug('{} at 0x{:08X} in section {}'.format(sym.name, value, sym.section)) # Merge relocations: for reloc in iobj.relocations: offset = offsets[reloc.section] + reloc.offset - self.dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) + dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) # Apply layout rules: - # TODO + self.layout_sections(dst, layout) # Perform relocations: - for reloc in self.dst.relocations: + for reloc in dst.relocations: # Lookup symbol: - if reloc.sym not in self.dst.symbols: + if reloc.sym not in dst.symbols: raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) - sym = self.dst.symbols[reloc.sym] - # patch up: - section = self.dst.get_section(reloc.section) + + sym_value = dst.get_symbol_value(reloc.sym) + section = dst.get_section(reloc.section) # 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) + if reloc.typ in self.target.reloc_map: + f = self.target.reloc_map[reloc.typ] + f(reloc, sym_value, section, reloc_value) else: raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) - return self.dst + # Create memories for the second time + # TODO: make this nicer? + self.layout_sections(dst, layout) + + return dst