Mercurial > lcfOS
annotate python/ppci/linker.py @ 393:6ae782a085e0
Added init program
author | Windel Bouwman |
---|---|
date | Sat, 17 May 2014 21:17:40 +0200 |
parents | 2a970e7270e2 |
children |
rev | line source |
---|---|
348 | 1 import logging |
334 | 2 from .objectfile import ObjectFile |
335 | 3 from . import CompilerError |
386 | 4 from .layout import Layout, Section, SymbolDefinition, Align |
383 | 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 |
386 | 14 def merge_sections(self, objs, dst): |
334 | 15 for iobj in objs: |
335 | 16 offsets = {} |
17 # Merge sections: | |
18 for in_s in iobj.sections.values(): | |
385 | 19 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
|
20 # 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
|
21 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
|
22 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
|
23 |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
24 # 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
|
25 offsets[in_s.name] = out_s.Size |
335 | 26 out_s.add_data(in_s.data) |
348 | 27 self.logger.debug('{} {}({})'.format(offsets[in_s.name], iobj, in_s.name)) |
335 | 28 |
29 # Merge symbols: | |
30 for sym in iobj.symbols.values(): | |
385 | 31 out_s = dst.get_section(sym.section) |
32 value = offsets[sym.section] + sym.value | |
33 dst.add_symbol(sym.name, value, sym.section) | |
363 | 34 self.logger.debug('{} at 0x{:08X} in section {}'.format(sym.name, value, sym.section)) |
335 | 35 |
36 # Merge relocations: | |
37 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
|
38 offset = offsets[reloc.section] + reloc.offset |
385 | 39 dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) |
335 | 40 |
386 | 41 def layout_sections(self, dst, layout): |
42 """ Use the given layout to place sections into memories """ | |
43 # Create sections with address: | |
44 dst.images = {} | |
45 for mem in layout.memories: | |
46 cur_addr = mem.location | |
47 output_memory = bytearray() | |
48 for memory_input in mem.inputs: | |
49 if type(memory_input) is Section: | |
50 section = dst.get_section(memory_input.section_name) | |
51 section.address = cur_addr | |
52 cur_addr += section.Size | |
53 output_memory += section.data | |
54 # TODO: align sections | |
55 elif type(memory_input) is SymbolDefinition: | |
56 dst.add_symbol(memory_input.symbol_name, cur_addr, "code") | |
57 elif type(memory_input) is Align: | |
58 while (cur_addr % memory_input.alignment) != 0: | |
59 cur_addr += 1 | |
60 output_memory += bytes([0]) | |
61 else: | |
62 print(memory_input) | |
63 dst.images[mem.name] = bytes(output_memory) | |
381 | 64 |
386 | 65 def do_relocations(self, dst): |
66 """ Perform the correct relocation as listed """ | |
385 | 67 for reloc in dst.relocations: |
335 | 68 # Lookup symbol: |
385 | 69 if reloc.sym not in dst.symbols: |
335 | 70 raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) |
385 | 71 |
72 sym_value = dst.get_symbol_value(reloc.sym) | |
73 section = dst.get_section(reloc.section) | |
335 | 74 |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
75 # 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
|
76 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
|
77 |
385 | 78 if reloc.typ in self.target.reloc_map: |
79 f = self.target.reloc_map[reloc.typ] | |
80 f(reloc, sym_value, section, reloc_value) | |
335 | 81 else: |
82 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) | |
83 | |
386 | 84 def link(self, objs, layout): |
85 """ Link together the given object files using the layout """ | |
86 assert type(objs) is list | |
87 assert type(layout) is Layout | |
88 # Create new object file to store output: | |
89 dst = ObjectFile() | |
90 | |
91 # First merge all sections into output sections: | |
92 self.merge_sections(objs, dst) | |
93 | |
94 # Apply layout rules: | |
95 self.layout_sections(dst, layout) | |
96 | |
97 # Perform relocations: | |
98 self.do_relocations(dst) | |
99 | |
385 | 100 # Create memories for the second time |
101 # TODO: make this nicer? | |
102 self.layout_sections(dst, layout) | |
103 | |
104 return dst |