Add support for DT_RELR/SHT_RELR compressed relocation sections (#395)
[pyelftools.git] / elftools / ehabi / decoder.py
1 # -------------------------------------------------------------------------------
2 # elftools: ehabi/decoder.py
3 #
4 # Decode ARM exception handler bytecode.
5 #
6 # LeadroyaL (leadroyal@qq.com)
7 # This code is in the public domain
8 # -------------------------------------------------------------------------------
9 from collections import namedtuple
10
11
12 class EHABIBytecodeDecoder(object):
13 """ Decoder of a sequence of ARM exception handler abi bytecode.
14
15 Reference:
16 https://github.com/llvm/llvm-project/blob/master/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
17 https://developer.arm.com/documentation/ihi0038/b/
18
19 Accessible attributes:
20
21 mnemonic_array:
22 MnemonicItem array.
23
24 Parameters:
25
26 bytecode_array:
27 Integer array, raw data of bytecode.
28
29 """
30
31 def __init__(self, bytecode_array):
32 self._bytecode_array = bytecode_array
33 self._index = None
34 self.mnemonic_array = None
35 self._decode()
36
37 def _decode(self):
38 """ Decode bytecode array, put result into mnemonic_array.
39 """
40 self._index = 0
41 self.mnemonic_array = []
42 while self._index < len(self._bytecode_array):
43 for mask, value, handler in self.ring:
44 if (self._bytecode_array[self._index] & mask) == value:
45 start_idx = self._index
46 mnemonic = handler(self)
47 end_idx = self._index
48 self.mnemonic_array.append(
49 MnemonicItem(self._bytecode_array[start_idx: end_idx], mnemonic))
50 break
51
52 def _decode_00xxxxxx(self):
53 # SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
54 # ((Opcode & 0x3f) << 2) + 4);
55 opcode = self._bytecode_array[self._index]
56 self._index += 1
57 return 'vsp = vsp + %u' % (((opcode & 0x3f) << 2) + 4)
58
59 def _decode_01xxxxxx(self):
60 # SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
61 # ((Opcode & 0x3f) << 2) + 4);
62 opcode = self._bytecode_array[self._index]
63 self._index += 1
64 return 'vsp = vsp - %u' % (((opcode & 0x3f) << 2) + 4)
65
66 gpr_register_names = ("r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
67 "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc")
68
69 def _calculate_range(self, start, count):
70 return ((1 << (count + 1)) - 1) << start
71
72 def _printGPR(self, gpr_mask):
73 hits = [self.gpr_register_names[i] for i in range(32) if gpr_mask & (1 << i) != 0]
74 return '{%s}' % ', '.join(hits)
75
76 def _print_registers(self, vfp_mask, prefix):
77 hits = [prefix + str(i) for i in range(32) if vfp_mask & (1 << i) != 0]
78 return '{%s}' % ', '.join(hits)
79
80 def _decode_1000iiii_iiiiiiii(self):
81 op0 = self._bytecode_array[self._index]
82 self._index += 1
83 op1 = self._bytecode_array[self._index]
84 self._index += 1
85 # uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
86 # SW.startLine()
87 # << format("0x%02X 0x%02X ; %s",
88 # Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
89 # if (GPRMask)
90 # PrintGPR(GPRMask);
91 gpr_mask = (op1 << 4) | ((op0 & 0x0f) << 12)
92 if gpr_mask == 0:
93 return 'refuse to unwind'
94 else:
95 return 'pop %s' % self._printGPR(gpr_mask)
96
97 def _decode_10011101(self):
98 self._index += 1
99 return 'reserved (ARM MOVrr)'
100
101 def _decode_10011111(self):
102 self._index += 1
103 return 'reserved (WiMMX MOVrr)'
104
105 def _decode_1001nnnn(self):
106 # SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
107 opcode = self._bytecode_array[self._index]
108 self._index += 1
109 return 'vsp = r%u' % (opcode & 0x0f)
110
111 def _decode_10100nnn(self):
112 # SW.startLine() << format("0x%02X ; pop ", Opcode);
113 # PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
114 opcode = self._bytecode_array[self._index]
115 self._index += 1
116 return 'pop %s' % self._printGPR(self._calculate_range(4, opcode & 0x07))
117
118 def _decode_10101nnn(self):
119 # SW.startLine() << format("0x%02X ; pop ", Opcode);
120 # PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
121 opcode = self._bytecode_array[self._index]
122 self._index += 1
123 return 'pop %s' % self._printGPR(self._calculate_range(4, opcode & 0x07) | (1 << 14))
124
125 def _decode_10110000(self):
126 # SW.startLine() << format("0x%02X ; finish\n", Opcode);
127 self._index += 1
128 return 'finish'
129
130 def _decode_10110001_0000iiii(self):
131 # SW.startLine()
132 # << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
133 # ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
134 # if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
135 # PrintGPR((Opcode1 & 0x0f));
136 self._index += 1 # skip constant byte
137 op1 = self._bytecode_array[self._index]
138 self._index += 1
139 if (op1 & 0xf0) != 0 or op1 == 0x00:
140 return 'spare'
141 else:
142 return 'pop %s' % self._printGPR((op1 & 0x0f))
143
144 def _decode_10110010_uleb128(self):
145 # SmallVector<uint8_t, 4> ULEB;
146 # do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
147 # uint64_t Value = 0;
148 # for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
149 # Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
150 # OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
151 self._index += 1 # skip constant byte
152 uleb_buffer = [self._bytecode_array[self._index]]
153 self._index += 1
154 while self._bytecode_array[self._index] & 0x80 == 0:
155 uleb_buffer.append(self._bytecode_array[self._index])
156 self._index += 1
157 value = 0
158 for b in reversed(uleb_buffer):
159 value = (value << 7) + (b & 0x7F)
160 return 'vsp = vsp + %u' % (0x204 + (value << 2))
161
162 def _decode_10110011_sssscccc(self):
163 # these two decoders are equal
164 return self._decode_11001001_sssscccc()
165
166 def _decode_101101nn(self):
167 return self._spare()
168
169 def _decode_10111nnn(self):
170 # SW.startLine() << format("0x%02X ; pop ", Opcode);
171 # PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
172 opcode = self._bytecode_array[self._index]
173 self._index += 1
174 return 'pop %s' % self._print_registers(self._calculate_range(8, opcode & 0x07), "d")
175
176 def _decode_11000110_sssscccc(self):
177 # SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
178 # uint8_t Start = ((Opcode1 & 0xf0) >> 4);
179 # uint8_t Count = ((Opcode1 & 0x0f) >> 0);
180 # PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
181 self._index += 1 # skip constant byte
182 op1 = self._bytecode_array[self._index]
183 self._index += 1
184 start = ((op1 & 0xf0) >> 4)
185 count = ((op1 & 0x0f) >> 0)
186 return 'pop %s' % self._print_registers(self._calculate_range(start, count), "wR")
187
188 def _decode_11000111_0000iiii(self):
189 # SW.startLine()
190 # << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
191 # ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
192 # if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
193 # PrintRegisters(Opcode1 & 0x0f, "wCGR");
194 self._index += 1 # skip constant byte
195 op1 = self._bytecode_array[self._index]
196 self._index += 1
197 if (op1 & 0xf0) != 0 or op1 == 0x00:
198 return 'spare'
199 else:
200 return 'pop %s' % self._print_registers(op1 & 0x0f, "wCGR")
201
202 def _decode_11001000_sssscccc(self):
203 # SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
204 # uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
205 # uint8_t Count = ((Opcode1 & 0x0f) >> 0);
206 # PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
207 self._index += 1 # skip constant byte
208 op1 = self._bytecode_array[self._index]
209 self._index += 1
210 start = 16 + ((op1 & 0xf0) >> 4)
211 count = ((op1 & 0x0f) >> 0)
212 return 'pop %s' % self._print_registers(self._calculate_range(start, count), "d")
213
214 def _decode_11001001_sssscccc(self):
215 # SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
216 # uint8_t Start = ((Opcode1 & 0xf0) >> 4);
217 # uint8_t Count = ((Opcode1 & 0x0f) >> 0);
218 # PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
219 self._index += 1 # skip constant byte
220 op1 = self._bytecode_array[self._index]
221 self._index += 1
222 start = ((op1 & 0xf0) >> 4)
223 count = ((op1 & 0x0f) >> 0)
224 return 'pop %s' % self._print_registers(self._calculate_range(start, count), "d")
225
226 def _decode_11001yyy(self):
227 return self._spare()
228
229 def _decode_11000nnn(self):
230 # SW.startLine() << format("0x%02X ; pop ", Opcode);
231 # PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
232 opcode = self._bytecode_array[self._index]
233 self._index += 1
234 return 'pop %s' % self._print_registers(self._calculate_range(10, opcode & 0x07), "wR")
235
236 def _decode_11010nnn(self):
237 # these two decoders are equal
238 return self._decode_10111nnn()
239
240 def _decode_11xxxyyy(self):
241 return self._spare()
242
243 def _spare(self):
244 self._index += 1
245 return 'spare'
246
247 _DECODE_RECIPE_TYPE = namedtuple('_DECODE_RECIPE_TYPE', 'mask value handler')
248
249 ring = (
250 _DECODE_RECIPE_TYPE(mask=0xc0, value=0x00, handler=_decode_00xxxxxx),
251 _DECODE_RECIPE_TYPE(mask=0xc0, value=0x40, handler=_decode_01xxxxxx),
252 _DECODE_RECIPE_TYPE(mask=0xf0, value=0x80, handler=_decode_1000iiii_iiiiiiii),
253 _DECODE_RECIPE_TYPE(mask=0xff, value=0x9d, handler=_decode_10011101),
254 _DECODE_RECIPE_TYPE(mask=0xff, value=0x9f, handler=_decode_10011111),
255 _DECODE_RECIPE_TYPE(mask=0xf0, value=0x90, handler=_decode_1001nnnn),
256 _DECODE_RECIPE_TYPE(mask=0xf8, value=0xa0, handler=_decode_10100nnn),
257 _DECODE_RECIPE_TYPE(mask=0xf8, value=0xa8, handler=_decode_10101nnn),
258 _DECODE_RECIPE_TYPE(mask=0xff, value=0xb0, handler=_decode_10110000),
259 _DECODE_RECIPE_TYPE(mask=0xff, value=0xb1, handler=_decode_10110001_0000iiii),
260 _DECODE_RECIPE_TYPE(mask=0xff, value=0xb2, handler=_decode_10110010_uleb128),
261 _DECODE_RECIPE_TYPE(mask=0xff, value=0xb3, handler=_decode_10110011_sssscccc),
262 _DECODE_RECIPE_TYPE(mask=0xfc, value=0xb4, handler=_decode_101101nn),
263 _DECODE_RECIPE_TYPE(mask=0xf8, value=0xb8, handler=_decode_10111nnn),
264 _DECODE_RECIPE_TYPE(mask=0xff, value=0xc6, handler=_decode_11000110_sssscccc),
265 _DECODE_RECIPE_TYPE(mask=0xff, value=0xc7, handler=_decode_11000111_0000iiii),
266 _DECODE_RECIPE_TYPE(mask=0xff, value=0xc8, handler=_decode_11001000_sssscccc),
267 _DECODE_RECIPE_TYPE(mask=0xff, value=0xc9, handler=_decode_11001001_sssscccc),
268 _DECODE_RECIPE_TYPE(mask=0xc8, value=0xc8, handler=_decode_11001yyy),
269 _DECODE_RECIPE_TYPE(mask=0xf8, value=0xc0, handler=_decode_11000nnn),
270 _DECODE_RECIPE_TYPE(mask=0xf8, value=0xd0, handler=_decode_11010nnn),
271 _DECODE_RECIPE_TYPE(mask=0xc0, value=0xc0, handler=_decode_11xxxyyy),
272 )
273
274
275 class MnemonicItem(object):
276 """ Single mnemonic item.
277 """
278
279 def __init__(self, bytecode, mnemonic):
280 self.bytecode = bytecode
281 self.mnemonic = mnemonic
282
283 def __repr__(self):
284 return '%s ; %s' % (' '.join(['0x%02x' % x for x in self.bytecode]), self.mnemonic)