brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.9 KiB · 85c4165 Raw
245 lines · c
1//===--- DwarfCFIEHPrinter.h - DWARF-based 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_DWARFCFIEHPRINTER_H10#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H11 12#include "llvm-readobj.h"13#include "llvm/ADT/STLExtras.h"14#include "llvm/BinaryFormat/Dwarf.h"15#include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"16#include "llvm/DebugInfo/DWARF/DWARFContext.h"17#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"18#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"19#include "llvm/Object/ELF.h"20#include "llvm/Object/ELFObjectFile.h"21#include "llvm/Object/ELFTypes.h"22#include "llvm/Support/Casting.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/Endian.h"25#include "llvm/Support/Format.h"26#include "llvm/Support/ScopedPrinter.h"27#include "llvm/Support/type_traits.h"28 29namespace llvm {30namespace DwarfCFIEH {31 32template <typename ELFT> class PrinterContext {33  using Elf_Shdr = typename ELFT::Shdr;34  using Elf_Phdr = typename ELFT::Phdr;35 36  ScopedPrinter &W;37  const object::ELFObjectFile<ELFT> &ObjF;38 39  void printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const;40  void printEHFrame(const Elf_Shdr *EHFrameShdr) const;41 42public:43  PrinterContext(ScopedPrinter &W, const object::ELFObjectFile<ELFT> &ObjF)44      : W(W), ObjF(ObjF) {}45 46  void printUnwindInformation() const;47};48 49template <class ELFT>50static const typename ELFT::Shdr *51findSectionByAddress(const object::ELFObjectFile<ELFT> &ObjF, uint64_t Addr) {52  Expected<typename ELFT::ShdrRange> SectionsOrErr =53      ObjF.getELFFile().sections();54  if (!SectionsOrErr)55    reportError(SectionsOrErr.takeError(), ObjF.getFileName());56 57  for (const typename ELFT::Shdr &Shdr : *SectionsOrErr)58    if (Shdr.sh_addr == Addr)59      return &Shdr;60  return nullptr;61}62 63template <typename ELFT>64void PrinterContext<ELFT>::printUnwindInformation() const {65  const object::ELFFile<ELFT> &Obj = ObjF.getELFFile();66 67  Expected<typename ELFT::PhdrRange> PhdrsOrErr = Obj.program_headers();68  if (!PhdrsOrErr)69    reportError(PhdrsOrErr.takeError(), ObjF.getFileName());70 71  for (const Elf_Phdr &Phdr : *PhdrsOrErr) {72    if (Phdr.p_type != ELF::PT_GNU_EH_FRAME)73      continue;74 75    if (Phdr.p_memsz != Phdr.p_filesz)76      reportError(object::createError(77                      "p_memsz does not match p_filesz for GNU_EH_FRAME"),78                  ObjF.getFileName());79    printEHFrameHdr(&Phdr);80    break;81  }82 83  Expected<typename ELFT::ShdrRange> SectionsOrErr = Obj.sections();84  if (!SectionsOrErr)85    reportError(SectionsOrErr.takeError(), ObjF.getFileName());86 87  for (const Elf_Shdr &Shdr : *SectionsOrErr) {88    Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr);89    if (!NameOrErr)90      reportError(NameOrErr.takeError(), ObjF.getFileName());91    if (*NameOrErr == ".eh_frame")92      printEHFrame(&Shdr);93  }94}95 96template <typename ELFT>97void PrinterContext<ELFT>::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const {98  DictScope L(W, "EHFrameHeader");99  uint64_t EHFrameHdrAddress = EHFramePHdr->p_vaddr;100  W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);101  W.startLine() << format("Offset: 0x%" PRIx64 "\n", (uint64_t)EHFramePHdr->p_offset);102  W.startLine() << format("Size: 0x%" PRIx64 "\n", (uint64_t)EHFramePHdr->p_memsz);103 104  const object::ELFFile<ELFT> &Obj = ObjF.getELFFile();105  if (const Elf_Shdr *EHFrameHdr =106          findSectionByAddress(ObjF, EHFramePHdr->p_vaddr)) {107    Expected<StringRef> NameOrErr = Obj.getSectionName(*EHFrameHdr);108    if (!NameOrErr)109      reportError(NameOrErr.takeError(), ObjF.getFileName());110    W.printString("Corresponding Section", *NameOrErr);111  }112 113  Expected<ArrayRef<uint8_t>> Content = Obj.getSegmentContents(*EHFramePHdr);114  if (!Content)115    reportError(Content.takeError(), ObjF.getFileName());116 117  DataExtractor DE(*Content, ELFT::Endianness == llvm::endianness::little,118                   ELFT::Is64Bits ? 8 : 4);119 120  DictScope D(W, "Header");121  uint64_t Offset = 0;122 123  auto Version = DE.getU8(&Offset);124  W.printNumber("version", Version);125  if (Version != 1)126    reportError(127        object::createError("only version 1 of .eh_frame_hdr is supported"),128        ObjF.getFileName());129 130  uint64_t EHFramePtrEnc = DE.getU8(&Offset);131  W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);132  if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))133    reportError(object::createError("unexpected encoding eh_frame_ptr_enc"),134                ObjF.getFileName());135 136  uint64_t FDECountEnc = DE.getU8(&Offset);137  W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);138  if (FDECountEnc != dwarf::DW_EH_PE_udata4)139    reportError(object::createError("unexpected encoding fde_count_enc"),140                ObjF.getFileName());141 142  uint64_t TableEnc = DE.getU8(&Offset);143  W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);144  if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))145    reportError(object::createError("unexpected encoding table_enc"),146                ObjF.getFileName());147 148  auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;149  W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);150 151  auto FDECount = DE.getUnsigned(&Offset, 4);152  W.printNumber("fde_count", FDECount);153 154  unsigned NumEntries = 0;155  uint64_t PrevPC = 0;156  while (Offset + 8 <= EHFramePHdr->p_memsz && NumEntries < FDECount) {157    DictScope D(W, std::string("entry ") + std::to_string(NumEntries));158 159    auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;160    W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);161    auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;162    W.startLine() << format("address: 0x%" PRIx64 "\n", Address);163 164    if (InitialPC < PrevPC)165      reportError(object::createError("initial_location is out of order"),166                  ObjF.getFileName());167 168    PrevPC = InitialPC;169    ++NumEntries;170  }171}172 173template <typename ELFT>174void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {175  uint64_t Address = EHFrameShdr->sh_addr;176  uint64_t ShOffset = EHFrameShdr->sh_offset;177  W.startLine() << format(".eh_frame section at offset 0x%" PRIx64178                          " address 0x%" PRIx64 ":\n",179                          ShOffset, Address);180  W.indent();181 182  Expected<ArrayRef<uint8_t>> DataOrErr =183      ObjF.getELFFile().getSectionContents(*EHFrameShdr);184  if (!DataOrErr)185    reportError(DataOrErr.takeError(), ObjF.getFileName());186 187  // Construct DWARFDataExtractor to handle relocations ("PC Begin" fields).188  std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(189      ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr);190  DWARFDataExtractor DE(191      DICtx->getDWARFObj(), DICtx->getDWARFObj().getEHFrameSection(),192      ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4);193  DWARFDebugFrame EHFrame(Triple::ArchType(ObjF.getArch()), /*IsEH=*/true,194                          /*EHFrameAddress=*/Address);195  if (Error E = EHFrame.parse(DE))196    reportError(std::move(E), ObjF.getFileName());197 198  for (const dwarf::FrameEntry &Entry : EHFrame) {199    std::optional<uint64_t> InitialLocation;200    if (const dwarf::CIE *CIE = dyn_cast<dwarf::CIE>(&Entry)) {201      W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",202                              Address + CIE->getOffset(), CIE->getLength());203      W.indent();204 205      W.printNumber("version", CIE->getVersion());206      W.printString("augmentation", CIE->getAugmentationString());207      W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());208      W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());209      W.printNumber("return_address_register", CIE->getReturnAddressRegister());210    } else {211      const dwarf::FDE *FDE = cast<dwarf::FDE>(&Entry);212      W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64213                              " cie=[0x%" PRIx64 "]\n",214                              Address + FDE->getOffset(), FDE->getLength(),215                              Address + FDE->getLinkedCIE()->getOffset());216      W.indent();217 218      InitialLocation = FDE->getInitialLocation();219      W.startLine() << format("initial_location: 0x%" PRIx64 "\n",220                              *InitialLocation);221      W.startLine() << format(222          "address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",223          FDE->getAddressRange(),224          FDE->getInitialLocation() + FDE->getAddressRange());225    }226 227    W.getOStream() << "\n";228    W.startLine() << "Program:\n";229    W.indent();230    auto DumpOpts = DIDumpOptions();231    DumpOpts.IsEH = true;232    printCFIProgram(Entry.cfis(), W.getOStream(), DumpOpts, W.getIndentLevel(),233                    InitialLocation);234    W.unindent();235    W.unindent();236    W.getOStream() << "\n";237  }238 239  W.unindent();240}241} // namespace DwarfCFIEH242} // namespace llvm243 244#endif245