brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.2 KiB · 5f3cc7d Raw
648 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H10#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H11 12#include "llvm-readobj.h"13#include "llvm/ADT/STLExtras.h"14#include "llvm/Object/ELF.h"15#include "llvm/Object/ELFTypes.h"16#include "llvm/Support/ARMEHABI.h"17#include "llvm/Support/Debug.h"18#include "llvm/Support/Endian.h"19#include "llvm/Support/Format.h"20#include "llvm/Support/ScopedPrinter.h"21#include "llvm/Support/type_traits.h"22 23namespace llvm {24namespace ARM {25namespace EHABI {26 27class OpcodeDecoder {28  ScopedPrinter &SW;29  raw_ostream &OS;30 31  struct RingEntry {32    uint8_t Mask;33    uint8_t Value;34    void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);35  };36  static ArrayRef<RingEntry> ring();37 38  void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);39  void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);40  void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI);41  void Decode_10011101(const uint8_t *Opcodes, unsigned &OI);42  void Decode_10011111(const uint8_t *Opcodes, unsigned &OI);43  void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI);44  void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI);45  void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI);46  void Decode_10110000(const uint8_t *Opcodes, unsigned &OI);47  void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI);48  void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI);49  void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI);50  void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI);51  void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI);52  void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI);53  void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI);54  void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI);55  void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI);56  void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI);57  void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI);58  void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI);59  void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI);60 61  void PrintGPR(uint16_t GPRMask);62  void PrintRegisters(uint32_t Mask, StringRef Prefix);63 64public:65  OpcodeDecoder(ScopedPrinter &SW) : SW(SW), OS(SW.getOStream()) {}66  void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);67};68 69inline ArrayRef<OpcodeDecoder::RingEntry> OpcodeDecoder::ring() {70  static const OpcodeDecoder::RingEntry Ring[] = {71      {0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx},72      {0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx},73      {0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii},74      {0xff, 0x9d, &OpcodeDecoder::Decode_10011101},75      {0xff, 0x9f, &OpcodeDecoder::Decode_10011111},76      {0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn},77      {0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn},78      {0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn},79      {0xff, 0xb0, &OpcodeDecoder::Decode_10110000},80      {0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii},81      {0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128},82      {0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc},83      {0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn},84      {0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn},85      {0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc},86      {0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii},87      {0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc},88      {0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc},89      {0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy},90      {0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn},91      {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn},92      {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy},93  };94  return ArrayRef(Ring);95}96 97inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes,98                                           unsigned &OI) {99  uint8_t Opcode = Opcodes[OI++ ^ 3];100  SW.startLine() << format("0x%02X      ; vsp = vsp + %u\n", Opcode,101                           ((Opcode & 0x3f) << 2) + 4);102}103inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes,104                                           unsigned &OI) {105  uint8_t Opcode = Opcodes[OI++ ^ 3];106  SW.startLine() << format("0x%02X      ; vsp = vsp - %u\n", Opcode,107                           ((Opcode & 0x3f) << 2) + 4);108}109inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,110                                                    unsigned &OI) {111  uint8_t Opcode0 = Opcodes[OI++ ^ 3];112  uint8_t Opcode1 = Opcodes[OI++ ^ 3];113 114  uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);115  SW.startLine()116    << format("0x%02X 0x%02X ; %s",117              Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");118  if (GPRMask)119    PrintGPR(GPRMask);120  OS << '\n';121}122inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes,123                                           unsigned &OI) {124  uint8_t Opcode = Opcodes[OI++ ^ 3];125  SW.startLine() << format("0x%02X      ; reserved (ARM MOVrr)\n", Opcode);126}127inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes,128                                           unsigned &OI) {129  uint8_t Opcode = Opcodes[OI++ ^ 3];130  SW.startLine() << format("0x%02X      ; reserved (WiMMX MOVrr)\n", Opcode);131}132inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes,133                                           unsigned &OI) {134  uint8_t Opcode = Opcodes[OI++ ^ 3];135  SW.startLine() << format("0x%02X      ; vsp = r%u\n", Opcode, (Opcode & 0x0f));136}137inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes,138                                           unsigned &OI) {139  uint8_t Opcode = Opcodes[OI++ ^ 3];140  SW.startLine() << format("0x%02X      ; pop ", Opcode);141  PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));142  OS << '\n';143}144inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes,145                                           unsigned &OI) {146  uint8_t Opcode = Opcodes[OI++ ^ 3];147  SW.startLine() << format("0x%02X      ; pop ", Opcode);148  PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));149  OS << '\n';150}151inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes,152                                           unsigned &OI) {153  uint8_t Opcode = Opcodes[OI++ ^ 3];154  SW.startLine() << format("0x%02X      ; finish\n", Opcode);155}156inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,157                                                    unsigned &OI) {158  uint8_t Opcode0 = Opcodes[OI++ ^ 3];159  uint8_t Opcode1 = Opcodes[OI++ ^ 3];160 161  SW.startLine() << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,162                           (Opcode1 & 0xf0) ? "spare" : "pop ");163  if (((Opcode1 & 0xf0) == 0x00) && Opcode1)164    PrintGPR((Opcode1 & 0x0f));165  OS << '\n';166}167inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,168                                                   unsigned &OI) {169  uint8_t Opcode = Opcodes[OI++ ^ 3];170  SW.startLine() << format("0x%02X ", Opcode);171 172  SmallVector<uint8_t, 4> ULEB;173  do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);174 175  for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)176    OS << format("0x%02X ", ULEB[BI]);177 178  uint64_t Value = 0;179  for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)180    Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));181 182  OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));183}184inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,185                                                    unsigned &OI) {186  uint8_t Opcode0 = Opcodes[OI++ ^ 3];187  uint8_t Opcode1 = Opcodes[OI++ ^ 3];188  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);189  uint8_t Start = ((Opcode1 & 0xf0) >> 4);190  uint8_t Count = ((Opcode1 & 0x0f) >> 0);191  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");192  OS << '\n';193}194inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes,195                                           unsigned &OI) {196  uint8_t Opcode = Opcodes[OI++ ^ 3];197  SW.startLine() << format("0x%02X      ; %s\n", Opcode,198                           (Opcode == 0xb4) ? "pop ra_auth_code" : "spare");199}200inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes,201                                           unsigned &OI) {202  uint8_t Opcode = Opcodes[OI++ ^ 3];203  SW.startLine() << format("0x%02X      ; pop ", Opcode);204  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");205  OS << '\n';206}207inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,208                                                    unsigned &OI) {209  uint8_t Opcode0 = Opcodes[OI++ ^ 3];210  uint8_t Opcode1 = Opcodes[OI++ ^ 3];211  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);212  uint8_t Start = ((Opcode1 & 0xf0) >> 4);213  uint8_t Count = ((Opcode1 & 0x0f) >> 0);214  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");215  OS << '\n';216}217inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,218                                                    unsigned &OI) {219  uint8_t Opcode0 = Opcodes[OI++ ^ 3];220  uint8_t Opcode1 = Opcodes[OI++ ^ 3];221  SW.startLine()222    << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,223              ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");224  if ((Opcode1 & 0xf0) == 0x00 && Opcode1)225      PrintRegisters(Opcode1 & 0x0f, "wCGR");226  OS << '\n';227}228inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,229                                                    unsigned &OI) {230  uint8_t Opcode0 = Opcodes[OI++ ^ 3];231  uint8_t Opcode1 = Opcodes[OI++ ^ 3];232  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);233  uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);234  uint8_t Count = ((Opcode1 & 0x0f) >> 0);235  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");236  OS << '\n';237}238inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,239                                                    unsigned &OI) {240  uint8_t Opcode0 = Opcodes[OI++ ^ 3];241  uint8_t Opcode1 = Opcodes[OI++ ^ 3];242  SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);243  uint8_t Start = ((Opcode1 & 0xf0) >> 4);244  uint8_t Count = ((Opcode1 & 0x0f) >> 0);245  PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");246  OS << '\n';247}248inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes,249                                           unsigned &OI) {250  uint8_t Opcode = Opcodes[OI++ ^ 3];251  SW.startLine() << format("0x%02X      ; spare\n", Opcode);252}253inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes,254                                           unsigned &OI) {255  uint8_t Opcode = Opcodes[OI++ ^ 3];256  SW.startLine() << format("0x%02X      ; pop ", Opcode);257  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");258  OS << '\n';259}260inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes,261                                           unsigned &OI) {262  uint8_t Opcode = Opcodes[OI++ ^ 3];263  SW.startLine() << format("0x%02X      ; pop ", Opcode);264  PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");265  OS << '\n';266}267inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes,268                                           unsigned &OI) {269  uint8_t Opcode = Opcodes[OI++ ^ 3];270  SW.startLine() << format("0x%02X      ; spare\n", Opcode);271}272 273inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {274  static const char *GPRRegisterNames[16] = {275    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",276    "fp", "ip", "sp", "lr", "pc"277  };278 279  OS << '{';280  bool Comma = false;281  for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {282    if (GPRMask & (1 << RI)) {283      if (Comma)284        OS << ", ";285      OS << GPRRegisterNames[RI];286      Comma = true;287    }288  }289  OS << '}';290}291 292inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {293  OS << '{';294  bool Comma = false;295  for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {296    if (VFPMask & (1 << RI)) {297      if (Comma)298        OS << ", ";299      OS << Prefix << RI;300      Comma = true;301    }302  }303  OS << '}';304}305 306inline void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset,307                                  size_t Length) {308  for (unsigned OCI = Offset; OCI < Length + Offset; ) {309    bool Decoded = false;310    for (const auto &RE : ring()) {311      if ((Opcodes[OCI ^ 3] & RE.Mask) == RE.Value) {312        (this->*RE.Routine)(Opcodes, OCI);313        Decoded = true;314        break;315      }316    }317    if (!Decoded)318      SW.startLine() << format("0x%02X      ; reserved\n", Opcodes[OCI++ ^ 3]);319  }320}321 322template <typename ET>323class PrinterContext {324  typedef typename ET::Sym Elf_Sym;325  typedef typename ET::Shdr Elf_Shdr;326  typedef typename ET::Rel Elf_Rel;327  typedef typename ET::Word Elf_Word;328 329  ScopedPrinter &SW;330  const object::ELFFile<ET> &ELF;331  StringRef FileName;332  const Elf_Shdr *Symtab;333  ArrayRef<Elf_Word> ShndxTable;334 335  static const size_t IndexTableEntrySize;336 337  static uint64_t PREL31(uint32_t Address, uint32_t Place) {338    uint64_t Location = Address & 0x7fffffff;339    if (Location & 0x40000000)340      Location |= (uint64_t) ~0x7fffffff;341    return Location + Place;342  }343 344  ErrorOr<StringRef>345  FunctionAtAddress(uint64_t Address,346                    std::optional<unsigned> SectionIndex) const;347  const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,348                                     off_t IndexTableOffset) const;349 350  void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const;351  void PrintExceptionTable(const Elf_Shdr &EHT,352                           uint64_t TableEntryOffset) const;353  void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;354 355public:356  PrinterContext(ScopedPrinter &SW, const object::ELFFile<ET> &ELF,357                 StringRef FileName, const Elf_Shdr *Symtab)358      : SW(SW), ELF(ELF), FileName(FileName), Symtab(Symtab) {}359 360  void PrintUnwindInformation() const;361};362 363template <typename ET>364const size_t PrinterContext<ET>::IndexTableEntrySize = 8;365 366template <typename ET>367ErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(368    uint64_t Address, std::optional<unsigned> SectionIndex) const {369  if (!Symtab)370    return inconvertibleErrorCode();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 (SectionIndex && *SectionIndex != Sym.st_shndx)378      continue;379 380    if (Sym.st_value == Address && Sym.getType() == ELF::STT_FUNC) {381      auto NameOrErr = Sym.getName(StrTable);382      if (!NameOrErr) {383        // TODO: Actually report errors helpfully.384        consumeError(NameOrErr.takeError());385        return inconvertibleErrorCode();386      }387      return *NameOrErr;388    }389  }390 391  return inconvertibleErrorCode();392}393 394template <typename ET>395const typename ET::Shdr *396PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,397                                       off_t IndexTableOffset) const {398  /// Iterate through the sections, searching for the relocation section399  /// associated with the unwind index table section specified by400  /// IndexSectionIndex.  Iterate the associated section searching for the401  /// relocation associated with the index table entry specified by402  /// IndexTableOffset.  The symbol is the section symbol for the exception403  /// handling table.  Use this symbol to recover the actual exception handling404  /// table.405 406  for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF.sections())) {407    if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)408      continue;409 410    auto SymTabOrErr = ELF.getSection(Sec.sh_link);411    if (!SymTabOrErr)412      reportError(SymTabOrErr.takeError(), FileName);413    const Elf_Shdr *SymTab = *SymTabOrErr;414 415    for (const Elf_Rel &R : unwrapOrError(FileName, ELF.rels(Sec))) {416      if (R.r_offset != static_cast<unsigned>(IndexTableOffset))417        continue;418 419      typename ET::Rela RelA;420      RelA.r_offset = R.r_offset;421      RelA.r_info = R.r_info;422      RelA.r_addend = 0;423 424      const Elf_Sym *Symbol =425          unwrapOrError(FileName, ELF.getRelocationSymbol(RelA, SymTab));426 427      auto Ret = ELF.getSection(*Symbol, SymTab, ShndxTable);428      if (!Ret)429        report_fatal_error(Twine(errorToErrorCode(Ret.takeError()).message()));430      return *Ret;431    }432  }433  return nullptr;434}435 436template <typename ET>437static const typename ET::Shdr *438findSectionContainingAddress(const object::ELFFile<ET> &Obj, StringRef FileName,439                             uint64_t Address) {440  for (const typename ET::Shdr &Sec : unwrapOrError(FileName, Obj.sections()))441    if (Address >= Sec.sh_addr && Address < Sec.sh_addr + Sec.sh_size)442      return &Sec;443  return nullptr;444}445 446template <typename ET>447void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr &EHT,448                                             uint64_t TableEntryOffset) const {449  // TODO: handle failure.450  Expected<ArrayRef<uint8_t>> Contents = ELF.getSectionContents(EHT);451  if (!Contents)452    return;453 454  /// ARM EHABI Section 6.2 - The generic model455  ///456  /// An exception-handling table entry for the generic model is laid out as:457  ///458  ///  3 3459  ///  1 0                            0460  /// +-+------------------------------+461  /// |0|  personality routine offset  |462  /// +-+------------------------------+463  /// |  personality routine data ...  |464  ///465  ///466  /// ARM EHABI Section 6.3 - The ARM-defined compact model467  ///468  /// An exception-handling table entry for the compact model looks like:469  ///470  ///  3 3 2 2  2 2471  ///  1 0 8 7  4 3                     0472  /// +-+---+----+-----------------------+473  /// |1| 0 | Ix | data for pers routine |474  /// +-+---+----+-----------------------+475  /// |  more personality routine data   |476 477  const support::ulittle32_t Word =478    *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset);479 480  if (Word & 0x80000000) {481    SW.printString("Model", StringRef("Compact"));482 483    unsigned PersonalityIndex = (Word & 0x0f000000) >> 24;484    SW.printNumber("PersonalityIndex", PersonalityIndex);485 486    switch (PersonalityIndex) {487    case AEABI_UNWIND_CPP_PR0:488      PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1);489      break;490    case AEABI_UNWIND_CPP_PR1:491    case AEABI_UNWIND_CPP_PR2:492      unsigned AdditionalWords = (Word & 0x00ff0000) >> 16;493      PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords,494                   2);495      break;496    }497  } else {498    SW.printString("Model", StringRef("Generic"));499    const bool IsRelocatable = ELF.getHeader().e_type == ELF::ET_REL;500    uint64_t Address = IsRelocatable501                           ? PREL31(Word, EHT.sh_addr)502                           : PREL31(Word, EHT.sh_addr + TableEntryOffset);503    SW.printHex("PersonalityRoutineAddress", Address);504    std::optional<unsigned> SecIndex =505        IsRelocatable ? std::optional<unsigned>(EHT.sh_link) : std::nullopt;506    if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))507      SW.printString("PersonalityRoutineName", *Name);508  }509}510 511template <typename ET>512void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,513                                      size_t Length, off_t Offset) const {514  ListScope OCC(SW, "Opcodes");515  OpcodeDecoder(SW).Decode(Entry, Offset, Length);516}517 518template <typename ET>519void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,520                                         const Elf_Shdr *IT) const {521  // TODO: handle failure.522  Expected<ArrayRef<uint8_t>> Contents = ELF.getSectionContents(*IT);523  if (!Contents)524    return;525 526  /// ARM EHABI Section 5 - Index Table Entries527  /// * The first word contains a PREL31 offset to the start of a function with528  ///   bit 31 clear529  /// * The second word contains one of:530  ///   - The PREL31 offset of the start of the table entry for the function,531  ///     with bit 31 clear532  ///   - The exception-handling table entry itself with bit 31 set533  ///   - The special bit pattern EXIDX_CANTUNWIND, indicating that associated534  ///     frames cannot be unwound535 536  const support::ulittle32_t *Data =537    reinterpret_cast<const support::ulittle32_t *>(Contents->data());538  const unsigned Entries = IT->sh_size / IndexTableEntrySize;539  const bool IsRelocatable = ELF.getHeader().e_type == ELF::ET_REL;540 541  ListScope E(SW, "Entries");542  for (unsigned Entry = 0; Entry < Entries; ++Entry) {543    DictScope E(SW, "Entry");544 545    const support::ulittle32_t Word0 =546      Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0];547    const support::ulittle32_t Word1 =548      Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1];549 550    if (Word0 & 0x80000000) {551      errs() << "corrupt unwind data in section " << SectionIndex << "\n";552      continue;553    }554 555    // FIXME: For a relocatable object ideally we might want to:556    // 1) Find a relocation for the offset of Word0.557    // 2) Verify this relocation is of an expected type (R_ARM_PREL31) and558    //    verify the symbol index.559    // 3) Resolve the relocation using it's symbol value, addend etc.560    // Currently the code assumes that Word0 contains an addend of a561    // R_ARM_PREL31 REL relocation that references a section symbol. RELA562    // relocations are not supported and it works because addresses of sections563    // are nulls in relocatable objects.564    //565    // For a non-relocatable object, Word0 contains a place-relative signed566    // offset to the referenced entity.567    const uint64_t Address =568        IsRelocatable569            ? PREL31(Word0, IT->sh_addr)570            : PREL31(Word0, IT->sh_addr + Entry * IndexTableEntrySize);571    SW.printHex("FunctionAddress", Address);572 573    // In a relocatable output we might have many .ARM.exidx sections linked to574    // their code sections via the sh_link field. For a non-relocatable ELF file575    // the sh_link field is not reliable, because we have one .ARM.exidx section576    // normally, but might have many code sections.577    std::optional<unsigned> SecIndex =578        IsRelocatable ? std::optional<unsigned>(IT->sh_link) : std::nullopt;579    if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))580      SW.printString("FunctionName", *Name);581 582    if (Word1 == EXIDX_CANTUNWIND) {583      SW.printString("Model", StringRef("CantUnwind"));584      continue;585    }586 587    if (Word1 & 0x80000000) {588      SW.printString("Model", StringRef("Compact (Inline)"));589 590      unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24;591      SW.printNumber("PersonalityIndex", PersonalityIndex);592 593      PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1);594    } else {595      const Elf_Shdr *EHT;596      uint64_t TableEntryAddress;597      if (IsRelocatable) {598        TableEntryAddress = PREL31(Word1, IT->sh_addr);599        EHT = FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4);600      } else {601        TableEntryAddress =602            PREL31(Word1, IT->sh_addr + Entry * IndexTableEntrySize + 4);603        EHT = findSectionContainingAddress(ELF, FileName, TableEntryAddress);604      }605 606      if (EHT)607        // TODO: handle failure.608        if (Expected<StringRef> Name = ELF.getSectionName(*EHT))609          SW.printString("ExceptionHandlingTable", *Name);610 611      SW.printHex(IsRelocatable ? "TableEntryOffset" : "TableEntryAddress",612                  TableEntryAddress);613      if (EHT) {614        if (IsRelocatable)615          PrintExceptionTable(*EHT, TableEntryAddress);616        else617          PrintExceptionTable(*EHT, TableEntryAddress - EHT->sh_addr);618      }619    }620  }621}622 623template <typename ET>624void PrinterContext<ET>::PrintUnwindInformation() const {625  DictScope UI(SW, "UnwindInformation");626 627  int SectionIndex = 0;628  for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF.sections())) {629    if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {630      DictScope UIT(SW, "UnwindIndexTable");631 632      SW.printNumber("SectionIndex", SectionIndex);633      // TODO: handle failure.634      if (Expected<StringRef> SectionName = ELF.getSectionName(Sec))635        SW.printString("SectionName", *SectionName);636      SW.printHex("SectionOffset", Sec.sh_offset);637 638      PrintIndexTable(SectionIndex, &Sec);639    }640    ++SectionIndex;641  }642}643}644}645}646 647#endif648