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
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
383
173e20a47fda Added linker description loader
Windel Bouwman
parents: 381
diff changeset
4 from .layout import Layout, Section
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
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
14 def layout_sections(self, dst, layout):
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
15 """ Use the given layout to place sections into memories """
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
16 # Create sections with address:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
17 dst.images = {}
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
18 for mem in layout.memories:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
19 cur_addr = mem.location
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
20 output_memory = bytearray()
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
21 for memory_input in mem.inputs:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
22 if type(memory_input) is Section:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
23 section = dst.get_section(memory_input.section_name)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
24 section.address = cur_addr
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
25 cur_addr += section.Size
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
26 output_memory += section.data
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
27 # TODO: align sections
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
28 else:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
29 print(memory_input)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
30 dst.images[mem.name] = bytes(output_memory)
348
442fb043d149 Added log option to zcc
Windel Bouwman
parents: 345
diff changeset
31
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 377
diff changeset
32 def link(self, objs, layout):
377
9667d78ba79e Switched to xml for project description
Windel Bouwman
parents: 365
diff changeset
33 assert type(objs) is list
383
173e20a47fda Added linker description loader
Windel Bouwman
parents: 381
diff changeset
34 assert type(layout) is Layout
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
35 # Create new object file to store output:
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
36 dst = ObjectFile()
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
37
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
38 # First copy all sections into output sections:
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
39 for iobj in objs:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
40 offsets = {}
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
41 # Merge sections:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
42 for in_s in iobj.sections.values():
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
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
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
50 out_s.add_data(in_s.data)
348
442fb043d149 Added log option to zcc
Windel Bouwman
parents: 345
diff changeset
51 self.logger.debug('{} {}({})'.format(offsets[in_s.name], iobj, in_s.name))
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
52
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
53 # Merge symbols:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
54 for sym in iobj.symbols.values():
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
55 out_s = dst.get_section(sym.section)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
56 value = offsets[sym.section] + sym.value
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
57 dst.add_symbol(sym.name, value, sym.section)
363
396e5cefba13 Removed debuginfo instruction
Windel Bouwman
parents: 354
diff changeset
58 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
59
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
60 # Merge relocations:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
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
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
63 dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
64
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 377
diff changeset
65 # Apply layout rules:
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
66 self.layout_sections(dst, layout)
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 377
diff changeset
67
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
68 # Perform relocations:
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
69 for reloc in dst.relocations:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
70 # Lookup symbol:
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
71 if reloc.sym not in dst.symbols:
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
72 raise CompilerError('Undefined reference "{}"'.format(reloc.sym))
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
73
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
74 sym_value = dst.get_symbol_value(reloc.sym)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
75 section = dst.get_section(reloc.section)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
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
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
80 if reloc.typ in self.target.reloc_map:
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
81 f = self.target.reloc_map[reloc.typ]
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
82 f(reloc, sym_value, section, reloc_value)
335
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
83 else:
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
84 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ))
582a1aaa3983 Added long branch format
Windel Bouwman
parents: 334
diff changeset
85
385
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
86 # Create memories for the second time
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
87 # TODO: make this nicer?
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
88 self.layout_sections(dst, layout)
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
89
d056b552d3f4 Made better use of layout
Windel Bouwman
parents: 383
diff changeset
90 return dst