Mercurial > lcfOS
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 |