diff options
Diffstat (limited to 'tools/llvm-readobj/ELFDumper.cpp')
| -rw-r--r-- | tools/llvm-readobj/ELFDumper.cpp | 706 | 
1 files changed, 445 insertions, 261 deletions
| diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 9678667abffe..f2b936904393 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -77,6 +77,7 @@ using namespace ELF;  #define TYPEDEF_ELF_TYPES(ELFT)                                                \    using ELFO = ELFFile<ELFT>;                                                  \ +  using Elf_Addr = typename ELFO::Elf_Addr;                                    \    using Elf_Shdr = typename ELFO::Elf_Shdr;                                    \    using Elf_Sym = typename ELFO::Elf_Sym;                                      \    using Elf_Dyn = typename ELFO::Elf_Dyn;                                      \ @@ -249,6 +250,9 @@ public:    Elf_Rela_Range dyn_relas() const;    std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,                                  bool IsDynamic) const; +  void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, +                           StringRef &SectionName, +                           unsigned &SectionIndex) const;    void printSymbolsHelper(bool IsDynamic) const;    const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } @@ -287,6 +291,8 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {      ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);  } +template <class ELFT> class MipsGOTParser; +  template <typename ELFT> class DumpStyle {  public:    using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr; @@ -310,6 +316,8 @@ public:    virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0;    virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;    virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; +  virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; +  virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;    const ELFDumper<ELFT> *dumper() const { return Dumper; }  private: @@ -337,6 +345,8 @@ public:    void printProgramHeaders(const ELFO *Obj) override;    void printHashHistogram(const ELFFile<ELFT> *Obj) override;    void printNotes(const ELFFile<ELFT> *Obj) override; +  void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; +  void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;  private:    struct Field { @@ -395,6 +405,8 @@ public:    void printProgramHeaders(const ELFO *Obj) override;    void printHashHistogram(const ELFFile<ELFT> *Obj) override;    void printNotes(const ELFFile<ELFT> *Obj) override; +  void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; +  void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;  private:    void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); @@ -735,11 +747,10 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,  }  template <typename ELFT> -static void -getSectionNameIndex(const ELFFile<ELFT> &Obj, const typename ELFT::Sym *Symbol, -                    const typename ELFT::Sym *FirstSym, -                    ArrayRef<typename ELFT::Word> ShndxTable, -                    StringRef &SectionName, unsigned &SectionIndex) { +void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol, +                                          const Elf_Sym *FirstSym, +                                          StringRef &SectionName, +                                          unsigned &SectionIndex) const {    SectionIndex = Symbol->st_shndx;    if (Symbol->isUndefined())      SectionName = "Undefined"; @@ -758,8 +769,8 @@ getSectionNameIndex(const ELFFile<ELFT> &Obj, const typename ELFT::Sym *Symbol,        SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(            Symbol, FirstSym, ShndxTable));      const typename ELFT::Shdr *Sec = -        unwrapOrError(Obj.getSection(SectionIndex)); -    SectionName = unwrapOrError(Obj.getSectionName(Sec)); +        unwrapOrError(Obj->getSection(SectionIndex)); +    SectionName = unwrapOrError(Obj->getSectionName(Sec));    }  } @@ -1905,47 +1916,83 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() {  template <class ELFT> class MipsGOTParser {  public:    TYPEDEF_ELF_TYPES(ELFT) -  using GOTEntry = typename ELFO::Elf_Addr; +  using Entry = typename ELFO::Elf_Addr; +  using Entries = ArrayRef<Entry>; -  MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, -                Elf_Dyn_Range DynTable, ScopedPrinter &W); +  const bool IsStatic; +  const ELFO * const Obj; -  void parseStaticGOT(); -  void parseGOT(); -  void parsePLT(); +  MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); -private: -  ELFDumper<ELFT> *Dumper; -  const ELFO *Obj; -  ScopedPrinter &W; -  Optional<uint64_t> DtPltGot; -  Optional<uint64_t> DtLocalGotNum; -  Optional<uint64_t> DtGotSym; -  Optional<uint64_t> DtMipsPltGot; -  Optional<uint64_t> DtJmpRel; +  bool hasGot() const { return !GotEntries.empty(); } +  bool hasPlt() const { return !PltEntries.empty(); } + +  uint64_t getGp() const; + +  const Entry *getGotLazyResolver() const; +  const Entry *getGotModulePointer() const; +  const Entry *getPltLazyResolver() const; +  const Entry *getPltModulePointer() const; + +  Entries getLocalEntries() const; +  Entries getGlobalEntries() const; +  Entries getOtherEntries() const; +  Entries getPltEntries() const; + +  uint64_t getGotAddress(const Entry * E) const; +  int64_t getGotOffset(const Entry * E) const; +  const Elf_Sym *getGotSym(const Entry *E) const; + +  uint64_t getPltAddress(const Entry * E) const; +  const Elf_Sym *getPltSym(const Entry *E) const; -  std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const; -  const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum); - -  void printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num); -  void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, -                     const GOTEntry *It); -  void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, -                           const GOTEntry *It, const Elf_Sym *Sym, -                           StringRef StrTable); -  void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, -                     const GOTEntry *It, StringRef Purpose); -  void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, -                     const GOTEntry *It, StringRef StrTable, -                     const Elf_Sym *Sym); +  StringRef getPltStrTable() const { return PltStrTable; } + +private: +  const Elf_Shdr *GotSec; +  size_t LocalNum; +  size_t GlobalNum; + +  const Elf_Shdr *PltSec; +  const Elf_Shdr *PltRelSec; +  const Elf_Shdr *PltSymTable; +  Elf_Sym_Range GotDynSyms; +  StringRef PltStrTable; + +  Entries GotEntries; +  Entries PltEntries;  };  } // end anonymous namespace  template <class ELFT> -MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, -                                   Elf_Dyn_Range DynTable, ScopedPrinter &W) -    : Dumper(Dumper), Obj(Obj), W(W) { +MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, +                                   Elf_Sym_Range DynSyms) +    : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0), +      GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) { +  // See "Global Offset Table" in Chapter 5 in the following document +  // for detailed GOT description. +  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + +  // Find static GOT secton. +  if (IsStatic) { +    GotSec = findSectionByName(*Obj, ".got"); +    if (!GotSec) +      reportError("Cannot find .got section"); + +    ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); +    GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), +                         Content.size() / sizeof(Entry)); +    LocalNum = GotEntries.size(); +    return; +  } + +  // Lookup dynamic table tags which define GOT/PLT layouts. +  Optional<uint64_t> DtPltGot; +  Optional<uint64_t> DtLocalGotNum; +  Optional<uint64_t> DtGotSym; +  Optional<uint64_t> DtMipsPltGot; +  Optional<uint64_t> DtJmpRel;    for (const auto &Entry : DynTable) {      switch (Entry.getTag()) {      case ELF::DT_PLTGOT: @@ -1965,261 +2012,175 @@ MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,        break;      }    } -} - -template <class ELFT> -void MipsGOTParser<ELFT>::printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num) { -  ArrayRef<uint8_t> GOT = unwrapOrError(Obj->getSectionContents(GOTShdr)); - -  const GOTEntry *GotBegin = makeGOTIter(GOT, 0); -  const GOTEntry *GotEnd = makeGOTIter(GOT, Num); -  const GOTEntry *It = GotBegin; - -  W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); -  { -    ListScope RS(W, "Reserved entries"); - -    { -      DictScope D(W, "Entry"); -      printGotEntry(GOTShdr->sh_addr, GotBegin, It++); -      W.printString("Purpose", StringRef("Lazy resolver")); -    } -    if (It != GotEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) { -      DictScope D(W, "Entry"); -      printGotEntry(GOTShdr->sh_addr, GotBegin, It++); -      W.printString("Purpose", StringRef("Module pointer (GNU extension)")); -    } +  // Find dynamic GOT section. +  if (DtPltGot || DtLocalGotNum || DtGotSym) { +    if (!DtPltGot) +      report_fatal_error("Cannot find PLTGOT dynamic table tag."); +    if (!DtLocalGotNum) +      report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag."); +    if (!DtGotSym) +      report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag."); + +    size_t DynSymTotal = DynSyms.size(); +    if (*DtGotSym > DynSymTotal) +      reportError("MIPS_GOTSYM exceeds a number of dynamic symbols"); + +    GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot); +    if (!GotSec) +      reportError("There is no not empty GOT section at 0x" + +                  Twine::utohexstr(*DtPltGot)); + +    LocalNum = *DtLocalGotNum; +    GlobalNum = DynSymTotal - *DtGotSym; + +    ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); +    GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), +                         Content.size() / sizeof(Entry)); +    GotDynSyms = DynSyms.drop_front(*DtGotSym);    } -  { -    ListScope LS(W, "Local entries"); -    for (; It != GotEnd; ++It) { -      DictScope D(W, "Entry"); -      printGotEntry(GOTShdr->sh_addr, GotBegin, It); -    } -  } -} -template <class ELFT> void MipsGOTParser<ELFT>::parseStaticGOT() { -  const Elf_Shdr *GOTShdr = findSectionByName(*Obj, ".got"); -  if (!GOTShdr) { -    W.startLine() << "Cannot find .got section.\n"; -    return; +  // Find PLT section. +  if (DtMipsPltGot || DtJmpRel) { +    if (!DtMipsPltGot) +      report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag."); +    if (!DtJmpRel) +      report_fatal_error("Cannot find JMPREL dynamic table tag."); + +    PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); +    if (!PltSec) +      report_fatal_error("There is no not empty PLTGOT section at 0x " + +                         Twine::utohexstr(*DtMipsPltGot)); + +    PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel); +    if (!PltRelSec) +      report_fatal_error("There is no not empty RELPLT section at 0x" + +                         Twine::utohexstr(*DtJmpRel)); + +    ArrayRef<uint8_t> PltContent = +        unwrapOrError(Obj->getSectionContents(PltSec)); +    PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()), +                         PltContent.size() / sizeof(Entry)); + +    PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link)); +    PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable));    } - -  DictScope GS(W, "Static GOT"); -  printLocalGOT(GOTShdr, GOTShdr->sh_size / sizeof(GOTEntry));  } -template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { -  // See "Global Offset Table" in Chapter 5 in the following document -  // for detailed GOT description. -  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf -  if (!DtPltGot) { -    W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; -    return; -  } -  if (!DtLocalGotNum) { -    W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; -    return; -  } -  if (!DtGotSym) { -    W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; -    return; -  } - -  std::size_t DynSymTotal = Dumper->dynamic_symbols().size(); - -  if (*DtGotSym > DynSymTotal) -    report_fatal_error("MIPS_GOTSYM exceeds a number of dynamic symbols"); - -  std::size_t GlobalGotNum = DynSymTotal - *DtGotSym; - -  if (*DtLocalGotNum + GlobalGotNum == 0) { -    W.startLine() << "GOT is empty.\n"; -    return; -  } - -  const Elf_Shdr *GOTShdr = findNotEmptySectionByAddress(Obj, *DtPltGot); -  if (!GOTShdr) -    report_fatal_error("There is no not empty GOT section at 0x" + -                       Twine::utohexstr(*DtPltGot)); - -  ArrayRef<uint8_t> GOT = unwrapOrError(Obj->getSectionContents(GOTShdr)); - -  if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT)) -    report_fatal_error("Number of GOT entries exceeds the size of GOT section"); - -  DictScope GS(W, "Primary GOT"); -  printLocalGOT(GOTShdr, *DtLocalGotNum); - -  { -    ListScope GS(W, "Global entries"); - -    const GOTEntry *GotBegin = makeGOTIter(GOT, 0); -    const GOTEntry *GotEnd = makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum); -    const Elf_Sym *GotDynSym = Dumper->dynamic_symbols().begin() + *DtGotSym; -    for (auto It = makeGOTIter(GOT, *DtLocalGotNum); It != GotEnd; ++It) { -      DictScope D(W, "Entry"); -      printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, -                          Dumper->getDynamicStringTable()); -    } -  } - -  std::size_t SpecGotNum = getGOTTotal(GOT) - *DtLocalGotNum - GlobalGotNum; -  W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum)); +template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { +  return GotSec->sh_addr + 0x7ff0;  } -template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() { -  if (!DtMipsPltGot) { -    W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n"; -    return; -  } -  if (!DtJmpRel) { -    W.startLine() << "Cannot find JMPREL dynamic table tag.\n"; -    return; -  } - -  const Elf_Shdr *PLTShdr = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); -  if (!PLTShdr) -    report_fatal_error("There is no not empty PLTGOT section at 0x " + -                       Twine::utohexstr(*DtMipsPltGot)); -  ArrayRef<uint8_t> PLT = unwrapOrError(Obj->getSectionContents(PLTShdr)); - -  const Elf_Shdr *PLTRelShdr = findNotEmptySectionByAddress(Obj, *DtJmpRel); -  if (!PLTRelShdr) -    report_fatal_error("There is no not empty RELPLT section at 0x" + -                       Twine::utohexstr(*DtJmpRel)); -  const Elf_Shdr *SymTable = -      unwrapOrError(Obj->getSection(PLTRelShdr->sh_link)); -  StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTable)); - -  const GOTEntry *PLTBegin = makeGOTIter(PLT, 0); -  const GOTEntry *PLTEnd = makeGOTIter(PLT, getGOTTotal(PLT)); -  const GOTEntry *It = PLTBegin; - -  DictScope GS(W, "PLT GOT"); -  { -    ListScope RS(W, "Reserved entries"); -    printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver"); -    if (It != PLTEnd) -      printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer"); -  } -  { -    ListScope GS(W, "Entries"); - -    switch (PLTRelShdr->sh_type) { -    case ELF::SHT_REL: -      for (const Elf_Rel &Rel : unwrapOrError(Obj->rels(PLTRelShdr))) { -        const Elf_Sym *Sym = -            unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable)); -        printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym); -        if (++It == PLTEnd) -          break; -      } -      break; -    case ELF::SHT_RELA: -      for (const Elf_Rela &Rel : unwrapOrError(Obj->relas(PLTRelShdr))) { -        const Elf_Sym *Sym = -            unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable)); -        printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym); -        if (++It == PLTEnd) -          break; -      } -      break; -    } -  } +template <class ELFT> +const typename MipsGOTParser<ELFT>::Entry * +MipsGOTParser<ELFT>::getGotLazyResolver() const { +  return LocalNum > 0 ? &GotEntries[0] : nullptr;  }  template <class ELFT> -std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const { -  return GOT.size() / sizeof(GOTEntry); +const typename MipsGOTParser<ELFT>::Entry * +MipsGOTParser<ELFT>::getGotModulePointer() const { +  if (LocalNum < 2) +    return nullptr; +  const Entry &E = GotEntries[1]; +  if ((E >> (sizeof(Entry) * 8 - 1)) == 0) +    return nullptr; +  return &E;  }  template <class ELFT> -const typename MipsGOTParser<ELFT>::GOTEntry * -MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) { -  const char *Data = reinterpret_cast<const char *>(GOT.data()); -  return reinterpret_cast<const GOTEntry *>(Data + EntryNum * sizeof(GOTEntry)); +typename MipsGOTParser<ELFT>::Entries +MipsGOTParser<ELFT>::getLocalEntries() const { +  size_t Skip = getGotModulePointer() ? 2 : 1; +  if (LocalNum - Skip <= 0) +    return Entries(); +  return GotEntries.slice(Skip, LocalNum - Skip);  }  template <class ELFT> -void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, -                                        const GOTEntry *BeginIt, -                                        const GOTEntry *It) { -  int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); -  W.printHex("Address", GotAddr + Offset); -  W.printNumber("Access", Offset - 0x7ff0); -  W.printHex("Initial", *It); +typename MipsGOTParser<ELFT>::Entries +MipsGOTParser<ELFT>::getGlobalEntries() const { +  if (GlobalNum == 0) +    return Entries(); +  return GotEntries.slice(LocalNum, GlobalNum);  }  template <class ELFT> -void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, -                                              const GOTEntry *BeginIt, -                                              const GOTEntry *It, -                                              const Elf_Sym *Sym, -                                              StringRef StrTable) { -  printGotEntry(GotAddr, BeginIt, It); +typename MipsGOTParser<ELFT>::Entries +MipsGOTParser<ELFT>::getOtherEntries() const { +  size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; +  if (OtherNum == 0) +    return Entries(); +  return GotEntries.slice(LocalNum + GlobalNum, OtherNum); +} -  W.printHex("Value", Sym->st_value); -  W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); +template <class ELFT> +uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { +  int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); +  return GotSec->sh_addr + Offset; +} -  unsigned SectionIndex = 0; -  StringRef SectionName; -  getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(), -                      Dumper->getShndxTable(), SectionName, SectionIndex); -  W.printHex("Section", SectionName, SectionIndex); +template <class ELFT> +int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { +  int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); +  return Offset - 0x7ff0; +} -  std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true); -  W.printNumber("Name", FullSymbolName, Sym->st_name); +template <class ELFT> +const typename MipsGOTParser<ELFT>::Elf_Sym * +MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { +  int64_t Offset = std::distance(GotEntries.data(), E); +  return &GotDynSyms[Offset - LocalNum];  }  template <class ELFT> -void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, -                                        const GOTEntry *BeginIt, -                                        const GOTEntry *It, StringRef Purpose) { -  DictScope D(W, "Entry"); -  int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); -  W.printHex("Address", PLTAddr + Offset); -  W.printHex("Initial", *It); -  W.printString("Purpose", Purpose); +const typename MipsGOTParser<ELFT>::Entry * +MipsGOTParser<ELFT>::getPltLazyResolver() const { +  return PltEntries.empty() ? nullptr : &PltEntries[0];  }  template <class ELFT> -void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, -                                        const GOTEntry *BeginIt, -                                        const GOTEntry *It, StringRef StrTable, -                                        const Elf_Sym *Sym) { -  DictScope D(W, "Entry"); -  int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); -  W.printHex("Address", PLTAddr + Offset); -  W.printHex("Initial", *It); -  W.printHex("Value", Sym->st_value); -  W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); +const typename MipsGOTParser<ELFT>::Entry * +MipsGOTParser<ELFT>::getPltModulePointer() const { +  return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; +} -  unsigned SectionIndex = 0; -  StringRef SectionName; -  getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(), -                      Dumper->getShndxTable(), SectionName, SectionIndex); -  W.printHex("Section", SectionName, SectionIndex); +template <class ELFT> +typename MipsGOTParser<ELFT>::Entries +MipsGOTParser<ELFT>::getPltEntries() const { +  if (PltEntries.size() <= 2) +    return Entries(); +  return PltEntries.slice(2, PltEntries.size() - 2); +} -  std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true); -  W.printNumber("Name", FullSymbolName, Sym->st_name); +template <class ELFT> +uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { +  int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); +  return PltSec->sh_addr + Offset;  } -template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { -  if (Obj->getHeader()->e_machine != EM_MIPS) { -    W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; -    return; +template <class ELFT> +const typename MipsGOTParser<ELFT>::Elf_Sym * +MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { +  int64_t Offset = std::distance(getPltEntries().data(), E); +  if (PltRelSec->sh_type == ELF::SHT_REL) { +    Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec)); +    return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); +  } else { +    Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec)); +    return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));    } +} -  MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W); -  if (dynamic_table().empty()) -    GOTParser.parseStaticGOT(); -  else { -    GOTParser.parseGOT(); -    GOTParser.parsePLT(); -  } +template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { +  if (Obj->getHeader()->e_machine != EM_MIPS) +    reportError("MIPS PLT GOT is available for MIPS targets only"); + +  MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols()); +  if (Parser.hasGot()) +    ELFDumperStyle->printMipsGOT(Parser); +  if (Parser.hasPlt()) +    ELFDumperStyle->printMipsPLT(Parser);  }  static const EnumEntry<unsigned> ElfMipsISAExtType[] = { @@ -3597,6 +3558,119 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {    }  } +template <class ELFT> +void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { +  size_t Bias = ELFT::Is64Bits ? 8 : 0; +  auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { +    OS.PadToColumn(2); +    OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); +    OS.PadToColumn(11 + Bias); +    OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; +    OS.PadToColumn(22 + Bias); +    OS << format_hex_no_prefix(*E, 8 + Bias); +    OS.PadToColumn(31 + 2 * Bias); +    OS << Purpose << "\n"; +  }; + +  OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); +  OS << " Canonical gp value: " +     << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; + +  OS << " Reserved entries:\n"; +  OS << "   Address     Access  Initial Purpose\n"; +  PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); +  if (Parser.getGotModulePointer()) +    PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); + +  if (!Parser.getLocalEntries().empty()) { +    OS << "\n"; +    OS << " Local entries:\n"; +    OS << "   Address     Access  Initial\n"; +    for (auto &E : Parser.getLocalEntries()) +      PrintEntry(&E, ""); +  } + +  if (Parser.IsStatic) +    return; + +  if (!Parser.getGlobalEntries().empty()) { +    OS << "\n"; +    OS << " Global entries:\n"; +    OS << "   Address     Access  Initial Sym.Val. Type    Ndx Name\n"; +    for (auto &E : Parser.getGlobalEntries()) { +      const Elf_Sym *Sym = Parser.getGotSym(&E); +      std::string SymName = this->dumper()->getFullSymbolName( +          Sym, this->dumper()->getDynamicStringTable(), false); + +      OS.PadToColumn(2); +      OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); +      OS.PadToColumn(11 + Bias); +      OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; +      OS.PadToColumn(22 + Bias); +      OS << to_string(format_hex_no_prefix(E, 8 + Bias)); +      OS.PadToColumn(31 + 2 * Bias); +      OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); +      OS.PadToColumn(40 + 3 * Bias); +      OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); +      OS.PadToColumn(48 + 3 * Bias); +      OS << getSymbolSectionNdx(Parser.Obj, Sym, +                                this->dumper()->dynamic_symbols().begin()); +      OS.PadToColumn(52 + 3 * Bias); +      OS << SymName << "\n"; +    } +  } + +  if (!Parser.getOtherEntries().empty()) +    OS << "\n Number of TLS and multi-GOT entries " +       << Parser.getOtherEntries().size() << "\n"; +} + +template <class ELFT> +void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { +  size_t Bias = ELFT::Is64Bits ? 8 : 0; +  auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { +    OS.PadToColumn(2); +    OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); +    OS.PadToColumn(11 + Bias); +    OS << format_hex_no_prefix(*E, 8 + Bias); +    OS.PadToColumn(20 + 2 * Bias); +    OS << Purpose << "\n"; +  }; + +  OS << "PLT GOT:\n\n"; + +  OS << " Reserved entries:\n"; +  OS << "   Address  Initial Purpose\n"; +  PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); +  if (Parser.getPltModulePointer()) +    PrintEntry(Parser.getGotModulePointer(), "Module pointer"); + +  if (!Parser.getPltEntries().empty()) { +    OS << "\n"; +    OS << " Entries:\n"; +    OS << "   Address  Initial Sym.Val. Type    Ndx Name\n"; +    for (auto &E : Parser.getPltEntries()) { +      const Elf_Sym *Sym = Parser.getPltSym(&E); +      std::string SymName = this->dumper()->getFullSymbolName( +          Sym, this->dumper()->getDynamicStringTable(), false); + +      OS.PadToColumn(2); +      OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); +      OS.PadToColumn(11 + Bias); +      OS << to_string(format_hex_no_prefix(E, 8 + Bias)); +      OS.PadToColumn(20 + 2 * Bias); +      OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); +      OS.PadToColumn(29 + 3 * Bias); +      OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); +      OS.PadToColumn(37 + 3 * Bias); +      OS << getSymbolSectionNdx(Parser.Obj, Sym, +                                this->dumper()->dynamic_symbols().begin()); +      OS.PadToColumn(41 + 3 * Bias); +      OS << SymName << "\n"; +    } +  } +} +  template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {    const Elf_Ehdr *e = Obj->getHeader();    { @@ -3854,8 +3928,7 @@ void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,                                    bool IsDynamic) {    unsigned SectionIndex = 0;    StringRef SectionName; -  getSectionNameIndex(*Obj, Symbol, First, this->dumper()->getShndxTable(), -                      SectionName, SectionIndex); +  this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex);    std::string FullSymbolName =        this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);    unsigned char SymbolType = Symbol->getType(); @@ -3992,3 +4065,114 @@ template <class ELFT>  void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {    W.startLine() << "printNotes not implemented!\n";  } + +template <class ELFT> +void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { +  auto PrintEntry = [&](const Elf_Addr *E) { +    W.printHex("Address", Parser.getGotAddress(E)); +    W.printNumber("Access", Parser.getGotOffset(E)); +    W.printHex("Initial", *E); +  }; + +  DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); + +  W.printHex("Canonical gp value", Parser.getGp()); +  { +    ListScope RS(W, "Reserved entries"); +    { +      DictScope D(W, "Entry"); +      PrintEntry(Parser.getGotLazyResolver()); +      W.printString("Purpose", StringRef("Lazy resolver")); +    } + +    if (Parser.getGotModulePointer()) { +      DictScope D(W, "Entry"); +      PrintEntry(Parser.getGotModulePointer()); +      W.printString("Purpose", StringRef("Module pointer (GNU extension)")); +    } +  } +  { +    ListScope LS(W, "Local entries"); +    for (auto &E : Parser.getLocalEntries()) { +      DictScope D(W, "Entry"); +      PrintEntry(&E); +    } +  } + +  if (Parser.IsStatic) +    return; + +  { +    ListScope GS(W, "Global entries"); +    for (auto &E : Parser.getGlobalEntries()) { +      DictScope D(W, "Entry"); + +      PrintEntry(&E); + +      const Elf_Sym *Sym = Parser.getGotSym(&E); +      W.printHex("Value", Sym->st_value); +      W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); + +      unsigned SectionIndex = 0; +      StringRef SectionName; +      this->dumper()->getSectionNameIndex( +          Sym, this->dumper()->dynamic_symbols().begin(), SectionName, +          SectionIndex); +      W.printHex("Section", SectionName, SectionIndex); + +      std::string SymName = this->dumper()->getFullSymbolName( +          Sym, this->dumper()->getDynamicStringTable(), true); +      W.printNumber("Name", SymName, Sym->st_name); +    } +  } + +  W.printNumber("Number of TLS and multi-GOT entries", +                uint64_t(Parser.getOtherEntries().size())); +} + +template <class ELFT> +void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { +  auto PrintEntry = [&](const Elf_Addr *E) { +    W.printHex("Address", Parser.getPltAddress(E)); +    W.printHex("Initial", *E); +  }; + +  DictScope GS(W, "PLT GOT"); + +  { +    ListScope RS(W, "Reserved entries"); +    { +      DictScope D(W, "Entry"); +      PrintEntry(Parser.getPltLazyResolver()); +      W.printString("Purpose", StringRef("PLT lazy resolver")); +    } + +    if (auto E = Parser.getPltModulePointer()) { +      DictScope D(W, "Entry"); +      PrintEntry(E); +      W.printString("Purpose", StringRef("Module pointer")); +    } +  } +  { +    ListScope LS(W, "Entries"); +    for (auto &E : Parser.getPltEntries()) { +      DictScope D(W, "Entry"); +      PrintEntry(&E); + +      const Elf_Sym *Sym = Parser.getPltSym(&E); +      W.printHex("Value", Sym->st_value); +      W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); + +      unsigned SectionIndex = 0; +      StringRef SectionName; +      this->dumper()->getSectionNameIndex( +          Sym, this->dumper()->dynamic_symbols().begin(), SectionName, +          SectionIndex); +      W.printHex("Section", SectionName, SectionIndex); + +      std::string SymName = +          this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true); +      W.printNumber("Name", SymName, Sym->st_name); +    } +  } +} | 
