1//===--- 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
10#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
11#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
12
13#include "Error.h"
14#include "llvm-readobj.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Object/ELF.h"
17#include "llvm/Object/ELFTypes.h"
18#include "llvm/Support/ARMEHABI.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/Endian.h"
21#include "llvm/Support/Format.h"
22#include "llvm/Support/ScopedPrinter.h"
23#include "llvm/Support/type_traits.h"
24
25namespace llvm {
26namespace ARM {
27namespace EHABI {
28
29class OpcodeDecoder {
30  ScopedPrinter &SW;
31  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  };
38  static const RingEntry Ring[];
39
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:
67  OpcodeDecoder(ScopedPrinter &SW) : SW(SW), OS(SW.getOStream()) {}
68  void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);
69};
70
71const OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = {
72  { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx },
73  { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx },
74  { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii },
75  { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 },
76  { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 },
77  { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn },
78  { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn },
79  { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn },
80  { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 },
81  { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii },
82  { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 },
83  { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc },
84  { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn },
85  { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn },
86  { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc },
87  { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii },
88  { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc },
89  { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc },
90  { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy },
91  { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn },
92  { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn },
93  { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy },
94};
95
96void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
97  uint8_t Opcode = Opcodes[OI++ ^ 3];
98  SW.startLine() << format("0x%02X      ; vsp = vsp + %u\n", Opcode,
99                           ((Opcode & 0x3f) << 2) + 4);
100}
101void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
102  uint8_t Opcode = Opcodes[OI++ ^ 3];
103  SW.startLine() << format("0x%02X      ; vsp = vsp - %u\n", Opcode,
104                           ((Opcode & 0x3f) << 2) + 4);
105}
106void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
107                                             unsigned &OI) {
108  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
109  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
110
111  uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
112  SW.startLine()
113    << format("0x%02X 0x%02X ; %s",
114              Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
115  if (GPRMask)
116    PrintGPR(GPRMask);
117  OS << '\n';
118}
119void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) {
120  uint8_t Opcode = Opcodes[OI++ ^ 3];
121  SW.startLine() << format("0x%02X      ; reserved (ARM MOVrr)\n", Opcode);
122}
123void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) {
124  uint8_t Opcode = Opcodes[OI++ ^ 3];
125  SW.startLine() << format("0x%02X      ; reserved (WiMMX MOVrr)\n", Opcode);
126}
127void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) {
128  uint8_t Opcode = Opcodes[OI++ ^ 3];
129  SW.startLine() << format("0x%02X      ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
130}
131void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) {
132  uint8_t Opcode = Opcodes[OI++ ^ 3];
133  SW.startLine() << format("0x%02X      ; pop ", Opcode);
134  PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
135  OS << '\n';
136}
137void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) {
138  uint8_t Opcode = Opcodes[OI++ ^ 3];
139  SW.startLine() << format("0x%02X      ; pop ", Opcode);
140  PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
141  OS << '\n';
142}
143void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) {
144  uint8_t Opcode = Opcodes[OI++ ^ 3];
145  SW.startLine() << format("0x%02X      ; finish\n", Opcode);
146}
147void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
148                                             unsigned &OI) {
149  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
150  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
151
152  SW.startLine()
153    << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
154              ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
155  if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
156    PrintGPR((Opcode1 & 0x0f));
157  OS << '\n';
158}
159void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
160                                            unsigned &OI) {
161  uint8_t Opcode = Opcodes[OI++ ^ 3];
162  SW.startLine() << format("0x%02X ", Opcode);
163
164  SmallVector<uint8_t, 4> ULEB;
165  do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
166
167  for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
168    OS << format("0x%02X ", ULEB[BI]);
169
170  uint64_t Value = 0;
171  for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
172    Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
173
174  OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
175}
176void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
177                                             unsigned &OI) {
178  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
179  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
180  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
181  uint8_t Start = ((Opcode1 & 0xf0) >> 4);
182  uint8_t Count = ((Opcode1 & 0x0f) >> 0);
183  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
184  OS << '\n';
185}
186void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) {
187  uint8_t Opcode = Opcodes[OI++ ^ 3];
188  SW.startLine() << format("0x%02X      ; spare\n", Opcode);
189}
190void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) {
191  uint8_t Opcode = Opcodes[OI++ ^ 3];
192  SW.startLine() << format("0x%02X      ; pop ", Opcode);
193  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
194  OS << '\n';
195}
196void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
197                                             unsigned &OI) {
198  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
199  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
200  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
201  uint8_t Start = ((Opcode1 & 0xf0) >> 4);
202  uint8_t Count = ((Opcode1 & 0x0f) >> 0);
203  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
204  OS << '\n';
205}
206void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
207                                             unsigned &OI) {
208  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
209  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
210  SW.startLine()
211    << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
212              ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
213  if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
214      PrintRegisters(Opcode1 & 0x0f, "wCGR");
215  OS << '\n';
216}
217void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
218                                             unsigned &OI) {
219  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
220  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
221  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
222  uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
223  uint8_t Count = ((Opcode1 & 0x0f) >> 0);
224  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
225  OS << '\n';
226}
227void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
228                                             unsigned &OI) {
229  uint8_t Opcode0 = Opcodes[OI++ ^ 3];
230  uint8_t Opcode1 = Opcodes[OI++ ^ 3];
231  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
232  uint8_t Start = ((Opcode1 & 0xf0) >> 4);
233  uint8_t Count = ((Opcode1 & 0x0f) >> 0);
234  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
235  OS << '\n';
236}
237void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) {
238  uint8_t Opcode = Opcodes[OI++ ^ 3];
239  SW.startLine() << format("0x%02X      ; spare\n", Opcode);
240}
241void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) {
242  uint8_t Opcode = Opcodes[OI++ ^ 3];
243  SW.startLine() << format("0x%02X      ; pop ", Opcode);
244  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
245  OS << '\n';
246}
247void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) {
248  uint8_t Opcode = Opcodes[OI++ ^ 3];
249  SW.startLine() << format("0x%02X      ; pop ", Opcode);
250  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
251  OS << '\n';
252}
253void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) {
254  uint8_t Opcode = Opcodes[OI++ ^ 3];
255  SW.startLine() << format("0x%02X      ; spare\n", Opcode);
256}
257
258void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
259  static const char *GPRRegisterNames[16] = {
260    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
261    "fp", "ip", "sp", "lr", "pc"
262  };
263
264  OS << '{';
265  bool Comma = false;
266  for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {
267    if (GPRMask & (1 << RI)) {
268      if (Comma)
269        OS << ", ";
270      OS << GPRRegisterNames[RI];
271      Comma = true;
272    }
273  }
274  OS << '}';
275}
276
277void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
278  OS << '{';
279  bool Comma = false;
280  for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
281    if (VFPMask & (1 << RI)) {
282      if (Comma)
283        OS << ", ";
284      OS << Prefix << RI;
285      Comma = true;
286    }
287  }
288  OS << '}';
289}
290
291void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) {
292  for (unsigned OCI = Offset; OCI < Length + Offset; ) {
293    bool Decoded = false;
294    for (unsigned REI = 0, REE = array_lengthof(Ring);
295         REI != REE && !Decoded; ++REI) {
296      if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) {
297        (this->*Ring[REI].Routine)(Opcodes, OCI);
298        Decoded = true;
299        break;
300      }
301    }
302    if (!Decoded)
303      SW.startLine() << format("0x%02X      ; reserved\n", Opcodes[OCI++ ^ 3]);
304  }
305}
306
307template <typename ET>
308class PrinterContext {
309  typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym;
310  typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr;
311  typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel;
312  typedef typename object::ELFFile<ET>::Elf_Word Elf_Word;
313
314  ScopedPrinter &SW;
315  const object::ELFFile<ET> *ELF;
316  const Elf_Shdr *Symtab;
317  ArrayRef<Elf_Word> ShndxTable;
318
319  static const size_t IndexTableEntrySize;
320
321  static uint64_t PREL31(uint32_t Address, uint32_t Place) {
322    uint64_t Location = Address & 0x7fffffff;
323    if (Location & 0x04000000)
324      Location |= (uint64_t) ~0x7fffffff;
325    return Location + Place;
326  }
327
328  ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const;
329  const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,
330                                     off_t IndexTableOffset) const;
331
332  void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const;
333  void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT,
334                           uint64_t TableEntryOffset) const;
335  void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;
336
337public:
338  PrinterContext(ScopedPrinter &SW, const object::ELFFile<ET> *ELF,
339                 const Elf_Shdr *Symtab)
340      : SW(SW), ELF(ELF), Symtab(Symtab) {}
341
342  void PrintUnwindInformation() const;
343};
344
345template <typename ET>
346const size_t PrinterContext<ET>::IndexTableEntrySize = 8;
347
348template <typename ET>
349ErrorOr<StringRef>
350PrinterContext<ET>::FunctionAtAddress(unsigned Section,
351                                      uint64_t Address) const {
352  ErrorOr<StringRef> StrTableOrErr = ELF->getStringTableForSymtab(*Symtab);
353  error(StrTableOrErr.getError());
354  StringRef StrTable = *StrTableOrErr;
355
356  for (const Elf_Sym &Sym : ELF->symbols(Symtab))
357    if (Sym.st_shndx == Section && Sym.st_value == Address &&
358        Sym.getType() == ELF::STT_FUNC) {
359      auto NameOrErr = Sym.getName(StrTable);
360      if (!NameOrErr) {
361        // TODO: Actually report errors helpfully.
362        consumeError(NameOrErr.takeError());
363        return readobj_error::unknown_symbol;
364      }
365      return *NameOrErr;
366    }
367  return readobj_error::unknown_symbol;
368}
369
370template <typename ET>
371const typename object::ELFFile<ET>::Elf_Shdr *
372PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
373                                       off_t IndexTableOffset) const {
374  /// Iterate through the sections, searching for the relocation section
375  /// associated with the unwind index table section specified by
376  /// IndexSectionIndex.  Iterate the associated section searching for the
377  /// relocation associated with the index table entry specified by
378  /// IndexTableOffset.  The symbol is the section symbol for the exception
379  /// handling table.  Use this symbol to recover the actual exception handling
380  /// table.
381
382  for (const Elf_Shdr &Sec : ELF->sections()) {
383    if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)
384      continue;
385
386    ErrorOr<const Elf_Shdr *> SymTabOrErr = ELF->getSection(Sec.sh_link);
387    error(SymTabOrErr.getError());
388    const Elf_Shdr *SymTab = *SymTabOrErr;
389
390    for (const Elf_Rel &R : ELF->rels(&Sec)) {
391      if (R.r_offset != static_cast<unsigned>(IndexTableOffset))
392        continue;
393
394      typename object::ELFFile<ET>::Elf_Rela RelA;
395      RelA.r_offset = R.r_offset;
396      RelA.r_info = R.r_info;
397      RelA.r_addend = 0;
398
399      const Elf_Sym *Symbol = ELF->getRelocationSymbol(&RelA, SymTab);
400
401      ErrorOr<const Elf_Shdr *> Ret =
402          ELF->getSection(Symbol, SymTab, ShndxTable);
403      if (std::error_code EC = Ret.getError())
404        report_fatal_error(EC.message());
405      return *Ret;
406    }
407  }
408  return nullptr;
409}
410
411template <typename ET>
412void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT,
413                                             const Elf_Shdr *EHT,
414                                             uint64_t TableEntryOffset) const {
415  ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT);
416  if (!Contents)
417    return;
418
419  /// ARM EHABI Section 6.2 - The generic model
420  ///
421  /// An exception-handling table entry for the generic model is laid out as:
422  ///
423  ///  3 3
424  ///  1 0                            0
425  /// +-+------------------------------+
426  /// |0|  personality routine offset  |
427  /// +-+------------------------------+
428  /// |  personality routine data ...  |
429  ///
430  ///
431  /// ARM EHABI Section 6.3 - The ARM-defined compact model
432  ///
433  /// An exception-handling table entry for the compact model looks like:
434  ///
435  ///  3 3 2 2  2 2
436  ///  1 0 8 7  4 3                     0
437  /// +-+---+----+-----------------------+
438  /// |1| 0 | Ix | data for pers routine |
439  /// +-+---+----+-----------------------+
440  /// |  more personality routine data   |
441
442  const support::ulittle32_t Word =
443    *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset);
444
445  if (Word & 0x80000000) {
446    SW.printString("Model", StringRef("Compact"));
447
448    unsigned PersonalityIndex = (Word & 0x0f000000) >> 24;
449    SW.printNumber("PersonalityIndex", PersonalityIndex);
450
451    switch (PersonalityIndex) {
452    case AEABI_UNWIND_CPP_PR0:
453      PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1);
454      break;
455    case AEABI_UNWIND_CPP_PR1:
456    case AEABI_UNWIND_CPP_PR2:
457      unsigned AdditionalWords = (Word & 0x00ff0000) >> 16;
458      PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords,
459                   2);
460      break;
461    }
462  } else {
463    SW.printString("Model", StringRef("Generic"));
464
465    uint64_t Address = PREL31(Word, EHT->sh_addr);
466    SW.printHex("PersonalityRoutineAddress", Address);
467    if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address))
468      SW.printString("PersonalityRoutineName", *Name);
469  }
470}
471
472template <typename ET>
473void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,
474                                      size_t Length, off_t Offset) const {
475  ListScope OCC(SW, "Opcodes");
476  OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
477}
478
479template <typename ET>
480void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,
481                                         const Elf_Shdr *IT) const {
482  ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT);
483  if (!Contents)
484    return;
485
486  /// ARM EHABI Section 5 - Index Table Entries
487  /// * The first word contains a PREL31 offset to the start of a function with
488  ///   bit 31 clear
489  /// * The second word contains one of:
490  ///   - The PREL31 offset of the start of the table entry for the function,
491  ///     with bit 31 clear
492  ///   - The exception-handling table entry itself with bit 31 set
493  ///   - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
494  ///     frames cannot be unwound
495
496  const support::ulittle32_t *Data =
497    reinterpret_cast<const support::ulittle32_t *>(Contents->data());
498  const unsigned Entries = IT->sh_size / IndexTableEntrySize;
499
500  ListScope E(SW, "Entries");
501  for (unsigned Entry = 0; Entry < Entries; ++Entry) {
502    DictScope E(SW, "Entry");
503
504    const support::ulittle32_t Word0 =
505      Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0];
506    const support::ulittle32_t Word1 =
507      Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1];
508
509    if (Word0 & 0x80000000) {
510      errs() << "corrupt unwind data in section " << SectionIndex << "\n";
511      continue;
512    }
513
514    const uint64_t Offset = PREL31(Word0, IT->sh_addr);
515    SW.printHex("FunctionAddress", Offset);
516    if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset))
517      SW.printString("FunctionName", *Name);
518
519    if (Word1 == EXIDX_CANTUNWIND) {
520      SW.printString("Model", StringRef("CantUnwind"));
521      continue;
522    }
523
524    if (Word1 & 0x80000000) {
525      SW.printString("Model", StringRef("Compact (Inline)"));
526
527      unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24;
528      SW.printNumber("PersonalityIndex", PersonalityIndex);
529
530      PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1);
531    } else {
532      const Elf_Shdr *EHT =
533        FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4);
534
535      if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT))
536        SW.printString("ExceptionHandlingTable", *Name);
537
538      uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr);
539      SW.printHex("TableEntryOffset", TableEntryOffset);
540
541      PrintExceptionTable(IT, EHT, TableEntryOffset);
542    }
543  }
544}
545
546template <typename ET>
547void PrinterContext<ET>::PrintUnwindInformation() const {
548  DictScope UI(SW, "UnwindInformation");
549
550  int SectionIndex = 0;
551  for (const Elf_Shdr &Sec : ELF->sections()) {
552    if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
553      DictScope UIT(SW, "UnwindIndexTable");
554
555      SW.printNumber("SectionIndex", SectionIndex);
556      if (ErrorOr<StringRef> SectionName = ELF->getSectionName(&Sec))
557        SW.printString("SectionName", *SectionName);
558      SW.printHex("SectionOffset", Sec.sh_offset);
559
560      PrintIndexTable(SectionIndex, &Sec);
561    }
562    ++SectionIndex;
563  }
564}
565}
566}
567}
568
569#endif
570
571