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
442fb043d149 Added log option to zcc
Windel Bouwman
parents: 345
diff changeset
1 import logging
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
2 from .objectfile import ObjectFile
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
3 from . import CompilerError
386
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
4 from .layout import Layout, Section, SymbolDefinition, Align
383
173e20a47fda Added linker description loader
Windel Bouwman
parents: 381
diff changeset
5
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
6
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
7 class Linker:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
8 """ Merges the sections of several object files and
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
9 performs relocation """
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
10 def __init__(self, target):
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
11 self.logger = logging.getLogger('Linker')
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
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
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
14 def merge_sections(self, objs, dst):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
15 for iobj in objs:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
16 offsets = {}
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
17 # Merge sections:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
18 for in_s in iobj.sections.values():
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
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
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
26 out_s.add_data(in_s.data)
348
442fb043d149 Added log option to zcc
Windel Bouwman
parents: 345
diff changeset
27 self.logger.debug('{} {}({})'.format(offsets[in_s.name], iobj, in_s.name))
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
28
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
29 # Merge symbols:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
30 for sym in iobj.symbols.values():
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
31 out_s = dst.get_section(sym.section)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
32 value = offsets[sym.section] + sym.value
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
33 dst.add_symbol(sym.name, value, sym.section)
363
396e5cefba13 Removed debuginfo instruction
Windel Bouwman
parents: 354
diff changeset
34 self.logger.debug('{} at 0x{:08X} in section {}'.format(sym.name, value, sym.section))
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
35
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
36 # Merge relocations:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
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
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
39 dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
40
386
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
41 def layout_sections(self, dst, layout):
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
42 """ Use the given layout to place sections into memories """
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
43 # Create sections with address:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
44 dst.images = {}
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
45 for mem in layout.memories:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
46 cur_addr = mem.location
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
47 output_memory = bytearray()
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
48 for memory_input in mem.inputs:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
49 if type(memory_input) is Section:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
50 section = dst.get_section(memory_input.section_name)
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
51 section.address = cur_addr
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
52 cur_addr += section.Size
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
53 output_memory += section.data
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
54 # TODO: align sections
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
55 elif type(memory_input) is SymbolDefinition:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
56 dst.add_symbol(memory_input.symbol_name, cur_addr, "code")
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
57 elif type(memory_input) is Align:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
58 while (cur_addr % memory_input.alignment) != 0:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
59 cur_addr += 1
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
60 output_memory += bytes([0])
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
61 else:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
62 print(memory_input)
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
63 dst.images[mem.name] = bytes(output_memory)
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 377
diff changeset
64
386
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
65 def do_relocations(self, dst):
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
66 """ Perform the correct relocation as listed """
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
67 for reloc in dst.relocations:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
68 # Lookup symbol:
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
69 if reloc.sym not in dst.symbols:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
70 raise CompilerError('Undefined reference "{}"'.format(reloc.sym))
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
71
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
72 sym_value = dst.get_symbol_value(reloc.sym)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
73 section = dst.get_section(reloc.section)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
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
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
78 if reloc.typ in self.target.reloc_map:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
79 f = self.target.reloc_map[reloc.typ]
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
80 f(reloc, sym_value, section, reloc_value)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
81 else:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
82 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ))
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
83
386
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
84 def link(self, objs, layout):
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
85 """ Link together the given object files using the layout """
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
86 assert type(objs) is list
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
87 assert type(layout) is Layout
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
88 # Create new object file to store output:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
89 dst = ObjectFile()
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
90
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
91 # First merge all sections into output sections:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
92 self.merge_sections(objs, dst)
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
93
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
94 # Apply layout rules:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
95 self.layout_sections(dst, layout)
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
96
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
97 # Perform relocations:
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
98 self.do_relocations(dst)
2a970e7270e2 Added repeat assembler macro
Windel Bouwman
parents: 385
diff changeset
99
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
100 # Create memories for the second time
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
101 # TODO: make this nicer?
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
102 self.layout_sections(dst, layout)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
103
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
104 return dst