Mercurial > lcfOS
annotate 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 |
rev | line source |
---|---|
348 | 1 import logging |
334 | 2 from .objectfile import ObjectFile |
335 | 3 from . import CompilerError |
383 | 4 from .layout import Layout, Section |
5 | |
335 | 6 |
385 | 7 class Linker: |
8 """ Merges the sections of several object files and | |
9 performs relocation """ | |
10 def __init__(self, target): | |
11 self.logger = logging.getLogger('Linker') | |
12 self.target = target | |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
13 |
385 | 14 def layout_sections(self, dst, layout): |
15 """ Use the given layout to place sections into memories """ | |
16 # Create sections with address: | |
17 dst.images = {} | |
18 for mem in layout.memories: | |
19 cur_addr = mem.location | |
20 output_memory = bytearray() | |
21 for memory_input in mem.inputs: | |
22 if type(memory_input) is Section: | |
23 section = dst.get_section(memory_input.section_name) | |
24 section.address = cur_addr | |
25 cur_addr += section.Size | |
26 output_memory += section.data | |
27 # TODO: align sections | |
28 else: | |
29 print(memory_input) | |
30 dst.images[mem.name] = bytes(output_memory) | |
348 | 31 |
381 | 32 def link(self, objs, layout): |
377 | 33 assert type(objs) is list |
383 | 34 assert type(layout) is Layout |
335 | 35 # Create new object file to store output: |
385 | 36 dst = ObjectFile() |
335 | 37 |
334 | 38 # First copy all sections into output sections: |
39 for iobj in objs: | |
335 | 40 offsets = {} |
41 # Merge sections: | |
42 for in_s in iobj.sections.values(): | |
385 | 43 out_s = dst.get_section(in_s.name) |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
44 # TODO: align section in other way: |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
45 while out_s.Size % 4 != 0: |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
46 out_s.add_data(bytes([0])) |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
47 |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
48 # Add new section: |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
49 offsets[in_s.name] = out_s.Size |
335 | 50 out_s.add_data(in_s.data) |
348 | 51 self.logger.debug('{} {}({})'.format(offsets[in_s.name], iobj, in_s.name)) |
335 | 52 |
53 # Merge symbols: | |
54 for sym in iobj.symbols.values(): | |
385 | 55 out_s = dst.get_section(sym.section) |
56 value = offsets[sym.section] + sym.value | |
57 dst.add_symbol(sym.name, value, sym.section) | |
363 | 58 self.logger.debug('{} at 0x{:08X} in section {}'.format(sym.name, value, sym.section)) |
335 | 59 |
60 # Merge relocations: | |
61 for reloc in iobj.relocations: | |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
62 offset = offsets[reloc.section] + reloc.offset |
385 | 63 dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) |
335 | 64 |
381 | 65 # Apply layout rules: |
385 | 66 self.layout_sections(dst, layout) |
381 | 67 |
335 | 68 # Perform relocations: |
385 | 69 for reloc in dst.relocations: |
335 | 70 # Lookup symbol: |
385 | 71 if reloc.sym not in dst.symbols: |
335 | 72 raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) |
385 | 73 |
74 sym_value = dst.get_symbol_value(reloc.sym) | |
75 section = dst.get_section(reloc.section) | |
335 | 76 |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
77 # Determine location in memory of reloc patchup position: |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
78 reloc_value = section.address + reloc.offset |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
79 |
385 | 80 if reloc.typ in self.target.reloc_map: |
81 f = self.target.reloc_map[reloc.typ] | |
82 f(reloc, sym_value, section, reloc_value) | |
335 | 83 else: |
84 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) | |
85 | |
385 | 86 # Create memories for the second time |
87 # TODO: make this nicer? | |
88 self.layout_sections(dst, layout) | |
89 | |
90 return dst |