blob: 51128f113c4c212797d3336c88c92989714cb4dc [file] [log] [blame]
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +00001//===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Benjamin Kramer00e08fc2014-08-13 16:26:38 +000010#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
11#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +000012
Chandler Carruth213fb8f2014-01-13 08:09:47 +000013#include "Error.h"
Benjamin Kramerb8c1bbf2016-01-27 19:29:56 +000014#include "llvm-readobj.h"
Saleem Abdulrasool2ef2fd42014-04-12 18:04:27 +000015#include "llvm/ADT/STLExtras.h"
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +000016#include "llvm/Object/ELF.h"
17#include "llvm/Object/ELFTypes.h"
18#include "llvm/Support/ARMEHABI.h"
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000019#include "llvm/Support/Debug.h"
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +000020#include "llvm/Support/Endian.h"
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000021#include "llvm/Support/Format.h"
Zachary Turner2448e9f2016-05-03 00:28:04 +000022#include "llvm/Support/ScopedPrinter.h"
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +000023#include "llvm/Support/type_traits.h"
24
25namespace llvm {
26namespace ARM {
27namespace EHABI {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000028
29class OpcodeDecoder {
Zachary Turner2448e9f2016-05-03 00:28:04 +000030 ScopedPrinter &SW;
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000031 raw_ostream &OS;
32
33 struct RingEntry {
34 uint8_t Mask;
35 uint8_t Value;
36 void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);
37 };
David Blaikie7e7cdf42017-11-16 22:30:36 +000038 static ArrayRef<RingEntry> ring();
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000039
40 void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);
41 void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);
42 void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI);
43 void Decode_10011101(const uint8_t *Opcodes, unsigned &OI);
44 void Decode_10011111(const uint8_t *Opcodes, unsigned &OI);
45 void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI);
46 void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI);
47 void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI);
48 void Decode_10110000(const uint8_t *Opcodes, unsigned &OI);
49 void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI);
50 void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI);
51 void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI);
52 void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI);
53 void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI);
54 void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI);
55 void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI);
56 void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI);
57 void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI);
58 void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI);
59 void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI);
60 void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI);
61 void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI);
62
63 void PrintGPR(uint16_t GPRMask);
64 void PrintRegisters(uint32_t Mask, StringRef Prefix);
65
66public:
Zachary Turner2448e9f2016-05-03 00:28:04 +000067 OpcodeDecoder(ScopedPrinter &SW) : SW(SW), OS(SW.getOStream()) {}
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000068 void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);
69};
70
David Blaikie7e7cdf42017-11-16 22:30:36 +000071inline ArrayRef<OpcodeDecoder::RingEntry> OpcodeDecoder::ring() {
72 static const OpcodeDecoder::RingEntry Ring[] = {
73 {0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx},
74 {0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx},
75 {0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii},
76 {0xff, 0x9d, &OpcodeDecoder::Decode_10011101},
77 {0xff, 0x9f, &OpcodeDecoder::Decode_10011111},
78 {0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn},
79 {0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn},
80 {0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn},
81 {0xff, 0xb0, &OpcodeDecoder::Decode_10110000},
82 {0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii},
83 {0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128},
84 {0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc},
85 {0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn},
86 {0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn},
87 {0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc},
88 {0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii},
89 {0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc},
90 {0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc},
91 {0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy},
92 {0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn},
93 {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn},
94 {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy},
95 };
David Blaikiea98c2a22017-11-16 22:40:02 +000096 return makeArrayRef(Ring);
David Blaikie7e7cdf42017-11-16 22:30:36 +000097}
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +000098
David Blaikie7e7cdf42017-11-16 22:30:36 +000099inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes,
100 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000101 uint8_t Opcode = Opcodes[OI++ ^ 3];
102 SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
103 ((Opcode & 0x3f) << 2) + 4);
104}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000105inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes,
106 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000107 uint8_t Opcode = Opcodes[OI++ ^ 3];
108 SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
109 ((Opcode & 0x3f) << 2) + 4);
110}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000111inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
112 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000113 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
114 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
115
116 uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
117 SW.startLine()
118 << format("0x%02X 0x%02X ; %s",
119 Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
120 if (GPRMask)
121 PrintGPR(GPRMask);
122 OS << '\n';
123}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000124inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes,
125 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000126 uint8_t Opcode = Opcodes[OI++ ^ 3];
127 SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode);
128}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000129inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes,
130 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000131 uint8_t Opcode = Opcodes[OI++ ^ 3];
132 SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode);
133}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000134inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes,
135 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000136 uint8_t Opcode = Opcodes[OI++ ^ 3];
137 SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
138}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000139inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes,
140 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000141 uint8_t Opcode = Opcodes[OI++ ^ 3];
142 SW.startLine() << format("0x%02X ; pop ", Opcode);
143 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
144 OS << '\n';
145}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000146inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes,
147 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000148 uint8_t Opcode = Opcodes[OI++ ^ 3];
149 SW.startLine() << format("0x%02X ; pop ", Opcode);
150 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
151 OS << '\n';
152}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000153inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes,
154 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000155 uint8_t Opcode = Opcodes[OI++ ^ 3];
156 SW.startLine() << format("0x%02X ; finish\n", Opcode);
157}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000158inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
159 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000160 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
161 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
162
163 SW.startLine()
164 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
165 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
166 if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
167 PrintGPR((Opcode1 & 0x0f));
168 OS << '\n';
169}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000170inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
171 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000172 uint8_t Opcode = Opcodes[OI++ ^ 3];
173 SW.startLine() << format("0x%02X ", Opcode);
174
175 SmallVector<uint8_t, 4> ULEB;
176 do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
177
178 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
179 OS << format("0x%02X ", ULEB[BI]);
180
181 uint64_t Value = 0;
182 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
183 Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
184
Saleem Abdulrasoolbb70b572014-01-21 04:31:29 +0000185 OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000186}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000187inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
188 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000189 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
190 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
191 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
192 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
193 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
194 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
195 OS << '\n';
196}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000197inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes,
198 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000199 uint8_t Opcode = Opcodes[OI++ ^ 3];
200 SW.startLine() << format("0x%02X ; spare\n", Opcode);
201}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000202inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes,
203 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000204 uint8_t Opcode = Opcodes[OI++ ^ 3];
205 SW.startLine() << format("0x%02X ; pop ", Opcode);
206 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
207 OS << '\n';
208}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000209inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
210 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000211 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
212 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
213 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
214 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
215 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
216 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
217 OS << '\n';
218}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000219inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
220 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000221 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
222 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
223 SW.startLine()
224 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
225 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
226 if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
227 PrintRegisters(Opcode1 & 0x0f, "wCGR");
228 OS << '\n';
229}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000230inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
231 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000232 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
233 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
234 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
235 uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
236 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
237 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
238 OS << '\n';
239}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000240inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
241 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000242 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
243 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
244 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
245 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
246 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
247 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
248 OS << '\n';
249}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000250inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes,
251 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000252 uint8_t Opcode = Opcodes[OI++ ^ 3];
253 SW.startLine() << format("0x%02X ; spare\n", Opcode);
254}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000255inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes,
256 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000257 uint8_t Opcode = Opcodes[OI++ ^ 3];
258 SW.startLine() << format("0x%02X ; pop ", Opcode);
259 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
260 OS << '\n';
261}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000262inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes,
263 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000264 uint8_t Opcode = Opcodes[OI++ ^ 3];
265 SW.startLine() << format("0x%02X ; pop ", Opcode);
266 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
267 OS << '\n';
268}
David Blaikie7e7cdf42017-11-16 22:30:36 +0000269inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes,
270 unsigned &OI) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000271 uint8_t Opcode = Opcodes[OI++ ^ 3];
272 SW.startLine() << format("0x%02X ; spare\n", Opcode);
273}
274
David Blaikie7e7cdf42017-11-16 22:30:36 +0000275inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000276 static const char *GPRRegisterNames[16] = {
277 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
278 "fp", "ip", "sp", "lr", "pc"
279 };
280
281 OS << '{';
282 bool Comma = false;
283 for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {
284 if (GPRMask & (1 << RI)) {
285 if (Comma)
286 OS << ", ";
287 OS << GPRRegisterNames[RI];
288 Comma = true;
289 }
290 }
291 OS << '}';
292}
293
David Blaikie7e7cdf42017-11-16 22:30:36 +0000294inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000295 OS << '{';
296 bool Comma = false;
297 for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
298 if (VFPMask & (1 << RI)) {
299 if (Comma)
300 OS << ", ";
301 OS << Prefix << RI;
302 Comma = true;
303 }
304 }
305 OS << '}';
306}
307
David Blaikie7e7cdf42017-11-16 22:30:36 +0000308inline void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset,
309 size_t Length) {
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000310 for (unsigned OCI = Offset; OCI < Length + Offset; ) {
311 bool Decoded = false;
David Blaikie7e7cdf42017-11-16 22:30:36 +0000312 for (const auto &RE : ring()) {
313 if ((Opcodes[OCI ^ 3] & RE.Mask) == RE.Value) {
314 (this->*RE.Routine)(Opcodes, OCI);
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000315 Decoded = true;
316 break;
317 }
318 }
319 if (!Decoded)
320 SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]);
321 }
322}
323
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000324template <typename ET>
325class PrinterContext {
Rui Ueyama5a286a02018-01-12 02:28:31 +0000326 typedef typename ET::Sym Elf_Sym;
327 typedef typename ET::Shdr Elf_Shdr;
328 typedef typename ET::Rel Elf_Rel;
329 typedef typename ET::Word Elf_Word;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000330
Zachary Turner2448e9f2016-05-03 00:28:04 +0000331 ScopedPrinter &SW;
Rafael Espindola4d79d2f2015-08-10 20:25:04 +0000332 const object::ELFFile<ET> *ELF;
333 const Elf_Shdr *Symtab;
Rafael Espindola0d34e642015-08-10 21:29:35 +0000334 ArrayRef<Elf_Word> ShndxTable;
Rafael Espindola4d79d2f2015-08-10 20:25:04 +0000335
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000336 static const size_t IndexTableEntrySize;
337
338 static uint64_t PREL31(uint32_t Address, uint32_t Place) {
339 uint64_t Location = Address & 0x7fffffff;
340 if (Location & 0x04000000)
341 Location |= (uint64_t) ~0x7fffffff;
342 return Location + Place;
343 }
344
345 ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const;
346 const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,
347 off_t IndexTableOffset) const;
348
349 void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const;
350 void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT,
351 uint64_t TableEntryOffset) const;
Saleem Abdulrasool3ca4db22014-01-09 04:31:18 +0000352 void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000353
354public:
Zachary Turner2448e9f2016-05-03 00:28:04 +0000355 PrinterContext(ScopedPrinter &SW, const object::ELFFile<ET> *ELF,
Rafael Espindola4d79d2f2015-08-10 20:25:04 +0000356 const Elf_Shdr *Symtab)
357 : SW(SW), ELF(ELF), Symtab(Symtab) {}
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000358
359 void PrintUnwindInformation() const;
360};
361
362template <typename ET>
363const size_t PrinterContext<ET>::IndexTableEntrySize = 8;
364
365template <typename ET>
Rafael Espindolae8f07a72015-06-29 12:38:31 +0000366ErrorOr<StringRef>
367PrinterContext<ET>::FunctionAtAddress(unsigned Section,
368 uint64_t Address) const {
Davide Italiano63830bc2016-11-16 05:10:28 +0000369 auto StrTableOrErr = ELF->getStringTableForSymtab(*Symtab);
370 if (!StrTableOrErr)
371 error(StrTableOrErr.takeError());
Rafael Espindola7eeb71d2015-07-21 16:26:21 +0000372 StringRef StrTable = *StrTableOrErr;
373
Rafael Espindola77e77782016-11-03 13:43:30 +0000374 for (const Elf_Sym &Sym : unwrapOrError(ELF->symbols(Symtab)))
Rafael Espindolae8f07a72015-06-29 12:38:31 +0000375 if (Sym.st_shndx == Section && Sym.st_value == Address &&
Kevin Enderby813e0cf2016-04-20 21:24:34 +0000376 Sym.getType() == ELF::STT_FUNC) {
377 auto NameOrErr = Sym.getName(StrTable);
378 if (!NameOrErr) {
379 // TODO: Actually report errors helpfully.
380 consumeError(NameOrErr.takeError());
381 return readobj_error::unknown_symbol;
382 }
383 return *NameOrErr;
384 }
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000385 return readobj_error::unknown_symbol;
386}
387
388template <typename ET>
Rui Ueyama5a286a02018-01-12 02:28:31 +0000389const typename ET::Shdr *
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000390PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
391 off_t IndexTableOffset) const {
392 /// Iterate through the sections, searching for the relocation section
393 /// associated with the unwind index table section specified by
394 /// IndexSectionIndex. Iterate the associated section searching for the
395 /// relocation associated with the index table entry specified by
396 /// IndexTableOffset. The symbol is the section symbol for the exception
397 /// handling table. Use this symbol to recover the actual exception handling
398 /// table.
399
Rafael Espindola8ee0ff82016-11-02 14:10:57 +0000400 for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) {
Rafael Espindolac505e6d2015-08-10 18:57:42 +0000401 if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)
402 continue;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000403
Davide Italiano63830bc2016-11-16 05:10:28 +0000404 auto SymTabOrErr = ELF->getSection(Sec.sh_link);
405 if (!SymTabOrErr)
406 error(SymTabOrErr.takeError());
Rafael Espindola3c4c9332015-09-02 15:07:39 +0000407 const Elf_Shdr *SymTab = *SymTabOrErr;
408
Rafael Espindolaa625bff2016-11-03 19:07:15 +0000409 for (const Elf_Rel &R : unwrapOrError(ELF->rels(&Sec))) {
Rafael Espindolac505e6d2015-08-10 18:57:42 +0000410 if (R.r_offset != static_cast<unsigned>(IndexTableOffset))
411 continue;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000412
Rui Ueyama5a286a02018-01-12 02:28:31 +0000413 typename ET::Rela RelA;
Rafael Espindolac505e6d2015-08-10 18:57:42 +0000414 RelA.r_offset = R.r_offset;
415 RelA.r_info = R.r_info;
416 RelA.r_addend = 0;
417
Rafael Espindolac771cb12016-11-03 18:05:33 +0000418 const Elf_Sym *Symbol =
419 unwrapOrError(ELF->getRelocationSymbol(&RelA, SymTab));
Rafael Espindolac505e6d2015-08-10 18:57:42 +0000420
Davide Italiano63830bc2016-11-16 05:10:28 +0000421 auto Ret = ELF->getSection(Symbol, SymTab, ShndxTable);
422 if (!Ret)
423 report_fatal_error(errorToErrorCode(Ret.takeError()).message());
Rafael Espindolac505e6d2015-08-10 18:57:42 +0000424 return *Ret;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000425 }
426 }
Craig Topperc34a25d2014-04-28 04:05:08 +0000427 return nullptr;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000428}
429
430template <typename ET>
431void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT,
432 const Elf_Shdr *EHT,
433 uint64_t TableEntryOffset) const {
Davide Italiano63830bc2016-11-16 05:10:28 +0000434 Expected<ArrayRef<uint8_t>> Contents = ELF->getSectionContents(EHT);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000435 if (!Contents)
436 return;
437
438 /// ARM EHABI Section 6.2 - The generic model
439 ///
440 /// An exception-handling table entry for the generic model is laid out as:
441 ///
442 /// 3 3
443 /// 1 0 0
444 /// +-+------------------------------+
445 /// |0| personality routine offset |
446 /// +-+------------------------------+
447 /// | personality routine data ... |
448 ///
449 ///
450 /// ARM EHABI Section 6.3 - The ARM-defined compact model
451 ///
452 /// An exception-handling table entry for the compact model looks like:
453 ///
454 /// 3 3 2 2 2 2
455 /// 1 0 8 7 4 3 0
456 /// +-+---+----+-----------------------+
457 /// |1| 0 | Ix | data for pers routine |
458 /// +-+---+----+-----------------------+
459 /// | more personality routine data |
460
Saleem Abdulrasoolfe097bf2014-01-09 04:31:14 +0000461 const support::ulittle32_t Word =
462 *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000463
464 if (Word & 0x80000000) {
465 SW.printString("Model", StringRef("Compact"));
466
467 unsigned PersonalityIndex = (Word & 0x0f000000) >> 24;
468 SW.printNumber("PersonalityIndex", PersonalityIndex);
469
470 switch (PersonalityIndex) {
471 case AEABI_UNWIND_CPP_PR0:
Saleem Abdulrasool804bd9d2014-02-08 23:17:08 +0000472 PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000473 break;
474 case AEABI_UNWIND_CPP_PR1:
475 case AEABI_UNWIND_CPP_PR2:
476 unsigned AdditionalWords = (Word & 0x00ff0000) >> 16;
Saleem Abdulrasool3ca4db22014-01-09 04:31:18 +0000477 PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords,
478 2);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000479 break;
480 }
481 } else {
482 SW.printString("Model", StringRef("Generic"));
483
484 uint64_t Address = PREL31(Word, EHT->sh_addr);
485 SW.printHex("PersonalityRoutineAddress", Address);
486 if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address))
487 SW.printString("PersonalityRoutineName", *Name);
488 }
489}
490
491template <typename ET>
Saleem Abdulrasool3ca4db22014-01-09 04:31:18 +0000492void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,
493 size_t Length, off_t Offset) const {
494 ListScope OCC(SW, "Opcodes");
Saleem Abdulrasoold28c0942014-01-21 02:33:15 +0000495 OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000496}
497
498template <typename ET>
499void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,
500 const Elf_Shdr *IT) const {
Davide Italiano63830bc2016-11-16 05:10:28 +0000501 Expected<ArrayRef<uint8_t>> Contents = ELF->getSectionContents(IT);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000502 if (!Contents)
503 return;
504
505 /// ARM EHABI Section 5 - Index Table Entries
506 /// * The first word contains a PREL31 offset to the start of a function with
507 /// bit 31 clear
508 /// * The second word contains one of:
509 /// - The PREL31 offset of the start of the table entry for the function,
510 /// with bit 31 clear
511 /// - The exception-handling table entry itself with bit 31 set
512 /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
513 /// frames cannot be unwound
514
Saleem Abdulrasoolfe097bf2014-01-09 04:31:14 +0000515 const support::ulittle32_t *Data =
516 reinterpret_cast<const support::ulittle32_t *>(Contents->data());
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000517 const unsigned Entries = IT->sh_size / IndexTableEntrySize;
518
519 ListScope E(SW, "Entries");
520 for (unsigned Entry = 0; Entry < Entries; ++Entry) {
521 DictScope E(SW, "Entry");
522
Saleem Abdulrasoolfe097bf2014-01-09 04:31:14 +0000523 const support::ulittle32_t Word0 =
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000524 Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0];
Saleem Abdulrasoolfe097bf2014-01-09 04:31:14 +0000525 const support::ulittle32_t Word1 =
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000526 Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1];
527
528 if (Word0 & 0x80000000) {
529 errs() << "corrupt unwind data in section " << SectionIndex << "\n";
530 continue;
531 }
532
533 const uint64_t Offset = PREL31(Word0, IT->sh_addr);
534 SW.printHex("FunctionAddress", Offset);
535 if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset))
536 SW.printString("FunctionName", *Name);
537
538 if (Word1 == EXIDX_CANTUNWIND) {
539 SW.printString("Model", StringRef("CantUnwind"));
540 continue;
541 }
542
543 if (Word1 & 0x80000000) {
544 SW.printString("Model", StringRef("Compact (Inline)"));
545
546 unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24;
547 SW.printNumber("PersonalityIndex", PersonalityIndex);
548
Saleem Abdulrasool3ca4db22014-01-09 04:31:18 +0000549 PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000550 } else {
551 const Elf_Shdr *EHT =
552 FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4);
553
Davide Italiano63830bc2016-11-16 05:10:28 +0000554 if (auto Name = ELF->getSectionName(EHT))
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000555 SW.printString("ExceptionHandlingTable", *Name);
556
557 uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr);
558 SW.printHex("TableEntryOffset", TableEntryOffset);
559
560 PrintExceptionTable(IT, EHT, TableEntryOffset);
561 }
562 }
563}
564
565template <typename ET>
566void PrinterContext<ET>::PrintUnwindInformation() const {
567 DictScope UI(SW, "UnwindInformation");
568
569 int SectionIndex = 0;
Rafael Espindola8ee0ff82016-11-02 14:10:57 +0000570 for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) {
Rafael Espindola6e0583f2015-06-30 19:13:25 +0000571 if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000572 DictScope UIT(SW, "UnwindIndexTable");
573
574 SW.printNumber("SectionIndex", SectionIndex);
Davide Italiano63830bc2016-11-16 05:10:28 +0000575 if (auto SectionName = ELF->getSectionName(&Sec))
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000576 SW.printString("SectionName", *SectionName);
Rafael Espindola6e0583f2015-06-30 19:13:25 +0000577 SW.printHex("SectionOffset", Sec.sh_offset);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000578
Rafael Espindola6e0583f2015-06-30 19:13:25 +0000579 PrintIndexTable(SectionIndex, &Sec);
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000580 }
Rafael Espindola6e0583f2015-06-30 19:13:25 +0000581 ++SectionIndex;
Saleem Abdulrasoolbc411902014-01-08 03:28:09 +0000582 }
583}
584}
585}
586}
587
588#endif