10b57cec5SDimitry Andric //===- ELFDumper.cpp - ELF-specific dumper --------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file implements the ELF-specific dumper for llvm-readobj. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "ARMEHABIPrinter.h" 150b57cec5SDimitry Andric #include "DwarfCFIEHPrinter.h" 160b57cec5SDimitry Andric #include "Error.h" 170b57cec5SDimitry Andric #include "ObjDumper.h" 180b57cec5SDimitry Andric #include "StackMapPrinter.h" 190b57cec5SDimitry Andric #include "llvm-readobj.h" 200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 210b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 220b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 240b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 250b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 270b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 280b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 290b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 300b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 310b57cec5SDimitry Andric #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" 320b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 330b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h" 340b57cec5SDimitry Andric #include "llvm/Object/ELF.h" 350b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 360b57cec5SDimitry Andric #include "llvm/Object/ELFTypes.h" 370b57cec5SDimitry Andric #include "llvm/Object/Error.h" 380b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 390b57cec5SDimitry Andric #include "llvm/Object/StackMapParser.h" 400b57cec5SDimitry Andric #include "llvm/Support/AMDGPUMetadata.h" 410b57cec5SDimitry Andric #include "llvm/Support/ARMAttributeParser.h" 420b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 430b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 440b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 450b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 460b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 470b57cec5SDimitry Andric #include "llvm/Support/Format.h" 480b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 490b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 500b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 510b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 520b57cec5SDimitry Andric #include "llvm/Support/MipsABIFlags.h" 530b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 540b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 550b57cec5SDimitry Andric #include <algorithm> 560b57cec5SDimitry Andric #include <cinttypes> 570b57cec5SDimitry Andric #include <cstddef> 580b57cec5SDimitry Andric #include <cstdint> 590b57cec5SDimitry Andric #include <cstdlib> 600b57cec5SDimitry Andric #include <iterator> 610b57cec5SDimitry Andric #include <memory> 620b57cec5SDimitry Andric #include <string> 630b57cec5SDimitry Andric #include <system_error> 640b57cec5SDimitry Andric #include <vector> 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric using namespace llvm; 670b57cec5SDimitry Andric using namespace llvm::object; 680b57cec5SDimitry Andric using namespace ELF; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ 710b57cec5SDimitry Andric case ns::enum: \ 720b57cec5SDimitry Andric return #enum; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric #define ENUM_ENT(enum, altName) \ 750b57cec5SDimitry Andric { #enum, altName, ELF::enum } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric #define ENUM_ENT_1(enum) \ 780b57cec5SDimitry Andric { #enum, #enum, ELF::enum } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric #define LLVM_READOBJ_PHDR_ENUM(ns, enum) \ 810b57cec5SDimitry Andric case ns::enum: \ 820b57cec5SDimitry Andric return std::string(#enum).substr(3); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric #define TYPEDEF_ELF_TYPES(ELFT) \ 850b57cec5SDimitry Andric using ELFO = ELFFile<ELFT>; \ 860b57cec5SDimitry Andric using Elf_Addr = typename ELFT::Addr; \ 870b57cec5SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; \ 880b57cec5SDimitry Andric using Elf_Sym = typename ELFT::Sym; \ 890b57cec5SDimitry Andric using Elf_Dyn = typename ELFT::Dyn; \ 900b57cec5SDimitry Andric using Elf_Dyn_Range = typename ELFT::DynRange; \ 910b57cec5SDimitry Andric using Elf_Rel = typename ELFT::Rel; \ 920b57cec5SDimitry Andric using Elf_Rela = typename ELFT::Rela; \ 930b57cec5SDimitry Andric using Elf_Relr = typename ELFT::Relr; \ 940b57cec5SDimitry Andric using Elf_Rel_Range = typename ELFT::RelRange; \ 950b57cec5SDimitry Andric using Elf_Rela_Range = typename ELFT::RelaRange; \ 960b57cec5SDimitry Andric using Elf_Relr_Range = typename ELFT::RelrRange; \ 970b57cec5SDimitry Andric using Elf_Phdr = typename ELFT::Phdr; \ 980b57cec5SDimitry Andric using Elf_Half = typename ELFT::Half; \ 990b57cec5SDimitry Andric using Elf_Ehdr = typename ELFT::Ehdr; \ 1000b57cec5SDimitry Andric using Elf_Word = typename ELFT::Word; \ 1010b57cec5SDimitry Andric using Elf_Hash = typename ELFT::Hash; \ 1020b57cec5SDimitry Andric using Elf_GnuHash = typename ELFT::GnuHash; \ 1030b57cec5SDimitry Andric using Elf_Note = typename ELFT::Note; \ 1040b57cec5SDimitry Andric using Elf_Sym_Range = typename ELFT::SymRange; \ 1050b57cec5SDimitry Andric using Elf_Versym = typename ELFT::Versym; \ 1060b57cec5SDimitry Andric using Elf_Verneed = typename ELFT::Verneed; \ 1070b57cec5SDimitry Andric using Elf_Vernaux = typename ELFT::Vernaux; \ 1080b57cec5SDimitry Andric using Elf_Verdef = typename ELFT::Verdef; \ 1090b57cec5SDimitry Andric using Elf_Verdaux = typename ELFT::Verdaux; \ 1100b57cec5SDimitry Andric using Elf_CGProfile = typename ELFT::CGProfile; \ 1110b57cec5SDimitry Andric using uintX_t = typename ELFT::uint; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric namespace { 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric template <class ELFT> class DumpStyle; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric /// Represents a contiguous uniform range in the file. We cannot just create a 1180b57cec5SDimitry Andric /// range directly because when creating one of these from the .dynamic table 1190b57cec5SDimitry Andric /// the size, entity size and virtual address are different entries in arbitrary 1200b57cec5SDimitry Andric /// order (DT_REL, DT_RELSZ, DT_RELENT for example). 1210b57cec5SDimitry Andric struct DynRegionInfo { 1220b57cec5SDimitry Andric DynRegionInfo() = default; 1230b57cec5SDimitry Andric DynRegionInfo(const void *A, uint64_t S, uint64_t ES) 1240b57cec5SDimitry Andric : Addr(A), Size(S), EntSize(ES) {} 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric /// Address in current address space. 1270b57cec5SDimitry Andric const void *Addr = nullptr; 1280b57cec5SDimitry Andric /// Size in bytes of the region. 1290b57cec5SDimitry Andric uint64_t Size = 0; 1300b57cec5SDimitry Andric /// Size of each entity in the region. 1310b57cec5SDimitry Andric uint64_t EntSize = 0; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric template <typename Type> ArrayRef<Type> getAsArrayRef() const { 1340b57cec5SDimitry Andric const Type *Start = reinterpret_cast<const Type *>(Addr); 1350b57cec5SDimitry Andric if (!Start) 1360b57cec5SDimitry Andric return {Start, Start}; 1370b57cec5SDimitry Andric if (EntSize != sizeof(Type) || Size % EntSize) { 1380b57cec5SDimitry Andric // TODO: Add a section index to this warning. 1390b57cec5SDimitry Andric reportWarning("invalid section size (" + Twine(Size) + 1400b57cec5SDimitry Andric ") or entity size (" + Twine(EntSize) + ")"); 1410b57cec5SDimitry Andric return {Start, Start}; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric return {Start, Start + (Size / EntSize)}; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric }; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric template <typename ELFT> class ELFDumper : public ObjDumper { 1480b57cec5SDimitry Andric public: 1490b57cec5SDimitry Andric ELFDumper(const object::ELFObjectFile<ELFT> *ObjF, ScopedPrinter &Writer); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void printFileHeaders() override; 1520b57cec5SDimitry Andric void printSectionHeaders() override; 1530b57cec5SDimitry Andric void printRelocations() override; 1540b57cec5SDimitry Andric void printDynamicRelocations() override; 1550b57cec5SDimitry Andric void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override; 1560b57cec5SDimitry Andric void printHashSymbols() override; 1570b57cec5SDimitry Andric void printUnwindInfo() override; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric void printDynamicTable() override; 1600b57cec5SDimitry Andric void printNeededLibraries() override; 1610b57cec5SDimitry Andric void printProgramHeaders(bool PrintProgramHeaders, 1620b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 1630b57cec5SDimitry Andric void printHashTable() override; 1640b57cec5SDimitry Andric void printGnuHashTable() override; 1650b57cec5SDimitry Andric void printLoadName() override; 1660b57cec5SDimitry Andric void printVersionInfo() override; 1670b57cec5SDimitry Andric void printGroupSections() override; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void printAttributes() override; 1700b57cec5SDimitry Andric void printMipsPLTGOT() override; 1710b57cec5SDimitry Andric void printMipsABIFlags() override; 1720b57cec5SDimitry Andric void printMipsReginfo() override; 1730b57cec5SDimitry Andric void printMipsOptions() override; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void printStackMap() const override; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric void printHashHistogram() override; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric void printCGProfile() override; 1800b57cec5SDimitry Andric void printAddrsig() override; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric void printNotes() override; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric void printELFLinkerOptions() override; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric const object::ELFObjectFile<ELFT> *getElfObject() const { return ObjF; }; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric private: 1890b57cec5SDimitry Andric std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric TYPEDEF_ELF_TYPES(ELFT) 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric DynRegionInfo checkDRI(DynRegionInfo DRI) { 1940b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 1950b57cec5SDimitry Andric if (DRI.Addr < Obj->base() || 1960b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(DRI.Addr) + DRI.Size > 1970b57cec5SDimitry Andric Obj->base() + Obj->getBufSize()) 1980b57cec5SDimitry Andric error(llvm::object::object_error::parse_failed); 1990b57cec5SDimitry Andric return DRI; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) { 2030b57cec5SDimitry Andric return checkDRI( 2040b57cec5SDimitry Andric {ObjF->getELFFile()->base() + P->p_offset, P->p_filesz, EntSize}); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric DynRegionInfo createDRIFrom(const Elf_Shdr *S) { 2080b57cec5SDimitry Andric return checkDRI( 2090b57cec5SDimitry Andric {ObjF->getELFFile()->base() + S->sh_offset, S->sh_size, S->sh_entsize}); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric void loadDynamicTable(const ELFFile<ELFT> *Obj); 2130b57cec5SDimitry Andric void parseDynamicTable(); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, 2160b57cec5SDimitry Andric bool &IsDefault) const; 2170b57cec5SDimitry Andric void LoadVersionMap() const; 2180b57cec5SDimitry Andric void LoadVersionNeeds(const Elf_Shdr *ec) const; 2190b57cec5SDimitry Andric void LoadVersionDefs(const Elf_Shdr *sec) const; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric const object::ELFObjectFile<ELFT> *ObjF; 2220b57cec5SDimitry Andric DynRegionInfo DynRelRegion; 2230b57cec5SDimitry Andric DynRegionInfo DynRelaRegion; 2240b57cec5SDimitry Andric DynRegionInfo DynRelrRegion; 2250b57cec5SDimitry Andric DynRegionInfo DynPLTRelRegion; 2260b57cec5SDimitry Andric DynRegionInfo DynSymRegion; 2270b57cec5SDimitry Andric DynRegionInfo DynamicTable; 2280b57cec5SDimitry Andric StringRef DynamicStringTable; 2290b57cec5SDimitry Andric StringRef SOName = "<Not found>"; 2300b57cec5SDimitry Andric const Elf_Hash *HashTable = nullptr; 2310b57cec5SDimitry Andric const Elf_GnuHash *GnuHashTable = nullptr; 2320b57cec5SDimitry Andric const Elf_Shdr *DotSymtabSec = nullptr; 2330b57cec5SDimitry Andric const Elf_Shdr *DotCGProfileSec = nullptr; 2340b57cec5SDimitry Andric const Elf_Shdr *DotAddrsigSec = nullptr; 2350b57cec5SDimitry Andric StringRef DynSymtabName; 2360b57cec5SDimitry Andric ArrayRef<Elf_Word> ShndxTable; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version 2390b57cec5SDimitry Andric const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r 2400b57cec5SDimitry Andric const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric // Records for each version index the corresponding Verdef or Vernaux entry. 2430b57cec5SDimitry Andric // This is filled the first time LoadVersionMap() is called. 2440b57cec5SDimitry Andric class VersionMapEntry : public PointerIntPair<const void *, 1> { 2450b57cec5SDimitry Andric public: 2460b57cec5SDimitry Andric // If the integer is 0, this is an Elf_Verdef*. 2470b57cec5SDimitry Andric // If the integer is 1, this is an Elf_Vernaux*. 2480b57cec5SDimitry Andric VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {} 2490b57cec5SDimitry Andric VersionMapEntry(const Elf_Verdef *verdef) 2500b57cec5SDimitry Andric : PointerIntPair<const void *, 1>(verdef, 0) {} 2510b57cec5SDimitry Andric VersionMapEntry(const Elf_Vernaux *vernaux) 2520b57cec5SDimitry Andric : PointerIntPair<const void *, 1>(vernaux, 1) {} 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric bool isNull() const { return getPointer() == nullptr; } 2550b57cec5SDimitry Andric bool isVerdef() const { return !isNull() && getInt() == 0; } 2560b57cec5SDimitry Andric bool isVernaux() const { return !isNull() && getInt() == 1; } 2570b57cec5SDimitry Andric const Elf_Verdef *getVerdef() const { 2580b57cec5SDimitry Andric return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric const Elf_Vernaux *getVernaux() const { 2610b57cec5SDimitry Andric return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric }; 2640b57cec5SDimitry Andric mutable SmallVector<VersionMapEntry, 16> VersionMap; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric public: 2670b57cec5SDimitry Andric Elf_Dyn_Range dynamic_table() const { 2680b57cec5SDimitry Andric // A valid .dynamic section contains an array of entries terminated 2690b57cec5SDimitry Andric // with a DT_NULL entry. However, sometimes the section content may 2700b57cec5SDimitry Andric // continue past the DT_NULL entry, so to dump the section correctly, 2710b57cec5SDimitry Andric // we first find the end of the entries by iterating over them. 2720b57cec5SDimitry Andric Elf_Dyn_Range Table = DynamicTable.getAsArrayRef<Elf_Dyn>(); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric size_t Size = 0; 2750b57cec5SDimitry Andric while (Size < Table.size()) 2760b57cec5SDimitry Andric if (Table[Size++].getTag() == DT_NULL) 2770b57cec5SDimitry Andric break; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric return Table.slice(0, Size); 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric Elf_Sym_Range dynamic_symbols() const { 2830b57cec5SDimitry Andric return DynSymRegion.getAsArrayRef<Elf_Sym>(); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric Elf_Rel_Range dyn_rels() const; 2870b57cec5SDimitry Andric Elf_Rela_Range dyn_relas() const; 2880b57cec5SDimitry Andric Elf_Relr_Range dyn_relrs() const; 2890b57cec5SDimitry Andric std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, 2900b57cec5SDimitry Andric bool IsDynamic) const; 2910b57cec5SDimitry Andric void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, 2920b57cec5SDimitry Andric StringRef &SectionName, 2930b57cec5SDimitry Andric unsigned &SectionIndex) const; 2940b57cec5SDimitry Andric std::string getStaticSymbolName(uint32_t Index) const; 2950b57cec5SDimitry Andric StringRef getSymbolVersionByIndex(StringRef StrTab, 2960b57cec5SDimitry Andric uint32_t VersionSymbolIndex, 2970b57cec5SDimitry Andric bool &IsDefault) const; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric void printSymbolsHelper(bool IsDynamic) const; 3000b57cec5SDimitry Andric void printDynamicEntry(raw_ostream &OS, uint64_t Type, uint64_t Value) const; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } 3030b57cec5SDimitry Andric const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } 3040b57cec5SDimitry Andric const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } 3050b57cec5SDimitry Andric ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; } 3060b57cec5SDimitry Andric StringRef getDynamicStringTable() const { return DynamicStringTable; } 3070b57cec5SDimitry Andric const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } 3080b57cec5SDimitry Andric const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } 3090b57cec5SDimitry Andric const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } 3100b57cec5SDimitry Andric const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } 3110b57cec5SDimitry Andric const DynRegionInfo &getDynamicTableRegion() const { return DynamicTable; } 3120b57cec5SDimitry Andric const Elf_Hash *getHashTable() const { return HashTable; } 3130b57cec5SDimitry Andric const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } 3140b57cec5SDimitry Andric }; 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric template <class ELFT> 3170b57cec5SDimitry Andric void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { 3180b57cec5SDimitry Andric StringRef StrTable, SymtabName; 3190b57cec5SDimitry Andric size_t Entries = 0; 3200b57cec5SDimitry Andric Elf_Sym_Range Syms(nullptr, nullptr); 3210b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 3220b57cec5SDimitry Andric if (IsDynamic) { 3230b57cec5SDimitry Andric StrTable = DynamicStringTable; 3240b57cec5SDimitry Andric Syms = dynamic_symbols(); 3250b57cec5SDimitry Andric SymtabName = DynSymtabName; 3260b57cec5SDimitry Andric if (DynSymRegion.Addr) 3270b57cec5SDimitry Andric Entries = DynSymRegion.Size / DynSymRegion.EntSize; 3280b57cec5SDimitry Andric } else { 3290b57cec5SDimitry Andric if (!DotSymtabSec) 3300b57cec5SDimitry Andric return; 3310b57cec5SDimitry Andric StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); 3320b57cec5SDimitry Andric Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); 3330b57cec5SDimitry Andric SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec)); 3340b57cec5SDimitry Andric Entries = DotSymtabSec->getEntityCount(); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric if (Syms.begin() == Syms.end()) 3370b57cec5SDimitry Andric return; 3380b57cec5SDimitry Andric ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries); 3390b57cec5SDimitry Andric for (const auto &Sym : Syms) 3400b57cec5SDimitry Andric ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric template <typename ELFT> class DumpStyle { 3460b57cec5SDimitry Andric public: 3470b57cec5SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 3480b57cec5SDimitry Andric using Elf_Sym = typename ELFT::Sym; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {} 3510b57cec5SDimitry Andric virtual ~DumpStyle() = default; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0; 3540b57cec5SDimitry Andric virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0; 3550b57cec5SDimitry Andric virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0; 3560b57cec5SDimitry Andric virtual void printSectionHeaders(const ELFFile<ELFT> *Obj) = 0; 3570b57cec5SDimitry Andric virtual void printSymbols(const ELFFile<ELFT> *Obj, bool PrintSymbols, 3580b57cec5SDimitry Andric bool PrintDynamicSymbols) = 0; 3590b57cec5SDimitry Andric virtual void printHashSymbols(const ELFFile<ELFT> *Obj) {} 3600b57cec5SDimitry Andric virtual void printDynamic(const ELFFile<ELFT> *Obj) {} 3610b57cec5SDimitry Andric virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0; 3620b57cec5SDimitry Andric virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name, 3630b57cec5SDimitry Andric size_t Offset) {} 3640b57cec5SDimitry Andric virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol, 3650b57cec5SDimitry Andric const Elf_Sym *FirstSym, StringRef StrTable, 3660b57cec5SDimitry Andric bool IsDynamic) = 0; 3670b57cec5SDimitry Andric virtual void printProgramHeaders(const ELFFile<ELFT> *Obj, 3680b57cec5SDimitry Andric bool PrintProgramHeaders, 3690b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) = 0; 3700b57cec5SDimitry Andric virtual void printVersionSymbolSection(const ELFFile<ELFT> *Obj, 3710b57cec5SDimitry Andric const Elf_Shdr *Sec) = 0; 3720b57cec5SDimitry Andric virtual void printVersionDefinitionSection(const ELFFile<ELFT> *Obj, 3730b57cec5SDimitry Andric const Elf_Shdr *Sec) = 0; 3740b57cec5SDimitry Andric virtual void printVersionDependencySection(const ELFFile<ELFT> *Obj, 3750b57cec5SDimitry Andric const Elf_Shdr *Sec) = 0; 3760b57cec5SDimitry Andric virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; 3770b57cec5SDimitry Andric virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0; 3780b57cec5SDimitry Andric virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0; 3790b57cec5SDimitry Andric virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; 3800b57cec5SDimitry Andric virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0; 3810b57cec5SDimitry Andric virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; 3820b57cec5SDimitry Andric virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0; 3830b57cec5SDimitry Andric const ELFDumper<ELFT> *dumper() const { return Dumper; } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric private: 3860b57cec5SDimitry Andric const ELFDumper<ELFT> *Dumper; 3870b57cec5SDimitry Andric }; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> { 3900b57cec5SDimitry Andric formatted_raw_ostream &OS; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric public: 3930b57cec5SDimitry Andric TYPEDEF_ELF_TYPES(ELFT) 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) 3960b57cec5SDimitry Andric : DumpStyle<ELFT>(Dumper), 3970b57cec5SDimitry Andric OS(static_cast<formatted_raw_ostream&>(W.getOStream())) { 3980b57cec5SDimitry Andric assert (&W.getOStream() == &llvm::fouts()); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric void printFileHeaders(const ELFO *Obj) override; 4020b57cec5SDimitry Andric void printGroupSections(const ELFFile<ELFT> *Obj) override; 4030b57cec5SDimitry Andric void printRelocations(const ELFO *Obj) override; 4040b57cec5SDimitry Andric void printSectionHeaders(const ELFO *Obj) override; 4050b57cec5SDimitry Andric void printSymbols(const ELFO *Obj, bool PrintSymbols, 4060b57cec5SDimitry Andric bool PrintDynamicSymbols) override; 4070b57cec5SDimitry Andric void printHashSymbols(const ELFO *Obj) override; 4080b57cec5SDimitry Andric void printDynamic(const ELFFile<ELFT> *Obj) override; 4090b57cec5SDimitry Andric void printDynamicRelocations(const ELFO *Obj) override; 4100b57cec5SDimitry Andric void printSymtabMessage(const ELFO *Obj, StringRef Name, 4110b57cec5SDimitry Andric size_t Offset) override; 4120b57cec5SDimitry Andric void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders, 4130b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 4140b57cec5SDimitry Andric void printVersionSymbolSection(const ELFFile<ELFT> *Obj, 4150b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 4160b57cec5SDimitry Andric void printVersionDefinitionSection(const ELFFile<ELFT> *Obj, 4170b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 4180b57cec5SDimitry Andric void printVersionDependencySection(const ELFFile<ELFT> *Obj, 4190b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 4200b57cec5SDimitry Andric void printHashHistogram(const ELFFile<ELFT> *Obj) override; 4210b57cec5SDimitry Andric void printCGProfile(const ELFFile<ELFT> *Obj) override; 4220b57cec5SDimitry Andric void printAddrsig(const ELFFile<ELFT> *Obj) override; 4230b57cec5SDimitry Andric void printNotes(const ELFFile<ELFT> *Obj) override; 4240b57cec5SDimitry Andric void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; 4250b57cec5SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 4260b57cec5SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric private: 4290b57cec5SDimitry Andric struct Field { 4300b57cec5SDimitry Andric std::string Str; 4310b57cec5SDimitry Andric unsigned Column; 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} 4340b57cec5SDimitry Andric Field(unsigned Col) : Column(Col) {} 4350b57cec5SDimitry Andric }; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric template <typename T, typename TEnum> 4380b57cec5SDimitry Andric std::string printEnum(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) { 4390b57cec5SDimitry Andric for (const auto &EnumItem : EnumValues) 4400b57cec5SDimitry Andric if (EnumItem.Value == Value) 4410b57cec5SDimitry Andric return EnumItem.AltName; 4420b57cec5SDimitry Andric return to_hexString(Value, false); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric template <typename T, typename TEnum> 4460b57cec5SDimitry Andric std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues, 4470b57cec5SDimitry Andric TEnum EnumMask1 = {}, TEnum EnumMask2 = {}, 4480b57cec5SDimitry Andric TEnum EnumMask3 = {}) { 4490b57cec5SDimitry Andric std::string Str; 4500b57cec5SDimitry Andric for (const auto &Flag : EnumValues) { 4510b57cec5SDimitry Andric if (Flag.Value == 0) 4520b57cec5SDimitry Andric continue; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric TEnum EnumMask{}; 4550b57cec5SDimitry Andric if (Flag.Value & EnumMask1) 4560b57cec5SDimitry Andric EnumMask = EnumMask1; 4570b57cec5SDimitry Andric else if (Flag.Value & EnumMask2) 4580b57cec5SDimitry Andric EnumMask = EnumMask2; 4590b57cec5SDimitry Andric else if (Flag.Value & EnumMask3) 4600b57cec5SDimitry Andric EnumMask = EnumMask3; 4610b57cec5SDimitry Andric bool IsEnum = (Flag.Value & EnumMask) != 0; 4620b57cec5SDimitry Andric if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 4630b57cec5SDimitry Andric (IsEnum && (Value & EnumMask) == Flag.Value)) { 4640b57cec5SDimitry Andric if (!Str.empty()) 4650b57cec5SDimitry Andric Str += ", "; 4660b57cec5SDimitry Andric Str += Flag.AltName; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric return Str; 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric formatted_raw_ostream &printField(struct Field F) { 4730b57cec5SDimitry Andric if (F.Column != 0) 4740b57cec5SDimitry Andric OS.PadToColumn(F.Column); 4750b57cec5SDimitry Andric OS << F.Str; 4760b57cec5SDimitry Andric OS.flush(); 4770b57cec5SDimitry Andric return OS; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, 4800b57cec5SDimitry Andric StringRef StrTable, uint32_t Bucket); 4810b57cec5SDimitry Andric void printRelocHeader(unsigned SType); 4820b57cec5SDimitry Andric void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, 4830b57cec5SDimitry Andric const Elf_Rela &R, bool IsRela); 4840b57cec5SDimitry Andric void printRelocation(const ELFO *Obj, const Elf_Sym *Sym, 4850b57cec5SDimitry Andric StringRef SymbolName, const Elf_Rela &R, bool IsRela); 4860b57cec5SDimitry Andric void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, 4870b57cec5SDimitry Andric StringRef StrTable, bool IsDynamic) override; 4880b57cec5SDimitry Andric std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol, 4890b57cec5SDimitry Andric const Elf_Sym *FirstSym); 4900b57cec5SDimitry Andric void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela); 4910b57cec5SDimitry Andric bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); 4920b57cec5SDimitry Andric bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); 4930b57cec5SDimitry Andric bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); 4940b57cec5SDimitry Andric bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); 4950b57cec5SDimitry Andric void printProgramHeaders(const ELFO *Obj); 4960b57cec5SDimitry Andric void printSectionMapping(const ELFO *Obj); 4970b57cec5SDimitry Andric }; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> { 5000b57cec5SDimitry Andric public: 5010b57cec5SDimitry Andric TYPEDEF_ELF_TYPES(ELFT) 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric LLVMStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) 5040b57cec5SDimitry Andric : DumpStyle<ELFT>(Dumper), W(W) {} 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric void printFileHeaders(const ELFO *Obj) override; 5070b57cec5SDimitry Andric void printGroupSections(const ELFFile<ELFT> *Obj) override; 5080b57cec5SDimitry Andric void printRelocations(const ELFO *Obj) override; 5090b57cec5SDimitry Andric void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj); 5100b57cec5SDimitry Andric void printSectionHeaders(const ELFO *Obj) override; 5110b57cec5SDimitry Andric void printSymbols(const ELFO *Obj, bool PrintSymbols, 5120b57cec5SDimitry Andric bool PrintDynamicSymbols) override; 5130b57cec5SDimitry Andric void printDynamic(const ELFFile<ELFT> *Obj) override; 5140b57cec5SDimitry Andric void printDynamicRelocations(const ELFO *Obj) override; 5150b57cec5SDimitry Andric void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders, 5160b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 5170b57cec5SDimitry Andric void printVersionSymbolSection(const ELFFile<ELFT> *Obj, 5180b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 5190b57cec5SDimitry Andric void printVersionDefinitionSection(const ELFFile<ELFT> *Obj, 5200b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 5210b57cec5SDimitry Andric void printVersionDependencySection(const ELFFile<ELFT> *Obj, 5220b57cec5SDimitry Andric const Elf_Shdr *Sec) override; 5230b57cec5SDimitry Andric void printHashHistogram(const ELFFile<ELFT> *Obj) override; 5240b57cec5SDimitry Andric void printCGProfile(const ELFFile<ELFT> *Obj) override; 5250b57cec5SDimitry Andric void printAddrsig(const ELFFile<ELFT> *Obj) override; 5260b57cec5SDimitry Andric void printNotes(const ELFFile<ELFT> *Obj) override; 5270b57cec5SDimitry Andric void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; 5280b57cec5SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 5290b57cec5SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric private: 5320b57cec5SDimitry Andric void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); 5330b57cec5SDimitry Andric void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); 5340b57cec5SDimitry Andric void printSymbols(const ELFO *Obj); 5350b57cec5SDimitry Andric void printDynamicSymbols(const ELFO *Obj); 5360b57cec5SDimitry Andric void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, 5370b57cec5SDimitry Andric StringRef StrTable, bool IsDynamic) override; 5380b57cec5SDimitry Andric void printProgramHeaders(const ELFO *Obj); 5390b57cec5SDimitry Andric void printSectionMapping(const ELFO *Obj) {} 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric ScopedPrinter &W; 5420b57cec5SDimitry Andric }; 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric } // end anonymous namespace 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric namespace llvm { 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric template <class ELFT> 5490b57cec5SDimitry Andric static std::error_code createELFDumper(const ELFObjectFile<ELFT> *Obj, 5500b57cec5SDimitry Andric ScopedPrinter &Writer, 5510b57cec5SDimitry Andric std::unique_ptr<ObjDumper> &Result) { 5520b57cec5SDimitry Andric Result.reset(new ELFDumper<ELFT>(Obj, Writer)); 5530b57cec5SDimitry Andric return readobj_error::success; 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric std::error_code createELFDumper(const object::ObjectFile *Obj, 5570b57cec5SDimitry Andric ScopedPrinter &Writer, 5580b57cec5SDimitry Andric std::unique_ptr<ObjDumper> &Result) { 5590b57cec5SDimitry Andric // Little-endian 32-bit 5600b57cec5SDimitry Andric if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) 5610b57cec5SDimitry Andric return createELFDumper(ELFObj, Writer, Result); 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric // Big-endian 32-bit 5640b57cec5SDimitry Andric if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) 5650b57cec5SDimitry Andric return createELFDumper(ELFObj, Writer, Result); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric // Little-endian 64-bit 5680b57cec5SDimitry Andric if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) 5690b57cec5SDimitry Andric return createELFDumper(ELFObj, Writer, Result); 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric // Big-endian 64-bit 5720b57cec5SDimitry Andric if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) 5730b57cec5SDimitry Andric return createELFDumper(ELFObj, Writer, Result); 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric return readobj_error::unsupported_obj_file_format; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric } // end namespace llvm 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric // Iterate through the versions needed section, and place each Elf_Vernaux 5810b57cec5SDimitry Andric // in the VersionMap according to its index. 5820b57cec5SDimitry Andric template <class ELFT> 5830b57cec5SDimitry Andric void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *Sec) const { 5840b57cec5SDimitry Andric unsigned VerneedSize = Sec->sh_size; // Size of section in bytes 5850b57cec5SDimitry Andric unsigned VerneedEntries = Sec->sh_info; // Number of Verneed entries 5860b57cec5SDimitry Andric const uint8_t *VerneedStart = reinterpret_cast<const uint8_t *>( 5870b57cec5SDimitry Andric ObjF->getELFFile()->base() + Sec->sh_offset); 5880b57cec5SDimitry Andric const uint8_t *VerneedEnd = VerneedStart + VerneedSize; 5890b57cec5SDimitry Andric // The first Verneed entry is at the start of the section. 5900b57cec5SDimitry Andric const uint8_t *VerneedBuf = VerneedStart; 5910b57cec5SDimitry Andric for (unsigned VerneedIndex = 0; VerneedIndex < VerneedEntries; 5920b57cec5SDimitry Andric ++VerneedIndex) { 5930b57cec5SDimitry Andric if (VerneedBuf + sizeof(Elf_Verneed) > VerneedEnd) 5940b57cec5SDimitry Andric report_fatal_error("Section ended unexpectedly while scanning " 5950b57cec5SDimitry Andric "version needed records."); 5960b57cec5SDimitry Andric const Elf_Verneed *Verneed = 5970b57cec5SDimitry Andric reinterpret_cast<const Elf_Verneed *>(VerneedBuf); 5980b57cec5SDimitry Andric if (Verneed->vn_version != ELF::VER_NEED_CURRENT) 5990b57cec5SDimitry Andric report_fatal_error("Unexpected verneed version"); 6000b57cec5SDimitry Andric // Iterate through the Vernaux entries 6010b57cec5SDimitry Andric const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux; 6020b57cec5SDimitry Andric for (unsigned VernauxIndex = 0; VernauxIndex < Verneed->vn_cnt; 6030b57cec5SDimitry Andric ++VernauxIndex) { 6040b57cec5SDimitry Andric if (VernauxBuf + sizeof(Elf_Vernaux) > VerneedEnd) 6050b57cec5SDimitry Andric report_fatal_error("Section ended unexpected while scanning auxiliary " 6060b57cec5SDimitry Andric "version needed records."); 6070b57cec5SDimitry Andric const Elf_Vernaux *Vernaux = 6080b57cec5SDimitry Andric reinterpret_cast<const Elf_Vernaux *>(VernauxBuf); 6090b57cec5SDimitry Andric size_t Index = Vernaux->vna_other & ELF::VERSYM_VERSION; 6100b57cec5SDimitry Andric if (Index >= VersionMap.size()) 6110b57cec5SDimitry Andric VersionMap.resize(Index + 1); 6120b57cec5SDimitry Andric VersionMap[Index] = VersionMapEntry(Vernaux); 6130b57cec5SDimitry Andric VernauxBuf += Vernaux->vna_next; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric VerneedBuf += Verneed->vn_next; 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric // Iterate through the version definitions, and place each Elf_Verdef 6200b57cec5SDimitry Andric // in the VersionMap according to its index. 6210b57cec5SDimitry Andric template <class ELFT> 6220b57cec5SDimitry Andric void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *Sec) const { 6230b57cec5SDimitry Andric unsigned VerdefSize = Sec->sh_size; // Size of section in bytes 6240b57cec5SDimitry Andric unsigned VerdefEntries = Sec->sh_info; // Number of Verdef entries 6250b57cec5SDimitry Andric const uint8_t *VerdefStart = reinterpret_cast<const uint8_t *>( 6260b57cec5SDimitry Andric ObjF->getELFFile()->base() + Sec->sh_offset); 6270b57cec5SDimitry Andric const uint8_t *VerdefEnd = VerdefStart + VerdefSize; 6280b57cec5SDimitry Andric // The first Verdef entry is at the start of the section. 6290b57cec5SDimitry Andric const uint8_t *VerdefBuf = VerdefStart; 6300b57cec5SDimitry Andric for (unsigned VerdefIndex = 0; VerdefIndex < VerdefEntries; ++VerdefIndex) { 6310b57cec5SDimitry Andric if (VerdefBuf + sizeof(Elf_Verdef) > VerdefEnd) 6320b57cec5SDimitry Andric report_fatal_error("Section ended unexpectedly while scanning " 6330b57cec5SDimitry Andric "version definitions."); 6340b57cec5SDimitry Andric const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf); 6350b57cec5SDimitry Andric if (Verdef->vd_version != ELF::VER_DEF_CURRENT) 6360b57cec5SDimitry Andric report_fatal_error("Unexpected verdef version"); 6370b57cec5SDimitry Andric size_t Index = Verdef->vd_ndx & ELF::VERSYM_VERSION; 6380b57cec5SDimitry Andric if (Index >= VersionMap.size()) 6390b57cec5SDimitry Andric VersionMap.resize(Index + 1); 6400b57cec5SDimitry Andric VersionMap[Index] = VersionMapEntry(Verdef); 6410b57cec5SDimitry Andric VerdefBuf += Verdef->vd_next; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() const { 6460b57cec5SDimitry Andric // If there is no dynamic symtab or version table, there is nothing to do. 6470b57cec5SDimitry Andric if (!DynSymRegion.Addr || !SymbolVersionSection) 6480b57cec5SDimitry Andric return; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric // Has the VersionMap already been loaded? 6510b57cec5SDimitry Andric if (!VersionMap.empty()) 6520b57cec5SDimitry Andric return; 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric // The first two version indexes are reserved. 6550b57cec5SDimitry Andric // Index 0 is LOCAL, index 1 is GLOBAL. 6560b57cec5SDimitry Andric VersionMap.push_back(VersionMapEntry()); 6570b57cec5SDimitry Andric VersionMap.push_back(VersionMapEntry()); 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric if (SymbolVersionDefSection) 6600b57cec5SDimitry Andric LoadVersionDefs(SymbolVersionDefSection); 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric if (SymbolVersionNeedSection) 6630b57cec5SDimitry Andric LoadVersionNeeds(SymbolVersionNeedSection); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric template <typename ELFT> 6670b57cec5SDimitry Andric StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, 6680b57cec5SDimitry Andric const Elf_Sym *Sym, 6690b57cec5SDimitry Andric bool &IsDefault) const { 6700b57cec5SDimitry Andric // This is a dynamic symbol. Look in the GNU symbol version table. 6710b57cec5SDimitry Andric if (!SymbolVersionSection) { 6720b57cec5SDimitry Andric // No version table. 6730b57cec5SDimitry Andric IsDefault = false; 6740b57cec5SDimitry Andric return ""; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // Determine the position in the symbol table of this entry. 6780b57cec5SDimitry Andric size_t EntryIndex = (reinterpret_cast<uintptr_t>(Sym) - 6790b57cec5SDimitry Andric reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) / 6800b57cec5SDimitry Andric sizeof(Elf_Sym); 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric // Get the corresponding version index entry. 6830b57cec5SDimitry Andric const Elf_Versym *Versym = 6840b57cec5SDimitry Andric unwrapOrError(ObjF->getELFFile()->template getEntry<Elf_Versym>( 6850b57cec5SDimitry Andric SymbolVersionSection, EntryIndex)); 6860b57cec5SDimitry Andric return this->getSymbolVersionByIndex(StrTab, Versym->vs_index, IsDefault); 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric static std::string maybeDemangle(StringRef Name) { 6900b57cec5SDimitry Andric return opts::Demangle ? demangle(Name) : Name.str(); 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric template <typename ELFT> 6940b57cec5SDimitry Andric std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { 6950b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 6960b57cec5SDimitry Andric StringRef StrTable = 6970b57cec5SDimitry Andric unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); 6980b57cec5SDimitry Andric Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); 6990b57cec5SDimitry Andric if (Index >= Syms.size()) 7000b57cec5SDimitry Andric reportError("Invalid symbol index"); 7010b57cec5SDimitry Andric const Elf_Sym *Sym = &Syms[Index]; 7020b57cec5SDimitry Andric return maybeDemangle(unwrapOrError(Sym->getName(StrTable))); 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric template <typename ELFT> 7060b57cec5SDimitry Andric StringRef ELFDumper<ELFT>::getSymbolVersionByIndex(StringRef StrTab, 7070b57cec5SDimitry Andric uint32_t SymbolVersionIndex, 7080b57cec5SDimitry Andric bool &IsDefault) const { 7090b57cec5SDimitry Andric size_t VersionIndex = SymbolVersionIndex & VERSYM_VERSION; 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric // Special markers for unversioned symbols. 7120b57cec5SDimitry Andric if (VersionIndex == VER_NDX_LOCAL || VersionIndex == VER_NDX_GLOBAL) { 7130b57cec5SDimitry Andric IsDefault = false; 7140b57cec5SDimitry Andric return ""; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric // Lookup this symbol in the version table. 7180b57cec5SDimitry Andric LoadVersionMap(); 7190b57cec5SDimitry Andric if (VersionIndex >= VersionMap.size() || VersionMap[VersionIndex].isNull()) 7200b57cec5SDimitry Andric reportError("Invalid version entry"); 7210b57cec5SDimitry Andric const VersionMapEntry &Entry = VersionMap[VersionIndex]; 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Get the version name string. 7240b57cec5SDimitry Andric size_t NameOffset; 7250b57cec5SDimitry Andric if (Entry.isVerdef()) { 7260b57cec5SDimitry Andric // The first Verdaux entry holds the name. 7270b57cec5SDimitry Andric NameOffset = Entry.getVerdef()->getAux()->vda_name; 7280b57cec5SDimitry Andric IsDefault = !(SymbolVersionIndex & VERSYM_HIDDEN); 7290b57cec5SDimitry Andric } else { 7300b57cec5SDimitry Andric NameOffset = Entry.getVernaux()->vna_name; 7310b57cec5SDimitry Andric IsDefault = false; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric if (NameOffset >= StrTab.size()) 7340b57cec5SDimitry Andric reportError("Invalid string offset"); 7350b57cec5SDimitry Andric return StrTab.data() + NameOffset; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric template <typename ELFT> 7390b57cec5SDimitry Andric std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, 7400b57cec5SDimitry Andric StringRef StrTable, 7410b57cec5SDimitry Andric bool IsDynamic) const { 7420b57cec5SDimitry Andric std::string SymbolName = 7430b57cec5SDimitry Andric maybeDemangle(unwrapOrError(Symbol->getName(StrTable))); 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) { 7460b57cec5SDimitry Andric unsigned SectionIndex; 7470b57cec5SDimitry Andric StringRef SectionName; 7480b57cec5SDimitry Andric Elf_Sym_Range Syms = 7490b57cec5SDimitry Andric unwrapOrError(ObjF->getELFFile()->symbols(DotSymtabSec)); 7500b57cec5SDimitry Andric getSectionNameIndex(Symbol, Syms.begin(), SectionName, SectionIndex); 7510b57cec5SDimitry Andric return SectionName; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric if (!IsDynamic) 7550b57cec5SDimitry Andric return SymbolName; 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric bool IsDefault; 7580b57cec5SDimitry Andric StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault); 7590b57cec5SDimitry Andric if (!Version.empty()) { 7600b57cec5SDimitry Andric SymbolName += (IsDefault ? "@@" : "@"); 7610b57cec5SDimitry Andric SymbolName += Version; 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric return SymbolName; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric template <typename ELFT> 7670b57cec5SDimitry Andric void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol, 7680b57cec5SDimitry Andric const Elf_Sym *FirstSym, 7690b57cec5SDimitry Andric StringRef &SectionName, 7700b57cec5SDimitry Andric unsigned &SectionIndex) const { 7710b57cec5SDimitry Andric SectionIndex = Symbol->st_shndx; 7720b57cec5SDimitry Andric if (Symbol->isUndefined()) 7730b57cec5SDimitry Andric SectionName = "Undefined"; 7740b57cec5SDimitry Andric else if (Symbol->isProcessorSpecific()) 7750b57cec5SDimitry Andric SectionName = "Processor Specific"; 7760b57cec5SDimitry Andric else if (Symbol->isOSSpecific()) 7770b57cec5SDimitry Andric SectionName = "Operating System Specific"; 7780b57cec5SDimitry Andric else if (Symbol->isAbsolute()) 7790b57cec5SDimitry Andric SectionName = "Absolute"; 7800b57cec5SDimitry Andric else if (Symbol->isCommon()) 7810b57cec5SDimitry Andric SectionName = "Common"; 7820b57cec5SDimitry Andric else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX) 7830b57cec5SDimitry Andric SectionName = "Reserved"; 7840b57cec5SDimitry Andric else { 7850b57cec5SDimitry Andric if (SectionIndex == SHN_XINDEX) 7860b57cec5SDimitry Andric SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( 7870b57cec5SDimitry Andric Symbol, FirstSym, ShndxTable)); 7880b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 7890b57cec5SDimitry Andric const typename ELFT::Shdr *Sec = 7900b57cec5SDimitry Andric unwrapOrError(Obj->getSection(SectionIndex)); 7910b57cec5SDimitry Andric SectionName = unwrapOrError(Obj->getSectionName(Sec)); 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric template <class ELFO> 7960b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr * 7970b57cec5SDimitry Andric findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { 7980b57cec5SDimitry Andric for (const auto &Shdr : unwrapOrError(Obj->sections())) 7990b57cec5SDimitry Andric if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) 8000b57cec5SDimitry Andric return &Shdr; 8010b57cec5SDimitry Andric return nullptr; 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric template <class ELFO> 8050b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, 8060b57cec5SDimitry Andric StringRef Name) { 8070b57cec5SDimitry Andric for (const auto &Shdr : unwrapOrError(Obj.sections())) { 8080b57cec5SDimitry Andric if (Name == unwrapOrError(Obj.getSectionName(&Shdr))) 8090b57cec5SDimitry Andric return &Shdr; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric return nullptr; 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfClass[] = { 8150b57cec5SDimitry Andric {"None", "none", ELF::ELFCLASSNONE}, 8160b57cec5SDimitry Andric {"32-bit", "ELF32", ELF::ELFCLASS32}, 8170b57cec5SDimitry Andric {"64-bit", "ELF64", ELF::ELFCLASS64}, 8180b57cec5SDimitry Andric }; 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDataEncoding[] = { 8210b57cec5SDimitry Andric {"None", "none", ELF::ELFDATANONE}, 8220b57cec5SDimitry Andric {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB}, 8230b57cec5SDimitry Andric {"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB}, 8240b57cec5SDimitry Andric }; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfObjectFileType[] = { 8270b57cec5SDimitry Andric {"None", "NONE (none)", ELF::ET_NONE}, 8280b57cec5SDimitry Andric {"Relocatable", "REL (Relocatable file)", ELF::ET_REL}, 8290b57cec5SDimitry Andric {"Executable", "EXEC (Executable file)", ELF::ET_EXEC}, 8300b57cec5SDimitry Andric {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN}, 8310b57cec5SDimitry Andric {"Core", "CORE (Core file)", ELF::ET_CORE}, 8320b57cec5SDimitry Andric }; 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfOSABI[] = { 8350b57cec5SDimitry Andric {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, 8360b57cec5SDimitry Andric {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, 8370b57cec5SDimitry Andric {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, 8380b57cec5SDimitry Andric {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, 8390b57cec5SDimitry Andric {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, 8400b57cec5SDimitry Andric {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, 8410b57cec5SDimitry Andric {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, 8420b57cec5SDimitry Andric {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, 8430b57cec5SDimitry Andric {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, 8440b57cec5SDimitry Andric {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, 8450b57cec5SDimitry Andric {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, 8460b57cec5SDimitry Andric {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, 8470b57cec5SDimitry Andric {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, 8480b57cec5SDimitry Andric {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, 8490b57cec5SDimitry Andric {"AROS", "AROS", ELF::ELFOSABI_AROS}, 8500b57cec5SDimitry Andric {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, 8510b57cec5SDimitry Andric {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, 8520b57cec5SDimitry Andric {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} 8530b57cec5SDimitry Andric }; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric static const EnumEntry<unsigned> SymVersionFlags[] = { 8560b57cec5SDimitry Andric {"Base", "BASE", VER_FLG_BASE}, 8570b57cec5SDimitry Andric {"Weak", "WEAK", VER_FLG_WEAK}, 8580b57cec5SDimitry Andric {"Info", "INFO", VER_FLG_INFO}}; 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric static const EnumEntry<unsigned> AMDGPUElfOSABI[] = { 8610b57cec5SDimitry Andric {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, 8620b57cec5SDimitry Andric {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL}, 8630b57cec5SDimitry Andric {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D} 8640b57cec5SDimitry Andric }; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric static const EnumEntry<unsigned> ARMElfOSABI[] = { 8670b57cec5SDimitry Andric {"ARM", "ARM", ELF::ELFOSABI_ARM} 8680b57cec5SDimitry Andric }; 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric static const EnumEntry<unsigned> C6000ElfOSABI[] = { 8710b57cec5SDimitry Andric {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI}, 8720b57cec5SDimitry Andric {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX} 8730b57cec5SDimitry Andric }; 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMachineType[] = { 8760b57cec5SDimitry Andric ENUM_ENT(EM_NONE, "None"), 8770b57cec5SDimitry Andric ENUM_ENT(EM_M32, "WE32100"), 8780b57cec5SDimitry Andric ENUM_ENT(EM_SPARC, "Sparc"), 8790b57cec5SDimitry Andric ENUM_ENT(EM_386, "Intel 80386"), 8800b57cec5SDimitry Andric ENUM_ENT(EM_68K, "MC68000"), 8810b57cec5SDimitry Andric ENUM_ENT(EM_88K, "MC88000"), 8820b57cec5SDimitry Andric ENUM_ENT(EM_IAMCU, "EM_IAMCU"), 8830b57cec5SDimitry Andric ENUM_ENT(EM_860, "Intel 80860"), 8840b57cec5SDimitry Andric ENUM_ENT(EM_MIPS, "MIPS R3000"), 8850b57cec5SDimitry Andric ENUM_ENT(EM_S370, "IBM System/370"), 8860b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"), 8870b57cec5SDimitry Andric ENUM_ENT(EM_PARISC, "HPPA"), 8880b57cec5SDimitry Andric ENUM_ENT(EM_VPP500, "Fujitsu VPP500"), 8890b57cec5SDimitry Andric ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"), 8900b57cec5SDimitry Andric ENUM_ENT(EM_960, "Intel 80960"), 8910b57cec5SDimitry Andric ENUM_ENT(EM_PPC, "PowerPC"), 8920b57cec5SDimitry Andric ENUM_ENT(EM_PPC64, "PowerPC64"), 8930b57cec5SDimitry Andric ENUM_ENT(EM_S390, "IBM S/390"), 8940b57cec5SDimitry Andric ENUM_ENT(EM_SPU, "SPU"), 8950b57cec5SDimitry Andric ENUM_ENT(EM_V800, "NEC V800 series"), 8960b57cec5SDimitry Andric ENUM_ENT(EM_FR20, "Fujistsu FR20"), 8970b57cec5SDimitry Andric ENUM_ENT(EM_RH32, "TRW RH-32"), 8980b57cec5SDimitry Andric ENUM_ENT(EM_RCE, "Motorola RCE"), 8990b57cec5SDimitry Andric ENUM_ENT(EM_ARM, "ARM"), 9000b57cec5SDimitry Andric ENUM_ENT(EM_ALPHA, "EM_ALPHA"), 9010b57cec5SDimitry Andric ENUM_ENT(EM_SH, "Hitachi SH"), 9020b57cec5SDimitry Andric ENUM_ENT(EM_SPARCV9, "Sparc v9"), 9030b57cec5SDimitry Andric ENUM_ENT(EM_TRICORE, "Siemens Tricore"), 9040b57cec5SDimitry Andric ENUM_ENT(EM_ARC, "ARC"), 9050b57cec5SDimitry Andric ENUM_ENT(EM_H8_300, "Hitachi H8/300"), 9060b57cec5SDimitry Andric ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"), 9070b57cec5SDimitry Andric ENUM_ENT(EM_H8S, "Hitachi H8S"), 9080b57cec5SDimitry Andric ENUM_ENT(EM_H8_500, "Hitachi H8/500"), 9090b57cec5SDimitry Andric ENUM_ENT(EM_IA_64, "Intel IA-64"), 9100b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"), 9110b57cec5SDimitry Andric ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"), 9120b57cec5SDimitry Andric ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"), 9130b57cec5SDimitry Andric ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"), 9140b57cec5SDimitry Andric ENUM_ENT(EM_PCP, "Siemens PCP"), 9150b57cec5SDimitry Andric ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"), 9160b57cec5SDimitry Andric ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"), 9170b57cec5SDimitry Andric ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"), 9180b57cec5SDimitry Andric ENUM_ENT(EM_ME16, "Toyota ME16 processor"), 9190b57cec5SDimitry Andric ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"), 9200b57cec5SDimitry Andric ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"), 9210b57cec5SDimitry Andric ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"), 9220b57cec5SDimitry Andric ENUM_ENT(EM_PDSP, "Sony DSP processor"), 9230b57cec5SDimitry Andric ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"), 9240b57cec5SDimitry Andric ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"), 9250b57cec5SDimitry Andric ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"), 9260b57cec5SDimitry Andric ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"), 9270b57cec5SDimitry Andric ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"), 9280b57cec5SDimitry Andric ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"), 9290b57cec5SDimitry Andric ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"), 9300b57cec5SDimitry Andric ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"), 9310b57cec5SDimitry Andric ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"), 9320b57cec5SDimitry Andric ENUM_ENT(EM_SVX, "Silicon Graphics SVx"), 9330b57cec5SDimitry Andric ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"), 9340b57cec5SDimitry Andric ENUM_ENT(EM_VAX, "Digital VAX"), 9350b57cec5SDimitry Andric ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"), 9360b57cec5SDimitry Andric ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"), 9370b57cec5SDimitry Andric ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"), 9380b57cec5SDimitry Andric ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"), 9390b57cec5SDimitry Andric ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"), 9400b57cec5SDimitry Andric ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"), 9410b57cec5SDimitry Andric ENUM_ENT(EM_PRISM, "Vitesse Prism"), 9420b57cec5SDimitry Andric ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"), 9430b57cec5SDimitry Andric ENUM_ENT(EM_FR30, "Fujitsu FR30"), 9440b57cec5SDimitry Andric ENUM_ENT(EM_D10V, "Mitsubishi D10V"), 9450b57cec5SDimitry Andric ENUM_ENT(EM_D30V, "Mitsubishi D30V"), 9460b57cec5SDimitry Andric ENUM_ENT(EM_V850, "NEC v850"), 9470b57cec5SDimitry Andric ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"), 9480b57cec5SDimitry Andric ENUM_ENT(EM_MN10300, "Matsushita MN10300"), 9490b57cec5SDimitry Andric ENUM_ENT(EM_MN10200, "Matsushita MN10200"), 9500b57cec5SDimitry Andric ENUM_ENT(EM_PJ, "picoJava"), 9510b57cec5SDimitry Andric ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"), 9520b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"), 9530b57cec5SDimitry Andric ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"), 9540b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"), 9550b57cec5SDimitry Andric ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"), 9560b57cec5SDimitry Andric ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"), 9570b57cec5SDimitry Andric ENUM_ENT(EM_TPC, "Tenor Network TPC processor"), 9580b57cec5SDimitry Andric ENUM_ENT(EM_SNP1K, "EM_SNP1K"), 9590b57cec5SDimitry Andric ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"), 9600b57cec5SDimitry Andric ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"), 9610b57cec5SDimitry Andric ENUM_ENT(EM_MAX, "MAX Processor"), 9620b57cec5SDimitry Andric ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"), 9630b57cec5SDimitry Andric ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"), 9640b57cec5SDimitry Andric ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"), 9650b57cec5SDimitry Andric ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"), 9660b57cec5SDimitry Andric ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"), 9670b57cec5SDimitry Andric ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"), 9680b57cec5SDimitry Andric ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"), 9690b57cec5SDimitry Andric ENUM_ENT(EM_UNICORE, "Unicore"), 9700b57cec5SDimitry Andric ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"), 9710b57cec5SDimitry Andric ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"), 9720b57cec5SDimitry Andric ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"), 9730b57cec5SDimitry Andric ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"), 9740b57cec5SDimitry Andric ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"), 9750b57cec5SDimitry Andric ENUM_ENT(EM_C166, "Infineon Technologies xc16x"), 9760b57cec5SDimitry Andric ENUM_ENT(EM_M16C, "Renesas M16C"), 9770b57cec5SDimitry Andric ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"), 9780b57cec5SDimitry Andric ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"), 9790b57cec5SDimitry Andric ENUM_ENT(EM_M32C, "Renesas M32C"), 9800b57cec5SDimitry Andric ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"), 9810b57cec5SDimitry Andric ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"), 9820b57cec5SDimitry Andric ENUM_ENT(EM_SHARC, "EM_SHARC"), 9830b57cec5SDimitry Andric ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"), 9840b57cec5SDimitry Andric ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"), 9850b57cec5SDimitry Andric ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"), 9860b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"), 9870b57cec5SDimitry Andric ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"), 9880b57cec5SDimitry Andric ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"), 9890b57cec5SDimitry Andric ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"), 9900b57cec5SDimitry Andric ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"), 9910b57cec5SDimitry Andric ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"), 9920b57cec5SDimitry Andric ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"), 9930b57cec5SDimitry Andric ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"), 9940b57cec5SDimitry Andric ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"), 9950b57cec5SDimitry Andric ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"), 9960b57cec5SDimitry Andric ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"), 9970b57cec5SDimitry Andric ENUM_ENT(EM_8051, "Intel 8051 and variants"), 9980b57cec5SDimitry Andric ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"), 9990b57cec5SDimitry Andric ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"), 10000b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"), 10010b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"), 10020b57cec5SDimitry Andric ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"), 10030b57cec5SDimitry Andric ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"), 10040b57cec5SDimitry Andric ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"), 10050b57cec5SDimitry Andric ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"), 10060b57cec5SDimitry Andric ENUM_ENT(EM_RX, "Renesas RX"), 10070b57cec5SDimitry Andric ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"), 10080b57cec5SDimitry Andric ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"), 10090b57cec5SDimitry Andric ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"), 10100b57cec5SDimitry Andric ENUM_ENT(EM_CR16, "Xilinx MicroBlaze"), 10110b57cec5SDimitry Andric ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"), 10120b57cec5SDimitry Andric ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"), 10130b57cec5SDimitry Andric ENUM_ENT(EM_L10M, "EM_L10M"), 10140b57cec5SDimitry Andric ENUM_ENT(EM_K10M, "EM_K10M"), 10150b57cec5SDimitry Andric ENUM_ENT(EM_AARCH64, "AArch64"), 10160b57cec5SDimitry Andric ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"), 10170b57cec5SDimitry Andric ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"), 10180b57cec5SDimitry Andric ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"), 10190b57cec5SDimitry Andric ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"), 10200b57cec5SDimitry Andric ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"), 10210b57cec5SDimitry Andric ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"), 10220b57cec5SDimitry Andric ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"), 10230b57cec5SDimitry Andric ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"), 10240b57cec5SDimitry Andric ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"), 10250b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"), 10260b57cec5SDimitry Andric ENUM_ENT(EM_OPEN8, "EM_OPEN8"), 10270b57cec5SDimitry Andric ENUM_ENT(EM_RL78, "Renesas RL78"), 10280b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"), 10290b57cec5SDimitry Andric ENUM_ENT(EM_78KOR, "EM_78KOR"), 10300b57cec5SDimitry Andric ENUM_ENT(EM_56800EX, "EM_56800EX"), 10310b57cec5SDimitry Andric ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"), 10320b57cec5SDimitry Andric ENUM_ENT(EM_RISCV, "RISC-V"), 10330b57cec5SDimitry Andric ENUM_ENT(EM_LANAI, "EM_LANAI"), 10340b57cec5SDimitry Andric ENUM_ENT(EM_BPF, "EM_BPF"), 10350b57cec5SDimitry Andric }; 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymbolBindings[] = { 10380b57cec5SDimitry Andric {"Local", "LOCAL", ELF::STB_LOCAL}, 10390b57cec5SDimitry Andric {"Global", "GLOBAL", ELF::STB_GLOBAL}, 10400b57cec5SDimitry Andric {"Weak", "WEAK", ELF::STB_WEAK}, 10410b57cec5SDimitry Andric {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}}; 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymbolVisibilities[] = { 10440b57cec5SDimitry Andric {"DEFAULT", "DEFAULT", ELF::STV_DEFAULT}, 10450b57cec5SDimitry Andric {"INTERNAL", "INTERNAL", ELF::STV_INTERNAL}, 10460b57cec5SDimitry Andric {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, 10470b57cec5SDimitry Andric {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { 10500b57cec5SDimitry Andric { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } 10510b57cec5SDimitry Andric }; 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric static const char *getGroupType(uint32_t Flag) { 10540b57cec5SDimitry Andric if (Flag & ELF::GRP_COMDAT) 10550b57cec5SDimitry Andric return "COMDAT"; 10560b57cec5SDimitry Andric else 10570b57cec5SDimitry Andric return "(unknown)"; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSectionFlags[] = { 10610b57cec5SDimitry Andric ENUM_ENT(SHF_WRITE, "W"), 10620b57cec5SDimitry Andric ENUM_ENT(SHF_ALLOC, "A"), 10630b57cec5SDimitry Andric ENUM_ENT(SHF_EXCLUDE, "E"), 10640b57cec5SDimitry Andric ENUM_ENT(SHF_EXECINSTR, "X"), 10650b57cec5SDimitry Andric ENUM_ENT(SHF_MERGE, "M"), 10660b57cec5SDimitry Andric ENUM_ENT(SHF_STRINGS, "S"), 10670b57cec5SDimitry Andric ENUM_ENT(SHF_INFO_LINK, "I"), 10680b57cec5SDimitry Andric ENUM_ENT(SHF_LINK_ORDER, "L"), 10690b57cec5SDimitry Andric ENUM_ENT(SHF_OS_NONCONFORMING, "o"), 10700b57cec5SDimitry Andric ENUM_ENT(SHF_GROUP, "G"), 10710b57cec5SDimitry Andric ENUM_ENT(SHF_TLS, "T"), 10720b57cec5SDimitry Andric ENUM_ENT(SHF_MASKOS, "o"), 10730b57cec5SDimitry Andric ENUM_ENT(SHF_MASKPROC, "p"), 10740b57cec5SDimitry Andric ENUM_ENT_1(SHF_COMPRESSED), 10750b57cec5SDimitry Andric }; 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { 10780b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION), 10790b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION) 10800b57cec5SDimitry Andric }; 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfARMSectionFlags[] = { 10830b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) 10840b57cec5SDimitry Andric }; 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { 10870b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL) 10880b57cec5SDimitry Andric }; 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsSectionFlags[] = { 10910b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NODUPES), 10920b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NAMES ), 10930b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_LOCAL ), 10940b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP), 10950b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_GPREL ), 10960b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_MERGE ), 10970b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_ADDR ), 10980b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_STRING ) 10990b57cec5SDimitry Andric }; 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfX86_64SectionFlags[] = { 11020b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, SHF_X86_64_LARGE) 11030b57cec5SDimitry Andric }; 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric static std::string getGNUFlags(uint64_t Flags) { 11060b57cec5SDimitry Andric std::string Str; 11070b57cec5SDimitry Andric for (auto Entry : ElfSectionFlags) { 11080b57cec5SDimitry Andric uint64_t Flag = Entry.Value & Flags; 11090b57cec5SDimitry Andric Flags &= ~Entry.Value; 11100b57cec5SDimitry Andric switch (Flag) { 11110b57cec5SDimitry Andric case ELF::SHF_WRITE: 11120b57cec5SDimitry Andric case ELF::SHF_ALLOC: 11130b57cec5SDimitry Andric case ELF::SHF_EXECINSTR: 11140b57cec5SDimitry Andric case ELF::SHF_MERGE: 11150b57cec5SDimitry Andric case ELF::SHF_STRINGS: 11160b57cec5SDimitry Andric case ELF::SHF_INFO_LINK: 11170b57cec5SDimitry Andric case ELF::SHF_LINK_ORDER: 11180b57cec5SDimitry Andric case ELF::SHF_OS_NONCONFORMING: 11190b57cec5SDimitry Andric case ELF::SHF_GROUP: 11200b57cec5SDimitry Andric case ELF::SHF_TLS: 11210b57cec5SDimitry Andric case ELF::SHF_EXCLUDE: 11220b57cec5SDimitry Andric Str += Entry.AltName; 11230b57cec5SDimitry Andric break; 11240b57cec5SDimitry Andric default: 11250b57cec5SDimitry Andric if (Flag & ELF::SHF_MASKOS) 11260b57cec5SDimitry Andric Str += "o"; 11270b57cec5SDimitry Andric else if (Flag & ELF::SHF_MASKPROC) 11280b57cec5SDimitry Andric Str += "p"; 11290b57cec5SDimitry Andric else if (Flag) 11300b57cec5SDimitry Andric Str += "x"; 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric return Str; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric static const char *getElfSegmentType(unsigned Arch, unsigned Type) { 11370b57cec5SDimitry Andric // Check potentially overlapped processor-specific 11380b57cec5SDimitry Andric // program header type. 11390b57cec5SDimitry Andric switch (Arch) { 11400b57cec5SDimitry Andric case ELF::EM_ARM: 11410b57cec5SDimitry Andric switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); } 11420b57cec5SDimitry Andric break; 11430b57cec5SDimitry Andric case ELF::EM_MIPS: 11440b57cec5SDimitry Andric case ELF::EM_MIPS_RS3_LE: 11450b57cec5SDimitry Andric switch (Type) { 11460b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); 11470b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); 11480b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); 11490b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS); 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric break; 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric switch (Type) { 11550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL ); 11560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD ); 11570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC); 11580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP ); 11590b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE ); 11600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB ); 11610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR ); 11620b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS ); 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME); 11650b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND); 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); 11680b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); 11710b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); 11720b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric default: 11750b57cec5SDimitry Andric return ""; 11760b57cec5SDimitry Andric } 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric static std::string getElfPtType(unsigned Arch, unsigned Type) { 11800b57cec5SDimitry Andric switch (Type) { 11810b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_NULL) 11820b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_LOAD) 11830b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_DYNAMIC) 11840b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_INTERP) 11850b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_NOTE) 11860b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_SHLIB) 11870b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_PHDR) 11880b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_TLS) 11890b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_EH_FRAME) 11900b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_SUNW_UNWIND) 11910b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_STACK) 11920b57cec5SDimitry Andric LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_RELRO) 11930b57cec5SDimitry Andric default: 11940b57cec5SDimitry Andric // All machine specific PT_* types 11950b57cec5SDimitry Andric switch (Arch) { 11960b57cec5SDimitry Andric case ELF::EM_ARM: 11970b57cec5SDimitry Andric if (Type == ELF::PT_ARM_EXIDX) 11980b57cec5SDimitry Andric return "EXIDX"; 11990b57cec5SDimitry Andric break; 12000b57cec5SDimitry Andric case ELF::EM_MIPS: 12010b57cec5SDimitry Andric case ELF::EM_MIPS_RS3_LE: 12020b57cec5SDimitry Andric switch (Type) { 12030b57cec5SDimitry Andric case PT_MIPS_REGINFO: 12040b57cec5SDimitry Andric return "REGINFO"; 12050b57cec5SDimitry Andric case PT_MIPS_RTPROC: 12060b57cec5SDimitry Andric return "RTPROC"; 12070b57cec5SDimitry Andric case PT_MIPS_OPTIONS: 12080b57cec5SDimitry Andric return "OPTIONS"; 12090b57cec5SDimitry Andric case PT_MIPS_ABIFLAGS: 12100b57cec5SDimitry Andric return "ABIFLAGS"; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric break; 12130b57cec5SDimitry Andric } 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric return std::string("<unknown>: ") + to_string(format_hex(Type, 1)); 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric 12180b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSegmentFlags[] = { 12190b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_X), 12200b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_W), 12210b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_R) 12220b57cec5SDimitry Andric }; 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { 12250b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"), 12260b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_PIC, "pic"), 12270b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_CPIC, "cpic"), 12280b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI2, "abi2"), 12290b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"), 12300b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_FP64, "fp64"), 12310b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NAN2008, "nan2008"), 12320b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O32, "o32"), 12330b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O64, "o64"), 12340b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"), 12350b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"), 12360b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_3900, "3900"), 12370b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4010, "4010"), 12380b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4100, "4100"), 12390b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4650, "4650"), 12400b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4120, "4120"), 12410b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4111, "4111"), 12420b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"), 12430b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"), 12440b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"), 12450b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"), 12460b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"), 12470b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5400, "5400"), 12480b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5900, "5900"), 12490b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5500, "5500"), 12500b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_9000, "9000"), 12510b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"), 12520b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"), 12530b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"), 12540b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"), 12550b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"), 12560b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"), 12570b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_1, "mips1"), 12580b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_2, "mips2"), 12590b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_3, "mips3"), 12600b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_4, "mips4"), 12610b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_5, "mips5"), 12620b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32, "mips32"), 12630b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64, "mips64"), 12640b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"), 12650b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"), 12660b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"), 12670b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6") 12680b57cec5SDimitry Andric }; 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = { 12710b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE), 12720b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600), 12730b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630), 12740b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880), 12750b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670), 12760b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710), 12770b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730), 12780b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770), 12790b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR), 12800b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS), 12810b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER), 12820b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD), 12830b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO), 12840b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS), 12850b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS), 12860b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN), 12870b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS), 12880b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600), 12890b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601), 12900b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700), 12910b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701), 12920b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702), 12930b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703), 12940b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704), 12950b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801), 12960b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802), 12970b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803), 12980b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810), 12990b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900), 13000b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902), 13010b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904), 13020b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906), 13030b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908), 13040b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909), 13050b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010), 13060b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011), 13070b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012), 13080b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK), 13090b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_SRAM_ECC) 13100b57cec5SDimitry Andric }; 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { 13130b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_RVC, "RVC"), 13140b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"), 13150b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"), 13160b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"), 13170b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_RVE, "RVE") 13180b57cec5SDimitry Andric }; 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymOtherFlags[] = { 13210b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), 13220b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN), 13230b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED) 13240b57cec5SDimitry Andric }; 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = { 13270b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 13280b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 13290b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC), 13300b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS) 13310b57cec5SDimitry Andric }; 13320b57cec5SDimitry Andric 13330b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = { 13340b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 13350b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 13360b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16) 13370b57cec5SDimitry Andric }; 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric static const char *getElfMipsOptionsOdkType(unsigned Odk) { 13400b57cec5SDimitry Andric switch (Odk) { 13410b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL); 13420b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO); 13430b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS); 13440b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD); 13450b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH); 13460b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL); 13470b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS); 13480b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND); 13490b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR); 13500b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP); 13510b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT); 13520b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE); 13530b57cec5SDimitry Andric default: 13540b57cec5SDimitry Andric return "Unknown"; 13550b57cec5SDimitry Andric } 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric template <typename ELFT> 13590b57cec5SDimitry Andric void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) { 13600b57cec5SDimitry Andric // Try to locate the PT_DYNAMIC header. 13610b57cec5SDimitry Andric const Elf_Phdr *DynamicPhdr = nullptr; 13620b57cec5SDimitry Andric for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { 13630b57cec5SDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC) 13640b57cec5SDimitry Andric continue; 13650b57cec5SDimitry Andric DynamicPhdr = &Phdr; 13660b57cec5SDimitry Andric break; 13670b57cec5SDimitry Andric } 13680b57cec5SDimitry Andric 13690b57cec5SDimitry Andric // Try to locate the .dynamic section in the sections header table. 13700b57cec5SDimitry Andric const Elf_Shdr *DynamicSec = nullptr; 13710b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 13720b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_DYNAMIC) 13730b57cec5SDimitry Andric continue; 13740b57cec5SDimitry Andric DynamicSec = &Sec; 13750b57cec5SDimitry Andric break; 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric // Information in the section header has priority over the information 13790b57cec5SDimitry Andric // in a PT_DYNAMIC header. 13800b57cec5SDimitry Andric // Ignore sh_entsize and use the expected value for entry size explicitly. 13810b57cec5SDimitry Andric // This allows us to dump the dynamic sections with a broken sh_entsize 13820b57cec5SDimitry Andric // field. 13830b57cec5SDimitry Andric if (DynamicSec) { 13840b57cec5SDimitry Andric DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, 13850b57cec5SDimitry Andric DynamicSec->sh_size, sizeof(Elf_Dyn)}); 13860b57cec5SDimitry Andric parseDynamicTable(); 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric // If we have a PT_DYNAMIC header, we will either check the found dynamic 13900b57cec5SDimitry Andric // section or take the dynamic table data directly from the header. 13910b57cec5SDimitry Andric if (!DynamicPhdr) 13920b57cec5SDimitry Andric return; 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz > 13950b57cec5SDimitry Andric ObjF->getMemoryBufferRef().getBufferSize()) 13960b57cec5SDimitry Andric reportError( 13970b57cec5SDimitry Andric "PT_DYNAMIC segment offset + size exceeds the size of the file"); 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric if (!DynamicSec) { 14000b57cec5SDimitry Andric DynamicTable = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn)); 14010b57cec5SDimitry Andric parseDynamicTable(); 14020b57cec5SDimitry Andric return; 14030b57cec5SDimitry Andric } 14040b57cec5SDimitry Andric 14050b57cec5SDimitry Andric StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec)); 14060b57cec5SDimitry Andric if (DynamicSec->sh_addr + DynamicSec->sh_size > 14070b57cec5SDimitry Andric DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || 14080b57cec5SDimitry Andric DynamicSec->sh_addr < DynamicPhdr->p_vaddr) 14090b57cec5SDimitry Andric reportWarning("The SHT_DYNAMIC section '" + Name + 14100b57cec5SDimitry Andric "' is not contained within the " 14110b57cec5SDimitry Andric "PT_DYNAMIC segment"); 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr) 14140b57cec5SDimitry Andric reportWarning("The SHT_DYNAMIC section '" + Name + 14150b57cec5SDimitry Andric "' is not at the start of " 14160b57cec5SDimitry Andric "PT_DYNAMIC segment"); 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric template <typename ELFT> 14200b57cec5SDimitry Andric ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF, 14210b57cec5SDimitry Andric ScopedPrinter &Writer) 14220b57cec5SDimitry Andric : ObjDumper(Writer), ObjF(ObjF) { 14230b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 14260b57cec5SDimitry Andric switch (Sec.sh_type) { 14270b57cec5SDimitry Andric case ELF::SHT_SYMTAB: 14280b57cec5SDimitry Andric if (!DotSymtabSec) 14290b57cec5SDimitry Andric DotSymtabSec = &Sec; 14300b57cec5SDimitry Andric break; 14310b57cec5SDimitry Andric case ELF::SHT_DYNSYM: 14320b57cec5SDimitry Andric if (!DynSymRegion.Size) { 14330b57cec5SDimitry Andric DynSymRegion = createDRIFrom(&Sec); 14340b57cec5SDimitry Andric // This is only used (if Elf_Shdr present)for naming section in GNU 14350b57cec5SDimitry Andric // style 14360b57cec5SDimitry Andric DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec)); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (Expected<StringRef> E = Obj->getStringTableForSymtab(Sec)) 14390b57cec5SDimitry Andric DynamicStringTable = *E; 14400b57cec5SDimitry Andric else 14410b57cec5SDimitry Andric warn(E.takeError()); 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric break; 14440b57cec5SDimitry Andric case ELF::SHT_SYMTAB_SHNDX: 14450b57cec5SDimitry Andric ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec)); 14460b57cec5SDimitry Andric break; 14470b57cec5SDimitry Andric case ELF::SHT_GNU_versym: 14480b57cec5SDimitry Andric if (!SymbolVersionSection) 14490b57cec5SDimitry Andric SymbolVersionSection = &Sec; 14500b57cec5SDimitry Andric break; 14510b57cec5SDimitry Andric case ELF::SHT_GNU_verdef: 14520b57cec5SDimitry Andric if (!SymbolVersionDefSection) 14530b57cec5SDimitry Andric SymbolVersionDefSection = &Sec; 14540b57cec5SDimitry Andric break; 14550b57cec5SDimitry Andric case ELF::SHT_GNU_verneed: 14560b57cec5SDimitry Andric if (!SymbolVersionNeedSection) 14570b57cec5SDimitry Andric SymbolVersionNeedSection = &Sec; 14580b57cec5SDimitry Andric break; 14590b57cec5SDimitry Andric case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: 14600b57cec5SDimitry Andric if (!DotCGProfileSec) 14610b57cec5SDimitry Andric DotCGProfileSec = &Sec; 14620b57cec5SDimitry Andric break; 14630b57cec5SDimitry Andric case ELF::SHT_LLVM_ADDRSIG: 14640b57cec5SDimitry Andric if (!DotAddrsigSec) 14650b57cec5SDimitry Andric DotAddrsigSec = &Sec; 14660b57cec5SDimitry Andric break; 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric loadDynamicTable(Obj); 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric if (opts::Output == opts::GNU) 14730b57cec5SDimitry Andric ELFDumperStyle.reset(new GNUStyle<ELFT>(Writer, this)); 14740b57cec5SDimitry Andric else 14750b57cec5SDimitry Andric ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, this)); 14760b57cec5SDimitry Andric } 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric static const char *getTypeString(unsigned Arch, uint64_t Type) { 14790b57cec5SDimitry Andric #define DYNAMIC_TAG(n, v) 14800b57cec5SDimitry Andric switch (Arch) { 14810b57cec5SDimitry Andric 14820b57cec5SDimitry Andric case EM_AARCH64: 14830b57cec5SDimitry Andric switch (Type) { 14840b57cec5SDimitry Andric #define AARCH64_DYNAMIC_TAG(name, value) \ 14850b57cec5SDimitry Andric case DT_##name: \ 14860b57cec5SDimitry Andric return #name; 14870b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def" 14880b57cec5SDimitry Andric #undef AARCH64_DYNAMIC_TAG 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric break; 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric case EM_HEXAGON: 14930b57cec5SDimitry Andric switch (Type) { 14940b57cec5SDimitry Andric #define HEXAGON_DYNAMIC_TAG(name, value) \ 14950b57cec5SDimitry Andric case DT_##name: \ 14960b57cec5SDimitry Andric return #name; 14970b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def" 14980b57cec5SDimitry Andric #undef HEXAGON_DYNAMIC_TAG 14990b57cec5SDimitry Andric } 15000b57cec5SDimitry Andric break; 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric case EM_MIPS: 15030b57cec5SDimitry Andric switch (Type) { 15040b57cec5SDimitry Andric #define MIPS_DYNAMIC_TAG(name, value) \ 15050b57cec5SDimitry Andric case DT_##name: \ 15060b57cec5SDimitry Andric return #name; 15070b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def" 15080b57cec5SDimitry Andric #undef MIPS_DYNAMIC_TAG 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric break; 15110b57cec5SDimitry Andric 15120b57cec5SDimitry Andric case EM_PPC64: 15130b57cec5SDimitry Andric switch (Type) { 15140b57cec5SDimitry Andric #define PPC64_DYNAMIC_TAG(name, value) \ 15150b57cec5SDimitry Andric case DT_##name: \ 15160b57cec5SDimitry Andric return #name; 15170b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def" 15180b57cec5SDimitry Andric #undef PPC64_DYNAMIC_TAG 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric break; 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric #undef DYNAMIC_TAG 15230b57cec5SDimitry Andric switch (Type) { 15240b57cec5SDimitry Andric // Now handle all dynamic tags except the architecture specific ones 15250b57cec5SDimitry Andric #define AARCH64_DYNAMIC_TAG(name, value) 15260b57cec5SDimitry Andric #define MIPS_DYNAMIC_TAG(name, value) 15270b57cec5SDimitry Andric #define HEXAGON_DYNAMIC_TAG(name, value) 15280b57cec5SDimitry Andric #define PPC64_DYNAMIC_TAG(name, value) 15290b57cec5SDimitry Andric // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. 15300b57cec5SDimitry Andric #define DYNAMIC_TAG_MARKER(name, value) 15310b57cec5SDimitry Andric #define DYNAMIC_TAG(name, value) \ 15320b57cec5SDimitry Andric case DT_##name: \ 15330b57cec5SDimitry Andric return #name; 15340b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def" 15350b57cec5SDimitry Andric #undef DYNAMIC_TAG 15360b57cec5SDimitry Andric #undef AARCH64_DYNAMIC_TAG 15370b57cec5SDimitry Andric #undef MIPS_DYNAMIC_TAG 15380b57cec5SDimitry Andric #undef HEXAGON_DYNAMIC_TAG 15390b57cec5SDimitry Andric #undef PPC64_DYNAMIC_TAG 15400b57cec5SDimitry Andric #undef DYNAMIC_TAG_MARKER 15410b57cec5SDimitry Andric default: 15420b57cec5SDimitry Andric return "unknown"; 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric } 15450b57cec5SDimitry Andric 15460b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() { 15470b57cec5SDimitry Andric auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * { 15480b57cec5SDimitry Andric auto MappedAddrOrError = ObjF->getELFFile()->toMappedAddr(VAddr); 15490b57cec5SDimitry Andric if (!MappedAddrOrError) { 15500b57cec5SDimitry Andric reportWarning("Unable to parse DT_" + 15510b57cec5SDimitry Andric Twine(getTypeString( 15520b57cec5SDimitry Andric ObjF->getELFFile()->getHeader()->e_machine, Tag)) + 15530b57cec5SDimitry Andric ": " + llvm::toString(MappedAddrOrError.takeError())); 15540b57cec5SDimitry Andric return nullptr; 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric return MappedAddrOrError.get(); 15570b57cec5SDimitry Andric }; 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric uint64_t SONameOffset = 0; 15600b57cec5SDimitry Andric const char *StringTableBegin = nullptr; 15610b57cec5SDimitry Andric uint64_t StringTableSize = 0; 15620b57cec5SDimitry Andric for (const Elf_Dyn &Dyn : dynamic_table()) { 15630b57cec5SDimitry Andric switch (Dyn.d_tag) { 15640b57cec5SDimitry Andric case ELF::DT_HASH: 15650b57cec5SDimitry Andric HashTable = reinterpret_cast<const Elf_Hash *>( 15660b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 15670b57cec5SDimitry Andric break; 15680b57cec5SDimitry Andric case ELF::DT_GNU_HASH: 15690b57cec5SDimitry Andric GnuHashTable = reinterpret_cast<const Elf_GnuHash *>( 15700b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 15710b57cec5SDimitry Andric break; 15720b57cec5SDimitry Andric case ELF::DT_STRTAB: 15730b57cec5SDimitry Andric StringTableBegin = reinterpret_cast<const char *>( 15740b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 15750b57cec5SDimitry Andric break; 15760b57cec5SDimitry Andric case ELF::DT_STRSZ: 15770b57cec5SDimitry Andric StringTableSize = Dyn.getVal(); 15780b57cec5SDimitry Andric break; 15790b57cec5SDimitry Andric case ELF::DT_SYMTAB: 15800b57cec5SDimitry Andric DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 15810b57cec5SDimitry Andric DynSymRegion.EntSize = sizeof(Elf_Sym); 15820b57cec5SDimitry Andric break; 15830b57cec5SDimitry Andric case ELF::DT_RELA: 15840b57cec5SDimitry Andric DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 15850b57cec5SDimitry Andric break; 15860b57cec5SDimitry Andric case ELF::DT_RELASZ: 15870b57cec5SDimitry Andric DynRelaRegion.Size = Dyn.getVal(); 15880b57cec5SDimitry Andric break; 15890b57cec5SDimitry Andric case ELF::DT_RELAENT: 15900b57cec5SDimitry Andric DynRelaRegion.EntSize = Dyn.getVal(); 15910b57cec5SDimitry Andric break; 15920b57cec5SDimitry Andric case ELF::DT_SONAME: 15930b57cec5SDimitry Andric SONameOffset = Dyn.getVal(); 15940b57cec5SDimitry Andric break; 15950b57cec5SDimitry Andric case ELF::DT_REL: 15960b57cec5SDimitry Andric DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 15970b57cec5SDimitry Andric break; 15980b57cec5SDimitry Andric case ELF::DT_RELSZ: 15990b57cec5SDimitry Andric DynRelRegion.Size = Dyn.getVal(); 16000b57cec5SDimitry Andric break; 16010b57cec5SDimitry Andric case ELF::DT_RELENT: 16020b57cec5SDimitry Andric DynRelRegion.EntSize = Dyn.getVal(); 16030b57cec5SDimitry Andric break; 16040b57cec5SDimitry Andric case ELF::DT_RELR: 16050b57cec5SDimitry Andric case ELF::DT_ANDROID_RELR: 16060b57cec5SDimitry Andric DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 16070b57cec5SDimitry Andric break; 16080b57cec5SDimitry Andric case ELF::DT_RELRSZ: 16090b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRSZ: 16100b57cec5SDimitry Andric DynRelrRegion.Size = Dyn.getVal(); 16110b57cec5SDimitry Andric break; 16120b57cec5SDimitry Andric case ELF::DT_RELRENT: 16130b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRENT: 16140b57cec5SDimitry Andric DynRelrRegion.EntSize = Dyn.getVal(); 16150b57cec5SDimitry Andric break; 16160b57cec5SDimitry Andric case ELF::DT_PLTREL: 16170b57cec5SDimitry Andric if (Dyn.getVal() == DT_REL) 16180b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rel); 16190b57cec5SDimitry Andric else if (Dyn.getVal() == DT_RELA) 16200b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rela); 16210b57cec5SDimitry Andric else 16220b57cec5SDimitry Andric reportError(Twine("unknown DT_PLTREL value of ") + 16230b57cec5SDimitry Andric Twine((uint64_t)Dyn.getVal())); 16240b57cec5SDimitry Andric break; 16250b57cec5SDimitry Andric case ELF::DT_JMPREL: 16260b57cec5SDimitry Andric DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 16270b57cec5SDimitry Andric break; 16280b57cec5SDimitry Andric case ELF::DT_PLTRELSZ: 16290b57cec5SDimitry Andric DynPLTRelRegion.Size = Dyn.getVal(); 16300b57cec5SDimitry Andric break; 16310b57cec5SDimitry Andric } 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric if (StringTableBegin) 16340b57cec5SDimitry Andric DynamicStringTable = StringRef(StringTableBegin, StringTableSize); 16350b57cec5SDimitry Andric if (SONameOffset && SONameOffset < DynamicStringTable.size()) 16360b57cec5SDimitry Andric SOName = DynamicStringTable.data() + SONameOffset; 16370b57cec5SDimitry Andric } 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric template <typename ELFT> 16400b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const { 16410b57cec5SDimitry Andric return DynRelRegion.getAsArrayRef<Elf_Rel>(); 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric template <typename ELFT> 16450b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { 16460b57cec5SDimitry Andric return DynRelaRegion.getAsArrayRef<Elf_Rela>(); 16470b57cec5SDimitry Andric } 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric template <typename ELFT> 16500b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const { 16510b57cec5SDimitry Andric return DynRelrRegion.getAsArrayRef<Elf_Relr>(); 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printFileHeaders() { 16550b57cec5SDimitry Andric ELFDumperStyle->printFileHeaders(ObjF->getELFFile()); 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printSectionHeaders() { 16590b57cec5SDimitry Andric ELFDumperStyle->printSectionHeaders(ObjF->getELFFile()); 16600b57cec5SDimitry Andric } 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printRelocations() { 16630b57cec5SDimitry Andric ELFDumperStyle->printRelocations(ObjF->getELFFile()); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric template <class ELFT> 16670b57cec5SDimitry Andric void ELFDumper<ELFT>::printProgramHeaders( 16680b57cec5SDimitry Andric bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) { 16690b57cec5SDimitry Andric ELFDumperStyle->printProgramHeaders(ObjF->getELFFile(), PrintProgramHeaders, 16700b57cec5SDimitry Andric PrintSectionMapping); 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() { 16740b57cec5SDimitry Andric // Dump version symbol section. 16750b57cec5SDimitry Andric ELFDumperStyle->printVersionSymbolSection(ObjF->getELFFile(), 16760b57cec5SDimitry Andric SymbolVersionSection); 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric // Dump version definition section. 16790b57cec5SDimitry Andric ELFDumperStyle->printVersionDefinitionSection(ObjF->getELFFile(), 16800b57cec5SDimitry Andric SymbolVersionDefSection); 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric // Dump version dependency section. 16830b57cec5SDimitry Andric ELFDumperStyle->printVersionDependencySection(ObjF->getELFFile(), 16840b57cec5SDimitry Andric SymbolVersionNeedSection); 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() { 16880b57cec5SDimitry Andric ELFDumperStyle->printDynamicRelocations(ObjF->getELFFile()); 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric template <class ELFT> 16920b57cec5SDimitry Andric void ELFDumper<ELFT>::printSymbols(bool PrintSymbols, 16930b57cec5SDimitry Andric bool PrintDynamicSymbols) { 16940b57cec5SDimitry Andric ELFDumperStyle->printSymbols(ObjF->getELFFile(), PrintSymbols, 16950b57cec5SDimitry Andric PrintDynamicSymbols); 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printHashSymbols() { 16990b57cec5SDimitry Andric ELFDumperStyle->printHashSymbols(ObjF->getELFFile()); 17000b57cec5SDimitry Andric } 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() { 17030b57cec5SDimitry Andric ELFDumperStyle->printHashHistogram(ObjF->getELFFile()); 17040b57cec5SDimitry Andric } 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printCGProfile() { 17070b57cec5SDimitry Andric ELFDumperStyle->printCGProfile(ObjF->getELFFile()); 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNotes() { 17110b57cec5SDimitry Andric ELFDumperStyle->printNotes(ObjF->getELFFile()); 17120b57cec5SDimitry Andric } 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() { 17150b57cec5SDimitry Andric ELFDumperStyle->printELFLinkerOptions(ObjF->getELFFile()); 17160b57cec5SDimitry Andric } 17170b57cec5SDimitry Andric 17180b57cec5SDimitry Andric #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ 17190b57cec5SDimitry Andric { #enum, prefix##_##enum } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { 17220b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), 17230b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), 17240b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), 17250b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), 17260b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) 17270b57cec5SDimitry Andric }; 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { 17300b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), 17310b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), 17320b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), 17330b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), 17340b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), 17350b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), 17360b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), 17370b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), 17380b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), 17390b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), 17400b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), 17410b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), 17420b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), 17430b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), 17440b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), 17450b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), 17460b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND), 17470b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), 17480b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), 17490b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), 17500b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), 17510b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), 17520b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), 17530b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), 17540b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), 17550b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON) 17560b57cec5SDimitry Andric }; 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { 17590b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), 17600b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), 17610b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), 17620b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), 17630b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), 17640b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), 17650b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), 17660b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), 17670b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), 17680b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), 17690b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), 17700b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), 17710b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), 17720b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), 17730b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), 17740b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) 17750b57cec5SDimitry Andric }; 17760b57cec5SDimitry Andric 17770b57cec5SDimitry Andric #undef LLVM_READOBJ_DT_FLAG_ENT 17780b57cec5SDimitry Andric 17790b57cec5SDimitry Andric template <typename T, typename TFlag> 17800b57cec5SDimitry Andric void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { 17810b57cec5SDimitry Andric using FlagEntry = EnumEntry<TFlag>; 17820b57cec5SDimitry Andric using FlagVector = SmallVector<FlagEntry, 10>; 17830b57cec5SDimitry Andric FlagVector SetFlags; 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric for (const auto &Flag : Flags) { 17860b57cec5SDimitry Andric if (Flag.Value == 0) 17870b57cec5SDimitry Andric continue; 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric if ((Value & Flag.Value) == Flag.Value) 17900b57cec5SDimitry Andric SetFlags.push_back(Flag); 17910b57cec5SDimitry Andric } 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric for (const auto &Flag : SetFlags) { 17940b57cec5SDimitry Andric OS << Flag.Name << " "; 17950b57cec5SDimitry Andric } 17960b57cec5SDimitry Andric } 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric template <class ELFT> 17990b57cec5SDimitry Andric void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type, 18000b57cec5SDimitry Andric uint64_t Value) const { 18010b57cec5SDimitry Andric const char *ConvChar = 18020b57cec5SDimitry Andric (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64; 18030b57cec5SDimitry Andric 18040b57cec5SDimitry Andric // Handle custom printing of architecture specific tags 18050b57cec5SDimitry Andric switch (ObjF->getELFFile()->getHeader()->e_machine) { 18060b57cec5SDimitry Andric case EM_AARCH64: 18070b57cec5SDimitry Andric switch (Type) { 18080b57cec5SDimitry Andric case DT_AARCH64_BTI_PLT: 18090b57cec5SDimitry Andric case DT_AARCH64_PAC_PLT: 18100b57cec5SDimitry Andric OS << Value; 18110b57cec5SDimitry Andric return; 18120b57cec5SDimitry Andric default: 18130b57cec5SDimitry Andric break; 18140b57cec5SDimitry Andric } 18150b57cec5SDimitry Andric break; 18160b57cec5SDimitry Andric case EM_HEXAGON: 18170b57cec5SDimitry Andric switch (Type) { 18180b57cec5SDimitry Andric case DT_HEXAGON_VER: 18190b57cec5SDimitry Andric OS << Value; 18200b57cec5SDimitry Andric return; 18210b57cec5SDimitry Andric case DT_HEXAGON_SYMSZ: 18220b57cec5SDimitry Andric case DT_HEXAGON_PLT: 18230b57cec5SDimitry Andric OS << format(ConvChar, Value); 18240b57cec5SDimitry Andric return; 18250b57cec5SDimitry Andric default: 18260b57cec5SDimitry Andric break; 18270b57cec5SDimitry Andric } 18280b57cec5SDimitry Andric break; 18290b57cec5SDimitry Andric case EM_MIPS: 18300b57cec5SDimitry Andric switch (Type) { 18310b57cec5SDimitry Andric case DT_MIPS_RLD_VERSION: 18320b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTNO: 18330b57cec5SDimitry Andric case DT_MIPS_SYMTABNO: 18340b57cec5SDimitry Andric case DT_MIPS_UNREFEXTNO: 18350b57cec5SDimitry Andric OS << Value; 18360b57cec5SDimitry Andric return; 18370b57cec5SDimitry Andric case DT_MIPS_TIME_STAMP: 18380b57cec5SDimitry Andric case DT_MIPS_ICHECKSUM: 18390b57cec5SDimitry Andric case DT_MIPS_IVERSION: 18400b57cec5SDimitry Andric case DT_MIPS_BASE_ADDRESS: 18410b57cec5SDimitry Andric case DT_MIPS_MSYM: 18420b57cec5SDimitry Andric case DT_MIPS_CONFLICT: 18430b57cec5SDimitry Andric case DT_MIPS_LIBLIST: 18440b57cec5SDimitry Andric case DT_MIPS_CONFLICTNO: 18450b57cec5SDimitry Andric case DT_MIPS_LIBLISTNO: 18460b57cec5SDimitry Andric case DT_MIPS_GOTSYM: 18470b57cec5SDimitry Andric case DT_MIPS_HIPAGENO: 18480b57cec5SDimitry Andric case DT_MIPS_RLD_MAP: 18490b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS: 18500b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS_NO: 18510b57cec5SDimitry Andric case DT_MIPS_DELTA_INSTANCE: 18520b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC: 18530b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC_NO: 18540b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM: 18550b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM_NO: 18560b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM: 18570b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM_NO: 18580b57cec5SDimitry Andric case DT_MIPS_CXX_FLAGS: 18590b57cec5SDimitry Andric case DT_MIPS_PIXIE_INIT: 18600b57cec5SDimitry Andric case DT_MIPS_SYMBOL_LIB: 18610b57cec5SDimitry Andric case DT_MIPS_LOCALPAGE_GOTIDX: 18620b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTIDX: 18630b57cec5SDimitry Andric case DT_MIPS_HIDDEN_GOTIDX: 18640b57cec5SDimitry Andric case DT_MIPS_PROTECTED_GOTIDX: 18650b57cec5SDimitry Andric case DT_MIPS_OPTIONS: 18660b57cec5SDimitry Andric case DT_MIPS_INTERFACE: 18670b57cec5SDimitry Andric case DT_MIPS_DYNSTR_ALIGN: 18680b57cec5SDimitry Andric case DT_MIPS_INTERFACE_SIZE: 18690b57cec5SDimitry Andric case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: 18700b57cec5SDimitry Andric case DT_MIPS_PERF_SUFFIX: 18710b57cec5SDimitry Andric case DT_MIPS_COMPACT_SIZE: 18720b57cec5SDimitry Andric case DT_MIPS_GP_VALUE: 18730b57cec5SDimitry Andric case DT_MIPS_AUX_DYNAMIC: 18740b57cec5SDimitry Andric case DT_MIPS_PLTGOT: 18750b57cec5SDimitry Andric case DT_MIPS_RWPLT: 18760b57cec5SDimitry Andric case DT_MIPS_RLD_MAP_REL: 18770b57cec5SDimitry Andric OS << format(ConvChar, Value); 18780b57cec5SDimitry Andric return; 18790b57cec5SDimitry Andric case DT_MIPS_FLAGS: 18800b57cec5SDimitry Andric printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); 18810b57cec5SDimitry Andric return; 18820b57cec5SDimitry Andric default: 18830b57cec5SDimitry Andric break; 18840b57cec5SDimitry Andric } 18850b57cec5SDimitry Andric break; 18860b57cec5SDimitry Andric default: 18870b57cec5SDimitry Andric break; 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric switch (Type) { 18910b57cec5SDimitry Andric case DT_PLTREL: 18920b57cec5SDimitry Andric if (Value == DT_REL) { 18930b57cec5SDimitry Andric OS << "REL"; 18940b57cec5SDimitry Andric break; 18950b57cec5SDimitry Andric } else if (Value == DT_RELA) { 18960b57cec5SDimitry Andric OS << "RELA"; 18970b57cec5SDimitry Andric break; 18980b57cec5SDimitry Andric } 18990b57cec5SDimitry Andric LLVM_FALLTHROUGH; 19000b57cec5SDimitry Andric case DT_PLTGOT: 19010b57cec5SDimitry Andric case DT_HASH: 19020b57cec5SDimitry Andric case DT_STRTAB: 19030b57cec5SDimitry Andric case DT_SYMTAB: 19040b57cec5SDimitry Andric case DT_RELA: 19050b57cec5SDimitry Andric case DT_INIT: 19060b57cec5SDimitry Andric case DT_FINI: 19070b57cec5SDimitry Andric case DT_REL: 19080b57cec5SDimitry Andric case DT_JMPREL: 19090b57cec5SDimitry Andric case DT_INIT_ARRAY: 19100b57cec5SDimitry Andric case DT_FINI_ARRAY: 19110b57cec5SDimitry Andric case DT_PREINIT_ARRAY: 19120b57cec5SDimitry Andric case DT_DEBUG: 19130b57cec5SDimitry Andric case DT_VERDEF: 19140b57cec5SDimitry Andric case DT_VERNEED: 19150b57cec5SDimitry Andric case DT_VERSYM: 19160b57cec5SDimitry Andric case DT_GNU_HASH: 19170b57cec5SDimitry Andric case DT_NULL: 19180b57cec5SDimitry Andric OS << format(ConvChar, Value); 19190b57cec5SDimitry Andric break; 19200b57cec5SDimitry Andric case DT_RELACOUNT: 19210b57cec5SDimitry Andric case DT_RELCOUNT: 19220b57cec5SDimitry Andric case DT_VERDEFNUM: 19230b57cec5SDimitry Andric case DT_VERNEEDNUM: 19240b57cec5SDimitry Andric OS << Value; 19250b57cec5SDimitry Andric break; 19260b57cec5SDimitry Andric case DT_PLTRELSZ: 19270b57cec5SDimitry Andric case DT_RELASZ: 19280b57cec5SDimitry Andric case DT_RELAENT: 19290b57cec5SDimitry Andric case DT_STRSZ: 19300b57cec5SDimitry Andric case DT_SYMENT: 19310b57cec5SDimitry Andric case DT_RELSZ: 19320b57cec5SDimitry Andric case DT_RELENT: 19330b57cec5SDimitry Andric case DT_INIT_ARRAYSZ: 19340b57cec5SDimitry Andric case DT_FINI_ARRAYSZ: 19350b57cec5SDimitry Andric case DT_PREINIT_ARRAYSZ: 19360b57cec5SDimitry Andric case DT_ANDROID_RELSZ: 19370b57cec5SDimitry Andric case DT_ANDROID_RELASZ: 19380b57cec5SDimitry Andric OS << Value << " (bytes)"; 19390b57cec5SDimitry Andric break; 19400b57cec5SDimitry Andric case DT_NEEDED: 19410b57cec5SDimitry Andric case DT_SONAME: 19420b57cec5SDimitry Andric case DT_AUXILIARY: 19430b57cec5SDimitry Andric case DT_USED: 19440b57cec5SDimitry Andric case DT_FILTER: 19450b57cec5SDimitry Andric case DT_RPATH: 19460b57cec5SDimitry Andric case DT_RUNPATH: { 19470b57cec5SDimitry Andric const std::map<uint64_t, const char*> TagNames = { 19480b57cec5SDimitry Andric {DT_NEEDED, "Shared library"}, 19490b57cec5SDimitry Andric {DT_SONAME, "Library soname"}, 19500b57cec5SDimitry Andric {DT_AUXILIARY, "Auxiliary library"}, 19510b57cec5SDimitry Andric {DT_USED, "Not needed object"}, 19520b57cec5SDimitry Andric {DT_FILTER, "Filter library"}, 19530b57cec5SDimitry Andric {DT_RPATH, "Library rpath"}, 19540b57cec5SDimitry Andric {DT_RUNPATH, "Library runpath"}, 19550b57cec5SDimitry Andric }; 19560b57cec5SDimitry Andric OS << TagNames.at(Type) << ": "; 19570b57cec5SDimitry Andric if (DynamicStringTable.empty()) 19580b57cec5SDimitry Andric OS << "<String table is empty or was not found> "; 19590b57cec5SDimitry Andric else if (Value < DynamicStringTable.size()) 19600b57cec5SDimitry Andric OS << "[" << StringRef(DynamicStringTable.data() + Value) << "]"; 19610b57cec5SDimitry Andric else 19620b57cec5SDimitry Andric OS << "<Invalid offset 0x" << utohexstr(Value) << ">"; 19630b57cec5SDimitry Andric break; 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric case DT_FLAGS: 19660b57cec5SDimitry Andric printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); 19670b57cec5SDimitry Andric break; 19680b57cec5SDimitry Andric case DT_FLAGS_1: 19690b57cec5SDimitry Andric printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); 19700b57cec5SDimitry Andric break; 19710b57cec5SDimitry Andric default: 19720b57cec5SDimitry Andric OS << format(ConvChar, Value); 19730b57cec5SDimitry Andric break; 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() { 19780b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF); 19790b57cec5SDimitry Andric Ctx.printUnwindInformation(); 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric namespace { 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printUnwindInfo() { 19850b57cec5SDimitry Andric const ELFFile<ELF32LE> *Obj = ObjF->getELFFile(); 19860b57cec5SDimitry Andric const unsigned Machine = Obj->getHeader()->e_machine; 19870b57cec5SDimitry Andric if (Machine == EM_ARM) { 19880b57cec5SDimitry Andric ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec); 19890b57cec5SDimitry Andric Ctx.PrintUnwindInformation(); 19900b57cec5SDimitry Andric } 19910b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF); 19920b57cec5SDimitry Andric Ctx.printUnwindInformation(); 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric } // end anonymous namespace 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicTable() { 19980b57cec5SDimitry Andric ELFDumperStyle->printDynamic(ObjF->getELFFile()); 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() { 20020b57cec5SDimitry Andric ListScope D(W, "NeededLibraries"); 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric using LibsTy = std::vector<StringRef>; 20050b57cec5SDimitry Andric LibsTy Libs; 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric for (const auto &Entry : dynamic_table()) 20080b57cec5SDimitry Andric if (Entry.d_tag == ELF::DT_NEEDED) { 20090b57cec5SDimitry Andric uint64_t Value = Entry.d_un.d_val; 20100b57cec5SDimitry Andric if (Value < DynamicStringTable.size()) 20110b57cec5SDimitry Andric Libs.push_back(StringRef(DynamicStringTable.data() + Value)); 20120b57cec5SDimitry Andric else 20130b57cec5SDimitry Andric Libs.push_back("<Library name index out of range>"); 20140b57cec5SDimitry Andric } 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric llvm::stable_sort(Libs); 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric for (const auto &L : Libs) 20190b57cec5SDimitry Andric W.startLine() << L << "\n"; 20200b57cec5SDimitry Andric } 20210b57cec5SDimitry Andric 20220b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashTable() { 20230b57cec5SDimitry Andric DictScope D(W, "HashTable"); 20240b57cec5SDimitry Andric if (!HashTable) 20250b57cec5SDimitry Andric return; 20260b57cec5SDimitry Andric W.printNumber("Num Buckets", HashTable->nbucket); 20270b57cec5SDimitry Andric W.printNumber("Num Chains", HashTable->nchain); 20280b57cec5SDimitry Andric W.printList("Buckets", HashTable->buckets()); 20290b57cec5SDimitry Andric W.printList("Chains", HashTable->chains()); 20300b57cec5SDimitry Andric } 20310b57cec5SDimitry Andric 20320b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printGnuHashTable() { 20330b57cec5SDimitry Andric DictScope D(W, "GnuHashTable"); 20340b57cec5SDimitry Andric if (!GnuHashTable) 20350b57cec5SDimitry Andric return; 20360b57cec5SDimitry Andric W.printNumber("Num Buckets", GnuHashTable->nbuckets); 20370b57cec5SDimitry Andric W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); 20380b57cec5SDimitry Andric W.printNumber("Num Mask Words", GnuHashTable->maskwords); 20390b57cec5SDimitry Andric W.printNumber("Shift Count", GnuHashTable->shift2); 20400b57cec5SDimitry Andric W.printHexList("Bloom Filter", GnuHashTable->filter()); 20410b57cec5SDimitry Andric W.printList("Buckets", GnuHashTable->buckets()); 20420b57cec5SDimitry Andric Elf_Sym_Range Syms = dynamic_symbols(); 20430b57cec5SDimitry Andric unsigned NumSyms = std::distance(Syms.begin(), Syms.end()); 20440b57cec5SDimitry Andric if (!NumSyms) 20450b57cec5SDimitry Andric reportError("No dynamic symbol section"); 20460b57cec5SDimitry Andric W.printHexList("Values", GnuHashTable->values(NumSyms)); 20470b57cec5SDimitry Andric } 20480b57cec5SDimitry Andric 20490b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { 20500b57cec5SDimitry Andric W.printString("LoadName", SOName); 20510b57cec5SDimitry Andric } 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printAttributes() { 20540b57cec5SDimitry Andric W.startLine() << "Attributes not implemented.\n"; 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric 20570b57cec5SDimitry Andric namespace { 20580b57cec5SDimitry Andric 20590b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printAttributes() { 20600b57cec5SDimitry Andric const ELFFile<ELF32LE> *Obj = ObjF->getELFFile(); 20610b57cec5SDimitry Andric if (Obj->getHeader()->e_machine != EM_ARM) { 20620b57cec5SDimitry Andric W.startLine() << "Attributes not implemented.\n"; 20630b57cec5SDimitry Andric return; 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric DictScope BA(W, "BuildAttributes"); 20670b57cec5SDimitry Andric for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 20680b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) 20690b57cec5SDimitry Andric continue; 20700b57cec5SDimitry Andric 20710b57cec5SDimitry Andric ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec)); 20720b57cec5SDimitry Andric if (Contents[0] != ARMBuildAttrs::Format_Version) { 20730b57cec5SDimitry Andric errs() << "unrecognised FormatVersion: 0x" 20740b57cec5SDimitry Andric << Twine::utohexstr(Contents[0]) << '\n'; 20750b57cec5SDimitry Andric continue; 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric W.printHex("FormatVersion", Contents[0]); 20790b57cec5SDimitry Andric if (Contents.size() == 1) 20800b57cec5SDimitry Andric continue; 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric ARMAttributeParser(&W).Parse(Contents, true); 20830b57cec5SDimitry Andric } 20840b57cec5SDimitry Andric } 20850b57cec5SDimitry Andric 20860b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser { 20870b57cec5SDimitry Andric public: 20880b57cec5SDimitry Andric TYPEDEF_ELF_TYPES(ELFT) 20890b57cec5SDimitry Andric using Entry = typename ELFO::Elf_Addr; 20900b57cec5SDimitry Andric using Entries = ArrayRef<Entry>; 20910b57cec5SDimitry Andric 20920b57cec5SDimitry Andric const bool IsStatic; 20930b57cec5SDimitry Andric const ELFO * const Obj; 20940b57cec5SDimitry Andric 20950b57cec5SDimitry Andric MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric bool hasGot() const { return !GotEntries.empty(); } 20980b57cec5SDimitry Andric bool hasPlt() const { return !PltEntries.empty(); } 20990b57cec5SDimitry Andric 21000b57cec5SDimitry Andric uint64_t getGp() const; 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric const Entry *getGotLazyResolver() const; 21030b57cec5SDimitry Andric const Entry *getGotModulePointer() const; 21040b57cec5SDimitry Andric const Entry *getPltLazyResolver() const; 21050b57cec5SDimitry Andric const Entry *getPltModulePointer() const; 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric Entries getLocalEntries() const; 21080b57cec5SDimitry Andric Entries getGlobalEntries() const; 21090b57cec5SDimitry Andric Entries getOtherEntries() const; 21100b57cec5SDimitry Andric Entries getPltEntries() const; 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric uint64_t getGotAddress(const Entry * E) const; 21130b57cec5SDimitry Andric int64_t getGotOffset(const Entry * E) const; 21140b57cec5SDimitry Andric const Elf_Sym *getGotSym(const Entry *E) const; 21150b57cec5SDimitry Andric 21160b57cec5SDimitry Andric uint64_t getPltAddress(const Entry * E) const; 21170b57cec5SDimitry Andric const Elf_Sym *getPltSym(const Entry *E) const; 21180b57cec5SDimitry Andric 21190b57cec5SDimitry Andric StringRef getPltStrTable() const { return PltStrTable; } 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric private: 21220b57cec5SDimitry Andric const Elf_Shdr *GotSec; 21230b57cec5SDimitry Andric size_t LocalNum; 21240b57cec5SDimitry Andric size_t GlobalNum; 21250b57cec5SDimitry Andric 21260b57cec5SDimitry Andric const Elf_Shdr *PltSec; 21270b57cec5SDimitry Andric const Elf_Shdr *PltRelSec; 21280b57cec5SDimitry Andric const Elf_Shdr *PltSymTable; 21290b57cec5SDimitry Andric Elf_Sym_Range GotDynSyms; 21300b57cec5SDimitry Andric StringRef PltStrTable; 21310b57cec5SDimitry Andric 21320b57cec5SDimitry Andric Entries GotEntries; 21330b57cec5SDimitry Andric Entries PltEntries; 21340b57cec5SDimitry Andric }; 21350b57cec5SDimitry Andric 21360b57cec5SDimitry Andric } // end anonymous namespace 21370b57cec5SDimitry Andric 21380b57cec5SDimitry Andric template <class ELFT> 21390b57cec5SDimitry Andric MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, 21400b57cec5SDimitry Andric Elf_Sym_Range DynSyms) 21410b57cec5SDimitry Andric : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0), 21420b57cec5SDimitry Andric GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) { 21430b57cec5SDimitry Andric // See "Global Offset Table" in Chapter 5 in the following document 21440b57cec5SDimitry Andric // for detailed GOT description. 21450b57cec5SDimitry Andric // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf 21460b57cec5SDimitry Andric 21470b57cec5SDimitry Andric // Find static GOT secton. 21480b57cec5SDimitry Andric if (IsStatic) { 21490b57cec5SDimitry Andric GotSec = findSectionByName(*Obj, ".got"); 21500b57cec5SDimitry Andric if (!GotSec) 21510b57cec5SDimitry Andric reportError("Cannot find .got section"); 21520b57cec5SDimitry Andric 21530b57cec5SDimitry Andric ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); 21540b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 21550b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 21560b57cec5SDimitry Andric LocalNum = GotEntries.size(); 21570b57cec5SDimitry Andric return; 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric 21600b57cec5SDimitry Andric // Lookup dynamic table tags which define GOT/PLT layouts. 21610b57cec5SDimitry Andric Optional<uint64_t> DtPltGot; 21620b57cec5SDimitry Andric Optional<uint64_t> DtLocalGotNum; 21630b57cec5SDimitry Andric Optional<uint64_t> DtGotSym; 21640b57cec5SDimitry Andric Optional<uint64_t> DtMipsPltGot; 21650b57cec5SDimitry Andric Optional<uint64_t> DtJmpRel; 21660b57cec5SDimitry Andric for (const auto &Entry : DynTable) { 21670b57cec5SDimitry Andric switch (Entry.getTag()) { 21680b57cec5SDimitry Andric case ELF::DT_PLTGOT: 21690b57cec5SDimitry Andric DtPltGot = Entry.getVal(); 21700b57cec5SDimitry Andric break; 21710b57cec5SDimitry Andric case ELF::DT_MIPS_LOCAL_GOTNO: 21720b57cec5SDimitry Andric DtLocalGotNum = Entry.getVal(); 21730b57cec5SDimitry Andric break; 21740b57cec5SDimitry Andric case ELF::DT_MIPS_GOTSYM: 21750b57cec5SDimitry Andric DtGotSym = Entry.getVal(); 21760b57cec5SDimitry Andric break; 21770b57cec5SDimitry Andric case ELF::DT_MIPS_PLTGOT: 21780b57cec5SDimitry Andric DtMipsPltGot = Entry.getVal(); 21790b57cec5SDimitry Andric break; 21800b57cec5SDimitry Andric case ELF::DT_JMPREL: 21810b57cec5SDimitry Andric DtJmpRel = Entry.getVal(); 21820b57cec5SDimitry Andric break; 21830b57cec5SDimitry Andric } 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric // Find dynamic GOT section. 21870b57cec5SDimitry Andric if (DtPltGot || DtLocalGotNum || DtGotSym) { 21880b57cec5SDimitry Andric if (!DtPltGot) 21890b57cec5SDimitry Andric report_fatal_error("Cannot find PLTGOT dynamic table tag."); 21900b57cec5SDimitry Andric if (!DtLocalGotNum) 21910b57cec5SDimitry Andric report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag."); 21920b57cec5SDimitry Andric if (!DtGotSym) 21930b57cec5SDimitry Andric report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag."); 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric size_t DynSymTotal = DynSyms.size(); 21960b57cec5SDimitry Andric if (*DtGotSym > DynSymTotal) 21970b57cec5SDimitry Andric reportError("MIPS_GOTSYM exceeds a number of dynamic symbols"); 21980b57cec5SDimitry Andric 21990b57cec5SDimitry Andric GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot); 22000b57cec5SDimitry Andric if (!GotSec) 22010b57cec5SDimitry Andric reportError("There is no not empty GOT section at 0x" + 22020b57cec5SDimitry Andric Twine::utohexstr(*DtPltGot)); 22030b57cec5SDimitry Andric 22040b57cec5SDimitry Andric LocalNum = *DtLocalGotNum; 22050b57cec5SDimitry Andric GlobalNum = DynSymTotal - *DtGotSym; 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); 22080b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 22090b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 22100b57cec5SDimitry Andric GotDynSyms = DynSyms.drop_front(*DtGotSym); 22110b57cec5SDimitry Andric } 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric // Find PLT section. 22140b57cec5SDimitry Andric if (DtMipsPltGot || DtJmpRel) { 22150b57cec5SDimitry Andric if (!DtMipsPltGot) 22160b57cec5SDimitry Andric report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag."); 22170b57cec5SDimitry Andric if (!DtJmpRel) 22180b57cec5SDimitry Andric report_fatal_error("Cannot find JMPREL dynamic table tag."); 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); 22210b57cec5SDimitry Andric if (!PltSec) 22220b57cec5SDimitry Andric report_fatal_error("There is no not empty PLTGOT section at 0x " + 22230b57cec5SDimitry Andric Twine::utohexstr(*DtMipsPltGot)); 22240b57cec5SDimitry Andric 22250b57cec5SDimitry Andric PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel); 22260b57cec5SDimitry Andric if (!PltRelSec) 22270b57cec5SDimitry Andric report_fatal_error("There is no not empty RELPLT section at 0x" + 22280b57cec5SDimitry Andric Twine::utohexstr(*DtJmpRel)); 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric ArrayRef<uint8_t> PltContent = 22310b57cec5SDimitry Andric unwrapOrError(Obj->getSectionContents(PltSec)); 22320b57cec5SDimitry Andric PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()), 22330b57cec5SDimitry Andric PltContent.size() / sizeof(Entry)); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link)); 22360b57cec5SDimitry Andric PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable)); 22370b57cec5SDimitry Andric } 22380b57cec5SDimitry Andric } 22390b57cec5SDimitry Andric 22400b57cec5SDimitry Andric template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { 22410b57cec5SDimitry Andric return GotSec->sh_addr + 0x7ff0; 22420b57cec5SDimitry Andric } 22430b57cec5SDimitry Andric 22440b57cec5SDimitry Andric template <class ELFT> 22450b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 22460b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotLazyResolver() const { 22470b57cec5SDimitry Andric return LocalNum > 0 ? &GotEntries[0] : nullptr; 22480b57cec5SDimitry Andric } 22490b57cec5SDimitry Andric 22500b57cec5SDimitry Andric template <class ELFT> 22510b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 22520b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotModulePointer() const { 22530b57cec5SDimitry Andric if (LocalNum < 2) 22540b57cec5SDimitry Andric return nullptr; 22550b57cec5SDimitry Andric const Entry &E = GotEntries[1]; 22560b57cec5SDimitry Andric if ((E >> (sizeof(Entry) * 8 - 1)) == 0) 22570b57cec5SDimitry Andric return nullptr; 22580b57cec5SDimitry Andric return &E; 22590b57cec5SDimitry Andric } 22600b57cec5SDimitry Andric 22610b57cec5SDimitry Andric template <class ELFT> 22620b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 22630b57cec5SDimitry Andric MipsGOTParser<ELFT>::getLocalEntries() const { 22640b57cec5SDimitry Andric size_t Skip = getGotModulePointer() ? 2 : 1; 22650b57cec5SDimitry Andric if (LocalNum - Skip <= 0) 22660b57cec5SDimitry Andric return Entries(); 22670b57cec5SDimitry Andric return GotEntries.slice(Skip, LocalNum - Skip); 22680b57cec5SDimitry Andric } 22690b57cec5SDimitry Andric 22700b57cec5SDimitry Andric template <class ELFT> 22710b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 22720b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGlobalEntries() const { 22730b57cec5SDimitry Andric if (GlobalNum == 0) 22740b57cec5SDimitry Andric return Entries(); 22750b57cec5SDimitry Andric return GotEntries.slice(LocalNum, GlobalNum); 22760b57cec5SDimitry Andric } 22770b57cec5SDimitry Andric 22780b57cec5SDimitry Andric template <class ELFT> 22790b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 22800b57cec5SDimitry Andric MipsGOTParser<ELFT>::getOtherEntries() const { 22810b57cec5SDimitry Andric size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; 22820b57cec5SDimitry Andric if (OtherNum == 0) 22830b57cec5SDimitry Andric return Entries(); 22840b57cec5SDimitry Andric return GotEntries.slice(LocalNum + GlobalNum, OtherNum); 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric 22870b57cec5SDimitry Andric template <class ELFT> 22880b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { 22890b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 22900b57cec5SDimitry Andric return GotSec->sh_addr + Offset; 22910b57cec5SDimitry Andric } 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric template <class ELFT> 22940b57cec5SDimitry Andric int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { 22950b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 22960b57cec5SDimitry Andric return Offset - 0x7ff0; 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric template <class ELFT> 23000b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 23010b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { 23020b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E); 23030b57cec5SDimitry Andric return &GotDynSyms[Offset - LocalNum]; 23040b57cec5SDimitry Andric } 23050b57cec5SDimitry Andric 23060b57cec5SDimitry Andric template <class ELFT> 23070b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 23080b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltLazyResolver() const { 23090b57cec5SDimitry Andric return PltEntries.empty() ? nullptr : &PltEntries[0]; 23100b57cec5SDimitry Andric } 23110b57cec5SDimitry Andric 23120b57cec5SDimitry Andric template <class ELFT> 23130b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 23140b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltModulePointer() const { 23150b57cec5SDimitry Andric return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; 23160b57cec5SDimitry Andric } 23170b57cec5SDimitry Andric 23180b57cec5SDimitry Andric template <class ELFT> 23190b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 23200b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltEntries() const { 23210b57cec5SDimitry Andric if (PltEntries.size() <= 2) 23220b57cec5SDimitry Andric return Entries(); 23230b57cec5SDimitry Andric return PltEntries.slice(2, PltEntries.size() - 2); 23240b57cec5SDimitry Andric } 23250b57cec5SDimitry Andric 23260b57cec5SDimitry Andric template <class ELFT> 23270b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { 23280b57cec5SDimitry Andric int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); 23290b57cec5SDimitry Andric return PltSec->sh_addr + Offset; 23300b57cec5SDimitry Andric } 23310b57cec5SDimitry Andric 23320b57cec5SDimitry Andric template <class ELFT> 23330b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 23340b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { 23350b57cec5SDimitry Andric int64_t Offset = std::distance(getPltEntries().data(), E); 23360b57cec5SDimitry Andric if (PltRelSec->sh_type == ELF::SHT_REL) { 23370b57cec5SDimitry Andric Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec)); 23380b57cec5SDimitry Andric return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); 23390b57cec5SDimitry Andric } else { 23400b57cec5SDimitry Andric Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec)); 23410b57cec5SDimitry Andric return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric } 23440b57cec5SDimitry Andric 23450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { 23460b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 23470b57cec5SDimitry Andric if (Obj->getHeader()->e_machine != EM_MIPS) 23480b57cec5SDimitry Andric reportError("MIPS PLT GOT is available for MIPS targets only"); 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols()); 23510b57cec5SDimitry Andric if (Parser.hasGot()) 23520b57cec5SDimitry Andric ELFDumperStyle->printMipsGOT(Parser); 23530b57cec5SDimitry Andric if (Parser.hasPlt()) 23540b57cec5SDimitry Andric ELFDumperStyle->printMipsPLT(Parser); 23550b57cec5SDimitry Andric } 23560b57cec5SDimitry Andric 23570b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsISAExtType[] = { 23580b57cec5SDimitry Andric {"None", Mips::AFL_EXT_NONE}, 23590b57cec5SDimitry Andric {"Broadcom SB-1", Mips::AFL_EXT_SB1}, 23600b57cec5SDimitry Andric {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, 23610b57cec5SDimitry Andric {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, 23620b57cec5SDimitry Andric {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, 23630b57cec5SDimitry Andric {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, 23640b57cec5SDimitry Andric {"LSI R4010", Mips::AFL_EXT_4010}, 23650b57cec5SDimitry Andric {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, 23660b57cec5SDimitry Andric {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, 23670b57cec5SDimitry Andric {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, 23680b57cec5SDimitry Andric {"MIPS R4650", Mips::AFL_EXT_4650}, 23690b57cec5SDimitry Andric {"MIPS R5900", Mips::AFL_EXT_5900}, 23700b57cec5SDimitry Andric {"MIPS R10000", Mips::AFL_EXT_10000}, 23710b57cec5SDimitry Andric {"NEC VR4100", Mips::AFL_EXT_4100}, 23720b57cec5SDimitry Andric {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, 23730b57cec5SDimitry Andric {"NEC VR4120", Mips::AFL_EXT_4120}, 23740b57cec5SDimitry Andric {"NEC VR5400", Mips::AFL_EXT_5400}, 23750b57cec5SDimitry Andric {"NEC VR5500", Mips::AFL_EXT_5500}, 23760b57cec5SDimitry Andric {"RMI Xlr", Mips::AFL_EXT_XLR}, 23770b57cec5SDimitry Andric {"Toshiba R3900", Mips::AFL_EXT_3900} 23780b57cec5SDimitry Andric }; 23790b57cec5SDimitry Andric 23800b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsASEFlags[] = { 23810b57cec5SDimitry Andric {"DSP", Mips::AFL_ASE_DSP}, 23820b57cec5SDimitry Andric {"DSPR2", Mips::AFL_ASE_DSPR2}, 23830b57cec5SDimitry Andric {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, 23840b57cec5SDimitry Andric {"MCU", Mips::AFL_ASE_MCU}, 23850b57cec5SDimitry Andric {"MDMX", Mips::AFL_ASE_MDMX}, 23860b57cec5SDimitry Andric {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, 23870b57cec5SDimitry Andric {"MT", Mips::AFL_ASE_MT}, 23880b57cec5SDimitry Andric {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, 23890b57cec5SDimitry Andric {"VZ", Mips::AFL_ASE_VIRT}, 23900b57cec5SDimitry Andric {"MSA", Mips::AFL_ASE_MSA}, 23910b57cec5SDimitry Andric {"MIPS16", Mips::AFL_ASE_MIPS16}, 23920b57cec5SDimitry Andric {"microMIPS", Mips::AFL_ASE_MICROMIPS}, 23930b57cec5SDimitry Andric {"XPA", Mips::AFL_ASE_XPA}, 23940b57cec5SDimitry Andric {"CRC", Mips::AFL_ASE_CRC}, 23950b57cec5SDimitry Andric {"GINV", Mips::AFL_ASE_GINV}, 23960b57cec5SDimitry Andric }; 23970b57cec5SDimitry Andric 23980b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFpABIType[] = { 23990b57cec5SDimitry Andric {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, 24000b57cec5SDimitry Andric {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, 24010b57cec5SDimitry Andric {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, 24020b57cec5SDimitry Andric {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, 24030b57cec5SDimitry Andric {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", 24040b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, 24050b57cec5SDimitry Andric {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, 24060b57cec5SDimitry Andric {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, 24070b57cec5SDimitry Andric {"Hard float compat (32-bit CPU, 64-bit FPU)", 24080b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_64A} 24090b57cec5SDimitry Andric }; 24100b57cec5SDimitry Andric 24110b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFlags1[] { 24120b57cec5SDimitry Andric {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, 24130b57cec5SDimitry Andric }; 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric static int getMipsRegisterSize(uint8_t Flag) { 24160b57cec5SDimitry Andric switch (Flag) { 24170b57cec5SDimitry Andric case Mips::AFL_REG_NONE: 24180b57cec5SDimitry Andric return 0; 24190b57cec5SDimitry Andric case Mips::AFL_REG_32: 24200b57cec5SDimitry Andric return 32; 24210b57cec5SDimitry Andric case Mips::AFL_REG_64: 24220b57cec5SDimitry Andric return 64; 24230b57cec5SDimitry Andric case Mips::AFL_REG_128: 24240b57cec5SDimitry Andric return 128; 24250b57cec5SDimitry Andric default: 24260b57cec5SDimitry Andric return -1; 24270b57cec5SDimitry Andric } 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric 24300b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() { 24310b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 24320b57cec5SDimitry Andric const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags"); 24330b57cec5SDimitry Andric if (!Shdr) { 24340b57cec5SDimitry Andric W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; 24350b57cec5SDimitry Andric return; 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); 24380b57cec5SDimitry Andric if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) { 24390b57cec5SDimitry Andric W.startLine() << "The .MIPS.abiflags section has a wrong size.\n"; 24400b57cec5SDimitry Andric return; 24410b57cec5SDimitry Andric } 24420b57cec5SDimitry Andric 24430b57cec5SDimitry Andric auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data()); 24440b57cec5SDimitry Andric 24450b57cec5SDimitry Andric raw_ostream &OS = W.getOStream(); 24460b57cec5SDimitry Andric DictScope GS(W, "MIPS ABI Flags"); 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric W.printNumber("Version", Flags->version); 24490b57cec5SDimitry Andric W.startLine() << "ISA: "; 24500b57cec5SDimitry Andric if (Flags->isa_rev <= 1) 24510b57cec5SDimitry Andric OS << format("MIPS%u", Flags->isa_level); 24520b57cec5SDimitry Andric else 24530b57cec5SDimitry Andric OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); 24540b57cec5SDimitry Andric OS << "\n"; 24550b57cec5SDimitry Andric W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)); 24560b57cec5SDimitry Andric W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags)); 24570b57cec5SDimitry Andric W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)); 24580b57cec5SDimitry Andric W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); 24590b57cec5SDimitry Andric W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); 24600b57cec5SDimitry Andric W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); 24610b57cec5SDimitry Andric W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1)); 24620b57cec5SDimitry Andric W.printHex("Flags 2", Flags->flags2); 24630b57cec5SDimitry Andric } 24640b57cec5SDimitry Andric 24650b57cec5SDimitry Andric template <class ELFT> 24660b57cec5SDimitry Andric static void printMipsReginfoData(ScopedPrinter &W, 24670b57cec5SDimitry Andric const Elf_Mips_RegInfo<ELFT> &Reginfo) { 24680b57cec5SDimitry Andric W.printHex("GP", Reginfo.ri_gp_value); 24690b57cec5SDimitry Andric W.printHex("General Mask", Reginfo.ri_gprmask); 24700b57cec5SDimitry Andric W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]); 24710b57cec5SDimitry Andric W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]); 24720b57cec5SDimitry Andric W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]); 24730b57cec5SDimitry Andric W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]); 24740b57cec5SDimitry Andric } 24750b57cec5SDimitry Andric 24760b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { 24770b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 24780b57cec5SDimitry Andric const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo"); 24790b57cec5SDimitry Andric if (!Shdr) { 24800b57cec5SDimitry Andric W.startLine() << "There is no .reginfo section in the file.\n"; 24810b57cec5SDimitry Andric return; 24820b57cec5SDimitry Andric } 24830b57cec5SDimitry Andric ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); 24840b57cec5SDimitry Andric if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) { 24850b57cec5SDimitry Andric W.startLine() << "The .reginfo section has a wrong size.\n"; 24860b57cec5SDimitry Andric return; 24870b57cec5SDimitry Andric } 24880b57cec5SDimitry Andric 24890b57cec5SDimitry Andric DictScope GS(W, "MIPS RegInfo"); 24900b57cec5SDimitry Andric auto *Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Sec.data()); 24910b57cec5SDimitry Andric printMipsReginfoData(W, *Reginfo); 24920b57cec5SDimitry Andric } 24930b57cec5SDimitry Andric 24940b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { 24950b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 24960b57cec5SDimitry Andric const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.options"); 24970b57cec5SDimitry Andric if (!Shdr) { 24980b57cec5SDimitry Andric W.startLine() << "There is no .MIPS.options section in the file.\n"; 24990b57cec5SDimitry Andric return; 25000b57cec5SDimitry Andric } 25010b57cec5SDimitry Andric 25020b57cec5SDimitry Andric DictScope GS(W, "MIPS Options"); 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); 25050b57cec5SDimitry Andric while (!Sec.empty()) { 25060b57cec5SDimitry Andric if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) { 25070b57cec5SDimitry Andric W.startLine() << "The .MIPS.options section has a wrong size.\n"; 25080b57cec5SDimitry Andric return; 25090b57cec5SDimitry Andric } 25100b57cec5SDimitry Andric auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(Sec.data()); 25110b57cec5SDimitry Andric DictScope GS(W, getElfMipsOptionsOdkType(O->kind)); 25120b57cec5SDimitry Andric switch (O->kind) { 25130b57cec5SDimitry Andric case ODK_REGINFO: 25140b57cec5SDimitry Andric printMipsReginfoData(W, O->getRegInfo()); 25150b57cec5SDimitry Andric break; 25160b57cec5SDimitry Andric default: 25170b57cec5SDimitry Andric W.startLine() << "Unsupported MIPS options tag.\n"; 25180b57cec5SDimitry Andric break; 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric Sec = Sec.slice(O->size); 25210b57cec5SDimitry Andric } 25220b57cec5SDimitry Andric } 25230b57cec5SDimitry Andric 25240b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { 25250b57cec5SDimitry Andric const ELFFile<ELFT> *Obj = ObjF->getELFFile(); 25260b57cec5SDimitry Andric const Elf_Shdr *StackMapSection = nullptr; 25270b57cec5SDimitry Andric for (const auto &Sec : unwrapOrError(Obj->sections())) { 25280b57cec5SDimitry Andric StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); 25290b57cec5SDimitry Andric if (Name == ".llvm_stackmaps") { 25300b57cec5SDimitry Andric StackMapSection = &Sec; 25310b57cec5SDimitry Andric break; 25320b57cec5SDimitry Andric } 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric 25350b57cec5SDimitry Andric if (!StackMapSection) 25360b57cec5SDimitry Andric return; 25370b57cec5SDimitry Andric 25380b57cec5SDimitry Andric ArrayRef<uint8_t> StackMapContentsArray = 25390b57cec5SDimitry Andric unwrapOrError(Obj->getSectionContents(StackMapSection)); 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric prettyPrintStackMap( 25420b57cec5SDimitry Andric W, StackMapParser<ELFT::TargetEndianness>(StackMapContentsArray)); 25430b57cec5SDimitry Andric } 25440b57cec5SDimitry Andric 25450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printGroupSections() { 25460b57cec5SDimitry Andric ELFDumperStyle->printGroupSections(ObjF->getELFFile()); 25470b57cec5SDimitry Andric } 25480b57cec5SDimitry Andric 25490b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printAddrsig() { 25500b57cec5SDimitry Andric ELFDumperStyle->printAddrsig(ObjF->getELFFile()); 25510b57cec5SDimitry Andric } 25520b57cec5SDimitry Andric 25530b57cec5SDimitry Andric static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, 25540b57cec5SDimitry Andric StringRef Str2) { 25550b57cec5SDimitry Andric OS.PadToColumn(2u); 25560b57cec5SDimitry Andric OS << Str1; 25570b57cec5SDimitry Andric OS.PadToColumn(37u); 25580b57cec5SDimitry Andric OS << Str2 << "\n"; 25590b57cec5SDimitry Andric OS.flush(); 25600b57cec5SDimitry Andric } 25610b57cec5SDimitry Andric 25620b57cec5SDimitry Andric template <class ELFT> 25630b57cec5SDimitry Andric static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) { 25640b57cec5SDimitry Andric const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); 25650b57cec5SDimitry Andric if (ElfHeader->e_shnum != 0) 25660b57cec5SDimitry Andric return to_string(ElfHeader->e_shnum); 25670b57cec5SDimitry Andric 25680b57cec5SDimitry Andric ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); 25690b57cec5SDimitry Andric if (Arr.empty()) 25700b57cec5SDimitry Andric return "0"; 25710b57cec5SDimitry Andric return "0 (" + to_string(Arr[0].sh_size) + ")"; 25720b57cec5SDimitry Andric } 25730b57cec5SDimitry Andric 25740b57cec5SDimitry Andric template <class ELFT> 25750b57cec5SDimitry Andric static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) { 25760b57cec5SDimitry Andric const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); 25770b57cec5SDimitry Andric if (ElfHeader->e_shstrndx != SHN_XINDEX) 25780b57cec5SDimitry Andric return to_string(ElfHeader->e_shstrndx); 25790b57cec5SDimitry Andric 25800b57cec5SDimitry Andric ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); 25810b57cec5SDimitry Andric if (Arr.empty()) 25820b57cec5SDimitry Andric return "65535 (corrupt: out of range)"; 25830b57cec5SDimitry Andric return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) + 25840b57cec5SDimitry Andric ")"; 25850b57cec5SDimitry Andric } 25860b57cec5SDimitry Andric 25870b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { 25880b57cec5SDimitry Andric const Elf_Ehdr *e = Obj->getHeader(); 25890b57cec5SDimitry Andric OS << "ELF Header:\n"; 25900b57cec5SDimitry Andric OS << " Magic: "; 25910b57cec5SDimitry Andric std::string Str; 25920b57cec5SDimitry Andric for (int i = 0; i < ELF::EI_NIDENT; i++) 25930b57cec5SDimitry Andric OS << format(" %02x", static_cast<int>(e->e_ident[i])); 25940b57cec5SDimitry Andric OS << "\n"; 25950b57cec5SDimitry Andric Str = printEnum(e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); 25960b57cec5SDimitry Andric printFields(OS, "Class:", Str); 25970b57cec5SDimitry Andric Str = printEnum(e->e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding)); 25980b57cec5SDimitry Andric printFields(OS, "Data:", Str); 25990b57cec5SDimitry Andric OS.PadToColumn(2u); 26000b57cec5SDimitry Andric OS << "Version:"; 26010b57cec5SDimitry Andric OS.PadToColumn(37u); 26020b57cec5SDimitry Andric OS << to_hexString(e->e_ident[ELF::EI_VERSION]); 26030b57cec5SDimitry Andric if (e->e_version == ELF::EV_CURRENT) 26040b57cec5SDimitry Andric OS << " (current)"; 26050b57cec5SDimitry Andric OS << "\n"; 26060b57cec5SDimitry Andric Str = printEnum(e->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI)); 26070b57cec5SDimitry Andric printFields(OS, "OS/ABI:", Str); 26080b57cec5SDimitry Andric Str = "0x" + to_hexString(e->e_ident[ELF::EI_ABIVERSION]); 26090b57cec5SDimitry Andric printFields(OS, "ABI Version:", Str); 26100b57cec5SDimitry Andric Str = printEnum(e->e_type, makeArrayRef(ElfObjectFileType)); 26110b57cec5SDimitry Andric printFields(OS, "Type:", Str); 26120b57cec5SDimitry Andric Str = printEnum(e->e_machine, makeArrayRef(ElfMachineType)); 26130b57cec5SDimitry Andric printFields(OS, "Machine:", Str); 26140b57cec5SDimitry Andric Str = "0x" + to_hexString(e->e_version); 26150b57cec5SDimitry Andric printFields(OS, "Version:", Str); 26160b57cec5SDimitry Andric Str = "0x" + to_hexString(e->e_entry); 26170b57cec5SDimitry Andric printFields(OS, "Entry point address:", Str); 26180b57cec5SDimitry Andric Str = to_string(e->e_phoff) + " (bytes into file)"; 26190b57cec5SDimitry Andric printFields(OS, "Start of program headers:", Str); 26200b57cec5SDimitry Andric Str = to_string(e->e_shoff) + " (bytes into file)"; 26210b57cec5SDimitry Andric printFields(OS, "Start of section headers:", Str); 26220b57cec5SDimitry Andric std::string ElfFlags; 26230b57cec5SDimitry Andric if (e->e_machine == EM_MIPS) 26240b57cec5SDimitry Andric ElfFlags = 26250b57cec5SDimitry Andric printFlags(e->e_flags, makeArrayRef(ElfHeaderMipsFlags), 26260b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), 26270b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_MACH)); 26280b57cec5SDimitry Andric else if (e->e_machine == EM_RISCV) 26290b57cec5SDimitry Andric ElfFlags = printFlags(e->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); 26300b57cec5SDimitry Andric Str = "0x" + to_hexString(e->e_flags); 26310b57cec5SDimitry Andric if (!ElfFlags.empty()) 26320b57cec5SDimitry Andric Str = Str + ", " + ElfFlags; 26330b57cec5SDimitry Andric printFields(OS, "Flags:", Str); 26340b57cec5SDimitry Andric Str = to_string(e->e_ehsize) + " (bytes)"; 26350b57cec5SDimitry Andric printFields(OS, "Size of this header:", Str); 26360b57cec5SDimitry Andric Str = to_string(e->e_phentsize) + " (bytes)"; 26370b57cec5SDimitry Andric printFields(OS, "Size of program headers:", Str); 26380b57cec5SDimitry Andric Str = to_string(e->e_phnum); 26390b57cec5SDimitry Andric printFields(OS, "Number of program headers:", Str); 26400b57cec5SDimitry Andric Str = to_string(e->e_shentsize) + " (bytes)"; 26410b57cec5SDimitry Andric printFields(OS, "Size of section headers:", Str); 26420b57cec5SDimitry Andric Str = getSectionHeadersNumString(Obj); 26430b57cec5SDimitry Andric printFields(OS, "Number of section headers:", Str); 26440b57cec5SDimitry Andric Str = getSectionHeaderTableIndexString(Obj); 26450b57cec5SDimitry Andric printFields(OS, "Section header string table index:", Str); 26460b57cec5SDimitry Andric } 26470b57cec5SDimitry Andric 26480b57cec5SDimitry Andric namespace { 26490b57cec5SDimitry Andric struct GroupMember { 26500b57cec5SDimitry Andric StringRef Name; 26510b57cec5SDimitry Andric uint64_t Index; 26520b57cec5SDimitry Andric }; 26530b57cec5SDimitry Andric 26540b57cec5SDimitry Andric struct GroupSection { 26550b57cec5SDimitry Andric StringRef Name; 26560b57cec5SDimitry Andric std::string Signature; 26570b57cec5SDimitry Andric uint64_t ShName; 26580b57cec5SDimitry Andric uint64_t Index; 26590b57cec5SDimitry Andric uint32_t Link; 26600b57cec5SDimitry Andric uint32_t Info; 26610b57cec5SDimitry Andric uint32_t Type; 26620b57cec5SDimitry Andric std::vector<GroupMember> Members; 26630b57cec5SDimitry Andric }; 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric template <class ELFT> 26660b57cec5SDimitry Andric std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) { 26670b57cec5SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 26680b57cec5SDimitry Andric using Elf_Sym = typename ELFT::Sym; 26690b57cec5SDimitry Andric using Elf_Word = typename ELFT::Word; 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric std::vector<GroupSection> Ret; 26720b57cec5SDimitry Andric uint64_t I = 0; 26730b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 26740b57cec5SDimitry Andric ++I; 26750b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_GROUP) 26760b57cec5SDimitry Andric continue; 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); 26790b57cec5SDimitry Andric StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); 26800b57cec5SDimitry Andric const Elf_Sym *Sym = 26810b57cec5SDimitry Andric unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info)); 26820b57cec5SDimitry Andric auto Data = 26830b57cec5SDimitry Andric unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec)); 26840b57cec5SDimitry Andric 26850b57cec5SDimitry Andric StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); 26860b57cec5SDimitry Andric StringRef Signature = StrTable.data() + Sym->st_name; 26870b57cec5SDimitry Andric Ret.push_back({Name, 26880b57cec5SDimitry Andric maybeDemangle(Signature), 26890b57cec5SDimitry Andric Sec.sh_name, 26900b57cec5SDimitry Andric I - 1, 26910b57cec5SDimitry Andric Sec.sh_link, 26920b57cec5SDimitry Andric Sec.sh_info, 26930b57cec5SDimitry Andric Data[0], 26940b57cec5SDimitry Andric {}}); 26950b57cec5SDimitry Andric 26960b57cec5SDimitry Andric std::vector<GroupMember> &GM = Ret.back().Members; 26970b57cec5SDimitry Andric for (uint32_t Ndx : Data.slice(1)) { 26980b57cec5SDimitry Andric auto Sec = unwrapOrError(Obj->getSection(Ndx)); 26990b57cec5SDimitry Andric const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); 27000b57cec5SDimitry Andric GM.push_back({Name, Ndx}); 27010b57cec5SDimitry Andric } 27020b57cec5SDimitry Andric } 27030b57cec5SDimitry Andric return Ret; 27040b57cec5SDimitry Andric } 27050b57cec5SDimitry Andric 27060b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> 27070b57cec5SDimitry Andric mapSectionsToGroups(ArrayRef<GroupSection> Groups) { 27080b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Ret; 27090b57cec5SDimitry Andric for (const GroupSection &G : Groups) 27100b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) 27110b57cec5SDimitry Andric Ret.insert({GM.Index, &G}); 27120b57cec5SDimitry Andric return Ret; 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric 27150b57cec5SDimitry Andric } // namespace 27160b57cec5SDimitry Andric 27170b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) { 27180b57cec5SDimitry Andric std::vector<GroupSection> V = getGroups<ELFT>(Obj); 27190b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 27200b57cec5SDimitry Andric for (const GroupSection &G : V) { 27210b57cec5SDimitry Andric OS << "\n" 27220b57cec5SDimitry Andric << getGroupType(G.Type) << " group section [" 27230b57cec5SDimitry Andric << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature 27240b57cec5SDimitry Andric << "] contains " << G.Members.size() << " sections:\n" 27250b57cec5SDimitry Andric << " [Index] Name\n"; 27260b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 27270b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 27280b57cec5SDimitry Andric if (MainGroup != &G) { 27290b57cec5SDimitry Andric OS.flush(); 27300b57cec5SDimitry Andric errs() << "Error: section [" << format_decimal(GM.Index, 5) 27310b57cec5SDimitry Andric << "] in group section [" << format_decimal(G.Index, 5) 27320b57cec5SDimitry Andric << "] already in group section [" 27330b57cec5SDimitry Andric << format_decimal(MainGroup->Index, 5) << "]"; 27340b57cec5SDimitry Andric errs().flush(); 27350b57cec5SDimitry Andric continue; 27360b57cec5SDimitry Andric } 27370b57cec5SDimitry Andric OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n"; 27380b57cec5SDimitry Andric } 27390b57cec5SDimitry Andric } 27400b57cec5SDimitry Andric 27410b57cec5SDimitry Andric if (V.empty()) 27420b57cec5SDimitry Andric OS << "There are no section groups in this file.\n"; 27430b57cec5SDimitry Andric } 27440b57cec5SDimitry Andric 27450b57cec5SDimitry Andric template <class ELFT> 27460b57cec5SDimitry Andric void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, 27470b57cec5SDimitry Andric const Elf_Rela &R, bool IsRela) { 27480b57cec5SDimitry Andric const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab)); 27490b57cec5SDimitry Andric std::string TargetName; 27500b57cec5SDimitry Andric if (Sym && Sym->getType() == ELF::STT_SECTION) { 27510b57cec5SDimitry Andric const Elf_Shdr *Sec = unwrapOrError( 27520b57cec5SDimitry Andric Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); 27530b57cec5SDimitry Andric TargetName = unwrapOrError(Obj->getSectionName(Sec)); 27540b57cec5SDimitry Andric } else if (Sym) { 27550b57cec5SDimitry Andric StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); 27560b57cec5SDimitry Andric TargetName = this->dumper()->getFullSymbolName( 27570b57cec5SDimitry Andric Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */); 27580b57cec5SDimitry Andric } 27590b57cec5SDimitry Andric printRelocation(Obj, Sym, TargetName, R, IsRela); 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 27620b57cec5SDimitry Andric template <class ELFT> 27630b57cec5SDimitry Andric void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Sym *Sym, 27640b57cec5SDimitry Andric StringRef SymbolName, const Elf_Rela &R, 27650b57cec5SDimitry Andric bool IsRela) { 27660b57cec5SDimitry Andric // First two fields are bit width dependent. The rest of them are fixed width. 27670b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 27680b57cec5SDimitry Andric Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; 27690b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 16 : 8; 27700b57cec5SDimitry Andric 27710b57cec5SDimitry Andric Fields[0].Str = to_string(format_hex_no_prefix(R.r_offset, Width)); 27720b57cec5SDimitry Andric Fields[1].Str = to_string(format_hex_no_prefix(R.r_info, Width)); 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric SmallString<32> RelocName; 27750b57cec5SDimitry Andric Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); 27760b57cec5SDimitry Andric Fields[2].Str = RelocName.c_str(); 27770b57cec5SDimitry Andric 27780b57cec5SDimitry Andric if (Sym && (!SymbolName.empty() || Sym->getValue() != 0)) 27790b57cec5SDimitry Andric Fields[3].Str = to_string(format_hex_no_prefix(Sym->getValue(), Width)); 27800b57cec5SDimitry Andric 27810b57cec5SDimitry Andric Fields[4].Str = SymbolName; 27820b57cec5SDimitry Andric for (const Field &F : Fields) 27830b57cec5SDimitry Andric printField(F); 27840b57cec5SDimitry Andric 27850b57cec5SDimitry Andric std::string Addend; 27860b57cec5SDimitry Andric if (IsRela) { 27870b57cec5SDimitry Andric int64_t RelAddend = R.r_addend; 27880b57cec5SDimitry Andric if (!SymbolName.empty()) { 27890b57cec5SDimitry Andric if (R.r_addend < 0) { 27900b57cec5SDimitry Andric Addend = " - "; 27910b57cec5SDimitry Andric RelAddend = std::abs(RelAddend); 27920b57cec5SDimitry Andric } else 27930b57cec5SDimitry Andric Addend = " + "; 27940b57cec5SDimitry Andric } 27950b57cec5SDimitry Andric 27960b57cec5SDimitry Andric Addend += to_hexString(RelAddend, false); 27970b57cec5SDimitry Andric } 27980b57cec5SDimitry Andric OS << Addend << "\n"; 27990b57cec5SDimitry Andric } 28000b57cec5SDimitry Andric 28010b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) { 28020b57cec5SDimitry Andric bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; 28030b57cec5SDimitry Andric bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; 28040b57cec5SDimitry Andric if (ELFT::Is64Bits) 28050b57cec5SDimitry Andric OS << " "; 28060b57cec5SDimitry Andric else 28070b57cec5SDimitry Andric OS << " "; 28080b57cec5SDimitry Andric if (IsRelr && opts::RawRelr) 28090b57cec5SDimitry Andric OS << "Data "; 28100b57cec5SDimitry Andric else 28110b57cec5SDimitry Andric OS << "Offset"; 28120b57cec5SDimitry Andric if (ELFT::Is64Bits) 28130b57cec5SDimitry Andric OS << " Info Type" 28140b57cec5SDimitry Andric << " Symbol's Value Symbol's Name"; 28150b57cec5SDimitry Andric else 28160b57cec5SDimitry Andric OS << " Info Type Sym. Value Symbol's Name"; 28170b57cec5SDimitry Andric if (IsRela) 28180b57cec5SDimitry Andric OS << " + Addend"; 28190b57cec5SDimitry Andric OS << "\n"; 28200b57cec5SDimitry Andric } 28210b57cec5SDimitry Andric 28220b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { 28230b57cec5SDimitry Andric bool HasRelocSections = false; 28240b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 28250b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && 28260b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && 28270b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_ANDROID_RELA && 28280b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_ANDROID_RELR) 28290b57cec5SDimitry Andric continue; 28300b57cec5SDimitry Andric HasRelocSections = true; 28310b57cec5SDimitry Andric StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); 28320b57cec5SDimitry Andric unsigned Entries = Sec.getEntityCount(); 28330b57cec5SDimitry Andric std::vector<Elf_Rela> AndroidRelas; 28340b57cec5SDimitry Andric if (Sec.sh_type == ELF::SHT_ANDROID_REL || 28350b57cec5SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELA) { 28360b57cec5SDimitry Andric // Android's packed relocation section needs to be unpacked first 28370b57cec5SDimitry Andric // to get the actual number of entries. 28380b57cec5SDimitry Andric AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); 28390b57cec5SDimitry Andric Entries = AndroidRelas.size(); 28400b57cec5SDimitry Andric } 28410b57cec5SDimitry Andric std::vector<Elf_Rela> RelrRelas; 28420b57cec5SDimitry Andric if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || 28430b57cec5SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELR)) { 28440b57cec5SDimitry Andric // .relr.dyn relative relocation section needs to be unpacked first 28450b57cec5SDimitry Andric // to get the actual number of entries. 28460b57cec5SDimitry Andric Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec)); 28470b57cec5SDimitry Andric RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); 28480b57cec5SDimitry Andric Entries = RelrRelas.size(); 28490b57cec5SDimitry Andric } 28500b57cec5SDimitry Andric uintX_t Offset = Sec.sh_offset; 28510b57cec5SDimitry Andric OS << "\nRelocation section '" << Name << "' at offset 0x" 28520b57cec5SDimitry Andric << to_hexString(Offset, false) << " contains " << Entries 28530b57cec5SDimitry Andric << " entries:\n"; 28540b57cec5SDimitry Andric printRelocHeader(Sec.sh_type); 28550b57cec5SDimitry Andric const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); 28560b57cec5SDimitry Andric switch (Sec.sh_type) { 28570b57cec5SDimitry Andric case ELF::SHT_REL: 28580b57cec5SDimitry Andric for (const auto &R : unwrapOrError(Obj->rels(&Sec))) { 28590b57cec5SDimitry Andric Elf_Rela Rela; 28600b57cec5SDimitry Andric Rela.r_offset = R.r_offset; 28610b57cec5SDimitry Andric Rela.r_info = R.r_info; 28620b57cec5SDimitry Andric Rela.r_addend = 0; 28630b57cec5SDimitry Andric printRelocation(Obj, SymTab, Rela, false); 28640b57cec5SDimitry Andric } 28650b57cec5SDimitry Andric break; 28660b57cec5SDimitry Andric case ELF::SHT_RELA: 28670b57cec5SDimitry Andric for (const auto &R : unwrapOrError(Obj->relas(&Sec))) 28680b57cec5SDimitry Andric printRelocation(Obj, SymTab, R, true); 28690b57cec5SDimitry Andric break; 28700b57cec5SDimitry Andric case ELF::SHT_RELR: 28710b57cec5SDimitry Andric case ELF::SHT_ANDROID_RELR: 28720b57cec5SDimitry Andric if (opts::RawRelr) 28730b57cec5SDimitry Andric for (const auto &R : unwrapOrError(Obj->relrs(&Sec))) 28740b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) 28750b57cec5SDimitry Andric << "\n"; 28760b57cec5SDimitry Andric else 28770b57cec5SDimitry Andric for (const auto &R : RelrRelas) 28780b57cec5SDimitry Andric printRelocation(Obj, SymTab, R, false); 28790b57cec5SDimitry Andric break; 28800b57cec5SDimitry Andric case ELF::SHT_ANDROID_REL: 28810b57cec5SDimitry Andric case ELF::SHT_ANDROID_RELA: 28820b57cec5SDimitry Andric for (const auto &R : AndroidRelas) 28830b57cec5SDimitry Andric printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA); 28840b57cec5SDimitry Andric break; 28850b57cec5SDimitry Andric } 28860b57cec5SDimitry Andric } 28870b57cec5SDimitry Andric if (!HasRelocSections) 28880b57cec5SDimitry Andric OS << "\nThere are no relocations in this file.\n"; 28890b57cec5SDimitry Andric } 28900b57cec5SDimitry Andric 28910b57cec5SDimitry Andric // Print the offset of a particular section from anyone of the ranges: 28920b57cec5SDimitry Andric // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER]. 28930b57cec5SDimitry Andric // If 'Type' does not fall within any of those ranges, then a string is 28940b57cec5SDimitry Andric // returned as '<unknown>' followed by the type value. 28950b57cec5SDimitry Andric static std::string getSectionTypeOffsetString(unsigned Type) { 28960b57cec5SDimitry Andric if (Type >= SHT_LOOS && Type <= SHT_HIOS) 28970b57cec5SDimitry Andric return "LOOS+0x" + to_hexString(Type - SHT_LOOS); 28980b57cec5SDimitry Andric else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC) 28990b57cec5SDimitry Andric return "LOPROC+0x" + to_hexString(Type - SHT_LOPROC); 29000b57cec5SDimitry Andric else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER) 29010b57cec5SDimitry Andric return "LOUSER+0x" + to_hexString(Type - SHT_LOUSER); 29020b57cec5SDimitry Andric return "0x" + to_hexString(Type) + ": <unknown>"; 29030b57cec5SDimitry Andric } 29040b57cec5SDimitry Andric 29050b57cec5SDimitry Andric static std::string getSectionTypeString(unsigned Arch, unsigned Type) { 29060b57cec5SDimitry Andric using namespace ELF; 29070b57cec5SDimitry Andric 29080b57cec5SDimitry Andric switch (Arch) { 29090b57cec5SDimitry Andric case EM_ARM: 29100b57cec5SDimitry Andric switch (Type) { 29110b57cec5SDimitry Andric case SHT_ARM_EXIDX: 29120b57cec5SDimitry Andric return "ARM_EXIDX"; 29130b57cec5SDimitry Andric case SHT_ARM_PREEMPTMAP: 29140b57cec5SDimitry Andric return "ARM_PREEMPTMAP"; 29150b57cec5SDimitry Andric case SHT_ARM_ATTRIBUTES: 29160b57cec5SDimitry Andric return "ARM_ATTRIBUTES"; 29170b57cec5SDimitry Andric case SHT_ARM_DEBUGOVERLAY: 29180b57cec5SDimitry Andric return "ARM_DEBUGOVERLAY"; 29190b57cec5SDimitry Andric case SHT_ARM_OVERLAYSECTION: 29200b57cec5SDimitry Andric return "ARM_OVERLAYSECTION"; 29210b57cec5SDimitry Andric } 29220b57cec5SDimitry Andric break; 29230b57cec5SDimitry Andric case EM_X86_64: 29240b57cec5SDimitry Andric switch (Type) { 29250b57cec5SDimitry Andric case SHT_X86_64_UNWIND: 29260b57cec5SDimitry Andric return "X86_64_UNWIND"; 29270b57cec5SDimitry Andric } 29280b57cec5SDimitry Andric break; 29290b57cec5SDimitry Andric case EM_MIPS: 29300b57cec5SDimitry Andric case EM_MIPS_RS3_LE: 29310b57cec5SDimitry Andric switch (Type) { 29320b57cec5SDimitry Andric case SHT_MIPS_REGINFO: 29330b57cec5SDimitry Andric return "MIPS_REGINFO"; 29340b57cec5SDimitry Andric case SHT_MIPS_OPTIONS: 29350b57cec5SDimitry Andric return "MIPS_OPTIONS"; 29360b57cec5SDimitry Andric case SHT_MIPS_DWARF: 29370b57cec5SDimitry Andric return "MIPS_DWARF"; 29380b57cec5SDimitry Andric case SHT_MIPS_ABIFLAGS: 29390b57cec5SDimitry Andric return "MIPS_ABIFLAGS"; 29400b57cec5SDimitry Andric } 29410b57cec5SDimitry Andric break; 29420b57cec5SDimitry Andric } 29430b57cec5SDimitry Andric switch (Type) { 29440b57cec5SDimitry Andric case SHT_NULL: 29450b57cec5SDimitry Andric return "NULL"; 29460b57cec5SDimitry Andric case SHT_PROGBITS: 29470b57cec5SDimitry Andric return "PROGBITS"; 29480b57cec5SDimitry Andric case SHT_SYMTAB: 29490b57cec5SDimitry Andric return "SYMTAB"; 29500b57cec5SDimitry Andric case SHT_STRTAB: 29510b57cec5SDimitry Andric return "STRTAB"; 29520b57cec5SDimitry Andric case SHT_RELA: 29530b57cec5SDimitry Andric return "RELA"; 29540b57cec5SDimitry Andric case SHT_HASH: 29550b57cec5SDimitry Andric return "HASH"; 29560b57cec5SDimitry Andric case SHT_DYNAMIC: 29570b57cec5SDimitry Andric return "DYNAMIC"; 29580b57cec5SDimitry Andric case SHT_NOTE: 29590b57cec5SDimitry Andric return "NOTE"; 29600b57cec5SDimitry Andric case SHT_NOBITS: 29610b57cec5SDimitry Andric return "NOBITS"; 29620b57cec5SDimitry Andric case SHT_REL: 29630b57cec5SDimitry Andric return "REL"; 29640b57cec5SDimitry Andric case SHT_SHLIB: 29650b57cec5SDimitry Andric return "SHLIB"; 29660b57cec5SDimitry Andric case SHT_DYNSYM: 29670b57cec5SDimitry Andric return "DYNSYM"; 29680b57cec5SDimitry Andric case SHT_INIT_ARRAY: 29690b57cec5SDimitry Andric return "INIT_ARRAY"; 29700b57cec5SDimitry Andric case SHT_FINI_ARRAY: 29710b57cec5SDimitry Andric return "FINI_ARRAY"; 29720b57cec5SDimitry Andric case SHT_PREINIT_ARRAY: 29730b57cec5SDimitry Andric return "PREINIT_ARRAY"; 29740b57cec5SDimitry Andric case SHT_GROUP: 29750b57cec5SDimitry Andric return "GROUP"; 29760b57cec5SDimitry Andric case SHT_SYMTAB_SHNDX: 29770b57cec5SDimitry Andric return "SYMTAB SECTION INDICES"; 29780b57cec5SDimitry Andric case SHT_ANDROID_REL: 29790b57cec5SDimitry Andric return "ANDROID_REL"; 29800b57cec5SDimitry Andric case SHT_ANDROID_RELA: 29810b57cec5SDimitry Andric return "ANDROID_RELA"; 29820b57cec5SDimitry Andric case SHT_RELR: 29830b57cec5SDimitry Andric case SHT_ANDROID_RELR: 29840b57cec5SDimitry Andric return "RELR"; 29850b57cec5SDimitry Andric case SHT_LLVM_ODRTAB: 29860b57cec5SDimitry Andric return "LLVM_ODRTAB"; 29870b57cec5SDimitry Andric case SHT_LLVM_LINKER_OPTIONS: 29880b57cec5SDimitry Andric return "LLVM_LINKER_OPTIONS"; 29890b57cec5SDimitry Andric case SHT_LLVM_CALL_GRAPH_PROFILE: 29900b57cec5SDimitry Andric return "LLVM_CALL_GRAPH_PROFILE"; 29910b57cec5SDimitry Andric case SHT_LLVM_ADDRSIG: 29920b57cec5SDimitry Andric return "LLVM_ADDRSIG"; 29930b57cec5SDimitry Andric case SHT_LLVM_DEPENDENT_LIBRARIES: 29940b57cec5SDimitry Andric return "LLVM_DEPENDENT_LIBRARIES"; 29950b57cec5SDimitry Andric // FIXME: Parse processor specific GNU attributes 29960b57cec5SDimitry Andric case SHT_GNU_ATTRIBUTES: 29970b57cec5SDimitry Andric return "ATTRIBUTES"; 29980b57cec5SDimitry Andric case SHT_GNU_HASH: 29990b57cec5SDimitry Andric return "GNU_HASH"; 30000b57cec5SDimitry Andric case SHT_GNU_verdef: 30010b57cec5SDimitry Andric return "VERDEF"; 30020b57cec5SDimitry Andric case SHT_GNU_verneed: 30030b57cec5SDimitry Andric return "VERNEED"; 30040b57cec5SDimitry Andric case SHT_GNU_versym: 30050b57cec5SDimitry Andric return "VERSYM"; 30060b57cec5SDimitry Andric default: 30070b57cec5SDimitry Andric return getSectionTypeOffsetString(Type); 30080b57cec5SDimitry Andric } 30090b57cec5SDimitry Andric return ""; 30100b57cec5SDimitry Andric } 30110b57cec5SDimitry Andric 30120b57cec5SDimitry Andric template <class ELFT> 30130b57cec5SDimitry Andric static StringRef getSectionName(const typename ELFT::Shdr &Sec, 30140b57cec5SDimitry Andric const ELFObjectFile<ELFT> &ElfObj, 30150b57cec5SDimitry Andric ArrayRef<typename ELFT::Shdr> Sections) { 30160b57cec5SDimitry Andric const ELFFile<ELFT> &Obj = *ElfObj.getELFFile(); 30170b57cec5SDimitry Andric uint32_t Index = Obj.getHeader()->e_shstrndx; 30180b57cec5SDimitry Andric if (Index == ELF::SHN_XINDEX) 30190b57cec5SDimitry Andric Index = Sections[0].sh_link; 30200b57cec5SDimitry Andric if (!Index) // no section string table. 30210b57cec5SDimitry Andric return ""; 30220b57cec5SDimitry Andric // TODO: Test a case when the sh_link of the section with index 0 is broken. 30230b57cec5SDimitry Andric if (Index >= Sections.size()) 30240b57cec5SDimitry Andric reportError(ElfObj.getFileName(), 30250b57cec5SDimitry Andric createError("section header string table index " + 30260b57cec5SDimitry Andric Twine(Index) + " does not exist")); 30270b57cec5SDimitry Andric StringRef Data = toStringRef(unwrapOrError( 30280b57cec5SDimitry Andric Obj.template getSectionContentsAsArray<uint8_t>(&Sections[Index]))); 30290b57cec5SDimitry Andric return unwrapOrError(Obj.getSectionName(&Sec, Data)); 30300b57cec5SDimitry Andric } 30310b57cec5SDimitry Andric 30320b57cec5SDimitry Andric template <class ELFT> 30330b57cec5SDimitry Andric void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) { 30340b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 0 : 8; 30350b57cec5SDimitry Andric ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections()); 30360b57cec5SDimitry Andric OS << "There are " << to_string(Sections.size()) 30370b57cec5SDimitry Andric << " section headers, starting at offset " 30380b57cec5SDimitry Andric << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n"; 30390b57cec5SDimitry Andric OS << "Section Headers:\n"; 30400b57cec5SDimitry Andric Field Fields[11] = { 30410b57cec5SDimitry Andric {"[Nr]", 2}, {"Name", 7}, {"Type", 25}, 30420b57cec5SDimitry Andric {"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias}, 30430b57cec5SDimitry Andric {"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias}, 30440b57cec5SDimitry Andric {"Inf", 82 - Bias}, {"Al", 86 - Bias}}; 30450b57cec5SDimitry Andric for (auto &F : Fields) 30460b57cec5SDimitry Andric printField(F); 30470b57cec5SDimitry Andric OS << "\n"; 30480b57cec5SDimitry Andric 30490b57cec5SDimitry Andric const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject(); 30500b57cec5SDimitry Andric size_t SectionIndex = 0; 30510b57cec5SDimitry Andric for (const Elf_Shdr &Sec : Sections) { 30520b57cec5SDimitry Andric Fields[0].Str = to_string(SectionIndex); 30530b57cec5SDimitry Andric Fields[1].Str = getSectionName(Sec, *ElfObj, Sections); 30540b57cec5SDimitry Andric Fields[2].Str = 30550b57cec5SDimitry Andric getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type); 30560b57cec5SDimitry Andric Fields[3].Str = 30570b57cec5SDimitry Andric to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8)); 30580b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); 30590b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6)); 30600b57cec5SDimitry Andric Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); 30610b57cec5SDimitry Andric Fields[7].Str = getGNUFlags(Sec.sh_flags); 30620b57cec5SDimitry Andric Fields[8].Str = to_string(Sec.sh_link); 30630b57cec5SDimitry Andric Fields[9].Str = to_string(Sec.sh_info); 30640b57cec5SDimitry Andric Fields[10].Str = to_string(Sec.sh_addralign); 30650b57cec5SDimitry Andric 30660b57cec5SDimitry Andric OS.PadToColumn(Fields[0].Column); 30670b57cec5SDimitry Andric OS << "[" << right_justify(Fields[0].Str, 2) << "]"; 30680b57cec5SDimitry Andric for (int i = 1; i < 7; i++) 30690b57cec5SDimitry Andric printField(Fields[i]); 30700b57cec5SDimitry Andric OS.PadToColumn(Fields[7].Column); 30710b57cec5SDimitry Andric OS << right_justify(Fields[7].Str, 3); 30720b57cec5SDimitry Andric OS.PadToColumn(Fields[8].Column); 30730b57cec5SDimitry Andric OS << right_justify(Fields[8].Str, 2); 30740b57cec5SDimitry Andric OS.PadToColumn(Fields[9].Column); 30750b57cec5SDimitry Andric OS << right_justify(Fields[9].Str, 3); 30760b57cec5SDimitry Andric OS.PadToColumn(Fields[10].Column); 30770b57cec5SDimitry Andric OS << right_justify(Fields[10].Str, 2); 30780b57cec5SDimitry Andric OS << "\n"; 30790b57cec5SDimitry Andric ++SectionIndex; 30800b57cec5SDimitry Andric } 30810b57cec5SDimitry Andric OS << "Key to Flags:\n" 30820b57cec5SDimitry Andric << " W (write), A (alloc), X (execute), M (merge), S (strings), l " 30830b57cec5SDimitry Andric "(large)\n" 30840b57cec5SDimitry Andric << " I (info), L (link order), G (group), T (TLS), E (exclude),\ 30850b57cec5SDimitry Andric x (unknown)\n" 30860b57cec5SDimitry Andric << " O (extra OS processing required) o (OS specific),\ 30870b57cec5SDimitry Andric p (processor specific)\n"; 30880b57cec5SDimitry Andric } 30890b57cec5SDimitry Andric 30900b57cec5SDimitry Andric template <class ELFT> 30910b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name, 30920b57cec5SDimitry Andric size_t Entries) { 30930b57cec5SDimitry Andric if (!Name.empty()) 30940b57cec5SDimitry Andric OS << "\nSymbol table '" << Name << "' contains " << Entries 30950b57cec5SDimitry Andric << " entries:\n"; 30960b57cec5SDimitry Andric else 30970b57cec5SDimitry Andric OS << "\n Symbol table for image:\n"; 30980b57cec5SDimitry Andric 30990b57cec5SDimitry Andric if (ELFT::Is64Bits) 31000b57cec5SDimitry Andric OS << " Num: Value Size Type Bind Vis Ndx Name\n"; 31010b57cec5SDimitry Andric else 31020b57cec5SDimitry Andric OS << " Num: Value Size Type Bind Vis Ndx Name\n"; 31030b57cec5SDimitry Andric } 31040b57cec5SDimitry Andric 31050b57cec5SDimitry Andric template <class ELFT> 31060b57cec5SDimitry Andric std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj, 31070b57cec5SDimitry Andric const Elf_Sym *Symbol, 31080b57cec5SDimitry Andric const Elf_Sym *FirstSym) { 31090b57cec5SDimitry Andric unsigned SectionIndex = Symbol->st_shndx; 31100b57cec5SDimitry Andric switch (SectionIndex) { 31110b57cec5SDimitry Andric case ELF::SHN_UNDEF: 31120b57cec5SDimitry Andric return "UND"; 31130b57cec5SDimitry Andric case ELF::SHN_ABS: 31140b57cec5SDimitry Andric return "ABS"; 31150b57cec5SDimitry Andric case ELF::SHN_COMMON: 31160b57cec5SDimitry Andric return "COM"; 31170b57cec5SDimitry Andric case ELF::SHN_XINDEX: 31180b57cec5SDimitry Andric return to_string( 31190b57cec5SDimitry Andric format_decimal(unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( 31200b57cec5SDimitry Andric Symbol, FirstSym, this->dumper()->getShndxTable())), 31210b57cec5SDimitry Andric 3)); 31220b57cec5SDimitry Andric default: 31230b57cec5SDimitry Andric // Find if: 31240b57cec5SDimitry Andric // Processor specific 31250b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC) 31260b57cec5SDimitry Andric return std::string("PRC[0x") + 31270b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 31280b57cec5SDimitry Andric // OS specific 31290b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS) 31300b57cec5SDimitry Andric return std::string("OS[0x") + 31310b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 31320b57cec5SDimitry Andric // Architecture reserved: 31330b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LORESERVE && 31340b57cec5SDimitry Andric SectionIndex <= ELF::SHN_HIRESERVE) 31350b57cec5SDimitry Andric return std::string("RSV[0x") + 31360b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 31370b57cec5SDimitry Andric // A normal section with an index 31380b57cec5SDimitry Andric return to_string(format_decimal(SectionIndex, 3)); 31390b57cec5SDimitry Andric } 31400b57cec5SDimitry Andric } 31410b57cec5SDimitry Andric 31420b57cec5SDimitry Andric template <class ELFT> 31430b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, 31440b57cec5SDimitry Andric const Elf_Sym *FirstSym, StringRef StrTable, 31450b57cec5SDimitry Andric bool IsDynamic) { 31460b57cec5SDimitry Andric static int Idx = 0; 31470b57cec5SDimitry Andric static bool Dynamic = true; 31480b57cec5SDimitry Andric 31490b57cec5SDimitry Andric // If this function was called with a different value from IsDynamic 31500b57cec5SDimitry Andric // from last call, happens when we move from dynamic to static symbol 31510b57cec5SDimitry Andric // table, "Num" field should be reset. 31520b57cec5SDimitry Andric if (!Dynamic != !IsDynamic) { 31530b57cec5SDimitry Andric Idx = 0; 31540b57cec5SDimitry Andric Dynamic = false; 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric 31570b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 31580b57cec5SDimitry Andric Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias, 31590b57cec5SDimitry Andric 31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias}; 31600b57cec5SDimitry Andric Fields[0].Str = to_string(format_decimal(Idx++, 6)) + ":"; 31610b57cec5SDimitry Andric Fields[1].Str = to_string( 31620b57cec5SDimitry Andric format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8)); 31630b57cec5SDimitry Andric Fields[2].Str = to_string(format_decimal(Symbol->st_size, 5)); 31640b57cec5SDimitry Andric 31650b57cec5SDimitry Andric unsigned char SymbolType = Symbol->getType(); 31660b57cec5SDimitry Andric if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && 31670b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 31680b57cec5SDimitry Andric Fields[3].Str = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); 31690b57cec5SDimitry Andric else 31700b57cec5SDimitry Andric Fields[3].Str = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); 31710b57cec5SDimitry Andric 31720b57cec5SDimitry Andric Fields[4].Str = 31730b57cec5SDimitry Andric printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); 31740b57cec5SDimitry Andric Fields[5].Str = 31750b57cec5SDimitry Andric printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities)); 31760b57cec5SDimitry Andric Fields[6].Str = getSymbolSectionNdx(Obj, Symbol, FirstSym); 31770b57cec5SDimitry Andric Fields[7].Str = 31780b57cec5SDimitry Andric this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); 31790b57cec5SDimitry Andric for (auto &Entry : Fields) 31800b57cec5SDimitry Andric printField(Entry); 31810b57cec5SDimitry Andric OS << "\n"; 31820b57cec5SDimitry Andric } 31830b57cec5SDimitry Andric 31840b57cec5SDimitry Andric template <class ELFT> 31850b57cec5SDimitry Andric void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, 31860b57cec5SDimitry Andric uint32_t Sym, StringRef StrTable, 31870b57cec5SDimitry Andric uint32_t Bucket) { 31880b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 31890b57cec5SDimitry Andric Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias, 31900b57cec5SDimitry Andric 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; 31910b57cec5SDimitry Andric Fields[0].Str = to_string(format_decimal(Sym, 5)); 31920b57cec5SDimitry Andric Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":"; 31930b57cec5SDimitry Andric 31940b57cec5SDimitry Andric const auto Symbol = FirstSym + Sym; 31950b57cec5SDimitry Andric Fields[2].Str = to_string( 31960b57cec5SDimitry Andric format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 18 : 8)); 31970b57cec5SDimitry Andric Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5)); 31980b57cec5SDimitry Andric 31990b57cec5SDimitry Andric unsigned char SymbolType = Symbol->getType(); 32000b57cec5SDimitry Andric if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && 32010b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 32020b57cec5SDimitry Andric Fields[4].Str = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); 32030b57cec5SDimitry Andric else 32040b57cec5SDimitry Andric Fields[4].Str = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); 32050b57cec5SDimitry Andric 32060b57cec5SDimitry Andric Fields[5].Str = 32070b57cec5SDimitry Andric printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); 32080b57cec5SDimitry Andric Fields[6].Str = 32090b57cec5SDimitry Andric printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities)); 32100b57cec5SDimitry Andric Fields[7].Str = getSymbolSectionNdx(Obj, Symbol, FirstSym); 32110b57cec5SDimitry Andric Fields[8].Str = this->dumper()->getFullSymbolName(Symbol, StrTable, true); 32120b57cec5SDimitry Andric 32130b57cec5SDimitry Andric for (auto &Entry : Fields) 32140b57cec5SDimitry Andric printField(Entry); 32150b57cec5SDimitry Andric OS << "\n"; 32160b57cec5SDimitry Andric } 32170b57cec5SDimitry Andric 32180b57cec5SDimitry Andric template <class ELFT> 32190b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols, 32200b57cec5SDimitry Andric bool PrintDynamicSymbols) { 32210b57cec5SDimitry Andric if (!PrintSymbols && !PrintDynamicSymbols) 32220b57cec5SDimitry Andric return; 32230b57cec5SDimitry Andric // GNU readelf prints both the .dynsym and .symtab with --symbols. 32240b57cec5SDimitry Andric this->dumper()->printSymbolsHelper(true); 32250b57cec5SDimitry Andric if (PrintSymbols) 32260b57cec5SDimitry Andric this->dumper()->printSymbolsHelper(false); 32270b57cec5SDimitry Andric } 32280b57cec5SDimitry Andric 32290b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) { 32300b57cec5SDimitry Andric if (this->dumper()->getDynamicStringTable().empty()) 32310b57cec5SDimitry Andric return; 32320b57cec5SDimitry Andric auto StringTable = this->dumper()->getDynamicStringTable(); 32330b57cec5SDimitry Andric auto DynSyms = this->dumper()->dynamic_symbols(); 32340b57cec5SDimitry Andric 32350b57cec5SDimitry Andric // Try printing .hash 32360b57cec5SDimitry Andric if (auto SysVHash = this->dumper()->getHashTable()) { 32370b57cec5SDimitry Andric OS << "\n Symbol table of .hash for image:\n"; 32380b57cec5SDimitry Andric if (ELFT::Is64Bits) 32390b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 32400b57cec5SDimitry Andric else 32410b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 32420b57cec5SDimitry Andric OS << "\n"; 32430b57cec5SDimitry Andric 32440b57cec5SDimitry Andric auto Buckets = SysVHash->buckets(); 32450b57cec5SDimitry Andric auto Chains = SysVHash->chains(); 32460b57cec5SDimitry Andric for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) { 32470b57cec5SDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 32480b57cec5SDimitry Andric continue; 32490b57cec5SDimitry Andric for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) { 32500b57cec5SDimitry Andric if (Ch == ELF::STN_UNDEF) 32510b57cec5SDimitry Andric break; 32520b57cec5SDimitry Andric printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); 32530b57cec5SDimitry Andric } 32540b57cec5SDimitry Andric } 32550b57cec5SDimitry Andric } 32560b57cec5SDimitry Andric 32570b57cec5SDimitry Andric // Try printing .gnu.hash 32580b57cec5SDimitry Andric if (auto GnuHash = this->dumper()->getGnuHashTable()) { 32590b57cec5SDimitry Andric OS << "\n Symbol table of .gnu.hash for image:\n"; 32600b57cec5SDimitry Andric if (ELFT::Is64Bits) 32610b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 32620b57cec5SDimitry Andric else 32630b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 32640b57cec5SDimitry Andric OS << "\n"; 32650b57cec5SDimitry Andric auto Buckets = GnuHash->buckets(); 32660b57cec5SDimitry Andric for (uint32_t Buc = 0; Buc < GnuHash->nbuckets; Buc++) { 32670b57cec5SDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 32680b57cec5SDimitry Andric continue; 32690b57cec5SDimitry Andric uint32_t Index = Buckets[Buc]; 32700b57cec5SDimitry Andric uint32_t GnuHashable = Index - GnuHash->symndx; 32710b57cec5SDimitry Andric // Print whole chain 32720b57cec5SDimitry Andric while (true) { 32730b57cec5SDimitry Andric printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc); 32740b57cec5SDimitry Andric // Chain ends at symbol with stopper bit 32750b57cec5SDimitry Andric if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1) 32760b57cec5SDimitry Andric break; 32770b57cec5SDimitry Andric } 32780b57cec5SDimitry Andric } 32790b57cec5SDimitry Andric } 32800b57cec5SDimitry Andric } 32810b57cec5SDimitry Andric 32820b57cec5SDimitry Andric static inline std::string printPhdrFlags(unsigned Flag) { 32830b57cec5SDimitry Andric std::string Str; 32840b57cec5SDimitry Andric Str = (Flag & PF_R) ? "R" : " "; 32850b57cec5SDimitry Andric Str += (Flag & PF_W) ? "W" : " "; 32860b57cec5SDimitry Andric Str += (Flag & PF_X) ? "E" : " "; 32870b57cec5SDimitry Andric return Str; 32880b57cec5SDimitry Andric } 32890b57cec5SDimitry Andric 32900b57cec5SDimitry Andric // SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO 32910b57cec5SDimitry Andric // PT_TLS must only have SHF_TLS sections 32920b57cec5SDimitry Andric template <class ELFT> 32930b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkTLSSections(const Elf_Phdr &Phdr, 32940b57cec5SDimitry Andric const Elf_Shdr &Sec) { 32950b57cec5SDimitry Andric return (((Sec.sh_flags & ELF::SHF_TLS) && 32960b57cec5SDimitry Andric ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) || 32970b57cec5SDimitry Andric (Phdr.p_type == ELF::PT_GNU_RELRO))) || 32980b57cec5SDimitry Andric (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS)); 32990b57cec5SDimitry Andric } 33000b57cec5SDimitry Andric 33010b57cec5SDimitry Andric // Non-SHT_NOBITS must have its offset inside the segment 33020b57cec5SDimitry Andric // Only non-zero section can be at end of segment 33030b57cec5SDimitry Andric template <class ELFT> 33040b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { 33050b57cec5SDimitry Andric if (Sec.sh_type == ELF::SHT_NOBITS) 33060b57cec5SDimitry Andric return true; 33070b57cec5SDimitry Andric bool IsSpecial = 33080b57cec5SDimitry Andric (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); 33090b57cec5SDimitry Andric // .tbss is special, it only has memory in PT_TLS and has NOBITS properties 33100b57cec5SDimitry Andric auto SectionSize = 33110b57cec5SDimitry Andric (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; 33120b57cec5SDimitry Andric if (Sec.sh_offset >= Phdr.p_offset) 33130b57cec5SDimitry Andric return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset) 33140b57cec5SDimitry Andric /*only non-zero sized sections at end*/ 33150b57cec5SDimitry Andric && (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz)); 33160b57cec5SDimitry Andric return false; 33170b57cec5SDimitry Andric } 33180b57cec5SDimitry Andric 33190b57cec5SDimitry Andric // SHF_ALLOC must have VMA inside segment 33200b57cec5SDimitry Andric // Only non-zero section can be at end of segment 33210b57cec5SDimitry Andric template <class ELFT> 33220b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { 33230b57cec5SDimitry Andric if (!(Sec.sh_flags & ELF::SHF_ALLOC)) 33240b57cec5SDimitry Andric return true; 33250b57cec5SDimitry Andric bool IsSpecial = 33260b57cec5SDimitry Andric (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); 33270b57cec5SDimitry Andric // .tbss is special, it only has memory in PT_TLS and has NOBITS properties 33280b57cec5SDimitry Andric auto SectionSize = 33290b57cec5SDimitry Andric (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; 33300b57cec5SDimitry Andric if (Sec.sh_addr >= Phdr.p_vaddr) 33310b57cec5SDimitry Andric return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) && 33320b57cec5SDimitry Andric (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz)); 33330b57cec5SDimitry Andric return false; 33340b57cec5SDimitry Andric } 33350b57cec5SDimitry Andric 33360b57cec5SDimitry Andric // No section with zero size must be at start or end of PT_DYNAMIC 33370b57cec5SDimitry Andric template <class ELFT> 33380b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { 33390b57cec5SDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0) 33400b57cec5SDimitry Andric return true; 33410b57cec5SDimitry Andric // Is section within the phdr both based on offset and VMA ? 33420b57cec5SDimitry Andric return ((Sec.sh_type == ELF::SHT_NOBITS) || 33430b57cec5SDimitry Andric (Sec.sh_offset > Phdr.p_offset && 33440b57cec5SDimitry Andric Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) && 33450b57cec5SDimitry Andric (!(Sec.sh_flags & ELF::SHF_ALLOC) || 33460b57cec5SDimitry Andric (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz)); 33470b57cec5SDimitry Andric } 33480b57cec5SDimitry Andric 33490b57cec5SDimitry Andric template <class ELFT> 33500b57cec5SDimitry Andric void GNUStyle<ELFT>::printProgramHeaders( 33510b57cec5SDimitry Andric const ELFO *Obj, bool PrintProgramHeaders, 33520b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) { 33530b57cec5SDimitry Andric if (PrintProgramHeaders) 33540b57cec5SDimitry Andric printProgramHeaders(Obj); 33550b57cec5SDimitry Andric 33560b57cec5SDimitry Andric // Display the section mapping along with the program headers, unless 33570b57cec5SDimitry Andric // -section-mapping is explicitly set to false. 33580b57cec5SDimitry Andric if (PrintSectionMapping != cl::BOU_FALSE) 33590b57cec5SDimitry Andric printSectionMapping(Obj); 33600b57cec5SDimitry Andric } 33610b57cec5SDimitry Andric 33620b57cec5SDimitry Andric template <class ELFT> 33630b57cec5SDimitry Andric void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { 33640b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 33650b57cec5SDimitry Andric const Elf_Ehdr *Header = Obj->getHeader(); 33660b57cec5SDimitry Andric Field Fields[8] = {2, 17, 26, 37 + Bias, 33670b57cec5SDimitry Andric 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias}; 33680b57cec5SDimitry Andric OS << "\nElf file type is " 33690b57cec5SDimitry Andric << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n" 33700b57cec5SDimitry Andric << "Entry point " << format_hex(Header->e_entry, 3) << "\n" 33710b57cec5SDimitry Andric << "There are " << Header->e_phnum << " program headers," 33720b57cec5SDimitry Andric << " starting at offset " << Header->e_phoff << "\n\n" 33730b57cec5SDimitry Andric << "Program Headers:\n"; 33740b57cec5SDimitry Andric if (ELFT::Is64Bits) 33750b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr " 33760b57cec5SDimitry Andric << " FileSiz MemSiz Flg Align\n"; 33770b57cec5SDimitry Andric else 33780b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr FileSiz " 33790b57cec5SDimitry Andric << "MemSiz Flg Align\n"; 33800b57cec5SDimitry Andric 33810b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 18 : 10; 33820b57cec5SDimitry Andric unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7; 33830b57cec5SDimitry Andric for (const auto &Phdr : unwrapOrError(Obj->program_headers())) { 33840b57cec5SDimitry Andric Fields[0].Str = getElfPtType(Header->e_machine, Phdr.p_type); 33850b57cec5SDimitry Andric Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8)); 33860b57cec5SDimitry Andric Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width)); 33870b57cec5SDimitry Andric Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width)); 33880b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth)); 33890b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth)); 33900b57cec5SDimitry Andric Fields[6].Str = printPhdrFlags(Phdr.p_flags); 33910b57cec5SDimitry Andric Fields[7].Str = to_string(format_hex(Phdr.p_align, 1)); 33920b57cec5SDimitry Andric for (auto Field : Fields) 33930b57cec5SDimitry Andric printField(Field); 33940b57cec5SDimitry Andric if (Phdr.p_type == ELF::PT_INTERP) { 33950b57cec5SDimitry Andric OS << "\n [Requesting program interpreter: "; 33960b57cec5SDimitry Andric OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]"; 33970b57cec5SDimitry Andric } 33980b57cec5SDimitry Andric OS << "\n"; 33990b57cec5SDimitry Andric } 34000b57cec5SDimitry Andric } 34010b57cec5SDimitry Andric 34020b57cec5SDimitry Andric template <class ELFT> 34030b57cec5SDimitry Andric void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) { 34040b57cec5SDimitry Andric OS << "\n Section to Segment mapping:\n Segment Sections...\n"; 34050b57cec5SDimitry Andric DenseSet<const Elf_Shdr *> BelongsToSegment; 34060b57cec5SDimitry Andric int Phnum = 0; 34070b57cec5SDimitry Andric for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { 34080b57cec5SDimitry Andric std::string Sections; 34090b57cec5SDimitry Andric OS << format(" %2.2d ", Phnum++); 34100b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 34110b57cec5SDimitry Andric // Check if each section is in a segment and then print mapping. 34120b57cec5SDimitry Andric // readelf additionally makes sure it does not print zero sized sections 34130b57cec5SDimitry Andric // at end of segments and for PT_DYNAMIC both start and end of section 34140b57cec5SDimitry Andric // .tbss must only be shown in PT_TLS section. 34150b57cec5SDimitry Andric bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) && 34160b57cec5SDimitry Andric ((Sec.sh_flags & ELF::SHF_TLS) != 0) && 34170b57cec5SDimitry Andric Phdr.p_type != ELF::PT_TLS; 34180b57cec5SDimitry Andric if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) && 34190b57cec5SDimitry Andric checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) && 34200b57cec5SDimitry Andric checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL)) { 34210b57cec5SDimitry Andric Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " "; 34220b57cec5SDimitry Andric BelongsToSegment.insert(&Sec); 34230b57cec5SDimitry Andric } 34240b57cec5SDimitry Andric } 34250b57cec5SDimitry Andric OS << Sections << "\n"; 34260b57cec5SDimitry Andric OS.flush(); 34270b57cec5SDimitry Andric } 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric // Display sections that do not belong to a segment. 34300b57cec5SDimitry Andric std::string Sections; 34310b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 34320b57cec5SDimitry Andric if (BelongsToSegment.find(&Sec) == BelongsToSegment.end()) 34330b57cec5SDimitry Andric Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + ' '; 34340b57cec5SDimitry Andric } 34350b57cec5SDimitry Andric if (!Sections.empty()) { 34360b57cec5SDimitry Andric OS << " None " << Sections << '\n'; 34370b57cec5SDimitry Andric OS.flush(); 34380b57cec5SDimitry Andric } 34390b57cec5SDimitry Andric } 34400b57cec5SDimitry Andric 34410b57cec5SDimitry Andric template <class ELFT> 34420b57cec5SDimitry Andric void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, 34430b57cec5SDimitry Andric bool IsRela) { 34440b57cec5SDimitry Andric uint32_t SymIndex = R.getSymbol(Obj->isMips64EL()); 34450b57cec5SDimitry Andric const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; 34460b57cec5SDimitry Andric std::string SymbolName = maybeDemangle( 34470b57cec5SDimitry Andric unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable()))); 34480b57cec5SDimitry Andric printRelocation(Obj, Sym, SymbolName, R, IsRela); 34490b57cec5SDimitry Andric } 34500b57cec5SDimitry Andric 34510b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printDynamic(const ELFO *Obj) { 34520b57cec5SDimitry Andric Elf_Dyn_Range Table = this->dumper()->dynamic_table(); 34530b57cec5SDimitry Andric if (Table.empty()) 34540b57cec5SDimitry Andric return; 34550b57cec5SDimitry Andric 34560b57cec5SDimitry Andric const DynRegionInfo &DynamicTableRegion = 34570b57cec5SDimitry Andric this->dumper()->getDynamicTableRegion(); 34580b57cec5SDimitry Andric 34590b57cec5SDimitry Andric OS << "Dynamic section at offset " 34600b57cec5SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(DynamicTableRegion.Addr) - 34610b57cec5SDimitry Andric Obj->base(), 34620b57cec5SDimitry Andric 1) 34630b57cec5SDimitry Andric << " contains " << Table.size() << " entries:\n"; 34640b57cec5SDimitry Andric 34650b57cec5SDimitry Andric bool Is64 = ELFT::Is64Bits; 34660b57cec5SDimitry Andric if (Is64) 34670b57cec5SDimitry Andric OS << " Tag Type Name/Value\n"; 34680b57cec5SDimitry Andric else 34690b57cec5SDimitry Andric OS << " Tag Type Name/Value\n"; 34700b57cec5SDimitry Andric for (auto Entry : Table) { 34710b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 34720b57cec5SDimitry Andric std::string TypeString = std::string("(") + 34730b57cec5SDimitry Andric getTypeString(Obj->getHeader()->e_machine, Tag) + 34740b57cec5SDimitry Andric ")"; 34750b57cec5SDimitry Andric OS << " " << format_hex(Tag, Is64 ? 18 : 10) 34760b57cec5SDimitry Andric << format(" %-20s ", TypeString.c_str()); 34770b57cec5SDimitry Andric this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal()); 34780b57cec5SDimitry Andric OS << "\n"; 34790b57cec5SDimitry Andric } 34800b57cec5SDimitry Andric } 34810b57cec5SDimitry Andric 34820b57cec5SDimitry Andric template <class ELFT> 34830b57cec5SDimitry Andric void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { 34840b57cec5SDimitry Andric const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); 34850b57cec5SDimitry Andric const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); 34860b57cec5SDimitry Andric const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); 34870b57cec5SDimitry Andric const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); 34880b57cec5SDimitry Andric if (DynRelaRegion.Size > 0) { 34890b57cec5SDimitry Andric OS << "\n'RELA' relocation section at offset " 34900b57cec5SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) - 34910b57cec5SDimitry Andric Obj->base(), 34920b57cec5SDimitry Andric 1) 34930b57cec5SDimitry Andric << " contains " << DynRelaRegion.Size << " bytes:\n"; 34940b57cec5SDimitry Andric printRelocHeader(ELF::SHT_RELA); 34950b57cec5SDimitry Andric for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) 34960b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela, true); 34970b57cec5SDimitry Andric } 34980b57cec5SDimitry Andric if (DynRelRegion.Size > 0) { 34990b57cec5SDimitry Andric OS << "\n'REL' relocation section at offset " 35000b57cec5SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) - 35010b57cec5SDimitry Andric Obj->base(), 35020b57cec5SDimitry Andric 1) 35030b57cec5SDimitry Andric << " contains " << DynRelRegion.Size << " bytes:\n"; 35040b57cec5SDimitry Andric printRelocHeader(ELF::SHT_REL); 35050b57cec5SDimitry Andric for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { 35060b57cec5SDimitry Andric Elf_Rela Rela; 35070b57cec5SDimitry Andric Rela.r_offset = Rel.r_offset; 35080b57cec5SDimitry Andric Rela.r_info = Rel.r_info; 35090b57cec5SDimitry Andric Rela.r_addend = 0; 35100b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela, false); 35110b57cec5SDimitry Andric } 35120b57cec5SDimitry Andric } 35130b57cec5SDimitry Andric if (DynRelrRegion.Size > 0) { 35140b57cec5SDimitry Andric OS << "\n'RELR' relocation section at offset " 35150b57cec5SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) - 35160b57cec5SDimitry Andric Obj->base(), 35170b57cec5SDimitry Andric 1) 35180b57cec5SDimitry Andric << " contains " << DynRelrRegion.Size << " bytes:\n"; 35190b57cec5SDimitry Andric printRelocHeader(ELF::SHT_REL); 35200b57cec5SDimitry Andric Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); 35210b57cec5SDimitry Andric std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); 35220b57cec5SDimitry Andric for (const Elf_Rela &Rela : RelrRelas) { 35230b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela, false); 35240b57cec5SDimitry Andric } 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric if (DynPLTRelRegion.Size) { 35270b57cec5SDimitry Andric OS << "\n'PLT' relocation section at offset " 35280b57cec5SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) - 35290b57cec5SDimitry Andric Obj->base(), 35300b57cec5SDimitry Andric 1) 35310b57cec5SDimitry Andric << " contains " << DynPLTRelRegion.Size << " bytes:\n"; 35320b57cec5SDimitry Andric } 35330b57cec5SDimitry Andric if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { 35340b57cec5SDimitry Andric printRelocHeader(ELF::SHT_RELA); 35350b57cec5SDimitry Andric for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) 35360b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela, true); 35370b57cec5SDimitry Andric } else { 35380b57cec5SDimitry Andric printRelocHeader(ELF::SHT_REL); 35390b57cec5SDimitry Andric for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { 35400b57cec5SDimitry Andric Elf_Rela Rela; 35410b57cec5SDimitry Andric Rela.r_offset = Rel.r_offset; 35420b57cec5SDimitry Andric Rela.r_info = Rel.r_info; 35430b57cec5SDimitry Andric Rela.r_addend = 0; 35440b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela, false); 35450b57cec5SDimitry Andric } 35460b57cec5SDimitry Andric } 35470b57cec5SDimitry Andric } 35480b57cec5SDimitry Andric 35490b57cec5SDimitry Andric template <class ELFT> 35500b57cec5SDimitry Andric static void printGNUVersionSectionProlog(formatted_raw_ostream &OS, 35510b57cec5SDimitry Andric const Twine &Name, unsigned EntriesNum, 35520b57cec5SDimitry Andric const ELFFile<ELFT> *Obj, 35530b57cec5SDimitry Andric const typename ELFT::Shdr *Sec) { 35540b57cec5SDimitry Andric StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); 35550b57cec5SDimitry Andric OS << Name << " section '" << SecName << "' " 35560b57cec5SDimitry Andric << "contains " << EntriesNum << " entries:\n"; 35570b57cec5SDimitry Andric 35580b57cec5SDimitry Andric const typename ELFT::Shdr *SymTab = 35590b57cec5SDimitry Andric unwrapOrError(Obj->getSection(Sec->sh_link)); 35600b57cec5SDimitry Andric StringRef SymTabName = unwrapOrError(Obj->getSectionName(SymTab)); 35610b57cec5SDimitry Andric OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16) 35620b57cec5SDimitry Andric << " Offset: " << format_hex(Sec->sh_offset, 8) 35630b57cec5SDimitry Andric << " Link: " << Sec->sh_link << " (" << SymTabName << ")\n"; 35640b57cec5SDimitry Andric } 35650b57cec5SDimitry Andric 35660b57cec5SDimitry Andric template <class ELFT> 35670b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj, 35680b57cec5SDimitry Andric const Elf_Shdr *Sec) { 35690b57cec5SDimitry Andric if (!Sec) 35700b57cec5SDimitry Andric return; 35710b57cec5SDimitry Andric 35720b57cec5SDimitry Andric unsigned Entries = Sec->sh_size / sizeof(Elf_Versym); 35730b57cec5SDimitry Andric printGNUVersionSectionProlog(OS, "Version symbols", Entries, Obj, Sec); 35740b57cec5SDimitry Andric 35750b57cec5SDimitry Andric const uint8_t *VersymBuf = 35760b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset); 35770b57cec5SDimitry Andric const ELFDumper<ELFT> *Dumper = this->dumper(); 35780b57cec5SDimitry Andric StringRef StrTable = Dumper->getDynamicStringTable(); 35790b57cec5SDimitry Andric 35800b57cec5SDimitry Andric // readelf prints 4 entries per line. 35810b57cec5SDimitry Andric for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) { 35820b57cec5SDimitry Andric OS << " " << format_hex_no_prefix(VersymRow, 3) << ":"; 35830b57cec5SDimitry Andric 35840b57cec5SDimitry Andric for (uint64_t VersymIndex = 0; 35850b57cec5SDimitry Andric (VersymIndex < 4) && (VersymIndex + VersymRow) < Entries; 35860b57cec5SDimitry Andric ++VersymIndex) { 35870b57cec5SDimitry Andric const Elf_Versym *Versym = 35880b57cec5SDimitry Andric reinterpret_cast<const Elf_Versym *>(VersymBuf); 35890b57cec5SDimitry Andric switch (Versym->vs_index) { 35900b57cec5SDimitry Andric case 0: 35910b57cec5SDimitry Andric OS << " 0 (*local*) "; 35920b57cec5SDimitry Andric break; 35930b57cec5SDimitry Andric case 1: 35940b57cec5SDimitry Andric OS << " 1 (*global*) "; 35950b57cec5SDimitry Andric break; 35960b57cec5SDimitry Andric default: 35970b57cec5SDimitry Andric OS << format("%4x%c", Versym->vs_index & VERSYM_VERSION, 35980b57cec5SDimitry Andric Versym->vs_index & VERSYM_HIDDEN ? 'h' : ' '); 35990b57cec5SDimitry Andric 36000b57cec5SDimitry Andric bool IsDefault = true; 36010b57cec5SDimitry Andric std::string VersionName = Dumper->getSymbolVersionByIndex( 36020b57cec5SDimitry Andric StrTable, Versym->vs_index, IsDefault); 36030b57cec5SDimitry Andric 36040b57cec5SDimitry Andric if (!VersionName.empty()) 36050b57cec5SDimitry Andric VersionName = "(" + VersionName + ")"; 36060b57cec5SDimitry Andric else 36070b57cec5SDimitry Andric VersionName = "(*invalid*)"; 36080b57cec5SDimitry Andric OS << left_justify(VersionName, 13); 36090b57cec5SDimitry Andric } 36100b57cec5SDimitry Andric VersymBuf += sizeof(Elf_Versym); 36110b57cec5SDimitry Andric } 36120b57cec5SDimitry Andric OS << '\n'; 36130b57cec5SDimitry Andric } 36140b57cec5SDimitry Andric OS << '\n'; 36150b57cec5SDimitry Andric } 36160b57cec5SDimitry Andric 36170b57cec5SDimitry Andric static std::string versionFlagToString(unsigned Flags) { 36180b57cec5SDimitry Andric if (Flags == 0) 36190b57cec5SDimitry Andric return "none"; 36200b57cec5SDimitry Andric 36210b57cec5SDimitry Andric std::string Ret; 36220b57cec5SDimitry Andric auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) { 36230b57cec5SDimitry Andric if (!(Flags & Flag)) 36240b57cec5SDimitry Andric return; 36250b57cec5SDimitry Andric if (!Ret.empty()) 36260b57cec5SDimitry Andric Ret += " | "; 36270b57cec5SDimitry Andric Ret += Name; 36280b57cec5SDimitry Andric Flags &= ~Flag; 36290b57cec5SDimitry Andric }; 36300b57cec5SDimitry Andric 36310b57cec5SDimitry Andric AddFlag(VER_FLG_BASE, "BASE"); 36320b57cec5SDimitry Andric AddFlag(VER_FLG_WEAK, "WEAK"); 36330b57cec5SDimitry Andric AddFlag(VER_FLG_INFO, "INFO"); 36340b57cec5SDimitry Andric AddFlag(~0, "<unknown>"); 36350b57cec5SDimitry Andric return Ret; 36360b57cec5SDimitry Andric } 36370b57cec5SDimitry Andric 36380b57cec5SDimitry Andric template <class ELFT> 36390b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj, 36400b57cec5SDimitry Andric const Elf_Shdr *Sec) { 36410b57cec5SDimitry Andric if (!Sec) 36420b57cec5SDimitry Andric return; 36430b57cec5SDimitry Andric 36440b57cec5SDimitry Andric unsigned VerDefsNum = Sec->sh_info; 36450b57cec5SDimitry Andric printGNUVersionSectionProlog(OS, "Version definition", VerDefsNum, Obj, Sec); 36460b57cec5SDimitry Andric 36470b57cec5SDimitry Andric const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link)); 36480b57cec5SDimitry Andric StringRef StringTable( 36490b57cec5SDimitry Andric reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset), 36500b57cec5SDimitry Andric (size_t)StrTabSec->sh_size); 36510b57cec5SDimitry Andric 36520b57cec5SDimitry Andric const uint8_t *VerdefBuf = unwrapOrError(Obj->getSectionContents(Sec)).data(); 36530b57cec5SDimitry Andric const uint8_t *Begin = VerdefBuf; 36540b57cec5SDimitry Andric 36550b57cec5SDimitry Andric while (VerDefsNum--) { 36560b57cec5SDimitry Andric const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf); 36570b57cec5SDimitry Andric OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u", 36580b57cec5SDimitry Andric VerdefBuf - Begin, (unsigned)Verdef->vd_version, 36590b57cec5SDimitry Andric versionFlagToString(Verdef->vd_flags).c_str(), 36600b57cec5SDimitry Andric (unsigned)Verdef->vd_ndx, (unsigned)Verdef->vd_cnt); 36610b57cec5SDimitry Andric 36620b57cec5SDimitry Andric const uint8_t *VerdauxBuf = VerdefBuf + Verdef->vd_aux; 36630b57cec5SDimitry Andric const Elf_Verdaux *Verdaux = 36640b57cec5SDimitry Andric reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf); 36650b57cec5SDimitry Andric OS << format(" Name: %s\n", 36660b57cec5SDimitry Andric StringTable.drop_front(Verdaux->vda_name).data()); 36670b57cec5SDimitry Andric 36680b57cec5SDimitry Andric for (unsigned I = 1; I < Verdef->vd_cnt; ++I) { 36690b57cec5SDimitry Andric VerdauxBuf += Verdaux->vda_next; 36700b57cec5SDimitry Andric Verdaux = reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf); 36710b57cec5SDimitry Andric OS << format(" 0x%04x: Parent %u: %s\n", VerdauxBuf - Begin, I, 36720b57cec5SDimitry Andric StringTable.drop_front(Verdaux->vda_name).data()); 36730b57cec5SDimitry Andric } 36740b57cec5SDimitry Andric 36750b57cec5SDimitry Andric VerdefBuf += Verdef->vd_next; 36760b57cec5SDimitry Andric } 36770b57cec5SDimitry Andric OS << '\n'; 36780b57cec5SDimitry Andric } 36790b57cec5SDimitry Andric 36800b57cec5SDimitry Andric template <class ELFT> 36810b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj, 36820b57cec5SDimitry Andric const Elf_Shdr *Sec) { 36830b57cec5SDimitry Andric if (!Sec) 36840b57cec5SDimitry Andric return; 36850b57cec5SDimitry Andric 36860b57cec5SDimitry Andric unsigned VerneedNum = Sec->sh_info; 36870b57cec5SDimitry Andric printGNUVersionSectionProlog(OS, "Version needs", VerneedNum, Obj, Sec); 36880b57cec5SDimitry Andric 36890b57cec5SDimitry Andric ArrayRef<uint8_t> SecData = unwrapOrError(Obj->getSectionContents(Sec)); 36900b57cec5SDimitry Andric 36910b57cec5SDimitry Andric const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link)); 36920b57cec5SDimitry Andric StringRef StringTable = { 36930b57cec5SDimitry Andric reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset), 36940b57cec5SDimitry Andric (size_t)StrTabSec->sh_size}; 36950b57cec5SDimitry Andric 36960b57cec5SDimitry Andric const uint8_t *VerneedBuf = SecData.data(); 36970b57cec5SDimitry Andric for (unsigned I = 0; I < VerneedNum; ++I) { 36980b57cec5SDimitry Andric const Elf_Verneed *Verneed = 36990b57cec5SDimitry Andric reinterpret_cast<const Elf_Verneed *>(VerneedBuf); 37000b57cec5SDimitry Andric 37010b57cec5SDimitry Andric OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", 37020b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Verneed) - SecData.begin(), 37030b57cec5SDimitry Andric (unsigned)Verneed->vn_version, 37040b57cec5SDimitry Andric StringTable.drop_front(Verneed->vn_file).data(), 37050b57cec5SDimitry Andric (unsigned)Verneed->vn_cnt); 37060b57cec5SDimitry Andric 37070b57cec5SDimitry Andric const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux; 37080b57cec5SDimitry Andric for (unsigned J = 0; J < Verneed->vn_cnt; ++J) { 37090b57cec5SDimitry Andric const Elf_Vernaux *Vernaux = 37100b57cec5SDimitry Andric reinterpret_cast<const Elf_Vernaux *>(VernauxBuf); 37110b57cec5SDimitry Andric 37120b57cec5SDimitry Andric OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", 37130b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Vernaux) - SecData.begin(), 37140b57cec5SDimitry Andric StringTable.drop_front(Vernaux->vna_name).data(), 37150b57cec5SDimitry Andric versionFlagToString(Vernaux->vna_flags).c_str(), 37160b57cec5SDimitry Andric (unsigned)Vernaux->vna_other); 37170b57cec5SDimitry Andric VernauxBuf += Vernaux->vna_next; 37180b57cec5SDimitry Andric } 37190b57cec5SDimitry Andric VerneedBuf += Verneed->vn_next; 37200b57cec5SDimitry Andric } 37210b57cec5SDimitry Andric OS << '\n'; 37220b57cec5SDimitry Andric } 37230b57cec5SDimitry Andric 37240b57cec5SDimitry Andric // Hash histogram shows statistics of how efficient the hash was for the 37250b57cec5SDimitry Andric // dynamic symbol table. The table shows number of hash buckets for different 37260b57cec5SDimitry Andric // lengths of chains as absolute number and percentage of the total buckets. 37270b57cec5SDimitry Andric // Additionally cumulative coverage of symbols for each set of buckets. 37280b57cec5SDimitry Andric template <class ELFT> 37290b57cec5SDimitry Andric void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { 37300b57cec5SDimitry Andric // Print histogram for .hash section 37310b57cec5SDimitry Andric if (const Elf_Hash *HashTable = this->dumper()->getHashTable()) { 37320b57cec5SDimitry Andric size_t NBucket = HashTable->nbucket; 37330b57cec5SDimitry Andric size_t NChain = HashTable->nchain; 37340b57cec5SDimitry Andric ArrayRef<Elf_Word> Buckets = HashTable->buckets(); 37350b57cec5SDimitry Andric ArrayRef<Elf_Word> Chains = HashTable->chains(); 37360b57cec5SDimitry Andric size_t TotalSyms = 0; 37370b57cec5SDimitry Andric // If hash table is correct, we have at least chains with 0 length 37380b57cec5SDimitry Andric size_t MaxChain = 1; 37390b57cec5SDimitry Andric size_t CumulativeNonZero = 0; 37400b57cec5SDimitry Andric 37410b57cec5SDimitry Andric if (NChain == 0 || NBucket == 0) 37420b57cec5SDimitry Andric return; 37430b57cec5SDimitry Andric 37440b57cec5SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 37450b57cec5SDimitry Andric // Go over all buckets and and note chain lengths of each bucket (total 37460b57cec5SDimitry Andric // unique chain lengths). 37470b57cec5SDimitry Andric for (size_t B = 0; B < NBucket; B++) { 37480b57cec5SDimitry Andric for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C]) 37490b57cec5SDimitry Andric if (MaxChain <= ++ChainLen[B]) 37500b57cec5SDimitry Andric MaxChain++; 37510b57cec5SDimitry Andric TotalSyms += ChainLen[B]; 37520b57cec5SDimitry Andric } 37530b57cec5SDimitry Andric 37540b57cec5SDimitry Andric if (!TotalSyms) 37550b57cec5SDimitry Andric return; 37560b57cec5SDimitry Andric 37570b57cec5SDimitry Andric std::vector<size_t> Count(MaxChain, 0) ; 37580b57cec5SDimitry Andric // Count how long is the chain for each bucket 37590b57cec5SDimitry Andric for (size_t B = 0; B < NBucket; B++) 37600b57cec5SDimitry Andric ++Count[ChainLen[B]]; 37610b57cec5SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 37620b57cec5SDimitry Andric // coverage of the symbols 37630b57cec5SDimitry Andric OS << "Histogram for bucket list length (total of " << NBucket 37640b57cec5SDimitry Andric << " buckets)\n" 37650b57cec5SDimitry Andric << " Length Number % of total Coverage\n"; 37660b57cec5SDimitry Andric for (size_t I = 0; I < MaxChain; I++) { 37670b57cec5SDimitry Andric CumulativeNonZero += Count[I] * I; 37680b57cec5SDimitry Andric OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], 37690b57cec5SDimitry Andric (Count[I] * 100.0) / NBucket, 37700b57cec5SDimitry Andric (CumulativeNonZero * 100.0) / TotalSyms); 37710b57cec5SDimitry Andric } 37720b57cec5SDimitry Andric } 37730b57cec5SDimitry Andric 37740b57cec5SDimitry Andric // Print histogram for .gnu.hash section 37750b57cec5SDimitry Andric if (const Elf_GnuHash *GnuHashTable = this->dumper()->getGnuHashTable()) { 37760b57cec5SDimitry Andric size_t NBucket = GnuHashTable->nbuckets; 37770b57cec5SDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets(); 37780b57cec5SDimitry Andric unsigned NumSyms = this->dumper()->dynamic_symbols().size(); 37790b57cec5SDimitry Andric if (!NumSyms) 37800b57cec5SDimitry Andric return; 37810b57cec5SDimitry Andric ArrayRef<Elf_Word> Chains = GnuHashTable->values(NumSyms); 37820b57cec5SDimitry Andric size_t Symndx = GnuHashTable->symndx; 37830b57cec5SDimitry Andric size_t TotalSyms = 0; 37840b57cec5SDimitry Andric size_t MaxChain = 1; 37850b57cec5SDimitry Andric size_t CumulativeNonZero = 0; 37860b57cec5SDimitry Andric 37870b57cec5SDimitry Andric if (Chains.empty() || NBucket == 0) 37880b57cec5SDimitry Andric return; 37890b57cec5SDimitry Andric 37900b57cec5SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 37910b57cec5SDimitry Andric 37920b57cec5SDimitry Andric for (size_t B = 0; B < NBucket; B++) { 37930b57cec5SDimitry Andric if (!Buckets[B]) 37940b57cec5SDimitry Andric continue; 37950b57cec5SDimitry Andric size_t Len = 1; 37960b57cec5SDimitry Andric for (size_t C = Buckets[B] - Symndx; 37970b57cec5SDimitry Andric C < Chains.size() && (Chains[C] & 1) == 0; C++) 37980b57cec5SDimitry Andric if (MaxChain < ++Len) 37990b57cec5SDimitry Andric MaxChain++; 38000b57cec5SDimitry Andric ChainLen[B] = Len; 38010b57cec5SDimitry Andric TotalSyms += Len; 38020b57cec5SDimitry Andric } 38030b57cec5SDimitry Andric MaxChain++; 38040b57cec5SDimitry Andric 38050b57cec5SDimitry Andric if (!TotalSyms) 38060b57cec5SDimitry Andric return; 38070b57cec5SDimitry Andric 38080b57cec5SDimitry Andric std::vector<size_t> Count(MaxChain, 0) ; 38090b57cec5SDimitry Andric for (size_t B = 0; B < NBucket; B++) 38100b57cec5SDimitry Andric ++Count[ChainLen[B]]; 38110b57cec5SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 38120b57cec5SDimitry Andric // coverage of the symbols 38130b57cec5SDimitry Andric OS << "Histogram for `.gnu.hash' bucket list length (total of " << NBucket 38140b57cec5SDimitry Andric << " buckets)\n" 38150b57cec5SDimitry Andric << " Length Number % of total Coverage\n"; 38160b57cec5SDimitry Andric for (size_t I = 0; I <MaxChain; I++) { 38170b57cec5SDimitry Andric CumulativeNonZero += Count[I] * I; 38180b57cec5SDimitry Andric OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], 38190b57cec5SDimitry Andric (Count[I] * 100.0) / NBucket, 38200b57cec5SDimitry Andric (CumulativeNonZero * 100.0) / TotalSyms); 38210b57cec5SDimitry Andric } 38220b57cec5SDimitry Andric } 38230b57cec5SDimitry Andric } 38240b57cec5SDimitry Andric 38250b57cec5SDimitry Andric template <class ELFT> 38260b57cec5SDimitry Andric void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { 38270b57cec5SDimitry Andric OS << "GNUStyle::printCGProfile not implemented\n"; 38280b57cec5SDimitry Andric } 38290b57cec5SDimitry Andric 38300b57cec5SDimitry Andric template <class ELFT> 38310b57cec5SDimitry Andric void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { 38320b57cec5SDimitry Andric OS << "GNUStyle::printAddrsig not implemented\n"; 38330b57cec5SDimitry Andric } 38340b57cec5SDimitry Andric 38350b57cec5SDimitry Andric static StringRef getGenericNoteTypeName(const uint32_t NT) { 38360b57cec5SDimitry Andric static const struct { 38370b57cec5SDimitry Andric uint32_t ID; 38380b57cec5SDimitry Andric const char *Name; 38390b57cec5SDimitry Andric } Notes[] = { 38400b57cec5SDimitry Andric {ELF::NT_VERSION, "NT_VERSION (version)"}, 38410b57cec5SDimitry Andric {ELF::NT_ARCH, "NT_ARCH (architecture)"}, 38420b57cec5SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"}, 38430b57cec5SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"}, 38440b57cec5SDimitry Andric }; 38450b57cec5SDimitry Andric 38460b57cec5SDimitry Andric for (const auto &Note : Notes) 38470b57cec5SDimitry Andric if (Note.ID == NT) 38480b57cec5SDimitry Andric return Note.Name; 38490b57cec5SDimitry Andric 38500b57cec5SDimitry Andric return ""; 38510b57cec5SDimitry Andric } 38520b57cec5SDimitry Andric 38530b57cec5SDimitry Andric static std::string getGNUNoteTypeName(const uint32_t NT) { 38540b57cec5SDimitry Andric static const struct { 38550b57cec5SDimitry Andric uint32_t ID; 38560b57cec5SDimitry Andric const char *Name; 38570b57cec5SDimitry Andric } Notes[] = { 38580b57cec5SDimitry Andric {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, 38590b57cec5SDimitry Andric {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, 38600b57cec5SDimitry Andric {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, 38610b57cec5SDimitry Andric {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, 38620b57cec5SDimitry Andric {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, 38630b57cec5SDimitry Andric }; 38640b57cec5SDimitry Andric 38650b57cec5SDimitry Andric for (const auto &Note : Notes) 38660b57cec5SDimitry Andric if (Note.ID == NT) 38670b57cec5SDimitry Andric return std::string(Note.Name); 38680b57cec5SDimitry Andric 38690b57cec5SDimitry Andric std::string string; 38700b57cec5SDimitry Andric raw_string_ostream OS(string); 38710b57cec5SDimitry Andric OS << format("Unknown note type (0x%08x)", NT); 38720b57cec5SDimitry Andric return OS.str(); 38730b57cec5SDimitry Andric } 38740b57cec5SDimitry Andric 38750b57cec5SDimitry Andric static std::string getFreeBSDNoteTypeName(const uint32_t NT) { 38760b57cec5SDimitry Andric static const struct { 38770b57cec5SDimitry Andric uint32_t ID; 38780b57cec5SDimitry Andric const char *Name; 38790b57cec5SDimitry Andric } Notes[] = { 38800b57cec5SDimitry Andric {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, 38810b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, 38820b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, 38830b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, 38840b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, 38850b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, 38860b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, 38870b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, 38880b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, 38890b57cec5SDimitry Andric "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, 38900b57cec5SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, 38910b57cec5SDimitry Andric }; 38920b57cec5SDimitry Andric 38930b57cec5SDimitry Andric for (const auto &Note : Notes) 38940b57cec5SDimitry Andric if (Note.ID == NT) 38950b57cec5SDimitry Andric return std::string(Note.Name); 38960b57cec5SDimitry Andric 38970b57cec5SDimitry Andric std::string string; 38980b57cec5SDimitry Andric raw_string_ostream OS(string); 38990b57cec5SDimitry Andric OS << format("Unknown note type (0x%08x)", NT); 39000b57cec5SDimitry Andric return OS.str(); 39010b57cec5SDimitry Andric } 39020b57cec5SDimitry Andric 39030b57cec5SDimitry Andric static std::string getAMDNoteTypeName(const uint32_t NT) { 39040b57cec5SDimitry Andric static const struct { 39050b57cec5SDimitry Andric uint32_t ID; 39060b57cec5SDimitry Andric const char *Name; 39070b57cec5SDimitry Andric } Notes[] = {{ELF::NT_AMD_AMDGPU_HSA_METADATA, 39080b57cec5SDimitry Andric "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"}, 39090b57cec5SDimitry Andric {ELF::NT_AMD_AMDGPU_ISA, "NT_AMD_AMDGPU_ISA (ISA Version)"}, 39100b57cec5SDimitry Andric {ELF::NT_AMD_AMDGPU_PAL_METADATA, 39110b57cec5SDimitry Andric "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"}}; 39120b57cec5SDimitry Andric 39130b57cec5SDimitry Andric for (const auto &Note : Notes) 39140b57cec5SDimitry Andric if (Note.ID == NT) 39150b57cec5SDimitry Andric return std::string(Note.Name); 39160b57cec5SDimitry Andric 39170b57cec5SDimitry Andric std::string string; 39180b57cec5SDimitry Andric raw_string_ostream OS(string); 39190b57cec5SDimitry Andric OS << format("Unknown note type (0x%08x)", NT); 39200b57cec5SDimitry Andric return OS.str(); 39210b57cec5SDimitry Andric } 39220b57cec5SDimitry Andric 39230b57cec5SDimitry Andric static std::string getAMDGPUNoteTypeName(const uint32_t NT) { 39240b57cec5SDimitry Andric if (NT == ELF::NT_AMDGPU_METADATA) 39250b57cec5SDimitry Andric return std::string("NT_AMDGPU_METADATA (AMDGPU Metadata)"); 39260b57cec5SDimitry Andric 39270b57cec5SDimitry Andric std::string string; 39280b57cec5SDimitry Andric raw_string_ostream OS(string); 39290b57cec5SDimitry Andric OS << format("Unknown note type (0x%08x)", NT); 39300b57cec5SDimitry Andric return OS.str(); 39310b57cec5SDimitry Andric } 39320b57cec5SDimitry Andric 39330b57cec5SDimitry Andric template <typename ELFT> 39340b57cec5SDimitry Andric static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, 39350b57cec5SDimitry Andric ArrayRef<uint8_t> Data) { 39360b57cec5SDimitry Andric std::string str; 39370b57cec5SDimitry Andric raw_string_ostream OS(str); 39380b57cec5SDimitry Andric uint32_t PrData; 39390b57cec5SDimitry Andric auto DumpBit = [&](uint32_t Flag, StringRef Name) { 39400b57cec5SDimitry Andric if (PrData & Flag) { 39410b57cec5SDimitry Andric PrData &= ~Flag; 39420b57cec5SDimitry Andric OS << Name; 39430b57cec5SDimitry Andric if (PrData) 39440b57cec5SDimitry Andric OS << ", "; 39450b57cec5SDimitry Andric } 39460b57cec5SDimitry Andric }; 39470b57cec5SDimitry Andric 39480b57cec5SDimitry Andric switch (Type) { 39490b57cec5SDimitry Andric default: 39500b57cec5SDimitry Andric OS << format("<application-specific type 0x%x>", Type); 39510b57cec5SDimitry Andric return OS.str(); 39520b57cec5SDimitry Andric case GNU_PROPERTY_STACK_SIZE: { 39530b57cec5SDimitry Andric OS << "stack size: "; 39540b57cec5SDimitry Andric if (DataSize == sizeof(typename ELFT::uint)) 39550b57cec5SDimitry Andric OS << formatv("{0:x}", 39560b57cec5SDimitry Andric (uint64_t)(*(const typename ELFT::Addr *)Data.data())); 39570b57cec5SDimitry Andric else 39580b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 39590b57cec5SDimitry Andric return OS.str(); 39600b57cec5SDimitry Andric } 39610b57cec5SDimitry Andric case GNU_PROPERTY_NO_COPY_ON_PROTECTED: 39620b57cec5SDimitry Andric OS << "no copy on protected"; 39630b57cec5SDimitry Andric if (DataSize) 39640b57cec5SDimitry Andric OS << format(" <corrupt length: 0x%x>", DataSize); 39650b57cec5SDimitry Andric return OS.str(); 39660b57cec5SDimitry Andric case GNU_PROPERTY_AARCH64_FEATURE_1_AND: 39670b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_1_AND: 39680b57cec5SDimitry Andric OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: " 39690b57cec5SDimitry Andric : "x86 feature: "); 39700b57cec5SDimitry Andric if (DataSize != 4) { 39710b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 39720b57cec5SDimitry Andric return OS.str(); 39730b57cec5SDimitry Andric } 39740b57cec5SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 39750b57cec5SDimitry Andric if (PrData == 0) { 39760b57cec5SDimitry Andric OS << "<None>"; 39770b57cec5SDimitry Andric return OS.str(); 39780b57cec5SDimitry Andric } 39790b57cec5SDimitry Andric if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { 39800b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI"); 39810b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC"); 39820b57cec5SDimitry Andric } else { 39830b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT"); 39840b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK"); 39850b57cec5SDimitry Andric } 39860b57cec5SDimitry Andric if (PrData) 39870b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 39880b57cec5SDimitry Andric return OS.str(); 39890b57cec5SDimitry Andric case GNU_PROPERTY_X86_ISA_1_NEEDED: 39900b57cec5SDimitry Andric case GNU_PROPERTY_X86_ISA_1_USED: 39910b57cec5SDimitry Andric OS << "x86 ISA " 39920b57cec5SDimitry Andric << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: "); 39930b57cec5SDimitry Andric if (DataSize != 4) { 39940b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 39950b57cec5SDimitry Andric return OS.str(); 39960b57cec5SDimitry Andric } 39970b57cec5SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 39980b57cec5SDimitry Andric if (PrData == 0) { 39990b57cec5SDimitry Andric OS << "<None>"; 40000b57cec5SDimitry Andric return OS.str(); 40010b57cec5SDimitry Andric } 40020b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_CMOV, "CMOV"); 40030b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSE, "SSE"); 40040b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSE2, "SSE2"); 40050b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSE3, "SSE3"); 40060b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSSE3, "SSSE3"); 40070b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_1, "SSE4_1"); 40080b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_2, "SSE4_2"); 40090b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX, "AVX"); 40100b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX2, "AVX2"); 40110b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_FMA, "FMA"); 40120b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512F, "AVX512F"); 40130b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512CD, "AVX512CD"); 40140b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512ER, "AVX512ER"); 40150b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512PF, "AVX512PF"); 40160b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512VL, "AVX512VL"); 40170b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512DQ, "AVX512DQ"); 40180b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512BW, "AVX512BW"); 40190b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS, "AVX512_4FMAPS"); 40200b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW, "AVX512_4VNNIW"); 40210b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_BITALG, "AVX512_BITALG"); 40220b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_IFMA, "AVX512_IFMA"); 40230b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI, "AVX512_VBMI"); 40240b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2, "AVX512_VBMI2"); 40250b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VNNI, "AVX512_VNNI"); 40260b57cec5SDimitry Andric if (PrData) 40270b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 40280b57cec5SDimitry Andric return OS.str(); 40290b57cec5SDimitry Andric break; 40300b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_NEEDED: 40310b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_USED: 40320b57cec5SDimitry Andric OS << "x86 feature " 40330b57cec5SDimitry Andric << (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: "); 40340b57cec5SDimitry Andric if (DataSize != 4) { 40350b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 40360b57cec5SDimitry Andric return OS.str(); 40370b57cec5SDimitry Andric } 40380b57cec5SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 40390b57cec5SDimitry Andric if (PrData == 0) { 40400b57cec5SDimitry Andric OS << "<None>"; 40410b57cec5SDimitry Andric return OS.str(); 40420b57cec5SDimitry Andric } 40430b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86"); 40440b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87"); 40450b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX"); 40460b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM"); 40470b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM"); 40480b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM"); 40490b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR"); 40500b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE"); 40510b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT"); 40520b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC"); 40530b57cec5SDimitry Andric if (PrData) 40540b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 40550b57cec5SDimitry Andric return OS.str(); 40560b57cec5SDimitry Andric } 40570b57cec5SDimitry Andric } 40580b57cec5SDimitry Andric 40590b57cec5SDimitry Andric template <typename ELFT> 40600b57cec5SDimitry Andric static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) { 40610b57cec5SDimitry Andric using Elf_Word = typename ELFT::Word; 40620b57cec5SDimitry Andric 40630b57cec5SDimitry Andric SmallVector<std::string, 4> Properties; 40640b57cec5SDimitry Andric while (Arr.size() >= 8) { 40650b57cec5SDimitry Andric uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); 40660b57cec5SDimitry Andric uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); 40670b57cec5SDimitry Andric Arr = Arr.drop_front(8); 40680b57cec5SDimitry Andric 40690b57cec5SDimitry Andric // Take padding size into account if present. 40700b57cec5SDimitry Andric uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); 40710b57cec5SDimitry Andric std::string str; 40720b57cec5SDimitry Andric raw_string_ostream OS(str); 40730b57cec5SDimitry Andric if (Arr.size() < PaddedSize) { 40740b57cec5SDimitry Andric OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize); 40750b57cec5SDimitry Andric Properties.push_back(OS.str()); 40760b57cec5SDimitry Andric break; 40770b57cec5SDimitry Andric } 40780b57cec5SDimitry Andric Properties.push_back( 40790b57cec5SDimitry Andric getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize))); 40800b57cec5SDimitry Andric Arr = Arr.drop_front(PaddedSize); 40810b57cec5SDimitry Andric } 40820b57cec5SDimitry Andric 40830b57cec5SDimitry Andric if (!Arr.empty()) 40840b57cec5SDimitry Andric Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>"); 40850b57cec5SDimitry Andric 40860b57cec5SDimitry Andric return Properties; 40870b57cec5SDimitry Andric } 40880b57cec5SDimitry Andric 40890b57cec5SDimitry Andric struct GNUAbiTag { 40900b57cec5SDimitry Andric std::string OSName; 40910b57cec5SDimitry Andric std::string ABI; 40920b57cec5SDimitry Andric bool IsValid; 40930b57cec5SDimitry Andric }; 40940b57cec5SDimitry Andric 40950b57cec5SDimitry Andric template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) { 40960b57cec5SDimitry Andric typedef typename ELFT::Word Elf_Word; 40970b57cec5SDimitry Andric 40980b57cec5SDimitry Andric ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()), 40990b57cec5SDimitry Andric reinterpret_cast<const Elf_Word *>(Desc.end())); 41000b57cec5SDimitry Andric 41010b57cec5SDimitry Andric if (Words.size() < 4) 41020b57cec5SDimitry Andric return {"", "", /*IsValid=*/false}; 41030b57cec5SDimitry Andric 41040b57cec5SDimitry Andric static const char *OSNames[] = { 41050b57cec5SDimitry Andric "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", 41060b57cec5SDimitry Andric }; 41070b57cec5SDimitry Andric StringRef OSName = "Unknown"; 41080b57cec5SDimitry Andric if (Words[0] < array_lengthof(OSNames)) 41090b57cec5SDimitry Andric OSName = OSNames[Words[0]]; 41100b57cec5SDimitry Andric uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; 41110b57cec5SDimitry Andric std::string str; 41120b57cec5SDimitry Andric raw_string_ostream ABI(str); 41130b57cec5SDimitry Andric ABI << Major << "." << Minor << "." << Patch; 41140b57cec5SDimitry Andric return {OSName, ABI.str(), /*IsValid=*/true}; 41150b57cec5SDimitry Andric } 41160b57cec5SDimitry Andric 41170b57cec5SDimitry Andric static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) { 41180b57cec5SDimitry Andric std::string str; 41190b57cec5SDimitry Andric raw_string_ostream OS(str); 41200b57cec5SDimitry Andric for (const auto &B : Desc) 41210b57cec5SDimitry Andric OS << format_hex_no_prefix(B, 2); 41220b57cec5SDimitry Andric return OS.str(); 41230b57cec5SDimitry Andric } 41240b57cec5SDimitry Andric 41250b57cec5SDimitry Andric static StringRef getGNUGoldVersion(ArrayRef<uint8_t> Desc) { 41260b57cec5SDimitry Andric return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 41270b57cec5SDimitry Andric } 41280b57cec5SDimitry Andric 41290b57cec5SDimitry Andric template <typename ELFT> 41300b57cec5SDimitry Andric static void printGNUNote(raw_ostream &OS, uint32_t NoteType, 41310b57cec5SDimitry Andric ArrayRef<uint8_t> Desc) { 41320b57cec5SDimitry Andric switch (NoteType) { 41330b57cec5SDimitry Andric default: 41340b57cec5SDimitry Andric return; 41350b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 41360b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 41370b57cec5SDimitry Andric if (!AbiTag.IsValid) 41380b57cec5SDimitry Andric OS << " <corrupt GNU_ABI_TAG>"; 41390b57cec5SDimitry Andric else 41400b57cec5SDimitry Andric OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI; 41410b57cec5SDimitry Andric break; 41420b57cec5SDimitry Andric } 41430b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 41440b57cec5SDimitry Andric OS << " Build ID: " << getGNUBuildId(Desc); 41450b57cec5SDimitry Andric break; 41460b57cec5SDimitry Andric } 41470b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 41480b57cec5SDimitry Andric OS << " Version: " << getGNUGoldVersion(Desc); 41490b57cec5SDimitry Andric break; 41500b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 41510b57cec5SDimitry Andric OS << " Properties:"; 41520b57cec5SDimitry Andric for (const auto &Property : getGNUPropertyList<ELFT>(Desc)) 41530b57cec5SDimitry Andric OS << " " << Property << "\n"; 41540b57cec5SDimitry Andric break; 41550b57cec5SDimitry Andric } 41560b57cec5SDimitry Andric OS << '\n'; 41570b57cec5SDimitry Andric } 41580b57cec5SDimitry Andric 41590b57cec5SDimitry Andric struct AMDNote { 41600b57cec5SDimitry Andric std::string Type; 41610b57cec5SDimitry Andric std::string Value; 41620b57cec5SDimitry Andric }; 41630b57cec5SDimitry Andric 41640b57cec5SDimitry Andric template <typename ELFT> 41650b57cec5SDimitry Andric static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 41660b57cec5SDimitry Andric switch (NoteType) { 41670b57cec5SDimitry Andric default: 41680b57cec5SDimitry Andric return {"", ""}; 41690b57cec5SDimitry Andric case ELF::NT_AMD_AMDGPU_HSA_METADATA: 41700b57cec5SDimitry Andric return { 41710b57cec5SDimitry Andric "HSA Metadata", 41720b57cec5SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())}; 41730b57cec5SDimitry Andric case ELF::NT_AMD_AMDGPU_ISA: 41740b57cec5SDimitry Andric return { 41750b57cec5SDimitry Andric "ISA Version", 41760b57cec5SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())}; 41770b57cec5SDimitry Andric } 41780b57cec5SDimitry Andric } 41790b57cec5SDimitry Andric 41800b57cec5SDimitry Andric struct AMDGPUNote { 41810b57cec5SDimitry Andric std::string Type; 41820b57cec5SDimitry Andric std::string Value; 41830b57cec5SDimitry Andric }; 41840b57cec5SDimitry Andric 41850b57cec5SDimitry Andric template <typename ELFT> 41860b57cec5SDimitry Andric static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 41870b57cec5SDimitry Andric switch (NoteType) { 41880b57cec5SDimitry Andric default: 41890b57cec5SDimitry Andric return {"", ""}; 41900b57cec5SDimitry Andric case ELF::NT_AMDGPU_METADATA: { 41910b57cec5SDimitry Andric auto MsgPackString = 41920b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 41930b57cec5SDimitry Andric msgpack::Document MsgPackDoc; 41940b57cec5SDimitry Andric if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false)) 41950b57cec5SDimitry Andric return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"}; 41960b57cec5SDimitry Andric 41970b57cec5SDimitry Andric AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true); 41980b57cec5SDimitry Andric if (!Verifier.verify(MsgPackDoc.getRoot())) 41990b57cec5SDimitry Andric return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"}; 42000b57cec5SDimitry Andric 42010b57cec5SDimitry Andric std::string HSAMetadataString; 42020b57cec5SDimitry Andric raw_string_ostream StrOS(HSAMetadataString); 42030b57cec5SDimitry Andric MsgPackDoc.toYAML(StrOS); 42040b57cec5SDimitry Andric 42050b57cec5SDimitry Andric return {"AMDGPU Metadata", StrOS.str()}; 42060b57cec5SDimitry Andric } 42070b57cec5SDimitry Andric } 42080b57cec5SDimitry Andric } 42090b57cec5SDimitry Andric 42100b57cec5SDimitry Andric template <class ELFT> 42110b57cec5SDimitry Andric void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { 42120b57cec5SDimitry Andric auto PrintHeader = [&](const typename ELFT::Off Offset, 42130b57cec5SDimitry Andric const typename ELFT::Addr Size) { 42140b57cec5SDimitry Andric OS << "Displaying notes found at file offset " << format_hex(Offset, 10) 42150b57cec5SDimitry Andric << " with length " << format_hex(Size, 10) << ":\n" 42160b57cec5SDimitry Andric << " Owner Data size\tDescription\n"; 42170b57cec5SDimitry Andric }; 42180b57cec5SDimitry Andric 42190b57cec5SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note) { 42200b57cec5SDimitry Andric StringRef Name = Note.getName(); 42210b57cec5SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(); 42220b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 42230b57cec5SDimitry Andric 42240b57cec5SDimitry Andric OS << " " << Name << std::string(22 - Name.size(), ' ') 42250b57cec5SDimitry Andric << format_hex(Descriptor.size(), 10) << '\t'; 42260b57cec5SDimitry Andric 42270b57cec5SDimitry Andric if (Name == "GNU") { 42280b57cec5SDimitry Andric OS << getGNUNoteTypeName(Type) << '\n'; 42290b57cec5SDimitry Andric printGNUNote<ELFT>(OS, Type, Descriptor); 42300b57cec5SDimitry Andric } else if (Name == "FreeBSD") { 42310b57cec5SDimitry Andric OS << getFreeBSDNoteTypeName(Type) << '\n'; 42320b57cec5SDimitry Andric } else if (Name == "AMD") { 42330b57cec5SDimitry Andric OS << getAMDNoteTypeName(Type) << '\n'; 42340b57cec5SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 42350b57cec5SDimitry Andric if (!N.Type.empty()) 42360b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 42370b57cec5SDimitry Andric } else if (Name == "AMDGPU") { 42380b57cec5SDimitry Andric OS << getAMDGPUNoteTypeName(Type) << '\n'; 42390b57cec5SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 42400b57cec5SDimitry Andric if (!N.Type.empty()) 42410b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 42420b57cec5SDimitry Andric } else { 42430b57cec5SDimitry Andric StringRef NoteType = getGenericNoteTypeName(Type); 42440b57cec5SDimitry Andric if (!NoteType.empty()) 42450b57cec5SDimitry Andric OS << NoteType; 42460b57cec5SDimitry Andric else 42470b57cec5SDimitry Andric OS << "Unknown note type: (" << format_hex(Type, 10) << ')'; 42480b57cec5SDimitry Andric } 42490b57cec5SDimitry Andric OS << '\n'; 42500b57cec5SDimitry Andric }; 42510b57cec5SDimitry Andric 42520b57cec5SDimitry Andric if (Obj->getHeader()->e_type == ELF::ET_CORE) { 42530b57cec5SDimitry Andric for (const auto &P : unwrapOrError(Obj->program_headers())) { 42540b57cec5SDimitry Andric if (P.p_type != PT_NOTE) 42550b57cec5SDimitry Andric continue; 42560b57cec5SDimitry Andric PrintHeader(P.p_offset, P.p_filesz); 42570b57cec5SDimitry Andric Error Err = Error::success(); 42580b57cec5SDimitry Andric for (const auto &Note : Obj->notes(P, Err)) 42590b57cec5SDimitry Andric ProcessNote(Note); 42600b57cec5SDimitry Andric if (Err) 42610b57cec5SDimitry Andric error(std::move(Err)); 42620b57cec5SDimitry Andric } 42630b57cec5SDimitry Andric } else { 42640b57cec5SDimitry Andric for (const auto &S : unwrapOrError(Obj->sections())) { 42650b57cec5SDimitry Andric if (S.sh_type != SHT_NOTE) 42660b57cec5SDimitry Andric continue; 42670b57cec5SDimitry Andric PrintHeader(S.sh_offset, S.sh_size); 42680b57cec5SDimitry Andric Error Err = Error::success(); 42690b57cec5SDimitry Andric for (const auto &Note : Obj->notes(S, Err)) 42700b57cec5SDimitry Andric ProcessNote(Note); 42710b57cec5SDimitry Andric if (Err) 42720b57cec5SDimitry Andric error(std::move(Err)); 42730b57cec5SDimitry Andric } 42740b57cec5SDimitry Andric } 42750b57cec5SDimitry Andric } 42760b57cec5SDimitry Andric 42770b57cec5SDimitry Andric template <class ELFT> 42780b57cec5SDimitry Andric void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { 42790b57cec5SDimitry Andric OS << "printELFLinkerOptions not implemented!\n"; 42800b57cec5SDimitry Andric } 42810b57cec5SDimitry Andric 42820b57cec5SDimitry Andric template <class ELFT> 42830b57cec5SDimitry Andric void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 42840b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 42850b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 42860b57cec5SDimitry Andric OS.PadToColumn(2); 42870b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); 42880b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 42890b57cec5SDimitry Andric OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; 42900b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 42910b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 42920b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 42930b57cec5SDimitry Andric OS << Purpose << "\n"; 42940b57cec5SDimitry Andric }; 42950b57cec5SDimitry Andric 42960b57cec5SDimitry Andric OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); 42970b57cec5SDimitry Andric OS << " Canonical gp value: " 42980b57cec5SDimitry Andric << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; 42990b57cec5SDimitry Andric 43000b57cec5SDimitry Andric OS << " Reserved entries:\n"; 43010b57cec5SDimitry Andric if (ELFT::Is64Bits) 43020b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 43030b57cec5SDimitry Andric else 43040b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 43050b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); 43060b57cec5SDimitry Andric if (Parser.getGotModulePointer()) 43070b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); 43080b57cec5SDimitry Andric 43090b57cec5SDimitry Andric if (!Parser.getLocalEntries().empty()) { 43100b57cec5SDimitry Andric OS << "\n"; 43110b57cec5SDimitry Andric OS << " Local entries:\n"; 43120b57cec5SDimitry Andric if (ELFT::Is64Bits) 43130b57cec5SDimitry Andric OS << " Address Access Initial\n"; 43140b57cec5SDimitry Andric else 43150b57cec5SDimitry Andric OS << " Address Access Initial\n"; 43160b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) 43170b57cec5SDimitry Andric PrintEntry(&E, ""); 43180b57cec5SDimitry Andric } 43190b57cec5SDimitry Andric 43200b57cec5SDimitry Andric if (Parser.IsStatic) 43210b57cec5SDimitry Andric return; 43220b57cec5SDimitry Andric 43230b57cec5SDimitry Andric if (!Parser.getGlobalEntries().empty()) { 43240b57cec5SDimitry Andric OS << "\n"; 43250b57cec5SDimitry Andric OS << " Global entries:\n"; 43260b57cec5SDimitry Andric if (ELFT::Is64Bits) 43270b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val." 43280b57cec5SDimitry Andric << " Type Ndx Name\n"; 43290b57cec5SDimitry Andric else 43300b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; 43310b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 43320b57cec5SDimitry Andric const Elf_Sym *Sym = Parser.getGotSym(&E); 43330b57cec5SDimitry Andric std::string SymName = this->dumper()->getFullSymbolName( 43340b57cec5SDimitry Andric Sym, this->dumper()->getDynamicStringTable(), false); 43350b57cec5SDimitry Andric 43360b57cec5SDimitry Andric OS.PadToColumn(2); 43370b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); 43380b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 43390b57cec5SDimitry Andric OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; 43400b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 43410b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 43420b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 43430b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); 43440b57cec5SDimitry Andric OS.PadToColumn(40 + 3 * Bias); 43450b57cec5SDimitry Andric OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); 43460b57cec5SDimitry Andric OS.PadToColumn(48 + 3 * Bias); 43470b57cec5SDimitry Andric OS << getSymbolSectionNdx(Parser.Obj, Sym, 43480b57cec5SDimitry Andric this->dumper()->dynamic_symbols().begin()); 43490b57cec5SDimitry Andric OS.PadToColumn(52 + 3 * Bias); 43500b57cec5SDimitry Andric OS << SymName << "\n"; 43510b57cec5SDimitry Andric } 43520b57cec5SDimitry Andric } 43530b57cec5SDimitry Andric 43540b57cec5SDimitry Andric if (!Parser.getOtherEntries().empty()) 43550b57cec5SDimitry Andric OS << "\n Number of TLS and multi-GOT entries " 43560b57cec5SDimitry Andric << Parser.getOtherEntries().size() << "\n"; 43570b57cec5SDimitry Andric } 43580b57cec5SDimitry Andric 43590b57cec5SDimitry Andric template <class ELFT> 43600b57cec5SDimitry Andric void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 43610b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 43620b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 43630b57cec5SDimitry Andric OS.PadToColumn(2); 43640b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias); 43650b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 43660b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 43670b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 43680b57cec5SDimitry Andric OS << Purpose << "\n"; 43690b57cec5SDimitry Andric }; 43700b57cec5SDimitry Andric 43710b57cec5SDimitry Andric OS << "PLT GOT:\n\n"; 43720b57cec5SDimitry Andric 43730b57cec5SDimitry Andric OS << " Reserved entries:\n"; 43740b57cec5SDimitry Andric OS << " Address Initial Purpose\n"; 43750b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); 43760b57cec5SDimitry Andric if (Parser.getPltModulePointer()) 43770b57cec5SDimitry Andric PrintEntry(Parser.getPltModulePointer(), "Module pointer"); 43780b57cec5SDimitry Andric 43790b57cec5SDimitry Andric if (!Parser.getPltEntries().empty()) { 43800b57cec5SDimitry Andric OS << "\n"; 43810b57cec5SDimitry Andric OS << " Entries:\n"; 43820b57cec5SDimitry Andric OS << " Address Initial Sym.Val. Type Ndx Name\n"; 43830b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 43840b57cec5SDimitry Andric const Elf_Sym *Sym = Parser.getPltSym(&E); 43850b57cec5SDimitry Andric std::string SymName = this->dumper()->getFullSymbolName( 43860b57cec5SDimitry Andric Sym, this->dumper()->getDynamicStringTable(), false); 43870b57cec5SDimitry Andric 43880b57cec5SDimitry Andric OS.PadToColumn(2); 43890b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias)); 43900b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 43910b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 43920b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 43930b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); 43940b57cec5SDimitry Andric OS.PadToColumn(29 + 3 * Bias); 43950b57cec5SDimitry Andric OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); 43960b57cec5SDimitry Andric OS.PadToColumn(37 + 3 * Bias); 43970b57cec5SDimitry Andric OS << getSymbolSectionNdx(Parser.Obj, Sym, 43980b57cec5SDimitry Andric this->dumper()->dynamic_symbols().begin()); 43990b57cec5SDimitry Andric OS.PadToColumn(41 + 3 * Bias); 44000b57cec5SDimitry Andric OS << SymName << "\n"; 44010b57cec5SDimitry Andric } 44020b57cec5SDimitry Andric } 44030b57cec5SDimitry Andric } 44040b57cec5SDimitry Andric 44050b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { 44060b57cec5SDimitry Andric const Elf_Ehdr *E = Obj->getHeader(); 44070b57cec5SDimitry Andric { 44080b57cec5SDimitry Andric DictScope D(W, "ElfHeader"); 44090b57cec5SDimitry Andric { 44100b57cec5SDimitry Andric DictScope D(W, "Ident"); 44110b57cec5SDimitry Andric W.printBinary("Magic", makeArrayRef(E->e_ident).slice(ELF::EI_MAG0, 4)); 44120b57cec5SDimitry Andric W.printEnum("Class", E->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); 44130b57cec5SDimitry Andric W.printEnum("DataEncoding", E->e_ident[ELF::EI_DATA], 44140b57cec5SDimitry Andric makeArrayRef(ElfDataEncoding)); 44150b57cec5SDimitry Andric W.printNumber("FileVersion", E->e_ident[ELF::EI_VERSION]); 44160b57cec5SDimitry Andric 44170b57cec5SDimitry Andric auto OSABI = makeArrayRef(ElfOSABI); 44180b57cec5SDimitry Andric if (E->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && 44190b57cec5SDimitry Andric E->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { 44200b57cec5SDimitry Andric switch (E->e_machine) { 44210b57cec5SDimitry Andric case ELF::EM_AMDGPU: 44220b57cec5SDimitry Andric OSABI = makeArrayRef(AMDGPUElfOSABI); 44230b57cec5SDimitry Andric break; 44240b57cec5SDimitry Andric case ELF::EM_ARM: 44250b57cec5SDimitry Andric OSABI = makeArrayRef(ARMElfOSABI); 44260b57cec5SDimitry Andric break; 44270b57cec5SDimitry Andric case ELF::EM_TI_C6000: 44280b57cec5SDimitry Andric OSABI = makeArrayRef(C6000ElfOSABI); 44290b57cec5SDimitry Andric break; 44300b57cec5SDimitry Andric } 44310b57cec5SDimitry Andric } 44320b57cec5SDimitry Andric W.printEnum("OS/ABI", E->e_ident[ELF::EI_OSABI], OSABI); 44330b57cec5SDimitry Andric W.printNumber("ABIVersion", E->e_ident[ELF::EI_ABIVERSION]); 44340b57cec5SDimitry Andric W.printBinary("Unused", makeArrayRef(E->e_ident).slice(ELF::EI_PAD)); 44350b57cec5SDimitry Andric } 44360b57cec5SDimitry Andric 44370b57cec5SDimitry Andric W.printEnum("Type", E->e_type, makeArrayRef(ElfObjectFileType)); 44380b57cec5SDimitry Andric W.printEnum("Machine", E->e_machine, makeArrayRef(ElfMachineType)); 44390b57cec5SDimitry Andric W.printNumber("Version", E->e_version); 44400b57cec5SDimitry Andric W.printHex("Entry", E->e_entry); 44410b57cec5SDimitry Andric W.printHex("ProgramHeaderOffset", E->e_phoff); 44420b57cec5SDimitry Andric W.printHex("SectionHeaderOffset", E->e_shoff); 44430b57cec5SDimitry Andric if (E->e_machine == EM_MIPS) 44440b57cec5SDimitry Andric W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderMipsFlags), 44450b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), 44460b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_MACH)); 44470b57cec5SDimitry Andric else if (E->e_machine == EM_AMDGPU) 44480b57cec5SDimitry Andric W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags), 44490b57cec5SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH)); 44500b57cec5SDimitry Andric else if (E->e_machine == EM_RISCV) 44510b57cec5SDimitry Andric W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); 44520b57cec5SDimitry Andric else 44530b57cec5SDimitry Andric W.printFlags("Flags", E->e_flags); 44540b57cec5SDimitry Andric W.printNumber("HeaderSize", E->e_ehsize); 44550b57cec5SDimitry Andric W.printNumber("ProgramHeaderEntrySize", E->e_phentsize); 44560b57cec5SDimitry Andric W.printNumber("ProgramHeaderCount", E->e_phnum); 44570b57cec5SDimitry Andric W.printNumber("SectionHeaderEntrySize", E->e_shentsize); 44580b57cec5SDimitry Andric W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj)); 44590b57cec5SDimitry Andric W.printString("StringTableSectionIndex", 44600b57cec5SDimitry Andric getSectionHeaderTableIndexString(Obj)); 44610b57cec5SDimitry Andric } 44620b57cec5SDimitry Andric } 44630b57cec5SDimitry Andric 44640b57cec5SDimitry Andric template <class ELFT> 44650b57cec5SDimitry Andric void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) { 44660b57cec5SDimitry Andric DictScope Lists(W, "Groups"); 44670b57cec5SDimitry Andric std::vector<GroupSection> V = getGroups<ELFT>(Obj); 44680b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 44690b57cec5SDimitry Andric for (const GroupSection &G : V) { 44700b57cec5SDimitry Andric DictScope D(W, "Group"); 44710b57cec5SDimitry Andric W.printNumber("Name", G.Name, G.ShName); 44720b57cec5SDimitry Andric W.printNumber("Index", G.Index); 44730b57cec5SDimitry Andric W.printNumber("Link", G.Link); 44740b57cec5SDimitry Andric W.printNumber("Info", G.Info); 44750b57cec5SDimitry Andric W.printHex("Type", getGroupType(G.Type), G.Type); 44760b57cec5SDimitry Andric W.startLine() << "Signature: " << G.Signature << "\n"; 44770b57cec5SDimitry Andric 44780b57cec5SDimitry Andric ListScope L(W, "Section(s) in group"); 44790b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 44800b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 44810b57cec5SDimitry Andric if (MainGroup != &G) { 44820b57cec5SDimitry Andric W.flush(); 44830b57cec5SDimitry Andric errs() << "Error: " << GM.Name << " (" << GM.Index 44840b57cec5SDimitry Andric << ") in a group " + G.Name + " (" << G.Index 44850b57cec5SDimitry Andric << ") is already in a group " + MainGroup->Name + " (" 44860b57cec5SDimitry Andric << MainGroup->Index << ")\n"; 44870b57cec5SDimitry Andric errs().flush(); 44880b57cec5SDimitry Andric continue; 44890b57cec5SDimitry Andric } 44900b57cec5SDimitry Andric W.startLine() << GM.Name << " (" << GM.Index << ")\n"; 44910b57cec5SDimitry Andric } 44920b57cec5SDimitry Andric } 44930b57cec5SDimitry Andric 44940b57cec5SDimitry Andric if (V.empty()) 44950b57cec5SDimitry Andric W.startLine() << "There are no group sections in the file.\n"; 44960b57cec5SDimitry Andric } 44970b57cec5SDimitry Andric 44980b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) { 44990b57cec5SDimitry Andric ListScope D(W, "Relocations"); 45000b57cec5SDimitry Andric 45010b57cec5SDimitry Andric int SectionNumber = -1; 45020b57cec5SDimitry Andric for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { 45030b57cec5SDimitry Andric ++SectionNumber; 45040b57cec5SDimitry Andric 45050b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && 45060b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && 45070b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_ANDROID_RELA && 45080b57cec5SDimitry Andric Sec.sh_type != ELF::SHT_ANDROID_RELR) 45090b57cec5SDimitry Andric continue; 45100b57cec5SDimitry Andric 45110b57cec5SDimitry Andric StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); 45120b57cec5SDimitry Andric 45130b57cec5SDimitry Andric W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; 45140b57cec5SDimitry Andric W.indent(); 45150b57cec5SDimitry Andric 45160b57cec5SDimitry Andric printRelocations(&Sec, Obj); 45170b57cec5SDimitry Andric 45180b57cec5SDimitry Andric W.unindent(); 45190b57cec5SDimitry Andric W.startLine() << "}\n"; 45200b57cec5SDimitry Andric } 45210b57cec5SDimitry Andric } 45220b57cec5SDimitry Andric 45230b57cec5SDimitry Andric template <class ELFT> 45240b57cec5SDimitry Andric void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { 45250b57cec5SDimitry Andric const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); 45260b57cec5SDimitry Andric 45270b57cec5SDimitry Andric switch (Sec->sh_type) { 45280b57cec5SDimitry Andric case ELF::SHT_REL: 45290b57cec5SDimitry Andric for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) { 45300b57cec5SDimitry Andric Elf_Rela Rela; 45310b57cec5SDimitry Andric Rela.r_offset = R.r_offset; 45320b57cec5SDimitry Andric Rela.r_info = R.r_info; 45330b57cec5SDimitry Andric Rela.r_addend = 0; 45340b57cec5SDimitry Andric printRelocation(Obj, Rela, SymTab); 45350b57cec5SDimitry Andric } 45360b57cec5SDimitry Andric break; 45370b57cec5SDimitry Andric case ELF::SHT_RELA: 45380b57cec5SDimitry Andric for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) 45390b57cec5SDimitry Andric printRelocation(Obj, R, SymTab); 45400b57cec5SDimitry Andric break; 45410b57cec5SDimitry Andric case ELF::SHT_RELR: 45420b57cec5SDimitry Andric case ELF::SHT_ANDROID_RELR: { 45430b57cec5SDimitry Andric Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); 45440b57cec5SDimitry Andric if (opts::RawRelr) { 45450b57cec5SDimitry Andric for (const Elf_Relr &R : Relrs) 45460b57cec5SDimitry Andric W.startLine() << W.hex(R) << "\n"; 45470b57cec5SDimitry Andric } else { 45480b57cec5SDimitry Andric std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); 45490b57cec5SDimitry Andric for (const Elf_Rela &R : RelrRelas) 45500b57cec5SDimitry Andric printRelocation(Obj, R, SymTab); 45510b57cec5SDimitry Andric } 45520b57cec5SDimitry Andric break; 45530b57cec5SDimitry Andric } 45540b57cec5SDimitry Andric case ELF::SHT_ANDROID_REL: 45550b57cec5SDimitry Andric case ELF::SHT_ANDROID_RELA: 45560b57cec5SDimitry Andric for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec))) 45570b57cec5SDimitry Andric printRelocation(Obj, R, SymTab); 45580b57cec5SDimitry Andric break; 45590b57cec5SDimitry Andric } 45600b57cec5SDimitry Andric } 45610b57cec5SDimitry Andric 45620b57cec5SDimitry Andric template <class ELFT> 45630b57cec5SDimitry Andric void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel, 45640b57cec5SDimitry Andric const Elf_Shdr *SymTab) { 45650b57cec5SDimitry Andric SmallString<32> RelocName; 45660b57cec5SDimitry Andric Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); 45670b57cec5SDimitry Andric std::string TargetName; 45680b57cec5SDimitry Andric const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab)); 45690b57cec5SDimitry Andric if (Sym && Sym->getType() == ELF::STT_SECTION) { 45700b57cec5SDimitry Andric const Elf_Shdr *Sec = unwrapOrError( 45710b57cec5SDimitry Andric Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); 45720b57cec5SDimitry Andric TargetName = unwrapOrError(Obj->getSectionName(Sec)); 45730b57cec5SDimitry Andric } else if (Sym) { 45740b57cec5SDimitry Andric StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); 45750b57cec5SDimitry Andric TargetName = this->dumper()->getFullSymbolName( 45760b57cec5SDimitry Andric Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */); 45770b57cec5SDimitry Andric } 45780b57cec5SDimitry Andric 45790b57cec5SDimitry Andric if (opts::ExpandRelocs) { 45800b57cec5SDimitry Andric DictScope Group(W, "Relocation"); 45810b57cec5SDimitry Andric W.printHex("Offset", Rel.r_offset); 45820b57cec5SDimitry Andric W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); 45830b57cec5SDimitry Andric W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-", 45840b57cec5SDimitry Andric Rel.getSymbol(Obj->isMips64EL())); 45850b57cec5SDimitry Andric W.printHex("Addend", Rel.r_addend); 45860b57cec5SDimitry Andric } else { 45870b57cec5SDimitry Andric raw_ostream &OS = W.startLine(); 45880b57cec5SDimitry Andric OS << W.hex(Rel.r_offset) << " " << RelocName << " " 45890b57cec5SDimitry Andric << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Rel.r_addend) 45900b57cec5SDimitry Andric << "\n"; 45910b57cec5SDimitry Andric } 45920b57cec5SDimitry Andric } 45930b57cec5SDimitry Andric 45940b57cec5SDimitry Andric template <class ELFT> 45950b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) { 45960b57cec5SDimitry Andric ListScope SectionsD(W, "Sections"); 45970b57cec5SDimitry Andric 45980b57cec5SDimitry Andric int SectionIndex = -1; 45990b57cec5SDimitry Andric ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections()); 46000b57cec5SDimitry Andric const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject(); 46010b57cec5SDimitry Andric for (const Elf_Shdr &Sec : Sections) { 46020b57cec5SDimitry Andric StringRef Name = getSectionName(Sec, *ElfObj, Sections); 46030b57cec5SDimitry Andric DictScope SectionD(W, "Section"); 46040b57cec5SDimitry Andric W.printNumber("Index", ++SectionIndex); 46050b57cec5SDimitry Andric W.printNumber("Name", Name, Sec.sh_name); 46060b57cec5SDimitry Andric W.printHex( 46070b57cec5SDimitry Andric "Type", 46080b57cec5SDimitry Andric object::getELFSectionTypeName(Obj->getHeader()->e_machine, Sec.sh_type), 46090b57cec5SDimitry Andric Sec.sh_type); 46100b57cec5SDimitry Andric std::vector<EnumEntry<unsigned>> SectionFlags(std::begin(ElfSectionFlags), 46110b57cec5SDimitry Andric std::end(ElfSectionFlags)); 46120b57cec5SDimitry Andric switch (Obj->getHeader()->e_machine) { 46130b57cec5SDimitry Andric case EM_ARM: 46140b57cec5SDimitry Andric SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), 46150b57cec5SDimitry Andric std::end(ElfARMSectionFlags)); 46160b57cec5SDimitry Andric break; 46170b57cec5SDimitry Andric case EM_HEXAGON: 46180b57cec5SDimitry Andric SectionFlags.insert(SectionFlags.end(), 46190b57cec5SDimitry Andric std::begin(ElfHexagonSectionFlags), 46200b57cec5SDimitry Andric std::end(ElfHexagonSectionFlags)); 46210b57cec5SDimitry Andric break; 46220b57cec5SDimitry Andric case EM_MIPS: 46230b57cec5SDimitry Andric SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags), 46240b57cec5SDimitry Andric std::end(ElfMipsSectionFlags)); 46250b57cec5SDimitry Andric break; 46260b57cec5SDimitry Andric case EM_X86_64: 46270b57cec5SDimitry Andric SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags), 46280b57cec5SDimitry Andric std::end(ElfX86_64SectionFlags)); 46290b57cec5SDimitry Andric break; 46300b57cec5SDimitry Andric case EM_XCORE: 46310b57cec5SDimitry Andric SectionFlags.insert(SectionFlags.end(), std::begin(ElfXCoreSectionFlags), 46320b57cec5SDimitry Andric std::end(ElfXCoreSectionFlags)); 46330b57cec5SDimitry Andric break; 46340b57cec5SDimitry Andric default: 46350b57cec5SDimitry Andric // Nothing to do. 46360b57cec5SDimitry Andric break; 46370b57cec5SDimitry Andric } 46380b57cec5SDimitry Andric W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags)); 46390b57cec5SDimitry Andric W.printHex("Address", Sec.sh_addr); 46400b57cec5SDimitry Andric W.printHex("Offset", Sec.sh_offset); 46410b57cec5SDimitry Andric W.printNumber("Size", Sec.sh_size); 46420b57cec5SDimitry Andric W.printNumber("Link", Sec.sh_link); 46430b57cec5SDimitry Andric W.printNumber("Info", Sec.sh_info); 46440b57cec5SDimitry Andric W.printNumber("AddressAlignment", Sec.sh_addralign); 46450b57cec5SDimitry Andric W.printNumber("EntrySize", Sec.sh_entsize); 46460b57cec5SDimitry Andric 46470b57cec5SDimitry Andric if (opts::SectionRelocations) { 46480b57cec5SDimitry Andric ListScope D(W, "Relocations"); 46490b57cec5SDimitry Andric printRelocations(&Sec, Obj); 46500b57cec5SDimitry Andric } 46510b57cec5SDimitry Andric 46520b57cec5SDimitry Andric if (opts::SectionSymbols) { 46530b57cec5SDimitry Andric ListScope D(W, "Symbols"); 46540b57cec5SDimitry Andric const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec(); 46550b57cec5SDimitry Andric StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); 46560b57cec5SDimitry Andric 46570b57cec5SDimitry Andric for (const Elf_Sym &Sym : unwrapOrError(Obj->symbols(Symtab))) { 46580b57cec5SDimitry Andric const Elf_Shdr *SymSec = unwrapOrError( 46590b57cec5SDimitry Andric Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable())); 46600b57cec5SDimitry Andric if (SymSec == &Sec) 46610b57cec5SDimitry Andric printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(), 46620b57cec5SDimitry Andric StrTable, false); 46630b57cec5SDimitry Andric } 46640b57cec5SDimitry Andric } 46650b57cec5SDimitry Andric 46660b57cec5SDimitry Andric if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { 46670b57cec5SDimitry Andric ArrayRef<uint8_t> Data = unwrapOrError(Obj->getSectionContents(&Sec)); 46680b57cec5SDimitry Andric W.printBinaryBlock( 46690b57cec5SDimitry Andric "SectionData", 46700b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Data.data()), Data.size())); 46710b57cec5SDimitry Andric } 46720b57cec5SDimitry Andric } 46730b57cec5SDimitry Andric } 46740b57cec5SDimitry Andric 46750b57cec5SDimitry Andric template <class ELFT> 46760b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, 46770b57cec5SDimitry Andric const Elf_Sym *First, StringRef StrTable, 46780b57cec5SDimitry Andric bool IsDynamic) { 46790b57cec5SDimitry Andric unsigned SectionIndex = 0; 46800b57cec5SDimitry Andric StringRef SectionName; 46810b57cec5SDimitry Andric this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex); 46820b57cec5SDimitry Andric std::string FullSymbolName = 46830b57cec5SDimitry Andric this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); 46840b57cec5SDimitry Andric unsigned char SymbolType = Symbol->getType(); 46850b57cec5SDimitry Andric 46860b57cec5SDimitry Andric DictScope D(W, "Symbol"); 46870b57cec5SDimitry Andric W.printNumber("Name", FullSymbolName, Symbol->st_name); 46880b57cec5SDimitry Andric W.printHex("Value", Symbol->st_value); 46890b57cec5SDimitry Andric W.printNumber("Size", Symbol->st_size); 46900b57cec5SDimitry Andric W.printEnum("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); 46910b57cec5SDimitry Andric if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && 46920b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 46930b57cec5SDimitry Andric W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); 46940b57cec5SDimitry Andric else 46950b57cec5SDimitry Andric W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); 46960b57cec5SDimitry Andric if (Symbol->st_other == 0) 46970b57cec5SDimitry Andric // Usually st_other flag is zero. Do not pollute the output 46980b57cec5SDimitry Andric // by flags enumeration in that case. 46990b57cec5SDimitry Andric W.printNumber("Other", 0); 47000b57cec5SDimitry Andric else { 47010b57cec5SDimitry Andric std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags), 47020b57cec5SDimitry Andric std::end(ElfSymOtherFlags)); 47030b57cec5SDimitry Andric if (Obj->getHeader()->e_machine == EM_MIPS) { 47040b57cec5SDimitry Andric // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16 47050b57cec5SDimitry Andric // flag overlapped with other ST_MIPS_xxx flags. So consider both 47060b57cec5SDimitry Andric // cases separately. 47070b57cec5SDimitry Andric if ((Symbol->st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) 47080b57cec5SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 47090b57cec5SDimitry Andric std::begin(ElfMips16SymOtherFlags), 47100b57cec5SDimitry Andric std::end(ElfMips16SymOtherFlags)); 47110b57cec5SDimitry Andric else 47120b57cec5SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 47130b57cec5SDimitry Andric std::begin(ElfMipsSymOtherFlags), 47140b57cec5SDimitry Andric std::end(ElfMipsSymOtherFlags)); 47150b57cec5SDimitry Andric } 47160b57cec5SDimitry Andric W.printFlags("Other", Symbol->st_other, makeArrayRef(SymOtherFlags), 0x3u); 47170b57cec5SDimitry Andric } 47180b57cec5SDimitry Andric W.printHex("Section", SectionName, SectionIndex); 47190b57cec5SDimitry Andric } 47200b57cec5SDimitry Andric 47210b57cec5SDimitry Andric template <class ELFT> 47220b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols, 47230b57cec5SDimitry Andric bool PrintDynamicSymbols) { 47240b57cec5SDimitry Andric if (PrintSymbols) 47250b57cec5SDimitry Andric printSymbols(Obj); 47260b57cec5SDimitry Andric if (PrintDynamicSymbols) 47270b57cec5SDimitry Andric printDynamicSymbols(Obj); 47280b57cec5SDimitry Andric } 47290b57cec5SDimitry Andric 47300b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) { 47310b57cec5SDimitry Andric ListScope Group(W, "Symbols"); 47320b57cec5SDimitry Andric this->dumper()->printSymbolsHelper(false); 47330b57cec5SDimitry Andric } 47340b57cec5SDimitry Andric 47350b57cec5SDimitry Andric template <class ELFT> 47360b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { 47370b57cec5SDimitry Andric ListScope Group(W, "DynamicSymbols"); 47380b57cec5SDimitry Andric this->dumper()->printSymbolsHelper(true); 47390b57cec5SDimitry Andric } 47400b57cec5SDimitry Andric 47410b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Obj) { 47420b57cec5SDimitry Andric Elf_Dyn_Range Table = this->dumper()->dynamic_table(); 47430b57cec5SDimitry Andric if (Table.empty()) 47440b57cec5SDimitry Andric return; 47450b57cec5SDimitry Andric 47460b57cec5SDimitry Andric raw_ostream &OS = W.getOStream(); 47470b57cec5SDimitry Andric W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n"; 47480b57cec5SDimitry Andric 47490b57cec5SDimitry Andric bool Is64 = ELFT::Is64Bits; 47500b57cec5SDimitry Andric if (Is64) 47510b57cec5SDimitry Andric W.startLine() << " Tag Type Name/Value\n"; 47520b57cec5SDimitry Andric else 47530b57cec5SDimitry Andric W.startLine() << " Tag Type Name/Value\n"; 47540b57cec5SDimitry Andric for (auto Entry : Table) { 47550b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 47560b57cec5SDimitry Andric W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, true) << " " 47570b57cec5SDimitry Andric << format("%-21s", 47580b57cec5SDimitry Andric getTypeString(Obj->getHeader()->e_machine, Tag)); 47590b57cec5SDimitry Andric this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal()); 47600b57cec5SDimitry Andric OS << "\n"; 47610b57cec5SDimitry Andric } 47620b57cec5SDimitry Andric 47630b57cec5SDimitry Andric W.startLine() << "]\n"; 47640b57cec5SDimitry Andric } 47650b57cec5SDimitry Andric 47660b57cec5SDimitry Andric template <class ELFT> 47670b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { 47680b57cec5SDimitry Andric const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); 47690b57cec5SDimitry Andric const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); 47700b57cec5SDimitry Andric const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); 47710b57cec5SDimitry Andric const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); 47720b57cec5SDimitry Andric if (DynRelRegion.Size && DynRelaRegion.Size) 47730b57cec5SDimitry Andric report_fatal_error("There are both REL and RELA dynamic relocations"); 47740b57cec5SDimitry Andric W.startLine() << "Dynamic Relocations {\n"; 47750b57cec5SDimitry Andric W.indent(); 47760b57cec5SDimitry Andric if (DynRelaRegion.Size > 0) 47770b57cec5SDimitry Andric for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) 47780b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela); 47790b57cec5SDimitry Andric else 47800b57cec5SDimitry Andric for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { 47810b57cec5SDimitry Andric Elf_Rela Rela; 47820b57cec5SDimitry Andric Rela.r_offset = Rel.r_offset; 47830b57cec5SDimitry Andric Rela.r_info = Rel.r_info; 47840b57cec5SDimitry Andric Rela.r_addend = 0; 47850b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela); 47860b57cec5SDimitry Andric } 47870b57cec5SDimitry Andric if (DynRelrRegion.Size > 0) { 47880b57cec5SDimitry Andric Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); 47890b57cec5SDimitry Andric std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); 47900b57cec5SDimitry Andric for (const Elf_Rela &Rela : RelrRelas) 47910b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela); 47920b57cec5SDimitry Andric } 47930b57cec5SDimitry Andric if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) 47940b57cec5SDimitry Andric for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) 47950b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela); 47960b57cec5SDimitry Andric else 47970b57cec5SDimitry Andric for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { 47980b57cec5SDimitry Andric Elf_Rela Rela; 47990b57cec5SDimitry Andric Rela.r_offset = Rel.r_offset; 48000b57cec5SDimitry Andric Rela.r_info = Rel.r_info; 48010b57cec5SDimitry Andric Rela.r_addend = 0; 48020b57cec5SDimitry Andric printDynamicRelocation(Obj, Rela); 48030b57cec5SDimitry Andric } 48040b57cec5SDimitry Andric W.unindent(); 48050b57cec5SDimitry Andric W.startLine() << "}\n"; 48060b57cec5SDimitry Andric } 48070b57cec5SDimitry Andric 48080b57cec5SDimitry Andric template <class ELFT> 48090b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { 48100b57cec5SDimitry Andric SmallString<32> RelocName; 48110b57cec5SDimitry Andric Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); 48120b57cec5SDimitry Andric std::string SymbolName; 48130b57cec5SDimitry Andric uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); 48140b57cec5SDimitry Andric const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; 48150b57cec5SDimitry Andric SymbolName = maybeDemangle( 48160b57cec5SDimitry Andric unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable()))); 48170b57cec5SDimitry Andric if (opts::ExpandRelocs) { 48180b57cec5SDimitry Andric DictScope Group(W, "Relocation"); 48190b57cec5SDimitry Andric W.printHex("Offset", Rel.r_offset); 48200b57cec5SDimitry Andric W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); 48210b57cec5SDimitry Andric W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); 48220b57cec5SDimitry Andric W.printHex("Addend", Rel.r_addend); 48230b57cec5SDimitry Andric } else { 48240b57cec5SDimitry Andric raw_ostream &OS = W.startLine(); 48250b57cec5SDimitry Andric OS << W.hex(Rel.r_offset) << " " << RelocName << " " 48260b57cec5SDimitry Andric << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Rel.r_addend) 48270b57cec5SDimitry Andric << "\n"; 48280b57cec5SDimitry Andric } 48290b57cec5SDimitry Andric } 48300b57cec5SDimitry Andric 48310b57cec5SDimitry Andric template <class ELFT> 48320b57cec5SDimitry Andric void LLVMStyle<ELFT>::printProgramHeaders( 48330b57cec5SDimitry Andric const ELFO *Obj, bool PrintProgramHeaders, 48340b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) { 48350b57cec5SDimitry Andric if (PrintProgramHeaders) 48360b57cec5SDimitry Andric printProgramHeaders(Obj); 48370b57cec5SDimitry Andric if (PrintSectionMapping == cl::BOU_TRUE) 48380b57cec5SDimitry Andric printSectionMapping(Obj); 48390b57cec5SDimitry Andric } 48400b57cec5SDimitry Andric 48410b57cec5SDimitry Andric template <class ELFT> 48420b57cec5SDimitry Andric void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { 48430b57cec5SDimitry Andric ListScope L(W, "ProgramHeaders"); 48440b57cec5SDimitry Andric 48450b57cec5SDimitry Andric for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { 48460b57cec5SDimitry Andric DictScope P(W, "ProgramHeader"); 48470b57cec5SDimitry Andric W.printHex("Type", 48480b57cec5SDimitry Andric getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), 48490b57cec5SDimitry Andric Phdr.p_type); 48500b57cec5SDimitry Andric W.printHex("Offset", Phdr.p_offset); 48510b57cec5SDimitry Andric W.printHex("VirtualAddress", Phdr.p_vaddr); 48520b57cec5SDimitry Andric W.printHex("PhysicalAddress", Phdr.p_paddr); 48530b57cec5SDimitry Andric W.printNumber("FileSize", Phdr.p_filesz); 48540b57cec5SDimitry Andric W.printNumber("MemSize", Phdr.p_memsz); 48550b57cec5SDimitry Andric W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags)); 48560b57cec5SDimitry Andric W.printNumber("Alignment", Phdr.p_align); 48570b57cec5SDimitry Andric } 48580b57cec5SDimitry Andric } 48590b57cec5SDimitry Andric 48600b57cec5SDimitry Andric template <class ELFT> 48610b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj, 48620b57cec5SDimitry Andric const Elf_Shdr *Sec) { 48630b57cec5SDimitry Andric DictScope SS(W, "Version symbols"); 48640b57cec5SDimitry Andric if (!Sec) 48650b57cec5SDimitry Andric return; 48660b57cec5SDimitry Andric 48670b57cec5SDimitry Andric StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); 48680b57cec5SDimitry Andric W.printNumber("Section Name", SecName, Sec->sh_name); 48690b57cec5SDimitry Andric W.printHex("Address", Sec->sh_addr); 48700b57cec5SDimitry Andric W.printHex("Offset", Sec->sh_offset); 48710b57cec5SDimitry Andric W.printNumber("Link", Sec->sh_link); 48720b57cec5SDimitry Andric 48730b57cec5SDimitry Andric const uint8_t *VersymBuf = 48740b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset); 48750b57cec5SDimitry Andric const ELFDumper<ELFT> *Dumper = this->dumper(); 48760b57cec5SDimitry Andric StringRef StrTable = Dumper->getDynamicStringTable(); 48770b57cec5SDimitry Andric 48780b57cec5SDimitry Andric // Same number of entries in the dynamic symbol table (DT_SYMTAB). 48790b57cec5SDimitry Andric ListScope Syms(W, "Symbols"); 48800b57cec5SDimitry Andric for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) { 48810b57cec5SDimitry Andric DictScope S(W, "Symbol"); 48820b57cec5SDimitry Andric const Elf_Versym *Versym = reinterpret_cast<const Elf_Versym *>(VersymBuf); 48830b57cec5SDimitry Andric std::string FullSymbolName = 48840b57cec5SDimitry Andric Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); 48850b57cec5SDimitry Andric W.printNumber("Version", Versym->vs_index & VERSYM_VERSION); 48860b57cec5SDimitry Andric W.printString("Name", FullSymbolName); 48870b57cec5SDimitry Andric VersymBuf += sizeof(Elf_Versym); 48880b57cec5SDimitry Andric } 48890b57cec5SDimitry Andric } 48900b57cec5SDimitry Andric 48910b57cec5SDimitry Andric template <class ELFT> 48920b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj, 48930b57cec5SDimitry Andric const Elf_Shdr *Sec) { 48940b57cec5SDimitry Andric DictScope SD(W, "SHT_GNU_verdef"); 48950b57cec5SDimitry Andric if (!Sec) 48960b57cec5SDimitry Andric return; 48970b57cec5SDimitry Andric 48980b57cec5SDimitry Andric const uint8_t *SecStartAddress = 48990b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset); 49000b57cec5SDimitry Andric const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size; 49010b57cec5SDimitry Andric const uint8_t *VerdefBuf = SecStartAddress; 49020b57cec5SDimitry Andric const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link)); 49030b57cec5SDimitry Andric 49040b57cec5SDimitry Andric unsigned VerDefsNum = Sec->sh_info; 49050b57cec5SDimitry Andric while (VerDefsNum--) { 49060b57cec5SDimitry Andric if (VerdefBuf + sizeof(Elf_Verdef) > SecEndAddress) 49070b57cec5SDimitry Andric // FIXME: report_fatal_error is not a good way to report error. We should 49080b57cec5SDimitry Andric // emit a parsing error here and below. 49090b57cec5SDimitry Andric report_fatal_error("invalid offset in the section"); 49100b57cec5SDimitry Andric 49110b57cec5SDimitry Andric const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf); 49120b57cec5SDimitry Andric DictScope Def(W, "Definition"); 49130b57cec5SDimitry Andric W.printNumber("Version", Verdef->vd_version); 49140b57cec5SDimitry Andric W.printEnum("Flags", Verdef->vd_flags, makeArrayRef(SymVersionFlags)); 49150b57cec5SDimitry Andric W.printNumber("Index", Verdef->vd_ndx); 49160b57cec5SDimitry Andric W.printNumber("Hash", Verdef->vd_hash); 49170b57cec5SDimitry Andric W.printString("Name", StringRef(reinterpret_cast<const char *>( 49180b57cec5SDimitry Andric Obj->base() + StrTab->sh_offset + 49190b57cec5SDimitry Andric Verdef->getAux()->vda_name))); 49200b57cec5SDimitry Andric if (!Verdef->vd_cnt) 49210b57cec5SDimitry Andric report_fatal_error("at least one definition string must exist"); 49220b57cec5SDimitry Andric if (Verdef->vd_cnt > 2) 49230b57cec5SDimitry Andric report_fatal_error("more than one predecessor is not expected"); 49240b57cec5SDimitry Andric 49250b57cec5SDimitry Andric if (Verdef->vd_cnt == 2) { 49260b57cec5SDimitry Andric const uint8_t *VerdauxBuf = 49270b57cec5SDimitry Andric VerdefBuf + Verdef->vd_aux + Verdef->getAux()->vda_next; 49280b57cec5SDimitry Andric const Elf_Verdaux *Verdaux = 49290b57cec5SDimitry Andric reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf); 49300b57cec5SDimitry Andric W.printString("Predecessor", 49310b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>( 49320b57cec5SDimitry Andric Obj->base() + StrTab->sh_offset + Verdaux->vda_name))); 49330b57cec5SDimitry Andric } 49340b57cec5SDimitry Andric VerdefBuf += Verdef->vd_next; 49350b57cec5SDimitry Andric } 49360b57cec5SDimitry Andric } 49370b57cec5SDimitry Andric 49380b57cec5SDimitry Andric template <class ELFT> 49390b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj, 49400b57cec5SDimitry Andric const Elf_Shdr *Sec) { 49410b57cec5SDimitry Andric DictScope SD(W, "SHT_GNU_verneed"); 49420b57cec5SDimitry Andric if (!Sec) 49430b57cec5SDimitry Andric return; 49440b57cec5SDimitry Andric 49450b57cec5SDimitry Andric const uint8_t *SecData = 49460b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset); 49470b57cec5SDimitry Andric const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link)); 49480b57cec5SDimitry Andric 49490b57cec5SDimitry Andric const uint8_t *VerneedBuf = SecData; 49500b57cec5SDimitry Andric unsigned VerneedNum = Sec->sh_info; 49510b57cec5SDimitry Andric for (unsigned I = 0; I < VerneedNum; ++I) { 49520b57cec5SDimitry Andric const Elf_Verneed *Verneed = 49530b57cec5SDimitry Andric reinterpret_cast<const Elf_Verneed *>(VerneedBuf); 49540b57cec5SDimitry Andric DictScope Entry(W, "Dependency"); 49550b57cec5SDimitry Andric W.printNumber("Version", Verneed->vn_version); 49560b57cec5SDimitry Andric W.printNumber("Count", Verneed->vn_cnt); 49570b57cec5SDimitry Andric W.printString("FileName", 49580b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>( 49590b57cec5SDimitry Andric Obj->base() + StrTab->sh_offset + Verneed->vn_file))); 49600b57cec5SDimitry Andric 49610b57cec5SDimitry Andric const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux; 49620b57cec5SDimitry Andric ListScope L(W, "Entries"); 49630b57cec5SDimitry Andric for (unsigned J = 0; J < Verneed->vn_cnt; ++J) { 49640b57cec5SDimitry Andric const Elf_Vernaux *Vernaux = 49650b57cec5SDimitry Andric reinterpret_cast<const Elf_Vernaux *>(VernauxBuf); 49660b57cec5SDimitry Andric DictScope Entry(W, "Entry"); 49670b57cec5SDimitry Andric W.printNumber("Hash", Vernaux->vna_hash); 49680b57cec5SDimitry Andric W.printEnum("Flags", Vernaux->vna_flags, makeArrayRef(SymVersionFlags)); 49690b57cec5SDimitry Andric W.printNumber("Index", Vernaux->vna_other); 49700b57cec5SDimitry Andric W.printString("Name", 49710b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>( 49720b57cec5SDimitry Andric Obj->base() + StrTab->sh_offset + Vernaux->vna_name))); 49730b57cec5SDimitry Andric VernauxBuf += Vernaux->vna_next; 49740b57cec5SDimitry Andric } 49750b57cec5SDimitry Andric VerneedBuf += Verneed->vn_next; 49760b57cec5SDimitry Andric } 49770b57cec5SDimitry Andric } 49780b57cec5SDimitry Andric 49790b57cec5SDimitry Andric template <class ELFT> 49800b57cec5SDimitry Andric void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { 49810b57cec5SDimitry Andric W.startLine() << "Hash Histogram not implemented!\n"; 49820b57cec5SDimitry Andric } 49830b57cec5SDimitry Andric 49840b57cec5SDimitry Andric template <class ELFT> 49850b57cec5SDimitry Andric void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { 49860b57cec5SDimitry Andric ListScope L(W, "CGProfile"); 49870b57cec5SDimitry Andric if (!this->dumper()->getDotCGProfileSec()) 49880b57cec5SDimitry Andric return; 49890b57cec5SDimitry Andric auto CGProfile = 49900b57cec5SDimitry Andric unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>( 49910b57cec5SDimitry Andric this->dumper()->getDotCGProfileSec())); 49920b57cec5SDimitry Andric for (const Elf_CGProfile &CGPE : CGProfile) { 49930b57cec5SDimitry Andric DictScope D(W, "CGProfileEntry"); 49940b57cec5SDimitry Andric W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), 49950b57cec5SDimitry Andric CGPE.cgp_from); 49960b57cec5SDimitry Andric W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), 49970b57cec5SDimitry Andric CGPE.cgp_to); 49980b57cec5SDimitry Andric W.printNumber("Weight", CGPE.cgp_weight); 49990b57cec5SDimitry Andric } 50000b57cec5SDimitry Andric } 50010b57cec5SDimitry Andric 50020b57cec5SDimitry Andric template <class ELFT> 50030b57cec5SDimitry Andric void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { 50040b57cec5SDimitry Andric ListScope L(W, "Addrsig"); 50050b57cec5SDimitry Andric if (!this->dumper()->getDotAddrsigSec()) 50060b57cec5SDimitry Andric return; 50070b57cec5SDimitry Andric ArrayRef<uint8_t> Contents = unwrapOrError( 50080b57cec5SDimitry Andric Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); 50090b57cec5SDimitry Andric const uint8_t *Cur = Contents.begin(); 50100b57cec5SDimitry Andric const uint8_t *End = Contents.end(); 50110b57cec5SDimitry Andric while (Cur != End) { 50120b57cec5SDimitry Andric unsigned Size; 50130b57cec5SDimitry Andric const char *Err; 50140b57cec5SDimitry Andric uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err); 50150b57cec5SDimitry Andric if (Err) 50160b57cec5SDimitry Andric reportError(Err); 50170b57cec5SDimitry Andric W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), 50180b57cec5SDimitry Andric SymIndex); 50190b57cec5SDimitry Andric Cur += Size; 50200b57cec5SDimitry Andric } 50210b57cec5SDimitry Andric } 50220b57cec5SDimitry Andric 50230b57cec5SDimitry Andric template <typename ELFT> 50240b57cec5SDimitry Andric static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, 50250b57cec5SDimitry Andric ScopedPrinter &W) { 50260b57cec5SDimitry Andric switch (NoteType) { 50270b57cec5SDimitry Andric default: 50280b57cec5SDimitry Andric return; 50290b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 50300b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 50310b57cec5SDimitry Andric if (!AbiTag.IsValid) { 50320b57cec5SDimitry Andric W.printString("ABI", "<corrupt GNU_ABI_TAG>"); 50330b57cec5SDimitry Andric } else { 50340b57cec5SDimitry Andric W.printString("OS", AbiTag.OSName); 50350b57cec5SDimitry Andric W.printString("ABI", AbiTag.ABI); 50360b57cec5SDimitry Andric } 50370b57cec5SDimitry Andric break; 50380b57cec5SDimitry Andric } 50390b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 50400b57cec5SDimitry Andric W.printString("Build ID", getGNUBuildId(Desc)); 50410b57cec5SDimitry Andric break; 50420b57cec5SDimitry Andric } 50430b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 50440b57cec5SDimitry Andric W.printString("Version", getGNUGoldVersion(Desc)); 50450b57cec5SDimitry Andric break; 50460b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 50470b57cec5SDimitry Andric ListScope D(W, "Property"); 50480b57cec5SDimitry Andric for (const auto &Property : getGNUPropertyList<ELFT>(Desc)) 50490b57cec5SDimitry Andric W.printString(Property); 50500b57cec5SDimitry Andric break; 50510b57cec5SDimitry Andric } 50520b57cec5SDimitry Andric } 50530b57cec5SDimitry Andric 50540b57cec5SDimitry Andric template <class ELFT> 50550b57cec5SDimitry Andric void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { 50560b57cec5SDimitry Andric ListScope L(W, "Notes"); 50570b57cec5SDimitry Andric 50580b57cec5SDimitry Andric auto PrintHeader = [&](const typename ELFT::Off Offset, 50590b57cec5SDimitry Andric const typename ELFT::Addr Size) { 50600b57cec5SDimitry Andric W.printHex("Offset", Offset); 50610b57cec5SDimitry Andric W.printHex("Size", Size); 50620b57cec5SDimitry Andric }; 50630b57cec5SDimitry Andric 50640b57cec5SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note) { 50650b57cec5SDimitry Andric DictScope D2(W, "Note"); 50660b57cec5SDimitry Andric StringRef Name = Note.getName(); 50670b57cec5SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(); 50680b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 50690b57cec5SDimitry Andric 50700b57cec5SDimitry Andric W.printString("Owner", Name); 50710b57cec5SDimitry Andric W.printHex("Data size", Descriptor.size()); 50720b57cec5SDimitry Andric if (Name == "GNU") { 50730b57cec5SDimitry Andric W.printString("Type", getGNUNoteTypeName(Type)); 50740b57cec5SDimitry Andric printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W); 50750b57cec5SDimitry Andric } else if (Name == "FreeBSD") { 50760b57cec5SDimitry Andric W.printString("Type", getFreeBSDNoteTypeName(Type)); 50770b57cec5SDimitry Andric } else if (Name == "AMD") { 50780b57cec5SDimitry Andric W.printString("Type", getAMDNoteTypeName(Type)); 50790b57cec5SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 50800b57cec5SDimitry Andric if (!N.Type.empty()) 50810b57cec5SDimitry Andric W.printString(N.Type, N.Value); 50820b57cec5SDimitry Andric } else if (Name == "AMDGPU") { 50830b57cec5SDimitry Andric W.printString("Type", getAMDGPUNoteTypeName(Type)); 50840b57cec5SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 50850b57cec5SDimitry Andric if (!N.Type.empty()) 50860b57cec5SDimitry Andric W.printString(N.Type, N.Value); 50870b57cec5SDimitry Andric } else { 50880b57cec5SDimitry Andric StringRef NoteType = getGenericNoteTypeName(Type); 50890b57cec5SDimitry Andric if (!NoteType.empty()) 50900b57cec5SDimitry Andric W.printString("Type", NoteType); 50910b57cec5SDimitry Andric else 50920b57cec5SDimitry Andric W.printString("Type", 50930b57cec5SDimitry Andric "Unknown (" + to_string(format_hex(Type, 10)) + ")"); 50940b57cec5SDimitry Andric } 50950b57cec5SDimitry Andric }; 50960b57cec5SDimitry Andric 50970b57cec5SDimitry Andric if (Obj->getHeader()->e_type == ELF::ET_CORE) { 50980b57cec5SDimitry Andric for (const auto &P : unwrapOrError(Obj->program_headers())) { 50990b57cec5SDimitry Andric if (P.p_type != PT_NOTE) 51000b57cec5SDimitry Andric continue; 51010b57cec5SDimitry Andric DictScope D(W, "NoteSection"); 51020b57cec5SDimitry Andric PrintHeader(P.p_offset, P.p_filesz); 51030b57cec5SDimitry Andric Error Err = Error::success(); 51040b57cec5SDimitry Andric for (const auto &Note : Obj->notes(P, Err)) 51050b57cec5SDimitry Andric ProcessNote(Note); 51060b57cec5SDimitry Andric if (Err) 51070b57cec5SDimitry Andric error(std::move(Err)); 51080b57cec5SDimitry Andric } 51090b57cec5SDimitry Andric } else { 51100b57cec5SDimitry Andric for (const auto &S : unwrapOrError(Obj->sections())) { 51110b57cec5SDimitry Andric if (S.sh_type != SHT_NOTE) 51120b57cec5SDimitry Andric continue; 51130b57cec5SDimitry Andric DictScope D(W, "NoteSection"); 51140b57cec5SDimitry Andric PrintHeader(S.sh_offset, S.sh_size); 51150b57cec5SDimitry Andric Error Err = Error::success(); 51160b57cec5SDimitry Andric for (const auto &Note : Obj->notes(S, Err)) 51170b57cec5SDimitry Andric ProcessNote(Note); 51180b57cec5SDimitry Andric if (Err) 51190b57cec5SDimitry Andric error(std::move(Err)); 51200b57cec5SDimitry Andric } 51210b57cec5SDimitry Andric } 51220b57cec5SDimitry Andric } 51230b57cec5SDimitry Andric 51240b57cec5SDimitry Andric template <class ELFT> 51250b57cec5SDimitry Andric void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { 51260b57cec5SDimitry Andric ListScope L(W, "LinkerOptions"); 51270b57cec5SDimitry Andric 51280b57cec5SDimitry Andric for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) { 51290b57cec5SDimitry Andric if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) 51300b57cec5SDimitry Andric continue; 51310b57cec5SDimitry Andric 51320b57cec5SDimitry Andric ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr)); 51330b57cec5SDimitry Andric for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) { 51340b57cec5SDimitry Andric StringRef Key = StringRef(reinterpret_cast<const char *>(P)); 51350b57cec5SDimitry Andric StringRef Value = 51360b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1); 51370b57cec5SDimitry Andric 51380b57cec5SDimitry Andric W.printString(Key, Value); 51390b57cec5SDimitry Andric 51400b57cec5SDimitry Andric P = P + Key.size() + Value.size() + 2; 51410b57cec5SDimitry Andric } 51420b57cec5SDimitry Andric } 51430b57cec5SDimitry Andric } 51440b57cec5SDimitry Andric 51450b57cec5SDimitry Andric template <class ELFT> 51460b57cec5SDimitry Andric void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 51470b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 51480b57cec5SDimitry Andric W.printHex("Address", Parser.getGotAddress(E)); 51490b57cec5SDimitry Andric W.printNumber("Access", Parser.getGotOffset(E)); 51500b57cec5SDimitry Andric W.printHex("Initial", *E); 51510b57cec5SDimitry Andric }; 51520b57cec5SDimitry Andric 51530b57cec5SDimitry Andric DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); 51540b57cec5SDimitry Andric 51550b57cec5SDimitry Andric W.printHex("Canonical gp value", Parser.getGp()); 51560b57cec5SDimitry Andric { 51570b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 51580b57cec5SDimitry Andric { 51590b57cec5SDimitry Andric DictScope D(W, "Entry"); 51600b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver()); 51610b57cec5SDimitry Andric W.printString("Purpose", StringRef("Lazy resolver")); 51620b57cec5SDimitry Andric } 51630b57cec5SDimitry Andric 51640b57cec5SDimitry Andric if (Parser.getGotModulePointer()) { 51650b57cec5SDimitry Andric DictScope D(W, "Entry"); 51660b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer()); 51670b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer (GNU extension)")); 51680b57cec5SDimitry Andric } 51690b57cec5SDimitry Andric } 51700b57cec5SDimitry Andric { 51710b57cec5SDimitry Andric ListScope LS(W, "Local entries"); 51720b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) { 51730b57cec5SDimitry Andric DictScope D(W, "Entry"); 51740b57cec5SDimitry Andric PrintEntry(&E); 51750b57cec5SDimitry Andric } 51760b57cec5SDimitry Andric } 51770b57cec5SDimitry Andric 51780b57cec5SDimitry Andric if (Parser.IsStatic) 51790b57cec5SDimitry Andric return; 51800b57cec5SDimitry Andric 51810b57cec5SDimitry Andric { 51820b57cec5SDimitry Andric ListScope GS(W, "Global entries"); 51830b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 51840b57cec5SDimitry Andric DictScope D(W, "Entry"); 51850b57cec5SDimitry Andric 51860b57cec5SDimitry Andric PrintEntry(&E); 51870b57cec5SDimitry Andric 51880b57cec5SDimitry Andric const Elf_Sym *Sym = Parser.getGotSym(&E); 51890b57cec5SDimitry Andric W.printHex("Value", Sym->st_value); 51900b57cec5SDimitry Andric W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); 51910b57cec5SDimitry Andric 51920b57cec5SDimitry Andric unsigned SectionIndex = 0; 51930b57cec5SDimitry Andric StringRef SectionName; 51940b57cec5SDimitry Andric this->dumper()->getSectionNameIndex( 51950b57cec5SDimitry Andric Sym, this->dumper()->dynamic_symbols().begin(), SectionName, 51960b57cec5SDimitry Andric SectionIndex); 51970b57cec5SDimitry Andric W.printHex("Section", SectionName, SectionIndex); 51980b57cec5SDimitry Andric 51990b57cec5SDimitry Andric std::string SymName = this->dumper()->getFullSymbolName( 52000b57cec5SDimitry Andric Sym, this->dumper()->getDynamicStringTable(), true); 52010b57cec5SDimitry Andric W.printNumber("Name", SymName, Sym->st_name); 52020b57cec5SDimitry Andric } 52030b57cec5SDimitry Andric } 52040b57cec5SDimitry Andric 52050b57cec5SDimitry Andric W.printNumber("Number of TLS and multi-GOT entries", 52060b57cec5SDimitry Andric uint64_t(Parser.getOtherEntries().size())); 52070b57cec5SDimitry Andric } 52080b57cec5SDimitry Andric 52090b57cec5SDimitry Andric template <class ELFT> 52100b57cec5SDimitry Andric void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 52110b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 52120b57cec5SDimitry Andric W.printHex("Address", Parser.getPltAddress(E)); 52130b57cec5SDimitry Andric W.printHex("Initial", *E); 52140b57cec5SDimitry Andric }; 52150b57cec5SDimitry Andric 52160b57cec5SDimitry Andric DictScope GS(W, "PLT GOT"); 52170b57cec5SDimitry Andric 52180b57cec5SDimitry Andric { 52190b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 52200b57cec5SDimitry Andric { 52210b57cec5SDimitry Andric DictScope D(W, "Entry"); 52220b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver()); 52230b57cec5SDimitry Andric W.printString("Purpose", StringRef("PLT lazy resolver")); 52240b57cec5SDimitry Andric } 52250b57cec5SDimitry Andric 52260b57cec5SDimitry Andric if (auto E = Parser.getPltModulePointer()) { 52270b57cec5SDimitry Andric DictScope D(W, "Entry"); 52280b57cec5SDimitry Andric PrintEntry(E); 52290b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer")); 52300b57cec5SDimitry Andric } 52310b57cec5SDimitry Andric } 52320b57cec5SDimitry Andric { 52330b57cec5SDimitry Andric ListScope LS(W, "Entries"); 52340b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 52350b57cec5SDimitry Andric DictScope D(W, "Entry"); 52360b57cec5SDimitry Andric PrintEntry(&E); 52370b57cec5SDimitry Andric 52380b57cec5SDimitry Andric const Elf_Sym *Sym = Parser.getPltSym(&E); 52390b57cec5SDimitry Andric W.printHex("Value", Sym->st_value); 52400b57cec5SDimitry Andric W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); 52410b57cec5SDimitry Andric 52420b57cec5SDimitry Andric unsigned SectionIndex = 0; 52430b57cec5SDimitry Andric StringRef SectionName; 52440b57cec5SDimitry Andric this->dumper()->getSectionNameIndex( 52450b57cec5SDimitry Andric Sym, this->dumper()->dynamic_symbols().begin(), SectionName, 52460b57cec5SDimitry Andric SectionIndex); 52470b57cec5SDimitry Andric W.printHex("Section", SectionName, SectionIndex); 52480b57cec5SDimitry Andric 52490b57cec5SDimitry Andric std::string SymName = 52500b57cec5SDimitry Andric this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true); 52510b57cec5SDimitry Andric W.printNumber("Name", SymName, Sym->st_name); 52520b57cec5SDimitry Andric } 52530b57cec5SDimitry Andric } 52540b57cec5SDimitry Andric } 5255