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