1 # -------------------------------------------------------------------------------
2 # elftools: ehabi/decoder.py
4 # Decode ARM exception handler bytecode.
6 # LeadroyaL (leadroyal@qq.com)
7 # This code is in the public domain
8 # -------------------------------------------------------------------------------
9 from collections
import namedtuple
12 class EHABIBytecodeDecoder(object):
13 """ Decoder of a sequence of ARM exception handler abi bytecode.
16 https://github.com/llvm/llvm-project/blob/master/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
17 https://developer.arm.com/documentation/ihi0038/b/
19 Accessible attributes:
27 Integer array, raw data of bytecode.
31 def __init__(self
, bytecode_array
):
32 self
._bytecode
_array
= bytecode_array
34 self
.mnemonic_array
= None
38 """ Decode bytecode array, put result into mnemonic_array.
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
)
48 self
.mnemonic_array
.append(
49 MnemonicItem(self
._bytecode
_array
[start_idx
: end_idx
], mnemonic
))
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
]
57 return 'vsp = vsp + %u' % (((opcode
& 0x3f) << 2) + 4)
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
]
64 return 'vsp = vsp - %u' % (((opcode
& 0x3f) << 2) + 4)
66 gpr_register_names
= ("r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
67 "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc")
69 def _calculate_range(self
, start
, count
):
70 return ((1 << (count
+ 1)) - 1) << start
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
)
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
)
80 def _decode_1000iiii_iiiiiiii(self
):
81 op0
= self
._bytecode
_array
[self
._index
]
83 op1
= self
._bytecode
_array
[self
._index
]
85 # uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
87 # << format("0x%02X 0x%02X ; %s",
88 # Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
91 gpr_mask
= (op1
<< 4) |
((op0
& 0x0f) << 12)
93 return 'refuse to unwind'
95 return 'pop %s' % self
._printGPR
(gpr_mask
)
97 def _decode_10011101(self
):
99 return 'reserved (ARM MOVrr)'
101 def _decode_10011111(self
):
103 return 'reserved (WiMMX MOVrr)'
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
]
109 return 'vsp = r%u' % (opcode
& 0x0f)
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
]
116 return 'pop %s' % self
._printGPR
(self
._calculate
_range
(4, opcode
& 0x07))
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
]
123 return 'pop %s' % self
._printGPR
(self
._calculate
_range
(4, opcode
& 0x07) |
(1 << 14))
125 def _decode_10110000(self
):
126 # SW.startLine() << format("0x%02X ; finish\n", Opcode);
130 def _decode_10110001_0000iiii(self
):
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
]
139 if (op1
& 0xf0) != 0 or op1
== 0x00:
142 return 'pop %s' % self
._printGPR
((op1
& 0x0f))
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
]]
154 while self
._bytecode
_array
[self
._index
] & 0x80 == 0:
155 uleb_buffer
.append(self
._bytecode
_array
[self
._index
])
158 for b
in reversed(uleb_buffer
):
159 value
= (value
<< 7) + (b
& 0x7F)
160 return 'vsp = vsp + %u' % (0x204 + (value
<< 2))
162 def _decode_10110011_sssscccc(self
):
163 # these two decoders are equal
164 return self
._decode
_11001001_sssscccc
()
166 def _decode_101101nn(self
):
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
]
174 return 'pop %s' % self
._print
_registers
(self
._calculate
_range
(8, opcode
& 0x07), "d")
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
]
184 start
= ((op1
& 0xf0) >> 4)
185 count
= ((op1
& 0x0f) >> 0)
186 return 'pop %s' % self
._print
_registers
(self
._calculate
_range
(start
, count
), "wR")
188 def _decode_11000111_0000iiii(self
):
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
]
197 if (op1
& 0xf0) != 0 or op1
== 0x00:
200 return 'pop %s' % self
._print
_registers
(op1
& 0x0f, "wCGR")
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
]
210 start
= 16 + ((op1
& 0xf0) >> 4)
211 count
= ((op1
& 0x0f) >> 0)
212 return 'pop %s' % self
._print
_registers
(self
._calculate
_range
(start
, count
), "d")
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
]
222 start
= ((op1
& 0xf0) >> 4)
223 count
= ((op1
& 0x0f) >> 0)
224 return 'pop %s' % self
._print
_registers
(self
._calculate
_range
(start
, count
), "d")
226 def _decode_11001yyy(self
):
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
]
234 return 'pop %s' % self
._print
_registers
(self
._calculate
_range
(10, opcode
& 0x07), "wR")
236 def _decode_11010nnn(self
):
237 # these two decoders are equal
238 return self
._decode
_10111nnn
()
240 def _decode_11xxxyyy(self
):
247 _DECODE_RECIPE_TYPE
= namedtuple('_DECODE_RECIPE_TYPE', 'mask value handler')
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
),
275 class MnemonicItem(object):
276 """ Single mnemonic item.
279 def __init__(self
, bytecode
, mnemonic
):
280 self
.bytecode
= bytecode
281 self
.mnemonic
= mnemonic
284 return '%s ; %s' % (' '.join(['0x%02x' % x
for x
in self
.bytecode
]), self
.mnemonic
)