Mercurial > lcfOS
annotate python/ppci/objectfile.py @ 386:2a970e7270e2
Added repeat assembler macro
author | Windel Bouwman |
---|---|
date | Thu, 01 May 2014 17:40:59 +0200 |
parents | d056b552d3f4 |
children |
rev | line source |
---|---|
334 | 1 |
2 """ | |
3 Object files are used to store assembled code. Information contained | |
4 is code, symbol table and relocation information. | |
5 """ | |
6 | |
377 | 7 import json |
8 import binascii | |
384 | 9 from . import CompilerError, make_num |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
10 |
334 | 11 class Symbol: |
335 | 12 def __init__(self, name, value, section): |
334 | 13 self.name = name |
14 self.value = value | |
335 | 15 self.section = section |
16 | |
17 def __repr__(self): | |
18 return 'SYM {}, val={} sec={}'.format(self.name, self.value, self.section) | |
334 | 19 |
377 | 20 def __eq__(self, other): |
21 return (self.name, self.value, self.section) == \ | |
22 (other.name, other.value, other.section) | |
23 | |
334 | 24 |
25 class Relocation: | |
342 | 26 """ Represents a relocation entry. A relocation always has a symbol to refer to |
27 and a relocation type """ | |
335 | 28 def __init__(self, sym, offset, typ, section): |
29 self.sym = sym | |
30 self.offset = offset | |
31 self.typ = typ | |
32 self.section = section | |
33 | |
34 def __repr__(self): | |
35 return 'RELOC {} off={} t={} sec={}'.format(self.sym, self.offset, self.typ, self.section) | |
334 | 36 |
377 | 37 def __eq__(self, other): |
38 return (self.sym, self.offset, self.typ, self.section) ==\ | |
39 (other.sym, other.offset, other.typ, other.section) | |
40 | |
334 | 41 |
42 class Section: | |
43 def __init__(self, name): | |
44 self.name = name | |
335 | 45 self.address = 0 |
46 self.data = bytearray() | |
47 | |
48 def add_data(self, data): | |
49 self.data += data | |
50 | |
51 @property | |
52 def Size(self): | |
53 return len(self.data) | |
54 | |
55 def __repr__(self): | |
56 return 'SECTION {}'.format(self.name) | |
334 | 57 |
377 | 58 def __eq__(self, other): |
59 return (self.name == other.name) and (self.address == other.address) \ | |
60 and (self.data == other.data) | |
61 | |
334 | 62 |
63 class ObjectFile: | |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
64 """ Container for sections with compiled code or data. |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
65 Also contains symbols and relocation entries """ |
334 | 66 def __init__(self): |
67 self.symbols = {} | |
68 self.sections = {} | |
69 self.relocations = [] | |
385 | 70 self.images = {} |
334 | 71 |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
72 def find_symbol(self, name): |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
73 return self.symbols[name] |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
74 |
335 | 75 def add_symbol(self, name, value, section): |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
76 if name in self.symbols: |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
77 raise CompilerError('{} already defined'.format(name)) |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
78 assert section in self.sections |
335 | 79 sym = Symbol(name, value, section) |
334 | 80 self.symbols[name] = sym |
81 return sym | |
335 | 82 |
83 def add_relocation(self, sym_name, offset, typ, section): | |
342 | 84 assert type(sym_name) is str, str(sym_name) |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
335
diff
changeset
|
85 assert section in self.sections |
377 | 86 # assert sym_name in self.symbols |
335 | 87 reloc = Relocation(sym_name, offset, typ, section) |
88 self.relocations.append(reloc) | |
89 return reloc | |
90 | |
91 def get_section(self, name): | |
92 if not name in self.sections: | |
93 self.sections[name] = Section(name) | |
94 return self.sections[name] | |
377 | 95 |
385 | 96 def get_image(self, name): |
97 return self.images[name] | |
98 | |
99 def get_symbol_value(self, name): | |
100 symbol = self.find_symbol(name) | |
101 section = self.get_section(symbol.section) | |
102 return symbol.value + section.address | |
103 | |
377 | 104 def __eq__(self, other): |
105 return (self.symbols == other.symbols) and \ | |
106 (self.sections == other.sections) and \ | |
107 (self.relocations == other.relocations) | |
108 | |
109 def save(self, f): | |
110 save_object(self, f) | |
111 | |
112 | |
113 def save_object(o, f): | |
114 json.dump(serialize(o), f, indent=2, sort_keys=True) | |
115 | |
116 | |
117 def load_object(f): | |
118 return deserialize(json.load(f)) | |
119 | |
120 | |
385 | 121 def bin2asc(data): |
122 return binascii.hexlify(data).decode('ascii') | |
123 | |
124 def asc2bin(data): | |
125 return bytearray(binascii.unhexlify(data.encode('ascii'))) | |
126 | |
127 | |
377 | 128 def serialize(x): |
129 res = {} | |
130 if isinstance(x, ObjectFile): | |
131 res['sections'] = [] | |
132 for sname in sorted(x.sections.keys()): | |
133 s = x.sections[sname] | |
134 res['sections'].append(serialize(s)) | |
135 res['symbols'] = [] | |
136 for sname in sorted(x.symbols.keys()): | |
137 s = x.symbols[sname] | |
138 res['symbols'].append(serialize(s)) | |
139 res['relocations'] = [] | |
140 for reloc in x.relocations: | |
141 res['relocations'].append(serialize(reloc)) | |
385 | 142 res['images'] = {} |
143 for image_name in x.images: | |
144 res['images'][image_name] = bin2asc(x.images[image_name]) | |
377 | 145 elif isinstance(x, Section): |
146 res['name'] = x.name | |
147 res['address'] = hex(x.address) | |
385 | 148 res['data'] = bin2asc(x.data) |
377 | 149 elif isinstance(x, Symbol): |
150 res['name'] = x.name | |
151 res['value'] = hex(x.value) | |
152 res['section'] = x.section | |
153 elif isinstance(x, Relocation): | |
154 res['symbol'] = x.sym | |
155 res['offset'] = hex(x.offset) | |
156 res['type'] = x.typ | |
157 res['section'] = x.section | |
158 return res | |
159 | |
160 | |
161 def deserialize(d): | |
162 obj = ObjectFile() | |
163 for section in d['sections']: | |
164 so = obj.get_section(section['name']) | |
384 | 165 so.address = make_num(section['address']) |
385 | 166 so.data = asc2bin(section['data']) |
377 | 167 for reloc in d['relocations']: |
384 | 168 obj.add_relocation(reloc['symbol'], make_num(reloc['offset']), |
377 | 169 reloc['type'], reloc['section']) |
170 for sym in d['symbols']: | |
384 | 171 obj.add_symbol(sym['name'], make_num(sym['value']), sym['section']) |
385 | 172 for image_name in d['images']: |
173 obj.images[image_name] = asc2bin(d['images'][image_name]) | |
377 | 174 return obj |
175 |