comparison python/ppci/linker.py @ 336:d1ecc493384e

Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
author Windel Bouwman
date Wed, 19 Feb 2014 22:32:15 +0100
parents 582a1aaa3983
children b4882ff0ed06
comparison
equal deleted inserted replaced
335:582a1aaa3983 336:d1ecc493384e
20 reloc_map[t] = c 20 reloc_map[t] = c
21 return f 21 return f
22 22
23 23
24 @reloc('lit_add_8') 24 @reloc('lit_add_8')
25 class LitAdd8: 25 def apply_lit8(reloc, sym, section, reloc_value):
26 def apply(self): 26 assert sym.value % 4 == 0
27 pass 27 offset = (sym.value - (align(reloc_value + 2, 4)))
28 assert offset in range(0, 1024, 4), str(offset)+str( self.dst.sections)
29 rel8 = offset >> 2
30 section.data[reloc.offset] = rel8
31
32
33 @reloc('wrap_new11')
34 def apply_wrap_new11(reloc, sym, section, reloc_value):
35 offset = sym.value - (align(reloc_value, 2) + 4)
36 assert offset in range(-2048, 2046, 2)
37 imm11 = wrap_negative(offset >> 1, 11)
38 section.data[reloc.offset] = (imm11 & 0xff)
39 section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7
40
41
42 @reloc('rel8')
43 def apply_rel8(reloc, sym, section, reloc_value):
44 assert sym.value % 2 == 0
45 offset = sym.value - (align(reloc_value, 2) + 4)
46 assert offset in range(-256, 254, 2), str(offset) + str(reloc)
47 imm8 = wrap_negative(offset >> 1, 8)
48 section.data[reloc.offset] = imm8
49
50
51 @reloc('bl_imm11_imm10')
52 def apply_bl_imm11(reloc, sym, section, reloc_value):
53 assert sym.value % 2 == 0
54 offset = sym.value - (align(reloc_value, 2) + 4)
55 assert offset in range(-16777216, 16777214, 2), str(offset)
56 imm32 = wrap_negative(offset >> 1, 32)
57 imm11 = imm32 & 0x7FF
58 imm10 = (imm32 >> 11) & 0x3FF
59 s = (imm32 >> 24) & 0x1
60 section.data[reloc.offset + 2] = imm11 & 0xFF
61 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
62 section.data[reloc.offset] = imm10 & 0xff
63 section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2)
64
65 @reloc('b_imm11_imm6')
66 def apply_b_imm11_imm6(reloc, sym, section, reloc_value):
67 assert sym.value % 2 == 0
68 offset = sym.value - (align(reloc_value, 2) + 4)
69 assert offset in range(-1048576, 1048574, 2), str(offset)
70 imm32 = wrap_negative(offset >> 1, 32)
71 imm11 = imm32 & 0x7FF
72 imm6 = (imm32 >> 11) & 0x3F
73 s = (imm32 >> 24) & 0x1
74 section.data[reloc.offset + 2] = imm11 & 0xFF
75 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
76 section.data[reloc.offset] |= imm6
77 section.data[reloc.offset + 1] |= (s << 2)
28 78
29 79
30 class Linker: 80 class Linker:
31 def set_symbol(self, sym): 81 """ Merges the sections of several object files and
32 self.dst.add_symbol(sym.name, sym.value, sym.section) 82 performs relocation """
33 83 def link(self, objs, layout={}):
34 def link(self, objs):
35 # Create new object file to store output: 84 # Create new object file to store output:
36 self.dst = ObjectFile() 85 self.dst = ObjectFile()
37 self.dst.get_section('code').address = 0x08000000 86
87 # Create sections with address:
88 for section_name, address in layout.items():
89 self.dst.get_section(section_name).address = address
38 90
39 # First copy all sections into output sections: 91 # First copy all sections into output sections:
40 for iobj in objs: 92 for iobj in objs:
41 offsets = {} 93 offsets = {}
42 # Merge sections: 94 # Merge sections:
43 for in_s in iobj.sections.values(): 95 for in_s in iobj.sections.values():
44 out_s = self.dst.get_section(in_s.name) 96 out_s = self.dst.get_section(in_s.name)
45 offsets[in_s.name] = out_s.address + out_s.Size 97 # TODO: align section in other way:
98 while out_s.Size % 4 != 0:
99 out_s.add_data(bytes([0]))
100
101 # Add new section:
102 offsets[in_s.name] = out_s.Size
46 out_s.add_data(in_s.data) 103 out_s.add_data(in_s.data)
47 # TODO: align section 104
48 105
49 # Merge symbols: 106 # Merge symbols:
50 for sym in iobj.symbols.values(): 107 for sym in iobj.symbols.values():
51 self.set_symbol(sym) 108 out_s = self.dst.get_section(sym.section)
109 value = offsets[sym.section] + out_s.address + sym.value
110 self.dst.add_symbol(sym.name, value, sym.section)
52 111
53 # Merge relocations: 112 # Merge relocations:
54 for reloc in iobj.relocations: 113 for reloc in iobj.relocations:
55 self.dst.add_relocation(reloc.sym, reloc.offset, reloc.typ, reloc.section) 114 offset = offsets[reloc.section] + reloc.offset
115 self.dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section)
56 116
57 # Check that there are no more unresolved symbols:
58 # Perform relocations: 117 # Perform relocations:
59 for reloc in self.dst.relocations: 118 for reloc in self.dst.relocations:
60 # Lookup symbol: 119 # Lookup symbol:
61 if reloc.sym not in self.dst.symbols: 120 if reloc.sym not in self.dst.symbols:
62 raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) 121 raise CompilerError('Undefined reference "{}"'.format(reloc.sym))
63 sym = self.dst.symbols[reloc.sym] 122 sym = self.dst.symbols[reloc.sym]
64 # patch up: 123 # patch up:
65 section = self.dst.get_section(reloc.section) 124 section = self.dst.get_section(reloc.section)
66 125
67 if reloc.typ == 'lit_add_8': 126 # Determine location in memory of reloc patchup position:
68 assert sym.value % 4 == 0 127 reloc_value = section.address + reloc.offset
69 offset = (sym.value - (align(reloc.offset + 2, 4))) 128
70 assert offset in range(0, 1024, 4) 129 if reloc.typ in reloc_map:
71 rel8 = offset >> 2 130 f = reloc_map[reloc.typ]
72 section.data[reloc.offset] = rel8 131 f(reloc, sym, section, reloc_value)
73 elif reloc.typ == 'wrap_new11':
74 offset = sym.value - (align(reloc.offset, 2) + 4)
75 assert offset in range(-2048, 2046, 2)
76 imm11 = wrap_negative(offset >> 1, 11)
77 section.data[reloc.offset] = (imm11 & 0xff)
78 section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7
79 elif reloc.typ == 'rel8':
80 assert sym.value % 2 == 0
81 offset = sym.value - (align(reloc.offset, 2) + 4)
82 assert offset in range(-256, 254, 2), str(offset) + str(reloc)
83 imm8 = wrap_negative(offset >> 1, 8)
84 section.data[reloc.offset] = imm8
85 elif reloc.typ == 'bl_imm11_imm10':
86 assert sym.value % 2 == 0
87 offset = sym.value - (align(reloc.offset, 2) + 4)
88 assert offset in range(-16777216, 16777214, 2), str(offset)
89 imm32 = wrap_negative(offset >> 1, 32)
90 imm11 = imm32 & 0x7FF
91 imm10 = (imm32 >> 11) & 0x3FF
92 s = (imm32 >> 24) & 0x1
93 section.data[reloc.offset + 2] = imm11 & 0xFF
94 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
95 section.data[reloc.offset] = imm10 & 0xff
96 section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2)
97 elif reloc.typ == 'b_imm11_imm6':
98 assert sym.value % 2 == 0
99 offset = sym.value - (align(reloc.offset, 2) + 4)
100 assert offset in range(-1048576, 1048574, 2), str(offset)
101 imm32 = wrap_negative(offset >> 1, 32)
102 imm11 = imm32 & 0x7FF
103 imm6 = (imm32 >> 11) & 0x3F
104 s = (imm32 >> 24) & 0x1
105 section.data[reloc.offset + 2] = imm11 & 0xFF
106 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
107 section.data[reloc.offset] |= imm6
108 section.data[reloc.offset + 1] |= (s << 2)
109 else: 132 else:
110 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) 133 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ))
111 134
112 return self.dst 135 return self.dst