Mercurial > lcfOS
view 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 source
import logging from .objectfile import ObjectFile from . import CompilerError from .layout import Layout, Section class Linker: """ Merges the sections of several object files and performs relocation """ def __init__(self, target): self.logger = logging.getLogger('Linker') self.target = target 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: 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 = dst.get_section(in_s.name) # 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) self.logger.debug('{} {}({})'.format(offsets[in_s.name], iobj, in_s.name)) # Merge symbols: for sym in iobj.symbols.values(): 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 dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) # Apply layout rules: self.layout_sections(dst, layout) # Perform relocations: for reloc in dst.relocations: # Lookup symbol: if reloc.sym not in dst.symbols: raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) 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 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)) # Create memories for the second time # TODO: make this nicer? self.layout_sections(dst, layout) return dst