Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
35230 views
//===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H9#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H1011#include "llvm-readobj.h"12#include "llvm/ADT/STLExtras.h"13#include "llvm/Object/ELF.h"14#include "llvm/Object/ELFTypes.h"15#include "llvm/Support/ARMEHABI.h"16#include "llvm/Support/Debug.h"17#include "llvm/Support/Endian.h"18#include "llvm/Support/Format.h"19#include "llvm/Support/ScopedPrinter.h"20#include "llvm/Support/type_traits.h"2122namespace llvm {23namespace ARM {24namespace EHABI {2526class OpcodeDecoder {27ScopedPrinter &SW;28raw_ostream &OS;2930struct RingEntry {31uint8_t Mask;32uint8_t Value;33void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);34};35static ArrayRef<RingEntry> ring();3637void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);38void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);39void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI);40void Decode_10011101(const uint8_t *Opcodes, unsigned &OI);41void Decode_10011111(const uint8_t *Opcodes, unsigned &OI);42void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI);43void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI);44void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI);45void Decode_10110000(const uint8_t *Opcodes, unsigned &OI);46void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI);47void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI);48void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI);49void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI);50void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI);51void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI);52void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI);53void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI);54void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI);55void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI);56void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI);57void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI);58void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI);5960void PrintGPR(uint16_t GPRMask);61void PrintRegisters(uint32_t Mask, StringRef Prefix);6263public:64OpcodeDecoder(ScopedPrinter &SW) : SW(SW), OS(SW.getOStream()) {}65void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);66};6768inline ArrayRef<OpcodeDecoder::RingEntry> OpcodeDecoder::ring() {69static const OpcodeDecoder::RingEntry Ring[] = {70{0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx},71{0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx},72{0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii},73{0xff, 0x9d, &OpcodeDecoder::Decode_10011101},74{0xff, 0x9f, &OpcodeDecoder::Decode_10011111},75{0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn},76{0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn},77{0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn},78{0xff, 0xb0, &OpcodeDecoder::Decode_10110000},79{0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii},80{0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128},81{0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc},82{0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn},83{0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn},84{0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc},85{0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii},86{0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc},87{0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc},88{0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy},89{0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn},90{0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn},91{0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy},92};93return ArrayRef(Ring);94}9596inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes,97unsigned &OI) {98uint8_t Opcode = Opcodes[OI++ ^ 3];99SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,100((Opcode & 0x3f) << 2) + 4);101}102inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes,103unsigned &OI) {104uint8_t Opcode = Opcodes[OI++ ^ 3];105SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,106((Opcode & 0x3f) << 2) + 4);107}108inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,109unsigned &OI) {110uint8_t Opcode0 = Opcodes[OI++ ^ 3];111uint8_t Opcode1 = Opcodes[OI++ ^ 3];112113uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);114SW.startLine()115<< format("0x%02X 0x%02X ; %s",116Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");117if (GPRMask)118PrintGPR(GPRMask);119OS << '\n';120}121inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes,122unsigned &OI) {123uint8_t Opcode = Opcodes[OI++ ^ 3];124SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode);125}126inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes,127unsigned &OI) {128uint8_t Opcode = Opcodes[OI++ ^ 3];129SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode);130}131inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes,132unsigned &OI) {133uint8_t Opcode = Opcodes[OI++ ^ 3];134SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));135}136inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes,137unsigned &OI) {138uint8_t Opcode = Opcodes[OI++ ^ 3];139SW.startLine() << format("0x%02X ; pop ", Opcode);140PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));141OS << '\n';142}143inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes,144unsigned &OI) {145uint8_t Opcode = Opcodes[OI++ ^ 3];146SW.startLine() << format("0x%02X ; pop ", Opcode);147PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));148OS << '\n';149}150inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes,151unsigned &OI) {152uint8_t Opcode = Opcodes[OI++ ^ 3];153SW.startLine() << format("0x%02X ; finish\n", Opcode);154}155inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,156unsigned &OI) {157uint8_t Opcode0 = Opcodes[OI++ ^ 3];158uint8_t Opcode1 = Opcodes[OI++ ^ 3];159160SW.startLine() << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,161(Opcode1 & 0xf0) ? "spare" : "pop ");162if (((Opcode1 & 0xf0) == 0x00) && Opcode1)163PrintGPR((Opcode1 & 0x0f));164OS << '\n';165}166inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,167unsigned &OI) {168uint8_t Opcode = Opcodes[OI++ ^ 3];169SW.startLine() << format("0x%02X ", Opcode);170171SmallVector<uint8_t, 4> ULEB;172do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);173174for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)175OS << format("0x%02X ", ULEB[BI]);176177uint64_t Value = 0;178for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)179Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));180181OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));182}183inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,184unsigned &OI) {185uint8_t Opcode0 = Opcodes[OI++ ^ 3];186uint8_t Opcode1 = Opcodes[OI++ ^ 3];187SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);188uint8_t Start = ((Opcode1 & 0xf0) >> 4);189uint8_t Count = ((Opcode1 & 0x0f) >> 0);190PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");191OS << '\n';192}193inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes,194unsigned &OI) {195uint8_t Opcode = Opcodes[OI++ ^ 3];196SW.startLine() << format("0x%02X ; %s\n", Opcode,197(Opcode == 0xb4) ? "pop ra_auth_code" : "spare");198}199inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes,200unsigned &OI) {201uint8_t Opcode = Opcodes[OI++ ^ 3];202SW.startLine() << format("0x%02X ; pop ", Opcode);203PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");204OS << '\n';205}206inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,207unsigned &OI) {208uint8_t Opcode0 = Opcodes[OI++ ^ 3];209uint8_t Opcode1 = Opcodes[OI++ ^ 3];210SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);211uint8_t Start = ((Opcode1 & 0xf0) >> 4);212uint8_t Count = ((Opcode1 & 0x0f) >> 0);213PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");214OS << '\n';215}216inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,217unsigned &OI) {218uint8_t Opcode0 = Opcodes[OI++ ^ 3];219uint8_t Opcode1 = Opcodes[OI++ ^ 3];220SW.startLine()221<< format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,222((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");223if ((Opcode1 & 0xf0) == 0x00 && Opcode1)224PrintRegisters(Opcode1 & 0x0f, "wCGR");225OS << '\n';226}227inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,228unsigned &OI) {229uint8_t Opcode0 = Opcodes[OI++ ^ 3];230uint8_t Opcode1 = Opcodes[OI++ ^ 3];231SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);232uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);233uint8_t Count = ((Opcode1 & 0x0f) >> 0);234PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");235OS << '\n';236}237inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,238unsigned &OI) {239uint8_t Opcode0 = Opcodes[OI++ ^ 3];240uint8_t Opcode1 = Opcodes[OI++ ^ 3];241SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);242uint8_t Start = ((Opcode1 & 0xf0) >> 4);243uint8_t Count = ((Opcode1 & 0x0f) >> 0);244PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");245OS << '\n';246}247inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes,248unsigned &OI) {249uint8_t Opcode = Opcodes[OI++ ^ 3];250SW.startLine() << format("0x%02X ; spare\n", Opcode);251}252inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes,253unsigned &OI) {254uint8_t Opcode = Opcodes[OI++ ^ 3];255SW.startLine() << format("0x%02X ; pop ", Opcode);256PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");257OS << '\n';258}259inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes,260unsigned &OI) {261uint8_t Opcode = Opcodes[OI++ ^ 3];262SW.startLine() << format("0x%02X ; pop ", Opcode);263PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");264OS << '\n';265}266inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes,267unsigned &OI) {268uint8_t Opcode = Opcodes[OI++ ^ 3];269SW.startLine() << format("0x%02X ; spare\n", Opcode);270}271272inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {273static const char *GPRRegisterNames[16] = {274"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",275"fp", "ip", "sp", "lr", "pc"276};277278OS << '{';279bool Comma = false;280for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {281if (GPRMask & (1 << RI)) {282if (Comma)283OS << ", ";284OS << GPRRegisterNames[RI];285Comma = true;286}287}288OS << '}';289}290291inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {292OS << '{';293bool Comma = false;294for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {295if (VFPMask & (1 << RI)) {296if (Comma)297OS << ", ";298OS << Prefix << RI;299Comma = true;300}301}302OS << '}';303}304305inline void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset,306size_t Length) {307for (unsigned OCI = Offset; OCI < Length + Offset; ) {308bool Decoded = false;309for (const auto &RE : ring()) {310if ((Opcodes[OCI ^ 3] & RE.Mask) == RE.Value) {311(this->*RE.Routine)(Opcodes, OCI);312Decoded = true;313break;314}315}316if (!Decoded)317SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]);318}319}320321template <typename ET>322class PrinterContext {323typedef typename ET::Sym Elf_Sym;324typedef typename ET::Shdr Elf_Shdr;325typedef typename ET::Rel Elf_Rel;326typedef typename ET::Word Elf_Word;327328ScopedPrinter &SW;329const object::ELFFile<ET> &ELF;330StringRef FileName;331const Elf_Shdr *Symtab;332ArrayRef<Elf_Word> ShndxTable;333334static const size_t IndexTableEntrySize;335336static uint64_t PREL31(uint32_t Address, uint32_t Place) {337uint64_t Location = Address & 0x7fffffff;338if (Location & 0x40000000)339Location |= (uint64_t) ~0x7fffffff;340return Location + Place;341}342343ErrorOr<StringRef>344FunctionAtAddress(uint64_t Address,345std::optional<unsigned> SectionIndex) const;346const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,347off_t IndexTableOffset) const;348349void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const;350void PrintExceptionTable(const Elf_Shdr &EHT,351uint64_t TableEntryOffset) const;352void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;353354public:355PrinterContext(ScopedPrinter &SW, const object::ELFFile<ET> &ELF,356StringRef FileName, const Elf_Shdr *Symtab)357: SW(SW), ELF(ELF), FileName(FileName), Symtab(Symtab) {}358359void PrintUnwindInformation() const;360};361362template <typename ET>363const size_t PrinterContext<ET>::IndexTableEntrySize = 8;364365template <typename ET>366ErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(367uint64_t Address, std::optional<unsigned> SectionIndex) const {368if (!Symtab)369return inconvertibleErrorCode();370auto StrTableOrErr = ELF.getStringTableForSymtab(*Symtab);371if (!StrTableOrErr)372reportError(StrTableOrErr.takeError(), FileName);373StringRef StrTable = *StrTableOrErr;374375for (const Elf_Sym &Sym : unwrapOrError(FileName, ELF.symbols(Symtab))) {376if (SectionIndex && *SectionIndex != Sym.st_shndx)377continue;378379if (Sym.st_value == Address && Sym.getType() == ELF::STT_FUNC) {380auto NameOrErr = Sym.getName(StrTable);381if (!NameOrErr) {382// TODO: Actually report errors helpfully.383consumeError(NameOrErr.takeError());384return inconvertibleErrorCode();385}386return *NameOrErr;387}388}389390return inconvertibleErrorCode();391}392393template <typename ET>394const typename ET::Shdr *395PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,396off_t IndexTableOffset) const {397/// Iterate through the sections, searching for the relocation section398/// associated with the unwind index table section specified by399/// IndexSectionIndex. Iterate the associated section searching for the400/// relocation associated with the index table entry specified by401/// IndexTableOffset. The symbol is the section symbol for the exception402/// handling table. Use this symbol to recover the actual exception handling403/// table.404405for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF.sections())) {406if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)407continue;408409auto SymTabOrErr = ELF.getSection(Sec.sh_link);410if (!SymTabOrErr)411reportError(SymTabOrErr.takeError(), FileName);412const Elf_Shdr *SymTab = *SymTabOrErr;413414for (const Elf_Rel &R : unwrapOrError(FileName, ELF.rels(Sec))) {415if (R.r_offset != static_cast<unsigned>(IndexTableOffset))416continue;417418typename ET::Rela RelA;419RelA.r_offset = R.r_offset;420RelA.r_info = R.r_info;421RelA.r_addend = 0;422423const Elf_Sym *Symbol =424unwrapOrError(FileName, ELF.getRelocationSymbol(RelA, SymTab));425426auto Ret = ELF.getSection(*Symbol, SymTab, ShndxTable);427if (!Ret)428report_fatal_error(Twine(errorToErrorCode(Ret.takeError()).message()));429return *Ret;430}431}432return nullptr;433}434435template <typename ET>436static const typename ET::Shdr *437findSectionContainingAddress(const object::ELFFile<ET> &Obj, StringRef FileName,438uint64_t Address) {439for (const typename ET::Shdr &Sec : unwrapOrError(FileName, Obj.sections()))440if (Address >= Sec.sh_addr && Address < Sec.sh_addr + Sec.sh_size)441return &Sec;442return nullptr;443}444445template <typename ET>446void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr &EHT,447uint64_t TableEntryOffset) const {448// TODO: handle failure.449Expected<ArrayRef<uint8_t>> Contents = ELF.getSectionContents(EHT);450if (!Contents)451return;452453/// ARM EHABI Section 6.2 - The generic model454///455/// An exception-handling table entry for the generic model is laid out as:456///457/// 3 3458/// 1 0 0459/// +-+------------------------------+460/// |0| personality routine offset |461/// +-+------------------------------+462/// | personality routine data ... |463///464///465/// ARM EHABI Section 6.3 - The ARM-defined compact model466///467/// An exception-handling table entry for the compact model looks like:468///469/// 3 3 2 2 2 2470/// 1 0 8 7 4 3 0471/// +-+---+----+-----------------------+472/// |1| 0 | Ix | data for pers routine |473/// +-+---+----+-----------------------+474/// | more personality routine data |475476const support::ulittle32_t Word =477*reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset);478479if (Word & 0x80000000) {480SW.printString("Model", StringRef("Compact"));481482unsigned PersonalityIndex = (Word & 0x0f000000) >> 24;483SW.printNumber("PersonalityIndex", PersonalityIndex);484485switch (PersonalityIndex) {486case AEABI_UNWIND_CPP_PR0:487PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1);488break;489case AEABI_UNWIND_CPP_PR1:490case AEABI_UNWIND_CPP_PR2:491unsigned AdditionalWords = (Word & 0x00ff0000) >> 16;492PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords,4932);494break;495}496} else {497SW.printString("Model", StringRef("Generic"));498const bool IsRelocatable = ELF.getHeader().e_type == ELF::ET_REL;499uint64_t Address = IsRelocatable500? PREL31(Word, EHT.sh_addr)501: PREL31(Word, EHT.sh_addr + TableEntryOffset);502SW.printHex("PersonalityRoutineAddress", Address);503std::optional<unsigned> SecIndex =504IsRelocatable ? std::optional<unsigned>(EHT.sh_link) : std::nullopt;505if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))506SW.printString("PersonalityRoutineName", *Name);507}508}509510template <typename ET>511void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,512size_t Length, off_t Offset) const {513ListScope OCC(SW, "Opcodes");514OpcodeDecoder(SW).Decode(Entry, Offset, Length);515}516517template <typename ET>518void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,519const Elf_Shdr *IT) const {520// TODO: handle failure.521Expected<ArrayRef<uint8_t>> Contents = ELF.getSectionContents(*IT);522if (!Contents)523return;524525/// ARM EHABI Section 5 - Index Table Entries526/// * The first word contains a PREL31 offset to the start of a function with527/// bit 31 clear528/// * The second word contains one of:529/// - The PREL31 offset of the start of the table entry for the function,530/// with bit 31 clear531/// - The exception-handling table entry itself with bit 31 set532/// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated533/// frames cannot be unwound534535const support::ulittle32_t *Data =536reinterpret_cast<const support::ulittle32_t *>(Contents->data());537const unsigned Entries = IT->sh_size / IndexTableEntrySize;538const bool IsRelocatable = ELF.getHeader().e_type == ELF::ET_REL;539540ListScope E(SW, "Entries");541for (unsigned Entry = 0; Entry < Entries; ++Entry) {542DictScope E(SW, "Entry");543544const support::ulittle32_t Word0 =545Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0];546const support::ulittle32_t Word1 =547Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1];548549if (Word0 & 0x80000000) {550errs() << "corrupt unwind data in section " << SectionIndex << "\n";551continue;552}553554// FIXME: For a relocatable object ideally we might want to:555// 1) Find a relocation for the offset of Word0.556// 2) Verify this relocation is of an expected type (R_ARM_PREL31) and557// verify the symbol index.558// 3) Resolve the relocation using it's symbol value, addend etc.559// Currently the code assumes that Word0 contains an addend of a560// R_ARM_PREL31 REL relocation that references a section symbol. RELA561// relocations are not supported and it works because addresses of sections562// are nulls in relocatable objects.563//564// For a non-relocatable object, Word0 contains a place-relative signed565// offset to the referenced entity.566const uint64_t Address =567IsRelocatable568? PREL31(Word0, IT->sh_addr)569: PREL31(Word0, IT->sh_addr + Entry * IndexTableEntrySize);570SW.printHex("FunctionAddress", Address);571572// In a relocatable output we might have many .ARM.exidx sections linked to573// their code sections via the sh_link field. For a non-relocatable ELF file574// the sh_link field is not reliable, because we have one .ARM.exidx section575// normally, but might have many code sections.576std::optional<unsigned> SecIndex =577IsRelocatable ? std::optional<unsigned>(IT->sh_link) : std::nullopt;578if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))579SW.printString("FunctionName", *Name);580581if (Word1 == EXIDX_CANTUNWIND) {582SW.printString("Model", StringRef("CantUnwind"));583continue;584}585586if (Word1 & 0x80000000) {587SW.printString("Model", StringRef("Compact (Inline)"));588589unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24;590SW.printNumber("PersonalityIndex", PersonalityIndex);591592PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1);593} else {594const Elf_Shdr *EHT;595uint64_t TableEntryAddress;596if (IsRelocatable) {597TableEntryAddress = PREL31(Word1, IT->sh_addr);598EHT = FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4);599} else {600TableEntryAddress =601PREL31(Word1, IT->sh_addr + Entry * IndexTableEntrySize + 4);602EHT = findSectionContainingAddress(ELF, FileName, TableEntryAddress);603}604605if (EHT)606// TODO: handle failure.607if (Expected<StringRef> Name = ELF.getSectionName(*EHT))608SW.printString("ExceptionHandlingTable", *Name);609610SW.printHex(IsRelocatable ? "TableEntryOffset" : "TableEntryAddress",611TableEntryAddress);612if (EHT) {613if (IsRelocatable)614PrintExceptionTable(*EHT, TableEntryAddress);615else616PrintExceptionTable(*EHT, TableEntryAddress - EHT->sh_addr);617}618}619}620}621622template <typename ET>623void PrinterContext<ET>::PrintUnwindInformation() const {624DictScope UI(SW, "UnwindInformation");625626int SectionIndex = 0;627for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF.sections())) {628if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {629DictScope UIT(SW, "UnwindIndexTable");630631SW.printNumber("SectionIndex", SectionIndex);632// TODO: handle failure.633if (Expected<StringRef> SectionName = ELF.getSectionName(Sec))634SW.printString("SectionName", *SectionName);635SW.printHex("SectionOffset", Sec.sh_offset);636637PrintIndexTable(SectionIndex, &Sec);638}639++SectionIndex;640}641}642}643}644}645646#endif647648649