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 "ObjDumper.h" 170b57cec5SDimitry Andric #include "StackMapPrinter.h" 180b57cec5SDimitry Andric #include "llvm-readobj.h" 190b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 2004eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h" 210b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 220b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 238bcb0991SDimitry Andric #include "llvm/ADT/MapVector.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" 3304eeddc0SDimitry Andric #include "llvm/BinaryFormat/MsgPackDocument.h" 340b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h" 350eae32dcSDimitry Andric #include "llvm/Object/Archive.h" 360b57cec5SDimitry Andric #include "llvm/Object/ELF.h" 370b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 380b57cec5SDimitry Andric #include "llvm/Object/ELFTypes.h" 390b57cec5SDimitry Andric #include "llvm/Object/Error.h" 400b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 418bcb0991SDimitry Andric #include "llvm/Object/RelocationResolver.h" 420b57cec5SDimitry Andric #include "llvm/Object/StackMapParser.h" 430b57cec5SDimitry Andric #include "llvm/Support/AMDGPUMetadata.h" 440b57cec5SDimitry Andric #include "llvm/Support/ARMAttributeParser.h" 450b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 460b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 470b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 480b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 490b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 500b57cec5SDimitry Andric #include "llvm/Support/Format.h" 510b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 520b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 530b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 54349cc55cSDimitry Andric #include "llvm/Support/MSP430AttributeParser.h" 55349cc55cSDimitry Andric #include "llvm/Support/MSP430Attributes.h" 560b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 570b57cec5SDimitry Andric #include "llvm/Support/MipsABIFlags.h" 585ffd83dbSDimitry Andric #include "llvm/Support/RISCVAttributeParser.h" 595ffd83dbSDimitry Andric #include "llvm/Support/RISCVAttributes.h" 600b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 610b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 620b57cec5SDimitry Andric #include <algorithm> 630b57cec5SDimitry Andric #include <cinttypes> 640b57cec5SDimitry Andric #include <cstddef> 650b57cec5SDimitry Andric #include <cstdint> 660b57cec5SDimitry Andric #include <cstdlib> 670b57cec5SDimitry Andric #include <iterator> 680b57cec5SDimitry Andric #include <memory> 69bdd1243dSDimitry Andric #include <optional> 700b57cec5SDimitry Andric #include <string> 710b57cec5SDimitry Andric #include <system_error> 720b57cec5SDimitry Andric #include <vector> 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric using namespace llvm; 750b57cec5SDimitry Andric using namespace llvm::object; 760b57cec5SDimitry Andric using namespace ELF; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ 790b57cec5SDimitry Andric case ns::enum: \ 800b57cec5SDimitry Andric return #enum; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric #define ENUM_ENT(enum, altName) \ 830b57cec5SDimitry Andric { #enum, altName, ELF::enum } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric #define ENUM_ENT_1(enum) \ 860b57cec5SDimitry Andric { #enum, #enum, ELF::enum } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric namespace { 890b57cec5SDimitry Andric 90e8d8bef9SDimitry Andric template <class ELFT> struct RelSymbol { 91e8d8bef9SDimitry Andric RelSymbol(const typename ELFT::Sym *S, StringRef N) 92e8d8bef9SDimitry Andric : Sym(S), Name(N.str()) {} 93e8d8bef9SDimitry Andric const typename ELFT::Sym *Sym; 94e8d8bef9SDimitry Andric std::string Name; 95e8d8bef9SDimitry Andric }; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric /// Represents a contiguous uniform range in the file. We cannot just create a 980b57cec5SDimitry Andric /// range directly because when creating one of these from the .dynamic table 990b57cec5SDimitry Andric /// the size, entity size and virtual address are different entries in arbitrary 1000b57cec5SDimitry Andric /// order (DT_REL, DT_RELSZ, DT_RELENT for example). 1010b57cec5SDimitry Andric struct DynRegionInfo { 102e8d8bef9SDimitry Andric DynRegionInfo(const Binary &Owner, const ObjDumper &D) 103e8d8bef9SDimitry Andric : Obj(&Owner), Dumper(&D) {} 104e8d8bef9SDimitry Andric DynRegionInfo(const Binary &Owner, const ObjDumper &D, const uint8_t *A, 105e8d8bef9SDimitry Andric uint64_t S, uint64_t ES) 106e8d8bef9SDimitry Andric : Addr(A), Size(S), EntSize(ES), Obj(&Owner), Dumper(&D) {} 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /// Address in current address space. 109e8d8bef9SDimitry Andric const uint8_t *Addr = nullptr; 1100b57cec5SDimitry Andric /// Size in bytes of the region. 1110b57cec5SDimitry Andric uint64_t Size = 0; 1120b57cec5SDimitry Andric /// Size of each entity in the region. 1130b57cec5SDimitry Andric uint64_t EntSize = 0; 1140b57cec5SDimitry Andric 115e8d8bef9SDimitry Andric /// Owner object. Used for error reporting. 116e8d8bef9SDimitry Andric const Binary *Obj; 117e8d8bef9SDimitry Andric /// Dumper used for error reporting. 118e8d8bef9SDimitry Andric const ObjDumper *Dumper; 1195ffd83dbSDimitry Andric /// Error prefix. Used for error reporting to provide more information. 1205ffd83dbSDimitry Andric std::string Context; 1215ffd83dbSDimitry Andric /// Region size name. Used for error reporting. 1225ffd83dbSDimitry Andric StringRef SizePrintName = "size"; 1235ffd83dbSDimitry Andric /// Entry size name. Used for error reporting. If this field is empty, errors 1245ffd83dbSDimitry Andric /// will not mention the entry size. 1255ffd83dbSDimitry Andric StringRef EntSizePrintName = "entry size"; 1268bcb0991SDimitry Andric 1270b57cec5SDimitry Andric template <typename Type> ArrayRef<Type> getAsArrayRef() const { 1280b57cec5SDimitry Andric const Type *Start = reinterpret_cast<const Type *>(Addr); 1290b57cec5SDimitry Andric if (!Start) 1300b57cec5SDimitry Andric return {Start, Start}; 131e8d8bef9SDimitry Andric 132e8d8bef9SDimitry Andric const uint64_t Offset = 133e8d8bef9SDimitry Andric Addr - (const uint8_t *)Obj->getMemoryBufferRef().getBufferStart(); 134e8d8bef9SDimitry Andric const uint64_t ObjSize = Obj->getMemoryBufferRef().getBufferSize(); 135e8d8bef9SDimitry Andric 136e8d8bef9SDimitry Andric if (Size > ObjSize - Offset) { 137e8d8bef9SDimitry Andric Dumper->reportUniqueWarning( 138e8d8bef9SDimitry Andric "unable to read data at 0x" + Twine::utohexstr(Offset) + 139e8d8bef9SDimitry Andric " of size 0x" + Twine::utohexstr(Size) + " (" + SizePrintName + 140e8d8bef9SDimitry Andric "): it goes past the end of the file of size 0x" + 141e8d8bef9SDimitry Andric Twine::utohexstr(ObjSize)); 142e8d8bef9SDimitry Andric return {Start, Start}; 143e8d8bef9SDimitry Andric } 144e8d8bef9SDimitry Andric 1455ffd83dbSDimitry Andric if (EntSize == sizeof(Type) && (Size % EntSize == 0)) 1460b57cec5SDimitry Andric return {Start, Start + (Size / EntSize)}; 1475ffd83dbSDimitry Andric 1485ffd83dbSDimitry Andric std::string Msg; 1495ffd83dbSDimitry Andric if (!Context.empty()) 1505ffd83dbSDimitry Andric Msg += Context + " has "; 1515ffd83dbSDimitry Andric 1525ffd83dbSDimitry Andric Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")") 1535ffd83dbSDimitry Andric .str(); 1545ffd83dbSDimitry Andric if (!EntSizePrintName.empty()) 1555ffd83dbSDimitry Andric Msg += 1565ffd83dbSDimitry Andric (" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")") 1575ffd83dbSDimitry Andric .str(); 1585ffd83dbSDimitry Andric 159e8d8bef9SDimitry Andric Dumper->reportUniqueWarning(Msg); 1605ffd83dbSDimitry Andric return {Start, Start}; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric }; 1630b57cec5SDimitry Andric 164e8d8bef9SDimitry Andric struct GroupMember { 165e8d8bef9SDimitry Andric StringRef Name; 166e8d8bef9SDimitry Andric uint64_t Index; 167e8d8bef9SDimitry Andric }; 168e8d8bef9SDimitry Andric 169e8d8bef9SDimitry Andric struct GroupSection { 170e8d8bef9SDimitry Andric StringRef Name; 171e8d8bef9SDimitry Andric std::string Signature; 172e8d8bef9SDimitry Andric uint64_t ShName; 173e8d8bef9SDimitry Andric uint64_t Index; 174e8d8bef9SDimitry Andric uint32_t Link; 175e8d8bef9SDimitry Andric uint32_t Info; 176e8d8bef9SDimitry Andric uint32_t Type; 177e8d8bef9SDimitry Andric std::vector<GroupMember> Members; 178e8d8bef9SDimitry Andric }; 179e8d8bef9SDimitry Andric 180480093f4SDimitry Andric namespace { 181480093f4SDimitry Andric 182e8d8bef9SDimitry Andric struct NoteType { 183e8d8bef9SDimitry Andric uint32_t ID; 184e8d8bef9SDimitry Andric StringRef Name; 185480093f4SDimitry Andric }; 186480093f4SDimitry Andric 187480093f4SDimitry Andric } // namespace 188480093f4SDimitry Andric 189e8d8bef9SDimitry Andric template <class ELFT> class Relocation { 1900b57cec5SDimitry Andric public: 191e8d8bef9SDimitry Andric Relocation(const typename ELFT::Rel &R, bool IsMips64EL) 192e8d8bef9SDimitry Andric : Type(R.getType(IsMips64EL)), Symbol(R.getSymbol(IsMips64EL)), 193e8d8bef9SDimitry Andric Offset(R.r_offset), Info(R.r_info) {} 1940b57cec5SDimitry Andric 195e8d8bef9SDimitry Andric Relocation(const typename ELFT::Rela &R, bool IsMips64EL) 196e8d8bef9SDimitry Andric : Relocation((const typename ELFT::Rel &)R, IsMips64EL) { 197e8d8bef9SDimitry Andric Addend = R.r_addend; 198e8d8bef9SDimitry Andric } 199e8d8bef9SDimitry Andric 200e8d8bef9SDimitry Andric uint32_t Type; 201e8d8bef9SDimitry Andric uint32_t Symbol; 202e8d8bef9SDimitry Andric typename ELFT::uint Offset; 203e8d8bef9SDimitry Andric typename ELFT::uint Info; 204bdd1243dSDimitry Andric std::optional<int64_t> Addend; 205e8d8bef9SDimitry Andric }; 206e8d8bef9SDimitry Andric 207e8d8bef9SDimitry Andric template <class ELFT> class MipsGOTParser; 208e8d8bef9SDimitry Andric 209e8d8bef9SDimitry Andric template <typename ELFT> class ELFDumper : public ObjDumper { 210e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 211e8d8bef9SDimitry Andric 212e8d8bef9SDimitry Andric public: 213e8d8bef9SDimitry Andric ELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer); 214e8d8bef9SDimitry Andric 2150b57cec5SDimitry Andric void printUnwindInfo() override; 2160b57cec5SDimitry Andric void printNeededLibraries() override; 2170b57cec5SDimitry Andric void printHashTable() override; 218e8d8bef9SDimitry Andric void printGnuHashTable() override; 2190b57cec5SDimitry Andric void printLoadName() override; 2200b57cec5SDimitry Andric void printVersionInfo() override; 2218bcb0991SDimitry Andric void printArchSpecificInfo() override; 2220b57cec5SDimitry Andric void printStackMap() const override; 22306c3fb27SDimitry Andric void printMemtag() override; 22406c3fb27SDimitry Andric ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr); 22506c3fb27SDimitry Andric 22606c3fb27SDimitry Andric // Hash histogram shows statistics of how efficient the hash was for the 22706c3fb27SDimitry Andric // dynamic symbol table. The table shows the number of hash buckets for 22806c3fb27SDimitry Andric // different lengths of chains as an absolute number and percentage of the 22906c3fb27SDimitry Andric // total buckets, and the cumulative coverage of symbols for each set of 23006c3fb27SDimitry Andric // buckets. 23106c3fb27SDimitry Andric void printHashHistograms() override; 2320b57cec5SDimitry Andric 233e8d8bef9SDimitry Andric const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; }; 2340b57cec5SDimitry Andric 235e8d8bef9SDimitry Andric std::string describe(const Elf_Shdr &Sec) const; 2360b57cec5SDimitry Andric 237e8d8bef9SDimitry Andric unsigned getHashTableEntSize() const { 238e8d8bef9SDimitry Andric // EM_S390 and ELF::EM_ALPHA platforms use 8-bytes entries in SHT_HASH 239e8d8bef9SDimitry Andric // sections. This violates the ELF specification. 240e8d8bef9SDimitry Andric if (Obj.getHeader().e_machine == ELF::EM_S390 || 241e8d8bef9SDimitry Andric Obj.getHeader().e_machine == ELF::EM_ALPHA) 242e8d8bef9SDimitry Andric return 8; 243e8d8bef9SDimitry Andric return 4; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 24606c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> 24706c3fb27SDimitry Andric getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const; 24806c3fb27SDimitry Andric 2490b57cec5SDimitry Andric Elf_Dyn_Range dynamic_table() const { 2500b57cec5SDimitry Andric // A valid .dynamic section contains an array of entries terminated 2510b57cec5SDimitry Andric // with a DT_NULL entry. However, sometimes the section content may 2520b57cec5SDimitry Andric // continue past the DT_NULL entry, so to dump the section correctly, 2530b57cec5SDimitry Andric // we first find the end of the entries by iterating over them. 254e8d8bef9SDimitry Andric Elf_Dyn_Range Table = DynamicTable.template getAsArrayRef<Elf_Dyn>(); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric size_t Size = 0; 2570b57cec5SDimitry Andric while (Size < Table.size()) 2580b57cec5SDimitry Andric if (Table[Size++].getTag() == DT_NULL) 2590b57cec5SDimitry Andric break; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric return Table.slice(0, Size); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric Elf_Sym_Range dynamic_symbols() const { 2655ffd83dbSDimitry Andric if (!DynSymRegion) 2665ffd83dbSDimitry Andric return Elf_Sym_Range(); 267e8d8bef9SDimitry Andric return DynSymRegion->template getAsArrayRef<Elf_Sym>(); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 270e8d8bef9SDimitry Andric const Elf_Shdr *findSectionByName(StringRef Name) const; 271e8d8bef9SDimitry Andric 272e8d8bef9SDimitry Andric StringRef getDynamicStringTable() const { return DynamicStringTable; } 273e8d8bef9SDimitry Andric 274e8d8bef9SDimitry Andric protected: 275e8d8bef9SDimitry Andric virtual void printVersionSymbolSection(const Elf_Shdr *Sec) = 0; 276e8d8bef9SDimitry Andric virtual void printVersionDefinitionSection(const Elf_Shdr *Sec) = 0; 277e8d8bef9SDimitry Andric virtual void printVersionDependencySection(const Elf_Shdr *Sec) = 0; 278e8d8bef9SDimitry Andric 279e8d8bef9SDimitry Andric void 280e8d8bef9SDimitry Andric printDependentLibsHelper(function_ref<void(const Elf_Shdr &)> OnSectionStart, 281e8d8bef9SDimitry Andric function_ref<void(StringRef, uint64_t)> OnLibEntry); 282e8d8bef9SDimitry Andric 283e8d8bef9SDimitry Andric virtual void printRelRelaReloc(const Relocation<ELFT> &R, 284e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) = 0; 285e8d8bef9SDimitry Andric virtual void printRelrReloc(const Elf_Relr &R) = 0; 286e8d8bef9SDimitry Andric virtual void printDynamicRelocHeader(unsigned Type, StringRef Name, 287e8d8bef9SDimitry Andric const DynRegionInfo &Reg) {} 288e8d8bef9SDimitry Andric void printReloc(const Relocation<ELFT> &R, unsigned RelIndex, 289e8d8bef9SDimitry Andric const Elf_Shdr &Sec, const Elf_Shdr *SymTab); 290e8d8bef9SDimitry Andric void printDynamicReloc(const Relocation<ELFT> &R); 291e8d8bef9SDimitry Andric void printDynamicRelocationsHelper(); 292e8d8bef9SDimitry Andric void printRelocationsHelper(const Elf_Shdr &Sec); 293e8d8bef9SDimitry Andric void forEachRelocationDo( 294e8d8bef9SDimitry Andric const Elf_Shdr &Sec, bool RawRelr, 295e8d8bef9SDimitry Andric llvm::function_ref<void(const Relocation<ELFT> &, unsigned, 296e8d8bef9SDimitry Andric const Elf_Shdr &, const Elf_Shdr *)> 297e8d8bef9SDimitry Andric RelRelaFn, 298e8d8bef9SDimitry Andric llvm::function_ref<void(const Elf_Relr &)> RelrFn); 299e8d8bef9SDimitry Andric 300e8d8bef9SDimitry Andric virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset, 301e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const {}; 302e8d8bef9SDimitry Andric virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 303e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 304bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 305e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const = 0; 306e8d8bef9SDimitry Andric 307e8d8bef9SDimitry Andric virtual void printMipsABIFlags() = 0; 308e8d8bef9SDimitry Andric virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; 309e8d8bef9SDimitry Andric virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0; 310e8d8bef9SDimitry Andric 31106c3fb27SDimitry Andric virtual void printMemtag( 31206c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 31306c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 31406c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0; 31506c3fb27SDimitry Andric 31606c3fb27SDimitry Andric virtual void printHashHistogram(const Elf_Hash &HashTable) const; 31706c3fb27SDimitry Andric virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const; 31806c3fb27SDimitry Andric virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain, 31906c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 32006c3fb27SDimitry Andric bool IsGnu) const = 0; 32106c3fb27SDimitry Andric 322e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Versym>> 323e8d8bef9SDimitry Andric getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab, 324e8d8bef9SDimitry Andric StringRef *StrTab, const Elf_Shdr **SymTabSec) const; 325e8d8bef9SDimitry Andric StringRef getPrintableSectionName(const Elf_Shdr &Sec) const; 326e8d8bef9SDimitry Andric 327e8d8bef9SDimitry Andric std::vector<GroupSection> getGroups(); 328e8d8bef9SDimitry Andric 329fe6060f1SDimitry Andric // Returns the function symbol index for the given address. Matches the 330fe6060f1SDimitry Andric // symbol's section with FunctionSec when specified. 331bdd1243dSDimitry Andric // Returns std::nullopt if no function symbol can be found for the address or 332bdd1243dSDimitry Andric // in case it is not defined in the specified section. 333bdd1243dSDimitry Andric SmallVector<uint32_t> getSymbolIndexesForFunctionAddress( 334bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec); 335e8d8bef9SDimitry Andric bool printFunctionStackSize(uint64_t SymValue, 336bdd1243dSDimitry Andric std::optional<const Elf_Shdr *> FunctionSec, 337e8d8bef9SDimitry Andric const Elf_Shdr &StackSizeSec, DataExtractor Data, 338e8d8bef9SDimitry Andric uint64_t *Offset); 339e8d8bef9SDimitry Andric void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec, 340e8d8bef9SDimitry Andric unsigned Ndx, const Elf_Shdr *SymTab, 341e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec, 342e8d8bef9SDimitry Andric const RelocationResolver &Resolver, DataExtractor Data); 343fe6060f1SDimitry Andric virtual void printStackSizeEntry(uint64_t Size, 344fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) = 0; 345e8d8bef9SDimitry Andric 346e8d8bef9SDimitry Andric void printRelocatableStackSizes(std::function<void()> PrintHeader); 347e8d8bef9SDimitry Andric void printNonRelocatableStackSizes(std::function<void()> PrintHeader); 348e8d8bef9SDimitry Andric 349e8d8bef9SDimitry Andric const object::ELFObjectFile<ELFT> &ObjF; 350e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj; 351e8d8bef9SDimitry Andric StringRef FileName; 352e8d8bef9SDimitry Andric 353e8d8bef9SDimitry Andric Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size, 354e8d8bef9SDimitry Andric uint64_t EntSize) { 355e8d8bef9SDimitry Andric if (Offset + Size < Offset || Offset + Size > Obj.getBufSize()) 356e8d8bef9SDimitry Andric return createError("offset (0x" + Twine::utohexstr(Offset) + 357e8d8bef9SDimitry Andric ") + size (0x" + Twine::utohexstr(Size) + 358e8d8bef9SDimitry Andric ") is greater than the file size (0x" + 359e8d8bef9SDimitry Andric Twine::utohexstr(Obj.getBufSize()) + ")"); 360e8d8bef9SDimitry Andric return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize); 361e8d8bef9SDimitry Andric } 362e8d8bef9SDimitry Andric 363349cc55cSDimitry Andric void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>, 364349cc55cSDimitry Andric support::endianness); 365e8d8bef9SDimitry Andric void printMipsReginfo(); 366e8d8bef9SDimitry Andric void printMipsOptions(); 367e8d8bef9SDimitry Andric 368e8d8bef9SDimitry Andric std::pair<const Elf_Phdr *, const Elf_Shdr *> findDynamic(); 369e8d8bef9SDimitry Andric void loadDynamicTable(); 370e8d8bef9SDimitry Andric void parseDynamicTable(); 371e8d8bef9SDimitry Andric 372e8d8bef9SDimitry Andric Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym, 373e8d8bef9SDimitry Andric bool &IsDefault) const; 374bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const; 375e8d8bef9SDimitry Andric 376e8d8bef9SDimitry Andric DynRegionInfo DynRelRegion; 377e8d8bef9SDimitry Andric DynRegionInfo DynRelaRegion; 378e8d8bef9SDimitry Andric DynRegionInfo DynRelrRegion; 379e8d8bef9SDimitry Andric DynRegionInfo DynPLTRelRegion; 380bdd1243dSDimitry Andric std::optional<DynRegionInfo> DynSymRegion; 381e8d8bef9SDimitry Andric DynRegionInfo DynSymTabShndxRegion; 382e8d8bef9SDimitry Andric DynRegionInfo DynamicTable; 383e8d8bef9SDimitry Andric StringRef DynamicStringTable; 384e8d8bef9SDimitry Andric const Elf_Hash *HashTable = nullptr; 385e8d8bef9SDimitry Andric const Elf_GnuHash *GnuHashTable = nullptr; 386e8d8bef9SDimitry Andric const Elf_Shdr *DotSymtabSec = nullptr; 387e8d8bef9SDimitry Andric const Elf_Shdr *DotDynsymSec = nullptr; 388e8d8bef9SDimitry Andric const Elf_Shdr *DotAddrsigSec = nullptr; 389e8d8bef9SDimitry Andric DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables; 390bdd1243dSDimitry Andric std::optional<uint64_t> SONameOffset; 391bdd1243dSDimitry Andric std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap; 392e8d8bef9SDimitry Andric 393e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version 394e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r 395e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d 396e8d8bef9SDimitry Andric 397e8d8bef9SDimitry Andric std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex, 398e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 399bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 4000b57cec5SDimitry Andric bool IsDynamic) const; 401e8d8bef9SDimitry Andric Expected<unsigned> 402e8d8bef9SDimitry Andric getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex, 403e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const; 404e8d8bef9SDimitry Andric Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol, 405480093f4SDimitry Andric unsigned SectionIndex) const; 4065ffd83dbSDimitry Andric std::string getStaticSymbolName(uint32_t Index) const; 4075ffd83dbSDimitry Andric StringRef getDynamicString(uint64_t Value) const; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric void printSymbolsHelper(bool IsDynamic) const; 4105ffd83dbSDimitry Andric std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; 4110b57cec5SDimitry Andric 412e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R, 413e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) const; 414480093f4SDimitry Andric 415e8d8bef9SDimitry Andric ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const; 4165ffd83dbSDimitry Andric 417e8d8bef9SDimitry Andric private: 418bdd1243dSDimitry Andric mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap; 4190b57cec5SDimitry Andric }; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric template <class ELFT> 422e8d8bef9SDimitry Andric std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const { 423e8d8bef9SDimitry Andric return ::describe(Obj, Sec); 424480093f4SDimitry Andric } 425480093f4SDimitry Andric 426e8d8bef9SDimitry Andric namespace { 427e8d8bef9SDimitry Andric 428e8d8bef9SDimitry Andric template <class ELFT> struct SymtabLink { 429e8d8bef9SDimitry Andric typename ELFT::SymRange Symbols; 430e8d8bef9SDimitry Andric StringRef StringTable; 431e8d8bef9SDimitry Andric const typename ELFT::Shdr *SymTab; 432e8d8bef9SDimitry Andric }; 433e8d8bef9SDimitry Andric 434e8d8bef9SDimitry Andric // Returns the linked symbol table, symbols and associated string table for a 435e8d8bef9SDimitry Andric // given section. 436480093f4SDimitry Andric template <class ELFT> 437e8d8bef9SDimitry Andric Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj, 438e8d8bef9SDimitry Andric const typename ELFT::Shdr &Sec, 439e8d8bef9SDimitry Andric unsigned ExpectedType) { 440480093f4SDimitry Andric Expected<const typename ELFT::Shdr *> SymtabOrErr = 441e8d8bef9SDimitry Andric Obj.getSection(Sec.sh_link); 442480093f4SDimitry Andric if (!SymtabOrErr) 443e8d8bef9SDimitry Andric return createError("invalid section linked to " + describe(Obj, Sec) + 444e8d8bef9SDimitry Andric ": " + toString(SymtabOrErr.takeError())); 445480093f4SDimitry Andric 446480093f4SDimitry Andric if ((*SymtabOrErr)->sh_type != ExpectedType) 447480093f4SDimitry Andric return createError( 448e8d8bef9SDimitry Andric "invalid section linked to " + describe(Obj, Sec) + ": expected " + 449e8d8bef9SDimitry Andric object::getELFSectionTypeName(Obj.getHeader().e_machine, ExpectedType) + 450480093f4SDimitry Andric ", but got " + 451e8d8bef9SDimitry Andric object::getELFSectionTypeName(Obj.getHeader().e_machine, 452480093f4SDimitry Andric (*SymtabOrErr)->sh_type)); 453480093f4SDimitry Andric 454e8d8bef9SDimitry Andric Expected<StringRef> StrTabOrErr = Obj.getLinkAsStrtab(**SymtabOrErr); 455480093f4SDimitry Andric if (!StrTabOrErr) 456480093f4SDimitry Andric return createError( 457480093f4SDimitry Andric "can't get a string table for the symbol table linked to " + 458e8d8bef9SDimitry Andric describe(Obj, Sec) + ": " + toString(StrTabOrErr.takeError())); 459480093f4SDimitry Andric 460e8d8bef9SDimitry Andric Expected<typename ELFT::SymRange> SymsOrErr = Obj.symbols(*SymtabOrErr); 461480093f4SDimitry Andric if (!SymsOrErr) 462e8d8bef9SDimitry Andric return createError("unable to read symbols from the " + describe(Obj, Sec) + 463e8d8bef9SDimitry Andric ": " + toString(SymsOrErr.takeError())); 464480093f4SDimitry Andric 465e8d8bef9SDimitry Andric return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr}; 466480093f4SDimitry Andric } 467480093f4SDimitry Andric 468e8d8bef9SDimitry Andric } // namespace 469e8d8bef9SDimitry Andric 470480093f4SDimitry Andric template <class ELFT> 471480093f4SDimitry Andric Expected<ArrayRef<typename ELFT::Versym>> 472e8d8bef9SDimitry Andric ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab, 473e8d8bef9SDimitry Andric StringRef *StrTab, 474e8d8bef9SDimitry Andric const Elf_Shdr **SymTabSec) const { 475e8d8bef9SDimitry Andric assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec)); 476e8d8bef9SDimitry Andric if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) % 477e8d8bef9SDimitry Andric sizeof(uint16_t) != 478e8d8bef9SDimitry Andric 0) 479e8d8bef9SDimitry Andric return createError("the " + describe(Sec) + " is misaligned"); 480480093f4SDimitry Andric 481480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VersionsOrErr = 482e8d8bef9SDimitry Andric Obj.template getSectionContentsAsArray<Elf_Versym>(Sec); 483480093f4SDimitry Andric if (!VersionsOrErr) 484e8d8bef9SDimitry Andric return createError("cannot read content of " + describe(Sec) + ": " + 485e8d8bef9SDimitry Andric toString(VersionsOrErr.takeError())); 486480093f4SDimitry Andric 487e8d8bef9SDimitry Andric Expected<SymtabLink<ELFT>> SymTabOrErr = 488e8d8bef9SDimitry Andric getLinkAsSymtab(Obj, Sec, SHT_DYNSYM); 489480093f4SDimitry Andric if (!SymTabOrErr) { 4905ffd83dbSDimitry Andric reportUniqueWarning(SymTabOrErr.takeError()); 491480093f4SDimitry Andric return *VersionsOrErr; 492480093f4SDimitry Andric } 493480093f4SDimitry Andric 494e8d8bef9SDimitry Andric if (SymTabOrErr->Symbols.size() != VersionsOrErr->size()) 495e8d8bef9SDimitry Andric reportUniqueWarning(describe(Sec) + ": the number of entries (" + 496e8d8bef9SDimitry Andric Twine(VersionsOrErr->size()) + 497480093f4SDimitry Andric ") does not match the number of symbols (" + 498e8d8bef9SDimitry Andric Twine(SymTabOrErr->Symbols.size()) + 499e8d8bef9SDimitry Andric ") in the symbol table with index " + 500e8d8bef9SDimitry Andric Twine(Sec.sh_link)); 501480093f4SDimitry Andric 502e8d8bef9SDimitry Andric if (SymTab) { 503e8d8bef9SDimitry Andric *SymTab = SymTabOrErr->Symbols; 504e8d8bef9SDimitry Andric *StrTab = SymTabOrErr->StringTable; 505e8d8bef9SDimitry Andric *SymTabSec = SymTabOrErr->SymTab; 506e8d8bef9SDimitry Andric } 507480093f4SDimitry Andric return *VersionsOrErr; 508480093f4SDimitry Andric } 509480093f4SDimitry Andric 510480093f4SDimitry Andric template <class ELFT> 5110b57cec5SDimitry Andric void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { 512bdd1243dSDimitry Andric std::optional<StringRef> StrTable; 5130b57cec5SDimitry Andric size_t Entries = 0; 5140b57cec5SDimitry Andric Elf_Sym_Range Syms(nullptr, nullptr); 515e8d8bef9SDimitry Andric const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec; 516e8d8bef9SDimitry Andric 5170b57cec5SDimitry Andric if (IsDynamic) { 5180b57cec5SDimitry Andric StrTable = DynamicStringTable; 5190b57cec5SDimitry Andric Syms = dynamic_symbols(); 5205ffd83dbSDimitry Andric Entries = Syms.size(); 521e8d8bef9SDimitry Andric } else if (DotSymtabSec) { 5225ffd83dbSDimitry Andric if (Expected<StringRef> StrTableOrErr = 523e8d8bef9SDimitry Andric Obj.getStringTableForSymtab(*DotSymtabSec)) 5245ffd83dbSDimitry Andric StrTable = *StrTableOrErr; 5255ffd83dbSDimitry Andric else 526e8d8bef9SDimitry Andric reportUniqueWarning( 5275ffd83dbSDimitry Andric "unable to get the string table for the SHT_SYMTAB section: " + 528e8d8bef9SDimitry Andric toString(StrTableOrErr.takeError())); 5295ffd83dbSDimitry Andric 530e8d8bef9SDimitry Andric if (Expected<Elf_Sym_Range> SymsOrErr = Obj.symbols(DotSymtabSec)) 5315ffd83dbSDimitry Andric Syms = *SymsOrErr; 5325ffd83dbSDimitry Andric else 5335ffd83dbSDimitry Andric reportUniqueWarning( 534e8d8bef9SDimitry Andric "unable to read symbols from the SHT_SYMTAB section: " + 535e8d8bef9SDimitry Andric toString(SymsOrErr.takeError())); 5360b57cec5SDimitry Andric Entries = DotSymtabSec->getEntityCount(); 5370b57cec5SDimitry Andric } 538e8d8bef9SDimitry Andric if (Syms.empty()) 5390b57cec5SDimitry Andric return; 5408bcb0991SDimitry Andric 5418bcb0991SDimitry Andric // The st_other field has 2 logical parts. The first two bits hold the symbol 5428bcb0991SDimitry Andric // visibility (STV_*) and the remainder hold other platform-specific values. 543e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed = 544e8d8bef9SDimitry Andric llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; }); 5458bcb0991SDimitry Andric 546e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable = 547e8d8bef9SDimitry Andric IsDynamic ? DataRegion<Elf_Word>( 548e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, 549e8d8bef9SDimitry Andric this->getElfObject().getELFFile().end()) 550e8d8bef9SDimitry Andric : DataRegion<Elf_Word>(this->getShndxTable(SymtabSec)); 551e8d8bef9SDimitry Andric 552e8d8bef9SDimitry Andric printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed); 553e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : Syms) 554e8d8bef9SDimitry Andric printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic, 5558bcb0991SDimitry Andric NonVisibilityBitsUsed); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 558e8d8bef9SDimitry Andric template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> { 5590b57cec5SDimitry Andric formatted_raw_ostream &OS; 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric public: 562e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 5630b57cec5SDimitry Andric 564e8d8bef9SDimitry Andric GNUELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 565e8d8bef9SDimitry Andric : ELFDumper<ELFT>(ObjF, Writer), 566e8d8bef9SDimitry Andric OS(static_cast<formatted_raw_ostream &>(Writer.getOStream())) { 567e8d8bef9SDimitry Andric assert(&this->W.getOStream() == &llvm::fouts()); 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 5700eae32dcSDimitry Andric void printFileSummary(StringRef FileStr, ObjectFile &Obj, 5710eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 5720eae32dcSDimitry Andric const Archive *A) override; 573e8d8bef9SDimitry Andric void printFileHeaders() override; 574e8d8bef9SDimitry Andric void printGroupSections() override; 575e8d8bef9SDimitry Andric void printRelocations() override; 576e8d8bef9SDimitry Andric void printSectionHeaders() override; 577e8d8bef9SDimitry Andric void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override; 578e8d8bef9SDimitry Andric void printHashSymbols() override; 579e8d8bef9SDimitry Andric void printSectionDetails() override; 580e8d8bef9SDimitry Andric void printDependentLibs() override; 581e8d8bef9SDimitry Andric void printDynamicTable() override; 582e8d8bef9SDimitry Andric void printDynamicRelocations() override; 583e8d8bef9SDimitry Andric void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset, 584e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const override; 585e8d8bef9SDimitry Andric void printProgramHeaders(bool PrintProgramHeaders, 5860b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 587e8d8bef9SDimitry Andric void printVersionSymbolSection(const Elf_Shdr *Sec) override; 588e8d8bef9SDimitry Andric void printVersionDefinitionSection(const Elf_Shdr *Sec) override; 589e8d8bef9SDimitry Andric void printVersionDependencySection(const Elf_Shdr *Sec) override; 590e8d8bef9SDimitry Andric void printCGProfile() override; 591fe6060f1SDimitry Andric void printBBAddrMaps() override; 592e8d8bef9SDimitry Andric void printAddrsig() override; 593e8d8bef9SDimitry Andric void printNotes() override; 594e8d8bef9SDimitry Andric void printELFLinkerOptions() override; 595e8d8bef9SDimitry Andric void printStackSizes() override; 59606c3fb27SDimitry Andric void printMemtag( 59706c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 59806c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 59906c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override; 60006c3fb27SDimitry Andric void printHashHistogramStats(size_t NBucket, size_t MaxChain, 60106c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 60206c3fb27SDimitry Andric bool IsGnu) const override; 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric private: 605e8d8bef9SDimitry Andric void printHashTableSymbols(const Elf_Hash &HashTable); 606e8d8bef9SDimitry Andric void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable); 6075ffd83dbSDimitry Andric 6080b57cec5SDimitry Andric struct Field { 6090b57cec5SDimitry Andric std::string Str; 6100b57cec5SDimitry Andric unsigned Column; 6110b57cec5SDimitry Andric 6125ffd83dbSDimitry Andric Field(StringRef S, unsigned Col) : Str(std::string(S)), Column(Col) {} 6130b57cec5SDimitry Andric Field(unsigned Col) : Column(Col) {} 6140b57cec5SDimitry Andric }; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric template <typename T, typename TEnum> 6170b57cec5SDimitry Andric std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues, 6180b57cec5SDimitry Andric TEnum EnumMask1 = {}, TEnum EnumMask2 = {}, 619e8d8bef9SDimitry Andric TEnum EnumMask3 = {}) const { 6200b57cec5SDimitry Andric std::string Str; 621e8d8bef9SDimitry Andric for (const EnumEntry<TEnum> &Flag : EnumValues) { 6220b57cec5SDimitry Andric if (Flag.Value == 0) 6230b57cec5SDimitry Andric continue; 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric TEnum EnumMask{}; 6260b57cec5SDimitry Andric if (Flag.Value & EnumMask1) 6270b57cec5SDimitry Andric EnumMask = EnumMask1; 6280b57cec5SDimitry Andric else if (Flag.Value & EnumMask2) 6290b57cec5SDimitry Andric EnumMask = EnumMask2; 6300b57cec5SDimitry Andric else if (Flag.Value & EnumMask3) 6310b57cec5SDimitry Andric EnumMask = EnumMask3; 6320b57cec5SDimitry Andric bool IsEnum = (Flag.Value & EnumMask) != 0; 6330b57cec5SDimitry Andric if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 6340b57cec5SDimitry Andric (IsEnum && (Value & EnumMask) == Flag.Value)) { 6350b57cec5SDimitry Andric if (!Str.empty()) 6360b57cec5SDimitry Andric Str += ", "; 6370b57cec5SDimitry Andric Str += Flag.AltName; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric return Str; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 643e8d8bef9SDimitry Andric formatted_raw_ostream &printField(struct Field F) const { 6440b57cec5SDimitry Andric if (F.Column != 0) 6450b57cec5SDimitry Andric OS.PadToColumn(F.Column); 6460b57cec5SDimitry Andric OS << F.Str; 6470b57cec5SDimitry Andric OS.flush(); 6480b57cec5SDimitry Andric return OS; 6490b57cec5SDimitry Andric } 650e8d8bef9SDimitry Andric void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex, 651e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, StringRef StrTable, 652e8d8bef9SDimitry Andric uint32_t Bucket); 653e8d8bef9SDimitry Andric void printRelrReloc(const Elf_Relr &R) override; 654e8d8bef9SDimitry Andric void printRelRelaReloc(const Relocation<ELFT> &R, 655e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) override; 656e8d8bef9SDimitry Andric void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 657e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 658bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 659e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const override; 660e8d8bef9SDimitry Andric void printDynamicRelocHeader(unsigned Type, StringRef Name, 661e8d8bef9SDimitry Andric const DynRegionInfo &Reg) override; 662e8d8bef9SDimitry Andric 663e8d8bef9SDimitry Andric std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex, 664e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const; 665e8d8bef9SDimitry Andric void printProgramHeaders() override; 666e8d8bef9SDimitry Andric void printSectionMapping() override; 667e8d8bef9SDimitry Andric void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec, 668480093f4SDimitry Andric const Twine &Label, unsigned EntriesNum); 6690b57cec5SDimitry Andric 670fe6060f1SDimitry Andric void printStackSizeEntry(uint64_t Size, 671fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) override; 672e8d8bef9SDimitry Andric 6730b57cec5SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 6740b57cec5SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 675e8d8bef9SDimitry Andric void printMipsABIFlags() override; 676e8d8bef9SDimitry Andric }; 677e8d8bef9SDimitry Andric 678e8d8bef9SDimitry Andric template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> { 679e8d8bef9SDimitry Andric public: 680e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 681e8d8bef9SDimitry Andric 682e8d8bef9SDimitry Andric LLVMELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 683e8d8bef9SDimitry Andric : ELFDumper<ELFT>(ObjF, Writer), W(Writer) {} 684e8d8bef9SDimitry Andric 685e8d8bef9SDimitry Andric void printFileHeaders() override; 686e8d8bef9SDimitry Andric void printGroupSections() override; 687e8d8bef9SDimitry Andric void printRelocations() override; 688e8d8bef9SDimitry Andric void printSectionHeaders() override; 689e8d8bef9SDimitry Andric void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override; 690e8d8bef9SDimitry Andric void printDependentLibs() override; 691e8d8bef9SDimitry Andric void printDynamicTable() override; 692e8d8bef9SDimitry Andric void printDynamicRelocations() override; 693e8d8bef9SDimitry Andric void printProgramHeaders(bool PrintProgramHeaders, 694e8d8bef9SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 695e8d8bef9SDimitry Andric void printVersionSymbolSection(const Elf_Shdr *Sec) override; 696e8d8bef9SDimitry Andric void printVersionDefinitionSection(const Elf_Shdr *Sec) override; 697e8d8bef9SDimitry Andric void printVersionDependencySection(const Elf_Shdr *Sec) override; 698e8d8bef9SDimitry Andric void printCGProfile() override; 699fe6060f1SDimitry Andric void printBBAddrMaps() override; 700e8d8bef9SDimitry Andric void printAddrsig() override; 701e8d8bef9SDimitry Andric void printNotes() override; 702e8d8bef9SDimitry Andric void printELFLinkerOptions() override; 703e8d8bef9SDimitry Andric void printStackSizes() override; 70406c3fb27SDimitry Andric void printMemtag( 70506c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 70606c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 70706c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override; 70806c3fb27SDimitry Andric void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex, 70906c3fb27SDimitry Andric DataRegion<Elf_Word> ShndxTable) const; 71006c3fb27SDimitry Andric void printHashHistogramStats(size_t NBucket, size_t MaxChain, 71106c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 71206c3fb27SDimitry Andric bool IsGnu) const override; 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric private: 715e8d8bef9SDimitry Andric void printRelrReloc(const Elf_Relr &R) override; 716e8d8bef9SDimitry Andric void printRelRelaReloc(const Relocation<ELFT> &R, 717e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) override; 718e8d8bef9SDimitry Andric 719e8d8bef9SDimitry Andric void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 720e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 721bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 722e8d8bef9SDimitry Andric bool /*NonVisibilityBitsUsed*/) const override; 723e8d8bef9SDimitry Andric void printProgramHeaders() override; 724e8d8bef9SDimitry Andric void printSectionMapping() override {} 725fe6060f1SDimitry Andric void printStackSizeEntry(uint64_t Size, 726fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) override; 727e8d8bef9SDimitry Andric 728e8d8bef9SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 729e8d8bef9SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 730e8d8bef9SDimitry Andric void printMipsABIFlags() override; 73106c3fb27SDimitry Andric virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; 7320b57cec5SDimitry Andric 7330eae32dcSDimitry Andric protected: 73406c3fb27SDimitry Andric virtual std::string getGroupSectionHeaderName() const; 73506c3fb27SDimitry Andric void printSymbolOtherField(const Elf_Sym &Symbol) const; 73606c3fb27SDimitry Andric virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R, 73706c3fb27SDimitry Andric StringRef SymbolName, 73806c3fb27SDimitry Andric StringRef RelocName); 73906c3fb27SDimitry Andric virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R, 74006c3fb27SDimitry Andric StringRef SymbolName, 74106c3fb27SDimitry Andric StringRef RelocName); 74206c3fb27SDimitry Andric virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, 74306c3fb27SDimitry Andric const unsigned SecNdx); 74406c3fb27SDimitry Andric virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const; 74506c3fb27SDimitry Andric virtual void printEmptyGroupMessage() const; 74606c3fb27SDimitry Andric 7470b57cec5SDimitry Andric ScopedPrinter &W; 7480b57cec5SDimitry Andric }; 7490b57cec5SDimitry Andric 7500eae32dcSDimitry Andric // JSONELFDumper shares most of the same implementation as LLVMELFDumper except 7510eae32dcSDimitry Andric // it uses a JSONScopedPrinter. 7520eae32dcSDimitry Andric template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> { 7530eae32dcSDimitry Andric public: 7540eae32dcSDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 7550eae32dcSDimitry Andric 7560eae32dcSDimitry Andric JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 7570eae32dcSDimitry Andric : LLVMELFDumper<ELFT>(ObjF, Writer) {} 7580eae32dcSDimitry Andric 75906c3fb27SDimitry Andric std::string getGroupSectionHeaderName() const override; 76006c3fb27SDimitry Andric 7610eae32dcSDimitry Andric void printFileSummary(StringRef FileStr, ObjectFile &Obj, 7620eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 7630eae32dcSDimitry Andric const Archive *A) override; 76406c3fb27SDimitry Andric virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override; 76506c3fb27SDimitry Andric 76606c3fb27SDimitry Andric void printDefaultRelRelaReloc(const Relocation<ELFT> &R, 76706c3fb27SDimitry Andric StringRef SymbolName, 76806c3fb27SDimitry Andric StringRef RelocName) override; 76906c3fb27SDimitry Andric 77006c3fb27SDimitry Andric void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, 77106c3fb27SDimitry Andric const unsigned SecNdx) override; 77206c3fb27SDimitry Andric 77306c3fb27SDimitry Andric void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override; 77406c3fb27SDimitry Andric 77506c3fb27SDimitry Andric void printEmptyGroupMessage() const override; 7760eae32dcSDimitry Andric 7770eae32dcSDimitry Andric private: 7780eae32dcSDimitry Andric std::unique_ptr<DictScope> FileScope; 7790eae32dcSDimitry Andric }; 7800eae32dcSDimitry Andric 7810b57cec5SDimitry Andric } // end anonymous namespace 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric namespace llvm { 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric template <class ELFT> 786e8d8bef9SDimitry Andric static std::unique_ptr<ObjDumper> 787e8d8bef9SDimitry Andric createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) { 788e8d8bef9SDimitry Andric if (opts::Output == opts::GNU) 789e8d8bef9SDimitry Andric return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer); 7900eae32dcSDimitry Andric else if (opts::Output == opts::JSON) 7910eae32dcSDimitry Andric return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer); 792e8d8bef9SDimitry Andric return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer); 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 795e8d8bef9SDimitry Andric std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj, 796e8d8bef9SDimitry Andric ScopedPrinter &Writer) { 7970b57cec5SDimitry Andric // Little-endian 32-bit 798e8d8bef9SDimitry Andric if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(&Obj)) 799e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric // Big-endian 32-bit 802e8d8bef9SDimitry Andric if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(&Obj)) 803e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Little-endian 64-bit 806e8d8bef9SDimitry Andric if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj)) 807e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric // Big-endian 64-bit 810e8d8bef9SDimitry Andric return createELFDumper(*cast<ELF64BEObjectFile>(&Obj), Writer); 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric } // end namespace llvm 8140b57cec5SDimitry Andric 815e8d8bef9SDimitry Andric template <class ELFT> 816bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> 817e8d8bef9SDimitry Andric ELFDumper<ELFT>::getVersionMap() const { 818e8d8bef9SDimitry Andric // If the VersionMap has already been loaded or if there is no dynamic symtab 819e8d8bef9SDimitry Andric // or version table, there is nothing to do. 820e8d8bef9SDimitry Andric if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection) 821e8d8bef9SDimitry Andric return &VersionMap; 8220b57cec5SDimitry Andric 823bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr = 824e8d8bef9SDimitry Andric Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection); 825e8d8bef9SDimitry Andric if (MapOrErr) 826e8d8bef9SDimitry Andric VersionMap = *MapOrErr; 827e8d8bef9SDimitry Andric else 828e8d8bef9SDimitry Andric return MapOrErr.takeError(); 8290b57cec5SDimitry Andric 830e8d8bef9SDimitry Andric return &VersionMap; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric template <typename ELFT> 834e8d8bef9SDimitry Andric Expected<StringRef> ELFDumper<ELFT>::getSymbolVersion(const Elf_Sym &Sym, 8350b57cec5SDimitry Andric bool &IsDefault) const { 8360b57cec5SDimitry Andric // This is a dynamic symbol. Look in the GNU symbol version table. 8370b57cec5SDimitry Andric if (!SymbolVersionSection) { 8380b57cec5SDimitry Andric // No version table. 8390b57cec5SDimitry Andric IsDefault = false; 8400b57cec5SDimitry Andric return ""; 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric 8435ffd83dbSDimitry Andric assert(DynSymRegion && "DynSymRegion has not been initialised"); 8440b57cec5SDimitry Andric // Determine the position in the symbol table of this entry. 845e8d8bef9SDimitry Andric size_t EntryIndex = (reinterpret_cast<uintptr_t>(&Sym) - 8465ffd83dbSDimitry Andric reinterpret_cast<uintptr_t>(DynSymRegion->Addr)) / 8470b57cec5SDimitry Andric sizeof(Elf_Sym); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric // Get the corresponding version index entry. 850e8d8bef9SDimitry Andric Expected<const Elf_Versym *> EntryOrErr = 851e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Versym>(*SymbolVersionSection, EntryIndex); 852e8d8bef9SDimitry Andric if (!EntryOrErr) 8535ffd83dbSDimitry Andric return EntryOrErr.takeError(); 854e8d8bef9SDimitry Andric 855e8d8bef9SDimitry Andric unsigned Version = (*EntryOrErr)->vs_index; 856e8d8bef9SDimitry Andric if (Version == VER_NDX_LOCAL || Version == VER_NDX_GLOBAL) { 857e8d8bef9SDimitry Andric IsDefault = false; 858e8d8bef9SDimitry Andric return ""; 859e8d8bef9SDimitry Andric } 860e8d8bef9SDimitry Andric 861bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr = 862e8d8bef9SDimitry Andric getVersionMap(); 863e8d8bef9SDimitry Andric if (!MapOrErr) 864e8d8bef9SDimitry Andric return MapOrErr.takeError(); 865e8d8bef9SDimitry Andric 866e8d8bef9SDimitry Andric return Obj.getSymbolVersionByIndex(Version, IsDefault, **MapOrErr, 867e8d8bef9SDimitry Andric Sym.st_shndx == ELF::SHN_UNDEF); 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric template <typename ELFT> 871e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> 872e8d8bef9SDimitry Andric ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R, 873e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) const { 874e8d8bef9SDimitry Andric if (R.Symbol == 0) 875e8d8bef9SDimitry Andric return RelSymbol<ELFT>(nullptr, ""); 876e8d8bef9SDimitry Andric 877e8d8bef9SDimitry Andric Expected<const Elf_Sym *> SymOrErr = 878e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Sym>(*SymTab, R.Symbol); 8795ffd83dbSDimitry Andric if (!SymOrErr) 880e8d8bef9SDimitry Andric return createError("unable to read an entry with index " + Twine(R.Symbol) + 881e8d8bef9SDimitry Andric " from " + describe(*SymTab) + ": " + 882e8d8bef9SDimitry Andric toString(SymOrErr.takeError())); 8835ffd83dbSDimitry Andric const Elf_Sym *Sym = *SymOrErr; 8845ffd83dbSDimitry Andric if (!Sym) 885e8d8bef9SDimitry Andric return RelSymbol<ELFT>(nullptr, ""); 8865ffd83dbSDimitry Andric 887e8d8bef9SDimitry Andric Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*SymTab); 8885ffd83dbSDimitry Andric if (!StrTableOrErr) 8895ffd83dbSDimitry Andric return StrTableOrErr.takeError(); 8905ffd83dbSDimitry Andric 891e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = 892e8d8bef9SDimitry Andric cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0)); 8935ffd83dbSDimitry Andric std::string SymbolName = 894e8d8bef9SDimitry Andric getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab), 895e8d8bef9SDimitry Andric *StrTableOrErr, SymTab->sh_type == SHT_DYNSYM); 896e8d8bef9SDimitry Andric return RelSymbol<ELFT>(Sym, SymbolName); 897e8d8bef9SDimitry Andric } 898e8d8bef9SDimitry Andric 899e8d8bef9SDimitry Andric template <typename ELFT> 900e8d8bef9SDimitry Andric ArrayRef<typename ELFT::Word> 901e8d8bef9SDimitry Andric ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const { 902e8d8bef9SDimitry Andric if (Symtab) { 903e8d8bef9SDimitry Andric auto It = ShndxTables.find(Symtab); 904e8d8bef9SDimitry Andric if (It != ShndxTables.end()) 905e8d8bef9SDimitry Andric return It->second; 906e8d8bef9SDimitry Andric } 907e8d8bef9SDimitry Andric return {}; 9085ffd83dbSDimitry Andric } 9095ffd83dbSDimitry Andric 9105ffd83dbSDimitry Andric static std::string maybeDemangle(StringRef Name) { 91106c3fb27SDimitry Andric return opts::Demangle ? demangle(Name) : Name.str(); 9125ffd83dbSDimitry Andric } 9135ffd83dbSDimitry Andric 9145ffd83dbSDimitry Andric template <typename ELFT> 9155ffd83dbSDimitry Andric std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { 9165ffd83dbSDimitry Andric auto Warn = [&](Error E) -> std::string { 917e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the name of symbol with index " + 918e8d8bef9SDimitry Andric Twine(Index) + ": " + toString(std::move(E))); 9195ffd83dbSDimitry Andric return "<?>"; 9205ffd83dbSDimitry Andric }; 9215ffd83dbSDimitry Andric 9228bcb0991SDimitry Andric Expected<const typename ELFT::Sym *> SymOrErr = 923e8d8bef9SDimitry Andric Obj.getSymbol(DotSymtabSec, Index); 9248bcb0991SDimitry Andric if (!SymOrErr) 9255ffd83dbSDimitry Andric return Warn(SymOrErr.takeError()); 9268bcb0991SDimitry Andric 927e8d8bef9SDimitry Andric Expected<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*DotSymtabSec); 9288bcb0991SDimitry Andric if (!StrTabOrErr) 9295ffd83dbSDimitry Andric return Warn(StrTabOrErr.takeError()); 9308bcb0991SDimitry Andric 9318bcb0991SDimitry Andric Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr); 9328bcb0991SDimitry Andric if (!NameOrErr) 9335ffd83dbSDimitry Andric return Warn(NameOrErr.takeError()); 9348bcb0991SDimitry Andric return maybeDemangle(*NameOrErr); 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric template <typename ELFT> 938bdd1243dSDimitry Andric std::string ELFDumper<ELFT>::getFullSymbolName( 939bdd1243dSDimitry Andric const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable, 940bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic) const { 9415ffd83dbSDimitry Andric if (!StrTable) 9425ffd83dbSDimitry Andric return "<?>"; 9435ffd83dbSDimitry Andric 9445ffd83dbSDimitry Andric std::string SymbolName; 945e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = Symbol.getName(*StrTable)) { 9465ffd83dbSDimitry Andric SymbolName = maybeDemangle(*NameOrErr); 9475ffd83dbSDimitry Andric } else { 9485ffd83dbSDimitry Andric reportUniqueWarning(NameOrErr.takeError()); 9495ffd83dbSDimitry Andric return "<?>"; 9505ffd83dbSDimitry Andric } 9510b57cec5SDimitry Andric 952e8d8bef9SDimitry Andric if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) { 953480093f4SDimitry Andric Expected<unsigned> SectionIndex = 954e8d8bef9SDimitry Andric getSymbolSectionIndex(Symbol, SymIndex, ShndxTable); 955480093f4SDimitry Andric if (!SectionIndex) { 9565ffd83dbSDimitry Andric reportUniqueWarning(SectionIndex.takeError()); 957480093f4SDimitry Andric return "<?>"; 958480093f4SDimitry Andric } 959480093f4SDimitry Andric Expected<StringRef> NameOrErr = getSymbolSectionName(Symbol, *SectionIndex); 960480093f4SDimitry Andric if (!NameOrErr) { 9615ffd83dbSDimitry Andric reportUniqueWarning(NameOrErr.takeError()); 962480093f4SDimitry Andric return ("<section " + Twine(*SectionIndex) + ">").str(); 963480093f4SDimitry Andric } 9645ffd83dbSDimitry Andric return std::string(*NameOrErr); 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric if (!IsDynamic) 9680b57cec5SDimitry Andric return SymbolName; 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric bool IsDefault; 971e8d8bef9SDimitry Andric Expected<StringRef> VersionOrErr = getSymbolVersion(Symbol, IsDefault); 972480093f4SDimitry Andric if (!VersionOrErr) { 9735ffd83dbSDimitry Andric reportUniqueWarning(VersionOrErr.takeError()); 974480093f4SDimitry Andric return SymbolName + "@<corrupt>"; 975480093f4SDimitry Andric } 976480093f4SDimitry Andric 977480093f4SDimitry Andric if (!VersionOrErr->empty()) { 9780b57cec5SDimitry Andric SymbolName += (IsDefault ? "@@" : "@"); 979480093f4SDimitry Andric SymbolName += *VersionOrErr; 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric return SymbolName; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric template <typename ELFT> 985480093f4SDimitry Andric Expected<unsigned> 986e8d8bef9SDimitry Andric ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex, 987e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const { 988e8d8bef9SDimitry Andric unsigned Ndx = Symbol.st_shndx; 989e8d8bef9SDimitry Andric if (Ndx == SHN_XINDEX) 990e8d8bef9SDimitry Andric return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, 991e8d8bef9SDimitry Andric ShndxTable); 992e8d8bef9SDimitry Andric if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE) 993e8d8bef9SDimitry Andric return Ndx; 994e8d8bef9SDimitry Andric 995bdd1243dSDimitry Andric auto CreateErr = [&](const Twine &Name, 996bdd1243dSDimitry Andric std::optional<unsigned> Offset = std::nullopt) { 997e8d8bef9SDimitry Andric std::string Desc; 998e8d8bef9SDimitry Andric if (Offset) 999e8d8bef9SDimitry Andric Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str(); 1000e8d8bef9SDimitry Andric else 1001e8d8bef9SDimitry Andric Desc = Name.str(); 1002e8d8bef9SDimitry Andric return createError( 1003e8d8bef9SDimitry Andric "unable to get section index for symbol with st_shndx = 0x" + 1004e8d8bef9SDimitry Andric Twine::utohexstr(Ndx) + " (" + Desc + ")"); 1005e8d8bef9SDimitry Andric }; 1006e8d8bef9SDimitry Andric 1007e8d8bef9SDimitry Andric if (Ndx >= ELF::SHN_LOPROC && Ndx <= ELF::SHN_HIPROC) 1008e8d8bef9SDimitry Andric return CreateErr("SHN_LOPROC", Ndx - ELF::SHN_LOPROC); 1009e8d8bef9SDimitry Andric if (Ndx >= ELF::SHN_LOOS && Ndx <= ELF::SHN_HIOS) 1010e8d8bef9SDimitry Andric return CreateErr("SHN_LOOS", Ndx - ELF::SHN_LOOS); 1011e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_UNDEF) 1012e8d8bef9SDimitry Andric return CreateErr("SHN_UNDEF"); 1013e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_ABS) 1014e8d8bef9SDimitry Andric return CreateErr("SHN_ABS"); 1015e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_COMMON) 1016e8d8bef9SDimitry Andric return CreateErr("SHN_COMMON"); 1017e8d8bef9SDimitry Andric return CreateErr("SHN_LORESERVE", Ndx - SHN_LORESERVE); 10180b57cec5SDimitry Andric } 1019480093f4SDimitry Andric 1020480093f4SDimitry Andric template <typename ELFT> 1021480093f4SDimitry Andric Expected<StringRef> 1022e8d8bef9SDimitry Andric ELFDumper<ELFT>::getSymbolSectionName(const Elf_Sym &Symbol, 1023480093f4SDimitry Andric unsigned SectionIndex) const { 1024e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(SectionIndex); 1025480093f4SDimitry Andric if (!SecOrErr) 1026480093f4SDimitry Andric return SecOrErr.takeError(); 1027e8d8bef9SDimitry Andric return Obj.getSectionName(**SecOrErr); 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric template <class ELFO> 10310b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr * 1032e8d8bef9SDimitry Andric findNotEmptySectionByAddress(const ELFO &Obj, StringRef FileName, 10338bcb0991SDimitry Andric uint64_t Addr) { 10345ffd83dbSDimitry Andric for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections())) 1035e8d8bef9SDimitry Andric if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) 10360b57cec5SDimitry Andric return &Shdr; 10370b57cec5SDimitry Andric return nullptr; 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 1040349cc55cSDimitry Andric const EnumEntry<unsigned> ElfClass[] = { 10410b57cec5SDimitry Andric {"None", "none", ELF::ELFCLASSNONE}, 10420b57cec5SDimitry Andric {"32-bit", "ELF32", ELF::ELFCLASS32}, 10430b57cec5SDimitry Andric {"64-bit", "ELF64", ELF::ELFCLASS64}, 10440b57cec5SDimitry Andric }; 10450b57cec5SDimitry Andric 1046349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDataEncoding[] = { 10470b57cec5SDimitry Andric {"None", "none", ELF::ELFDATANONE}, 10480b57cec5SDimitry Andric {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB}, 10490b57cec5SDimitry Andric {"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB}, 10500b57cec5SDimitry Andric }; 10510b57cec5SDimitry Andric 1052349cc55cSDimitry Andric const EnumEntry<unsigned> ElfObjectFileType[] = { 10530b57cec5SDimitry Andric {"None", "NONE (none)", ELF::ET_NONE}, 10540b57cec5SDimitry Andric {"Relocatable", "REL (Relocatable file)", ELF::ET_REL}, 10550b57cec5SDimitry Andric {"Executable", "EXEC (Executable file)", ELF::ET_EXEC}, 10560b57cec5SDimitry Andric {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN}, 10570b57cec5SDimitry Andric {"Core", "CORE (Core file)", ELF::ET_CORE}, 10580b57cec5SDimitry Andric }; 10590b57cec5SDimitry Andric 1060349cc55cSDimitry Andric const EnumEntry<unsigned> ElfOSABI[] = { 10610b57cec5SDimitry Andric {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, 10620b57cec5SDimitry Andric {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, 10630b57cec5SDimitry Andric {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, 10640b57cec5SDimitry Andric {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, 10650b57cec5SDimitry Andric {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, 10660b57cec5SDimitry Andric {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, 10670b57cec5SDimitry Andric {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, 10680b57cec5SDimitry Andric {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, 10690b57cec5SDimitry Andric {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, 10700b57cec5SDimitry Andric {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, 10710b57cec5SDimitry Andric {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, 10720b57cec5SDimitry Andric {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, 10730b57cec5SDimitry Andric {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, 10740b57cec5SDimitry Andric {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, 10750b57cec5SDimitry Andric {"AROS", "AROS", ELF::ELFOSABI_AROS}, 10760b57cec5SDimitry Andric {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, 10770b57cec5SDimitry Andric {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, 10780b57cec5SDimitry Andric {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} 10790b57cec5SDimitry Andric }; 10800b57cec5SDimitry Andric 1081349cc55cSDimitry Andric const EnumEntry<unsigned> AMDGPUElfOSABI[] = { 10820b57cec5SDimitry Andric {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, 10830b57cec5SDimitry Andric {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL}, 10840b57cec5SDimitry Andric {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D} 10850b57cec5SDimitry Andric }; 10860b57cec5SDimitry Andric 1087349cc55cSDimitry Andric const EnumEntry<unsigned> ARMElfOSABI[] = { 10880b57cec5SDimitry Andric {"ARM", "ARM", ELF::ELFOSABI_ARM} 10890b57cec5SDimitry Andric }; 10900b57cec5SDimitry Andric 1091349cc55cSDimitry Andric const EnumEntry<unsigned> C6000ElfOSABI[] = { 10920b57cec5SDimitry Andric {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI}, 10930b57cec5SDimitry Andric {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX} 10940b57cec5SDimitry Andric }; 10950b57cec5SDimitry Andric 1096349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMachineType[] = { 10970b57cec5SDimitry Andric ENUM_ENT(EM_NONE, "None"), 10980b57cec5SDimitry Andric ENUM_ENT(EM_M32, "WE32100"), 10990b57cec5SDimitry Andric ENUM_ENT(EM_SPARC, "Sparc"), 11000b57cec5SDimitry Andric ENUM_ENT(EM_386, "Intel 80386"), 11010b57cec5SDimitry Andric ENUM_ENT(EM_68K, "MC68000"), 11020b57cec5SDimitry Andric ENUM_ENT(EM_88K, "MC88000"), 11030b57cec5SDimitry Andric ENUM_ENT(EM_IAMCU, "EM_IAMCU"), 11040b57cec5SDimitry Andric ENUM_ENT(EM_860, "Intel 80860"), 11050b57cec5SDimitry Andric ENUM_ENT(EM_MIPS, "MIPS R3000"), 11060b57cec5SDimitry Andric ENUM_ENT(EM_S370, "IBM System/370"), 11070b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"), 11080b57cec5SDimitry Andric ENUM_ENT(EM_PARISC, "HPPA"), 11090b57cec5SDimitry Andric ENUM_ENT(EM_VPP500, "Fujitsu VPP500"), 11100b57cec5SDimitry Andric ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"), 11110b57cec5SDimitry Andric ENUM_ENT(EM_960, "Intel 80960"), 11120b57cec5SDimitry Andric ENUM_ENT(EM_PPC, "PowerPC"), 11130b57cec5SDimitry Andric ENUM_ENT(EM_PPC64, "PowerPC64"), 11140b57cec5SDimitry Andric ENUM_ENT(EM_S390, "IBM S/390"), 11150b57cec5SDimitry Andric ENUM_ENT(EM_SPU, "SPU"), 11160b57cec5SDimitry Andric ENUM_ENT(EM_V800, "NEC V800 series"), 11170b57cec5SDimitry Andric ENUM_ENT(EM_FR20, "Fujistsu FR20"), 11180b57cec5SDimitry Andric ENUM_ENT(EM_RH32, "TRW RH-32"), 11190b57cec5SDimitry Andric ENUM_ENT(EM_RCE, "Motorola RCE"), 11200b57cec5SDimitry Andric ENUM_ENT(EM_ARM, "ARM"), 11210b57cec5SDimitry Andric ENUM_ENT(EM_ALPHA, "EM_ALPHA"), 11220b57cec5SDimitry Andric ENUM_ENT(EM_SH, "Hitachi SH"), 11230b57cec5SDimitry Andric ENUM_ENT(EM_SPARCV9, "Sparc v9"), 11240b57cec5SDimitry Andric ENUM_ENT(EM_TRICORE, "Siemens Tricore"), 11250b57cec5SDimitry Andric ENUM_ENT(EM_ARC, "ARC"), 11260b57cec5SDimitry Andric ENUM_ENT(EM_H8_300, "Hitachi H8/300"), 11270b57cec5SDimitry Andric ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"), 11280b57cec5SDimitry Andric ENUM_ENT(EM_H8S, "Hitachi H8S"), 11290b57cec5SDimitry Andric ENUM_ENT(EM_H8_500, "Hitachi H8/500"), 11300b57cec5SDimitry Andric ENUM_ENT(EM_IA_64, "Intel IA-64"), 11310b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"), 11320b57cec5SDimitry Andric ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"), 11330b57cec5SDimitry Andric ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"), 11340b57cec5SDimitry Andric ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"), 11350b57cec5SDimitry Andric ENUM_ENT(EM_PCP, "Siemens PCP"), 11360b57cec5SDimitry Andric ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"), 11370b57cec5SDimitry Andric ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"), 11380b57cec5SDimitry Andric ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"), 11390b57cec5SDimitry Andric ENUM_ENT(EM_ME16, "Toyota ME16 processor"), 11400b57cec5SDimitry Andric ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"), 11410b57cec5SDimitry Andric ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"), 11420b57cec5SDimitry Andric ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"), 11430b57cec5SDimitry Andric ENUM_ENT(EM_PDSP, "Sony DSP processor"), 11440b57cec5SDimitry Andric ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"), 11450b57cec5SDimitry Andric ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"), 11460b57cec5SDimitry Andric ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"), 11470b57cec5SDimitry Andric ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"), 11480b57cec5SDimitry Andric ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"), 11490b57cec5SDimitry Andric ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"), 11500b57cec5SDimitry Andric ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"), 11510b57cec5SDimitry Andric ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"), 11520b57cec5SDimitry Andric ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"), 11530b57cec5SDimitry Andric ENUM_ENT(EM_SVX, "Silicon Graphics SVx"), 11540b57cec5SDimitry Andric ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"), 11550b57cec5SDimitry Andric ENUM_ENT(EM_VAX, "Digital VAX"), 11560b57cec5SDimitry Andric ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"), 11570b57cec5SDimitry Andric ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"), 11580b57cec5SDimitry Andric ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"), 11590b57cec5SDimitry Andric ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"), 11600b57cec5SDimitry Andric ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"), 11610b57cec5SDimitry Andric ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"), 11620b57cec5SDimitry Andric ENUM_ENT(EM_PRISM, "Vitesse Prism"), 11630b57cec5SDimitry Andric ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"), 11640b57cec5SDimitry Andric ENUM_ENT(EM_FR30, "Fujitsu FR30"), 11650b57cec5SDimitry Andric ENUM_ENT(EM_D10V, "Mitsubishi D10V"), 11660b57cec5SDimitry Andric ENUM_ENT(EM_D30V, "Mitsubishi D30V"), 11670b57cec5SDimitry Andric ENUM_ENT(EM_V850, "NEC v850"), 11680b57cec5SDimitry Andric ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"), 11690b57cec5SDimitry Andric ENUM_ENT(EM_MN10300, "Matsushita MN10300"), 11700b57cec5SDimitry Andric ENUM_ENT(EM_MN10200, "Matsushita MN10200"), 11710b57cec5SDimitry Andric ENUM_ENT(EM_PJ, "picoJava"), 11720b57cec5SDimitry Andric ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"), 11730b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"), 11740b57cec5SDimitry Andric ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"), 11750b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"), 11760b57cec5SDimitry Andric ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"), 11770b57cec5SDimitry Andric ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"), 11780b57cec5SDimitry Andric ENUM_ENT(EM_TPC, "Tenor Network TPC processor"), 11790b57cec5SDimitry Andric ENUM_ENT(EM_SNP1K, "EM_SNP1K"), 11800b57cec5SDimitry Andric ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"), 11810b57cec5SDimitry Andric ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"), 11820b57cec5SDimitry Andric ENUM_ENT(EM_MAX, "MAX Processor"), 11830b57cec5SDimitry Andric ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"), 11840b57cec5SDimitry Andric ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"), 11850b57cec5SDimitry Andric ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"), 11860b57cec5SDimitry Andric ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"), 11870b57cec5SDimitry Andric ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"), 11880b57cec5SDimitry Andric ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"), 11890b57cec5SDimitry Andric ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"), 11900b57cec5SDimitry Andric ENUM_ENT(EM_UNICORE, "Unicore"), 11910b57cec5SDimitry Andric ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"), 11920b57cec5SDimitry Andric ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"), 11930b57cec5SDimitry Andric ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"), 11940b57cec5SDimitry Andric ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"), 11950b57cec5SDimitry Andric ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"), 11960b57cec5SDimitry Andric ENUM_ENT(EM_C166, "Infineon Technologies xc16x"), 11970b57cec5SDimitry Andric ENUM_ENT(EM_M16C, "Renesas M16C"), 11980b57cec5SDimitry Andric ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"), 11990b57cec5SDimitry Andric ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"), 12000b57cec5SDimitry Andric ENUM_ENT(EM_M32C, "Renesas M32C"), 12010b57cec5SDimitry Andric ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"), 12020b57cec5SDimitry Andric ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"), 12030b57cec5SDimitry Andric ENUM_ENT(EM_SHARC, "EM_SHARC"), 12040b57cec5SDimitry Andric ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"), 12050b57cec5SDimitry Andric ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"), 12060b57cec5SDimitry Andric ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"), 12070b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"), 12080b57cec5SDimitry Andric ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"), 12090b57cec5SDimitry Andric ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"), 12100b57cec5SDimitry Andric ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"), 12110b57cec5SDimitry Andric ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"), 12120b57cec5SDimitry Andric ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"), 12130b57cec5SDimitry Andric ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"), 12140b57cec5SDimitry Andric ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"), 12150b57cec5SDimitry Andric ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"), 12160b57cec5SDimitry Andric ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"), 12170b57cec5SDimitry Andric ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"), 12180b57cec5SDimitry Andric ENUM_ENT(EM_8051, "Intel 8051 and variants"), 12190b57cec5SDimitry Andric ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"), 12200b57cec5SDimitry Andric ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"), 12210b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"), 12225ffd83dbSDimitry Andric // FIXME: Following EM_ECOG1X definitions is dead code since EM_ECOG1X has 12235ffd83dbSDimitry Andric // an identical number to EM_ECOG1. 12240b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"), 12250b57cec5SDimitry Andric ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"), 12260b57cec5SDimitry Andric ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"), 12270b57cec5SDimitry Andric ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"), 12280b57cec5SDimitry Andric ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"), 12290b57cec5SDimitry Andric ENUM_ENT(EM_RX, "Renesas RX"), 12300b57cec5SDimitry Andric ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"), 12310b57cec5SDimitry Andric ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"), 12320b57cec5SDimitry Andric ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"), 1233fe6060f1SDimitry Andric ENUM_ENT(EM_CR16, "National Semiconductor CompactRISC 16-bit processor"), 12340b57cec5SDimitry Andric ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"), 12350b57cec5SDimitry Andric ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"), 12360b57cec5SDimitry Andric ENUM_ENT(EM_L10M, "EM_L10M"), 12370b57cec5SDimitry Andric ENUM_ENT(EM_K10M, "EM_K10M"), 12380b57cec5SDimitry Andric ENUM_ENT(EM_AARCH64, "AArch64"), 12390b57cec5SDimitry Andric ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"), 12400b57cec5SDimitry Andric ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"), 12410b57cec5SDimitry Andric ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"), 12420b57cec5SDimitry Andric ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"), 1243fe6060f1SDimitry Andric ENUM_ENT(EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core"), 12440b57cec5SDimitry Andric ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"), 12450b57cec5SDimitry Andric ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"), 12460b57cec5SDimitry Andric ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"), 12470b57cec5SDimitry Andric ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"), 12480b57cec5SDimitry Andric ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"), 12490b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"), 12500b57cec5SDimitry Andric ENUM_ENT(EM_OPEN8, "EM_OPEN8"), 12510b57cec5SDimitry Andric ENUM_ENT(EM_RL78, "Renesas RL78"), 12520b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"), 12530b57cec5SDimitry Andric ENUM_ENT(EM_78KOR, "EM_78KOR"), 12540b57cec5SDimitry Andric ENUM_ENT(EM_56800EX, "EM_56800EX"), 12550b57cec5SDimitry Andric ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"), 12560b57cec5SDimitry Andric ENUM_ENT(EM_RISCV, "RISC-V"), 12570b57cec5SDimitry Andric ENUM_ENT(EM_LANAI, "EM_LANAI"), 12580b57cec5SDimitry Andric ENUM_ENT(EM_BPF, "EM_BPF"), 12595ffd83dbSDimitry Andric ENUM_ENT(EM_VE, "NEC SX-Aurora Vector Engine"), 126081ad6265SDimitry Andric ENUM_ENT(EM_LOONGARCH, "LoongArch"), 12610b57cec5SDimitry Andric }; 12620b57cec5SDimitry Andric 1263349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymbolBindings[] = { 12640b57cec5SDimitry Andric {"Local", "LOCAL", ELF::STB_LOCAL}, 12650b57cec5SDimitry Andric {"Global", "GLOBAL", ELF::STB_GLOBAL}, 12660b57cec5SDimitry Andric {"Weak", "WEAK", ELF::STB_WEAK}, 12670b57cec5SDimitry Andric {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}}; 12680b57cec5SDimitry Andric 1269349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymbolVisibilities[] = { 12700b57cec5SDimitry Andric {"DEFAULT", "DEFAULT", ELF::STV_DEFAULT}, 12710b57cec5SDimitry Andric {"INTERNAL", "INTERNAL", ELF::STV_INTERNAL}, 12720b57cec5SDimitry Andric {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, 12730b57cec5SDimitry Andric {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; 12740b57cec5SDimitry Andric 1275349cc55cSDimitry Andric const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { 12760b57cec5SDimitry Andric { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } 12770b57cec5SDimitry Andric }; 12780b57cec5SDimitry Andric 12790b57cec5SDimitry Andric static const char *getGroupType(uint32_t Flag) { 12800b57cec5SDimitry Andric if (Flag & ELF::GRP_COMDAT) 12810b57cec5SDimitry Andric return "COMDAT"; 12820b57cec5SDimitry Andric else 12830b57cec5SDimitry Andric return "(unknown)"; 12840b57cec5SDimitry Andric } 12850b57cec5SDimitry Andric 1286349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSectionFlags[] = { 12870b57cec5SDimitry Andric ENUM_ENT(SHF_WRITE, "W"), 12880b57cec5SDimitry Andric ENUM_ENT(SHF_ALLOC, "A"), 12890b57cec5SDimitry Andric ENUM_ENT(SHF_EXECINSTR, "X"), 12900b57cec5SDimitry Andric ENUM_ENT(SHF_MERGE, "M"), 12910b57cec5SDimitry Andric ENUM_ENT(SHF_STRINGS, "S"), 12920b57cec5SDimitry Andric ENUM_ENT(SHF_INFO_LINK, "I"), 12930b57cec5SDimitry Andric ENUM_ENT(SHF_LINK_ORDER, "L"), 1294480093f4SDimitry Andric ENUM_ENT(SHF_OS_NONCONFORMING, "O"), 12950b57cec5SDimitry Andric ENUM_ENT(SHF_GROUP, "G"), 12960b57cec5SDimitry Andric ENUM_ENT(SHF_TLS, "T"), 1297480093f4SDimitry Andric ENUM_ENT(SHF_COMPRESSED, "C"), 1298480093f4SDimitry Andric ENUM_ENT(SHF_EXCLUDE, "E"), 12990b57cec5SDimitry Andric }; 13000b57cec5SDimitry Andric 130181ad6265SDimitry Andric const EnumEntry<unsigned> ElfGNUSectionFlags[] = { 130281ad6265SDimitry Andric ENUM_ENT(SHF_GNU_RETAIN, "R") 130381ad6265SDimitry Andric }; 130481ad6265SDimitry Andric 130581ad6265SDimitry Andric const EnumEntry<unsigned> ElfSolarisSectionFlags[] = { 130681ad6265SDimitry Andric ENUM_ENT(SHF_SUNW_NODISCARD, "R") 130781ad6265SDimitry Andric }; 130881ad6265SDimitry Andric 1309349cc55cSDimitry Andric const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { 1310480093f4SDimitry Andric ENUM_ENT(XCORE_SHF_CP_SECTION, ""), 1311480093f4SDimitry Andric ENUM_ENT(XCORE_SHF_DP_SECTION, "") 13120b57cec5SDimitry Andric }; 13130b57cec5SDimitry Andric 1314349cc55cSDimitry Andric const EnumEntry<unsigned> ElfARMSectionFlags[] = { 1315480093f4SDimitry Andric ENUM_ENT(SHF_ARM_PURECODE, "y") 13160b57cec5SDimitry Andric }; 13170b57cec5SDimitry Andric 1318349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { 1319480093f4SDimitry Andric ENUM_ENT(SHF_HEX_GPREL, "") 13200b57cec5SDimitry Andric }; 13210b57cec5SDimitry Andric 1322349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsSectionFlags[] = { 1323480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NODUPES, ""), 1324480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NAMES, ""), 1325480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_LOCAL, ""), 1326480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NOSTRIP, ""), 1327480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_GPREL, ""), 1328480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_MERGE, ""), 1329480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_ADDR, ""), 1330480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_STRING, "") 13310b57cec5SDimitry Andric }; 13320b57cec5SDimitry Andric 1333349cc55cSDimitry Andric const EnumEntry<unsigned> ElfX86_64SectionFlags[] = { 1334480093f4SDimitry Andric ENUM_ENT(SHF_X86_64_LARGE, "l") 13350b57cec5SDimitry Andric }; 13360b57cec5SDimitry Andric 1337480093f4SDimitry Andric static std::vector<EnumEntry<unsigned>> 133881ad6265SDimitry Andric getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) { 1339480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags), 1340480093f4SDimitry Andric std::end(ElfSectionFlags)); 134181ad6265SDimitry Andric switch (EOSAbi) { 134281ad6265SDimitry Andric case ELFOSABI_SOLARIS: 134381ad6265SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags), 134481ad6265SDimitry Andric std::end(ElfSolarisSectionFlags)); 134581ad6265SDimitry Andric break; 134681ad6265SDimitry Andric default: 134781ad6265SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags), 134881ad6265SDimitry Andric std::end(ElfGNUSectionFlags)); 134981ad6265SDimitry Andric break; 135081ad6265SDimitry Andric } 1351480093f4SDimitry Andric switch (EMachine) { 1352480093f4SDimitry Andric case EM_ARM: 1353480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags), 1354480093f4SDimitry Andric std::end(ElfARMSectionFlags)); 1355480093f4SDimitry Andric break; 1356480093f4SDimitry Andric case EM_HEXAGON: 1357480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfHexagonSectionFlags), 1358480093f4SDimitry Andric std::end(ElfHexagonSectionFlags)); 1359480093f4SDimitry Andric break; 1360480093f4SDimitry Andric case EM_MIPS: 1361480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfMipsSectionFlags), 1362480093f4SDimitry Andric std::end(ElfMipsSectionFlags)); 1363480093f4SDimitry Andric break; 1364480093f4SDimitry Andric case EM_X86_64: 1365480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfX86_64SectionFlags), 1366480093f4SDimitry Andric std::end(ElfX86_64SectionFlags)); 1367480093f4SDimitry Andric break; 1368480093f4SDimitry Andric case EM_XCORE: 1369480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfXCoreSectionFlags), 1370480093f4SDimitry Andric std::end(ElfXCoreSectionFlags)); 13710b57cec5SDimitry Andric break; 13720b57cec5SDimitry Andric default: 1373480093f4SDimitry Andric break; 1374480093f4SDimitry Andric } 1375480093f4SDimitry Andric return Ret; 1376480093f4SDimitry Andric } 1377480093f4SDimitry Andric 137881ad6265SDimitry Andric static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine, 137981ad6265SDimitry Andric uint64_t Flags) { 1380480093f4SDimitry Andric // Here we are trying to build the flags string in the same way as GNU does. 1381480093f4SDimitry Andric // It is not that straightforward. Imagine we have sh_flags == 0x90000000. 1382480093f4SDimitry Andric // SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000. 1383480093f4SDimitry Andric // GNU readelf will not print "E" or "Ep" in this case, but will print just 1384480093f4SDimitry Andric // "p". It only will print "E" when no other processor flag is set. 1385480093f4SDimitry Andric std::string Str; 1386480093f4SDimitry Andric bool HasUnknownFlag = false; 1387480093f4SDimitry Andric bool HasOSFlag = false; 1388480093f4SDimitry Andric bool HasProcFlag = false; 1389480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> FlagsList = 139081ad6265SDimitry Andric getSectionFlagsForTarget(EOSAbi, EMachine); 1391480093f4SDimitry Andric while (Flags) { 1392480093f4SDimitry Andric // Take the least significant bit as a flag. 1393480093f4SDimitry Andric uint64_t Flag = Flags & -Flags; 1394480093f4SDimitry Andric Flags -= Flag; 1395480093f4SDimitry Andric 1396480093f4SDimitry Andric // Find the flag in the known flags list. 1397480093f4SDimitry Andric auto I = llvm::find_if(FlagsList, [=](const EnumEntry<unsigned> &E) { 1398480093f4SDimitry Andric // Flags with empty names are not printed in GNU style output. 1399480093f4SDimitry Andric return E.Value == Flag && !E.AltName.empty(); 1400480093f4SDimitry Andric }); 1401480093f4SDimitry Andric if (I != FlagsList.end()) { 1402480093f4SDimitry Andric Str += I->AltName; 1403480093f4SDimitry Andric continue; 1404480093f4SDimitry Andric } 1405480093f4SDimitry Andric 1406480093f4SDimitry Andric // If we did not find a matching regular flag, then we deal with an OS 1407480093f4SDimitry Andric // specific flag, processor specific flag or an unknown flag. 1408480093f4SDimitry Andric if (Flag & ELF::SHF_MASKOS) { 1409480093f4SDimitry Andric HasOSFlag = true; 1410480093f4SDimitry Andric Flags &= ~ELF::SHF_MASKOS; 1411480093f4SDimitry Andric } else if (Flag & ELF::SHF_MASKPROC) { 1412480093f4SDimitry Andric HasProcFlag = true; 1413480093f4SDimitry Andric // Mask off all the processor-specific bits. This removes the SHF_EXCLUDE 1414480093f4SDimitry Andric // bit if set so that it doesn't also get printed. 1415480093f4SDimitry Andric Flags &= ~ELF::SHF_MASKPROC; 1416480093f4SDimitry Andric } else { 1417480093f4SDimitry Andric HasUnknownFlag = true; 1418480093f4SDimitry Andric } 1419480093f4SDimitry Andric } 1420480093f4SDimitry Andric 1421480093f4SDimitry Andric // "o", "p" and "x" are printed last. 1422480093f4SDimitry Andric if (HasOSFlag) 14230b57cec5SDimitry Andric Str += "o"; 1424480093f4SDimitry Andric if (HasProcFlag) 14250b57cec5SDimitry Andric Str += "p"; 1426480093f4SDimitry Andric if (HasUnknownFlag) 14270b57cec5SDimitry Andric Str += "x"; 14280b57cec5SDimitry Andric return Str; 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 1431e8d8bef9SDimitry Andric static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { 1432e8d8bef9SDimitry Andric // Check potentially overlapped processor-specific program header type. 14330b57cec5SDimitry Andric switch (Arch) { 14340b57cec5SDimitry Andric case ELF::EM_ARM: 14350b57cec5SDimitry Andric switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); } 14360b57cec5SDimitry Andric break; 14370b57cec5SDimitry Andric case ELF::EM_MIPS: 14380b57cec5SDimitry Andric case ELF::EM_MIPS_RS3_LE: 14390b57cec5SDimitry Andric switch (Type) { 14400b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); 14410b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); 14420b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); 14430b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS); 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric break; 144681ad6265SDimitry Andric case ELF::EM_RISCV: 144781ad6265SDimitry Andric switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_RISCV_ATTRIBUTES); } 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric switch (Type) { 14510b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL); 14520b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD); 14530b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC); 14540b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP); 14550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE); 14560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB); 14570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR); 14580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS); 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME); 14610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND); 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); 14640b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); 1465480093f4SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY); 14660b57cec5SDimitry Andric 1467bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE); 14680b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); 14690b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); 14700b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); 14710b57cec5SDimitry Andric default: 14720b57cec5SDimitry Andric return ""; 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric 1476e8d8bef9SDimitry Andric static std::string getGNUPtType(unsigned Arch, unsigned Type) { 1477e8d8bef9SDimitry Andric StringRef Seg = segmentTypeToString(Arch, Type); 1478e8d8bef9SDimitry Andric if (Seg.empty()) 14790b57cec5SDimitry Andric return std::string("<unknown>: ") + to_string(format_hex(Type, 1)); 1480e8d8bef9SDimitry Andric 1481e8d8bef9SDimitry Andric // E.g. "PT_ARM_EXIDX" -> "EXIDX". 148281ad6265SDimitry Andric if (Seg.consume_front("PT_ARM_")) 148381ad6265SDimitry Andric return Seg.str(); 1484e8d8bef9SDimitry Andric 1485e8d8bef9SDimitry Andric // E.g. "PT_MIPS_REGINFO" -> "REGINFO". 148681ad6265SDimitry Andric if (Seg.consume_front("PT_MIPS_")) 148781ad6265SDimitry Andric return Seg.str(); 148881ad6265SDimitry Andric 148981ad6265SDimitry Andric // E.g. "PT_RISCV_ATTRIBUTES" 149081ad6265SDimitry Andric if (Seg.consume_front("PT_RISCV_")) 149181ad6265SDimitry Andric return Seg.str(); 1492e8d8bef9SDimitry Andric 1493e8d8bef9SDimitry Andric // E.g. "PT_LOAD" -> "LOAD". 1494e8d8bef9SDimitry Andric assert(Seg.startswith("PT_")); 1495e8d8bef9SDimitry Andric return Seg.drop_front(3).str(); 14960b57cec5SDimitry Andric } 14970b57cec5SDimitry Andric 1498349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSegmentFlags[] = { 14990b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_X), 15000b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_W), 15010b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_R) 15020b57cec5SDimitry Andric }; 15030b57cec5SDimitry Andric 1504349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { 15050b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"), 15060b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_PIC, "pic"), 15070b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_CPIC, "cpic"), 15080b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI2, "abi2"), 15090b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"), 15100b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_FP64, "fp64"), 15110b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NAN2008, "nan2008"), 15120b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O32, "o32"), 15130b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O64, "o64"), 15140b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"), 15150b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"), 15160b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_3900, "3900"), 15170b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4010, "4010"), 15180b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4100, "4100"), 15190b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4650, "4650"), 15200b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4120, "4120"), 15210b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4111, "4111"), 15220b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"), 15230b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"), 15240b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"), 15250b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"), 15260b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"), 15270b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5400, "5400"), 15280b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5900, "5900"), 15290b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5500, "5500"), 15300b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_9000, "9000"), 15310b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"), 15320b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"), 15330b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"), 15340b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"), 15350b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"), 15360b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"), 15370b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_1, "mips1"), 15380b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_2, "mips2"), 15390b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_3, "mips3"), 15400b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_4, "mips4"), 15410b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_5, "mips5"), 15420b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32, "mips32"), 15430b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64, "mips64"), 15440b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"), 15450b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"), 15460b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"), 15470b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6") 15480b57cec5SDimitry Andric }; 15490b57cec5SDimitry Andric 1550349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = { 15510b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE), 15520b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600), 15530b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630), 15540b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880), 15550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670), 15560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710), 15570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730), 15580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770), 15590b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR), 15600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS), 15610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER), 15620b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD), 15630b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO), 15640b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS), 15650b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS), 15660b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN), 15670b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS), 15680b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600), 15690b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601), 1570e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX602), 15710b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700), 15720b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701), 15730b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702), 15740b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703), 15750b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704), 1576e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX705), 15770b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801), 15780b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802), 15790b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803), 1580e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX805), 15810b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810), 15820b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900), 15830b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902), 15840b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904), 15850b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906), 15860b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908), 15870b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909), 1588fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A), 1589e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C), 159081ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940), 159106c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941), 159206c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942), 15930b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010), 15940b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011), 15950b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012), 1596fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013), 15975ffd83dbSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030), 1598e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031), 1599e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032), 1600e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033), 1601fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034), 1602fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035), 160381ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1036), 160481ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1100), 160581ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101), 160681ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102), 160781ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103), 160806c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150), 160906c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151), 1610fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_V3), 1611fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_V3) 1612fe6060f1SDimitry Andric }; 1613fe6060f1SDimitry Andric 1614349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = { 1615fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE), 1616fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600), 1617fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630), 1618fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880), 1619fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670), 1620fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710), 1621fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730), 1622fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770), 1623fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR), 1624fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS), 1625fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER), 1626fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD), 1627fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO), 1628fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS), 1629fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS), 1630fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN), 1631fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS), 1632fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600), 1633fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601), 1634fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX602), 1635fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700), 1636fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701), 1637fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702), 1638fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703), 1639fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704), 1640fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX705), 1641fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801), 1642fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802), 1643fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803), 1644fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX805), 1645fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810), 1646fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900), 1647fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902), 1648fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904), 1649fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906), 1650fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908), 1651fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909), 1652fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A), 1653fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C), 165481ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940), 165506c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941), 165606c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942), 1657fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010), 1658fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011), 1659fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012), 1660fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013), 1661fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030), 1662fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031), 1663fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032), 1664fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033), 1665fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034), 1666fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035), 166781ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1036), 166881ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1100), 166981ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101), 167081ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102), 167181ad6265SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103), 167206c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150), 167306c3fb27SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151), 1674fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ANY_V4), 1675fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_OFF_V4), 1676fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ON_V4), 1677fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ANY_V4), 1678fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_OFF_V4), 1679fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ON_V4) 16800b57cec5SDimitry Andric }; 16810b57cec5SDimitry Andric 1682349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { 16830b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_RVC, "RVC"), 16840b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"), 16850b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"), 16860b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"), 168704eeddc0SDimitry Andric ENUM_ENT(EF_RISCV_RVE, "RVE"), 168804eeddc0SDimitry Andric ENUM_ENT(EF_RISCV_TSO, "TSO"), 16890b57cec5SDimitry Andric }; 16900b57cec5SDimitry Andric 1691349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAVRFlags[] = { 1692fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1), 1693fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2), 1694fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25), 1695fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3), 1696fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31), 1697fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35), 1698fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4), 1699fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5), 1700fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51), 1701fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6), 1702fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY), 1703fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1), 1704fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2), 1705fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3), 1706fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4), 1707fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5), 1708fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6), 1709fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7), 1710fe6060f1SDimitry Andric ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"), 1711fe6060f1SDimitry Andric }; 1712fe6060f1SDimitry Andric 1713972a253aSDimitry Andric const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = { 1714bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"), 1715bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"), 1716bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"), 1717bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"), 1718bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"), 1719972a253aSDimitry Andric }; 1720972a253aSDimitry Andric 1721bdd1243dSDimitry Andric static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = { 1722bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE), 1723bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN), 1724bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT) 1725bdd1243dSDimitry Andric }; 1726fe6060f1SDimitry Andric 1727349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymOtherFlags[] = { 17280b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), 17290b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN), 17300b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED) 17310b57cec5SDimitry Andric }; 17320b57cec5SDimitry Andric 1733349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = { 17340b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 17350b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 17360b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC), 17370b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS) 17380b57cec5SDimitry Andric }; 17390b57cec5SDimitry Andric 1740349cc55cSDimitry Andric const EnumEntry<unsigned> ElfAArch64SymOtherFlags[] = { 1741e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS) 1742e8d8bef9SDimitry Andric }; 1743e8d8bef9SDimitry Andric 1744349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = { 17450b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 17460b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 17470b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16) 17480b57cec5SDimitry Andric }; 17490b57cec5SDimitry Andric 1750349cc55cSDimitry Andric const EnumEntry<unsigned> ElfRISCVSymOtherFlags[] = { 1751349cc55cSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)}; 1752349cc55cSDimitry Andric 17530b57cec5SDimitry Andric static const char *getElfMipsOptionsOdkType(unsigned Odk) { 17540b57cec5SDimitry Andric switch (Odk) { 17550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL); 17560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO); 17570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS); 17580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD); 17590b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH); 17600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL); 17610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS); 17620b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND); 17630b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR); 17640b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP); 17650b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT); 17660b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE); 17670b57cec5SDimitry Andric default: 17680b57cec5SDimitry Andric return "Unknown"; 17690b57cec5SDimitry Andric } 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric template <typename ELFT> 17738bcb0991SDimitry Andric std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *> 1774e8d8bef9SDimitry Andric ELFDumper<ELFT>::findDynamic() { 17750b57cec5SDimitry Andric // Try to locate the PT_DYNAMIC header. 17760b57cec5SDimitry Andric const Elf_Phdr *DynamicPhdr = nullptr; 1777e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = Obj.program_headers()) { 17785ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 17790b57cec5SDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC) 17800b57cec5SDimitry Andric continue; 17810b57cec5SDimitry Andric DynamicPhdr = &Phdr; 17820b57cec5SDimitry Andric break; 17830b57cec5SDimitry Andric } 17845ffd83dbSDimitry Andric } else { 1785e8d8bef9SDimitry Andric reportUniqueWarning( 17865ffd83dbSDimitry Andric "unable to read program headers to locate the PT_DYNAMIC segment: " + 1787e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 17885ffd83dbSDimitry Andric } 17890b57cec5SDimitry Andric 17900b57cec5SDimitry Andric // Try to locate the .dynamic section in the sections header table. 17910b57cec5SDimitry Andric const Elf_Shdr *DynamicSec = nullptr; 1792e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 17930b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_DYNAMIC) 17940b57cec5SDimitry Andric continue; 17950b57cec5SDimitry Andric DynamicSec = &Sec; 17960b57cec5SDimitry Andric break; 17970b57cec5SDimitry Andric } 17980b57cec5SDimitry Andric 1799e8d8bef9SDimitry Andric if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz > 1800e8d8bef9SDimitry Andric ObjF.getMemoryBufferRef().getBufferSize()) || 1801e8d8bef9SDimitry Andric (DynamicPhdr->p_offset + DynamicPhdr->p_filesz < 1802e8d8bef9SDimitry Andric DynamicPhdr->p_offset))) { 1803e8d8bef9SDimitry Andric reportUniqueWarning( 1804e8d8bef9SDimitry Andric "PT_DYNAMIC segment offset (0x" + 1805e8d8bef9SDimitry Andric Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" + 1806e8d8bef9SDimitry Andric Twine::utohexstr(DynamicPhdr->p_filesz) + 1807e8d8bef9SDimitry Andric ") exceeds the size of the file (0x" + 1808e8d8bef9SDimitry Andric Twine::utohexstr(ObjF.getMemoryBufferRef().getBufferSize()) + ")"); 18098bcb0991SDimitry Andric // Don't use the broken dynamic header. 18108bcb0991SDimitry Andric DynamicPhdr = nullptr; 18110b57cec5SDimitry Andric } 18120b57cec5SDimitry Andric 18138bcb0991SDimitry Andric if (DynamicPhdr && DynamicSec) { 18140b57cec5SDimitry Andric if (DynamicSec->sh_addr + DynamicSec->sh_size > 18150b57cec5SDimitry Andric DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || 18160b57cec5SDimitry Andric DynamicSec->sh_addr < DynamicPhdr->p_vaddr) 1817e8d8bef9SDimitry Andric reportUniqueWarning(describe(*DynamicSec) + 1818e8d8bef9SDimitry Andric " is not contained within the " 1819e8d8bef9SDimitry Andric "PT_DYNAMIC segment"); 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr) 1822e8d8bef9SDimitry Andric reportUniqueWarning(describe(*DynamicSec) + " is not at the start of " 1823e8d8bef9SDimitry Andric "PT_DYNAMIC segment"); 18248bcb0991SDimitry Andric } 18258bcb0991SDimitry Andric 18268bcb0991SDimitry Andric return std::make_pair(DynamicPhdr, DynamicSec); 18278bcb0991SDimitry Andric } 18288bcb0991SDimitry Andric 18298bcb0991SDimitry Andric template <typename ELFT> 1830e8d8bef9SDimitry Andric void ELFDumper<ELFT>::loadDynamicTable() { 18318bcb0991SDimitry Andric const Elf_Phdr *DynamicPhdr; 18328bcb0991SDimitry Andric const Elf_Shdr *DynamicSec; 1833e8d8bef9SDimitry Andric std::tie(DynamicPhdr, DynamicSec) = findDynamic(); 18348bcb0991SDimitry Andric if (!DynamicPhdr && !DynamicSec) 18358bcb0991SDimitry Andric return; 18368bcb0991SDimitry Andric 1837e8d8bef9SDimitry Andric DynRegionInfo FromPhdr(ObjF, *this); 18388bcb0991SDimitry Andric bool IsPhdrTableValid = false; 18398bcb0991SDimitry Andric if (DynamicPhdr) { 1840e8d8bef9SDimitry Andric // Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are 1841e8d8bef9SDimitry Andric // validated in findDynamic() and so createDRI() is not expected to fail. 1842e8d8bef9SDimitry Andric FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz, 1843e8d8bef9SDimitry Andric sizeof(Elf_Dyn))); 18445ffd83dbSDimitry Andric FromPhdr.SizePrintName = "PT_DYNAMIC size"; 18455ffd83dbSDimitry Andric FromPhdr.EntSizePrintName = ""; 1846e8d8bef9SDimitry Andric IsPhdrTableValid = !FromPhdr.template getAsArrayRef<Elf_Dyn>().empty(); 18478bcb0991SDimitry Andric } 18488bcb0991SDimitry Andric 18498bcb0991SDimitry Andric // Locate the dynamic table described in a section header. 18508bcb0991SDimitry Andric // Ignore sh_entsize and use the expected value for entry size explicitly. 18518bcb0991SDimitry Andric // This allows us to dump dynamic sections with a broken sh_entsize 18528bcb0991SDimitry Andric // field. 1853e8d8bef9SDimitry Andric DynRegionInfo FromSec(ObjF, *this); 18548bcb0991SDimitry Andric bool IsSecTableValid = false; 18558bcb0991SDimitry Andric if (DynamicSec) { 1856e8d8bef9SDimitry Andric Expected<DynRegionInfo> RegOrErr = 1857e8d8bef9SDimitry Andric createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn)); 1858e8d8bef9SDimitry Andric if (RegOrErr) { 1859e8d8bef9SDimitry Andric FromSec = *RegOrErr; 1860e8d8bef9SDimitry Andric FromSec.Context = describe(*DynamicSec); 18615ffd83dbSDimitry Andric FromSec.EntSizePrintName = ""; 1862e8d8bef9SDimitry Andric IsSecTableValid = !FromSec.template getAsArrayRef<Elf_Dyn>().empty(); 1863e8d8bef9SDimitry Andric } else { 1864e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the dynamic table from " + 1865e8d8bef9SDimitry Andric describe(*DynamicSec) + ": " + 1866e8d8bef9SDimitry Andric toString(RegOrErr.takeError())); 1867e8d8bef9SDimitry Andric } 18688bcb0991SDimitry Andric } 18698bcb0991SDimitry Andric 18708bcb0991SDimitry Andric // When we only have information from one of the SHT_DYNAMIC section header or 18718bcb0991SDimitry Andric // PT_DYNAMIC program header, just use that. 18728bcb0991SDimitry Andric if (!DynamicPhdr || !DynamicSec) { 18738bcb0991SDimitry Andric if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) { 18748bcb0991SDimitry Andric DynamicTable = DynamicPhdr ? FromPhdr : FromSec; 1875e8d8bef9SDimitry Andric parseDynamicTable(); 18768bcb0991SDimitry Andric } else { 1877e8d8bef9SDimitry Andric reportUniqueWarning("no valid dynamic table was found"); 18788bcb0991SDimitry Andric } 18798bcb0991SDimitry Andric return; 18808bcb0991SDimitry Andric } 18818bcb0991SDimitry Andric 18828bcb0991SDimitry Andric // At this point we have tables found from the section header and from the 18838bcb0991SDimitry Andric // dynamic segment. Usually they match, but we have to do sanity checks to 18848bcb0991SDimitry Andric // verify that. 18858bcb0991SDimitry Andric 18868bcb0991SDimitry Andric if (FromPhdr.Addr != FromSec.Addr) 1887e8d8bef9SDimitry Andric reportUniqueWarning("SHT_DYNAMIC section header and PT_DYNAMIC " 18888bcb0991SDimitry Andric "program header disagree about " 1889e8d8bef9SDimitry Andric "the location of the dynamic table"); 18908bcb0991SDimitry Andric 18918bcb0991SDimitry Andric if (!IsPhdrTableValid && !IsSecTableValid) { 1892e8d8bef9SDimitry Andric reportUniqueWarning("no valid dynamic table was found"); 18938bcb0991SDimitry Andric return; 18948bcb0991SDimitry Andric } 18958bcb0991SDimitry Andric 1896e8d8bef9SDimitry Andric // Information in the PT_DYNAMIC program header has priority over the 1897e8d8bef9SDimitry Andric // information in a section header. 18988bcb0991SDimitry Andric if (IsPhdrTableValid) { 18998bcb0991SDimitry Andric if (!IsSecTableValid) 1900e8d8bef9SDimitry Andric reportUniqueWarning( 1901e8d8bef9SDimitry Andric "SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used"); 19028bcb0991SDimitry Andric DynamicTable = FromPhdr; 19038bcb0991SDimitry Andric } else { 1904e8d8bef9SDimitry Andric reportUniqueWarning( 1905e8d8bef9SDimitry Andric "PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used"); 19068bcb0991SDimitry Andric DynamicTable = FromSec; 19078bcb0991SDimitry Andric } 19088bcb0991SDimitry Andric 1909e8d8bef9SDimitry Andric parseDynamicTable(); 19100b57cec5SDimitry Andric } 19110b57cec5SDimitry Andric 19120b57cec5SDimitry Andric template <typename ELFT> 1913e8d8bef9SDimitry Andric ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O, 19140b57cec5SDimitry Andric ScopedPrinter &Writer) 1915e8d8bef9SDimitry Andric : ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()), 1916e8d8bef9SDimitry Andric FileName(O.getFileName()), DynRelRegion(O, *this), 1917e8d8bef9SDimitry Andric DynRelaRegion(O, *this), DynRelrRegion(O, *this), 1918e8d8bef9SDimitry Andric DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this), 1919e8d8bef9SDimitry Andric DynamicTable(O, *this) { 1920e8d8bef9SDimitry Andric if (!O.IsContentValid()) 1921e8d8bef9SDimitry Andric return; 19225ffd83dbSDimitry Andric 1923e8d8bef9SDimitry Andric typename ELFT::ShdrRange Sections = cantFail(Obj.sections()); 19245ffd83dbSDimitry Andric for (const Elf_Shdr &Sec : Sections) { 19250b57cec5SDimitry Andric switch (Sec.sh_type) { 19260b57cec5SDimitry Andric case ELF::SHT_SYMTAB: 19270b57cec5SDimitry Andric if (!DotSymtabSec) 19280b57cec5SDimitry Andric DotSymtabSec = &Sec; 19290b57cec5SDimitry Andric break; 19300b57cec5SDimitry Andric case ELF::SHT_DYNSYM: 1931e8d8bef9SDimitry Andric if (!DotDynsymSec) 1932e8d8bef9SDimitry Andric DotDynsymSec = &Sec; 19330b57cec5SDimitry Andric 1934e8d8bef9SDimitry Andric if (!DynSymRegion) { 1935e8d8bef9SDimitry Andric Expected<DynRegionInfo> RegOrErr = 1936e8d8bef9SDimitry Andric createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize); 1937e8d8bef9SDimitry Andric if (RegOrErr) { 1938e8d8bef9SDimitry Andric DynSymRegion = *RegOrErr; 1939e8d8bef9SDimitry Andric DynSymRegion->Context = describe(Sec); 1940e8d8bef9SDimitry Andric 1941e8d8bef9SDimitry Andric if (Expected<StringRef> E = Obj.getStringTableForSymtab(Sec)) 19420b57cec5SDimitry Andric DynamicStringTable = *E; 19430b57cec5SDimitry Andric else 1944e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the string table for the " + 1945e8d8bef9SDimitry Andric describe(Sec) + ": " + toString(E.takeError())); 1946e8d8bef9SDimitry Andric } else { 1947e8d8bef9SDimitry Andric reportUniqueWarning("unable to read dynamic symbols from " + 1948e8d8bef9SDimitry Andric describe(Sec) + ": " + 1949e8d8bef9SDimitry Andric toString(RegOrErr.takeError())); 1950e8d8bef9SDimitry Andric } 19510b57cec5SDimitry Andric } 19520b57cec5SDimitry Andric break; 1953e8d8bef9SDimitry Andric case ELF::SHT_SYMTAB_SHNDX: { 1954e8d8bef9SDimitry Andric uint32_t SymtabNdx = Sec.sh_link; 1955e8d8bef9SDimitry Andric if (SymtabNdx >= Sections.size()) { 1956e8d8bef9SDimitry Andric reportUniqueWarning( 1957e8d8bef9SDimitry Andric "unable to get the associated symbol table for " + describe(Sec) + 1958e8d8bef9SDimitry Andric ": sh_link (" + Twine(SymtabNdx) + 1959e8d8bef9SDimitry Andric ") is greater than or equal to the total number of sections (" + 1960e8d8bef9SDimitry Andric Twine(Sections.size()) + ")"); 1961e8d8bef9SDimitry Andric continue; 1962e8d8bef9SDimitry Andric } 1963e8d8bef9SDimitry Andric 1964e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr = 1965e8d8bef9SDimitry Andric Obj.getSHNDXTable(Sec)) { 1966e8d8bef9SDimitry Andric if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr}) 1967e8d8bef9SDimitry Andric .second) 1968e8d8bef9SDimitry Andric reportUniqueWarning( 1969e8d8bef9SDimitry Andric "multiple SHT_SYMTAB_SHNDX sections are linked to " + 1970e8d8bef9SDimitry Andric describe(Sec)); 1971e8d8bef9SDimitry Andric } else { 1972e8d8bef9SDimitry Andric reportUniqueWarning(ShndxTableOrErr.takeError()); 1973e8d8bef9SDimitry Andric } 19740b57cec5SDimitry Andric break; 1975e8d8bef9SDimitry Andric } 19760b57cec5SDimitry Andric case ELF::SHT_GNU_versym: 19770b57cec5SDimitry Andric if (!SymbolVersionSection) 19780b57cec5SDimitry Andric SymbolVersionSection = &Sec; 19790b57cec5SDimitry Andric break; 19800b57cec5SDimitry Andric case ELF::SHT_GNU_verdef: 19810b57cec5SDimitry Andric if (!SymbolVersionDefSection) 19820b57cec5SDimitry Andric SymbolVersionDefSection = &Sec; 19830b57cec5SDimitry Andric break; 19840b57cec5SDimitry Andric case ELF::SHT_GNU_verneed: 19850b57cec5SDimitry Andric if (!SymbolVersionNeedSection) 19860b57cec5SDimitry Andric SymbolVersionNeedSection = &Sec; 19870b57cec5SDimitry Andric break; 19880b57cec5SDimitry Andric case ELF::SHT_LLVM_ADDRSIG: 19890b57cec5SDimitry Andric if (!DotAddrsigSec) 19900b57cec5SDimitry Andric DotAddrsigSec = &Sec; 19910b57cec5SDimitry Andric break; 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric } 19940b57cec5SDimitry Andric 1995e8d8bef9SDimitry Andric loadDynamicTable(); 19960b57cec5SDimitry Andric } 19970b57cec5SDimitry Andric 1998e8d8bef9SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() { 19990b57cec5SDimitry Andric auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * { 2000e8d8bef9SDimitry Andric auto MappedAddrOrError = Obj.toMappedAddr(VAddr, [&](const Twine &Msg) { 2001e8d8bef9SDimitry Andric this->reportUniqueWarning(Msg); 2002e8d8bef9SDimitry Andric return Error::success(); 2003e8d8bef9SDimitry Andric }); 20040b57cec5SDimitry Andric if (!MappedAddrOrError) { 2005e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to parse DT_" + 2006e8d8bef9SDimitry Andric Obj.getDynamicTagAsString(Tag) + ": " + 2007e8d8bef9SDimitry Andric llvm::toString(MappedAddrOrError.takeError())); 20080b57cec5SDimitry Andric return nullptr; 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric return MappedAddrOrError.get(); 20110b57cec5SDimitry Andric }; 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric const char *StringTableBegin = nullptr; 20140b57cec5SDimitry Andric uint64_t StringTableSize = 0; 2015bdd1243dSDimitry Andric std::optional<DynRegionInfo> DynSymFromTable; 20160b57cec5SDimitry Andric for (const Elf_Dyn &Dyn : dynamic_table()) { 20170b57cec5SDimitry Andric switch (Dyn.d_tag) { 20180b57cec5SDimitry Andric case ELF::DT_HASH: 20190b57cec5SDimitry Andric HashTable = reinterpret_cast<const Elf_Hash *>( 20200b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20210b57cec5SDimitry Andric break; 20220b57cec5SDimitry Andric case ELF::DT_GNU_HASH: 20230b57cec5SDimitry Andric GnuHashTable = reinterpret_cast<const Elf_GnuHash *>( 20240b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20250b57cec5SDimitry Andric break; 20260b57cec5SDimitry Andric case ELF::DT_STRTAB: 20270b57cec5SDimitry Andric StringTableBegin = reinterpret_cast<const char *>( 20280b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20290b57cec5SDimitry Andric break; 20300b57cec5SDimitry Andric case ELF::DT_STRSZ: 20310b57cec5SDimitry Andric StringTableSize = Dyn.getVal(); 20320b57cec5SDimitry Andric break; 20338bcb0991SDimitry Andric case ELF::DT_SYMTAB: { 20345ffd83dbSDimitry Andric // If we can't map the DT_SYMTAB value to an address (e.g. when there are 20355ffd83dbSDimitry Andric // no program headers), we ignore its value. 20368bcb0991SDimitry Andric if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) { 2037e8d8bef9SDimitry Andric DynSymFromTable.emplace(ObjF, *this); 20385ffd83dbSDimitry Andric DynSymFromTable->Addr = VA; 20395ffd83dbSDimitry Andric DynSymFromTable->EntSize = sizeof(Elf_Sym); 20405ffd83dbSDimitry Andric DynSymFromTable->EntSizePrintName = ""; 20418bcb0991SDimitry Andric } 20420b57cec5SDimitry Andric break; 20438bcb0991SDimitry Andric } 20445ffd83dbSDimitry Andric case ELF::DT_SYMENT: { 20455ffd83dbSDimitry Andric uint64_t Val = Dyn.getVal(); 20465ffd83dbSDimitry Andric if (Val != sizeof(Elf_Sym)) 2047e8d8bef9SDimitry Andric this->reportUniqueWarning("DT_SYMENT value of 0x" + 20485ffd83dbSDimitry Andric Twine::utohexstr(Val) + 20495ffd83dbSDimitry Andric " is not the size of a symbol (0x" + 2050e8d8bef9SDimitry Andric Twine::utohexstr(sizeof(Elf_Sym)) + ")"); 20515ffd83dbSDimitry Andric break; 20525ffd83dbSDimitry Andric } 20530b57cec5SDimitry Andric case ELF::DT_RELA: 20540b57cec5SDimitry Andric DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20550b57cec5SDimitry Andric break; 20560b57cec5SDimitry Andric case ELF::DT_RELASZ: 20570b57cec5SDimitry Andric DynRelaRegion.Size = Dyn.getVal(); 20585ffd83dbSDimitry Andric DynRelaRegion.SizePrintName = "DT_RELASZ value"; 20590b57cec5SDimitry Andric break; 20600b57cec5SDimitry Andric case ELF::DT_RELAENT: 20610b57cec5SDimitry Andric DynRelaRegion.EntSize = Dyn.getVal(); 20625ffd83dbSDimitry Andric DynRelaRegion.EntSizePrintName = "DT_RELAENT value"; 20630b57cec5SDimitry Andric break; 20640b57cec5SDimitry Andric case ELF::DT_SONAME: 20650b57cec5SDimitry Andric SONameOffset = Dyn.getVal(); 20660b57cec5SDimitry Andric break; 20670b57cec5SDimitry Andric case ELF::DT_REL: 20680b57cec5SDimitry Andric DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20690b57cec5SDimitry Andric break; 20700b57cec5SDimitry Andric case ELF::DT_RELSZ: 20710b57cec5SDimitry Andric DynRelRegion.Size = Dyn.getVal(); 20725ffd83dbSDimitry Andric DynRelRegion.SizePrintName = "DT_RELSZ value"; 20730b57cec5SDimitry Andric break; 20740b57cec5SDimitry Andric case ELF::DT_RELENT: 20750b57cec5SDimitry Andric DynRelRegion.EntSize = Dyn.getVal(); 20765ffd83dbSDimitry Andric DynRelRegion.EntSizePrintName = "DT_RELENT value"; 20770b57cec5SDimitry Andric break; 20780b57cec5SDimitry Andric case ELF::DT_RELR: 20790b57cec5SDimitry Andric case ELF::DT_ANDROID_RELR: 20800b57cec5SDimitry Andric DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20810b57cec5SDimitry Andric break; 20820b57cec5SDimitry Andric case ELF::DT_RELRSZ: 20830b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRSZ: 20840b57cec5SDimitry Andric DynRelrRegion.Size = Dyn.getVal(); 20855ffd83dbSDimitry Andric DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ 20865ffd83dbSDimitry Andric ? "DT_RELRSZ value" 20875ffd83dbSDimitry Andric : "DT_ANDROID_RELRSZ value"; 20880b57cec5SDimitry Andric break; 20890b57cec5SDimitry Andric case ELF::DT_RELRENT: 20900b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRENT: 20910b57cec5SDimitry Andric DynRelrRegion.EntSize = Dyn.getVal(); 20925ffd83dbSDimitry Andric DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT 20935ffd83dbSDimitry Andric ? "DT_RELRENT value" 20945ffd83dbSDimitry Andric : "DT_ANDROID_RELRENT value"; 20950b57cec5SDimitry Andric break; 20960b57cec5SDimitry Andric case ELF::DT_PLTREL: 20970b57cec5SDimitry Andric if (Dyn.getVal() == DT_REL) 20980b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rel); 20990b57cec5SDimitry Andric else if (Dyn.getVal() == DT_RELA) 21000b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rela); 21010b57cec5SDimitry Andric else 2102e8d8bef9SDimitry Andric reportUniqueWarning(Twine("unknown DT_PLTREL value of ") + 2103e8d8bef9SDimitry Andric Twine((uint64_t)Dyn.getVal())); 2104e8d8bef9SDimitry Andric DynPLTRelRegion.EntSizePrintName = "PLTREL entry size"; 21050b57cec5SDimitry Andric break; 21060b57cec5SDimitry Andric case ELF::DT_JMPREL: 21070b57cec5SDimitry Andric DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 21080b57cec5SDimitry Andric break; 21090b57cec5SDimitry Andric case ELF::DT_PLTRELSZ: 21100b57cec5SDimitry Andric DynPLTRelRegion.Size = Dyn.getVal(); 21115ffd83dbSDimitry Andric DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value"; 21120b57cec5SDimitry Andric break; 2113e8d8bef9SDimitry Andric case ELF::DT_SYMTAB_SHNDX: 2114e8d8bef9SDimitry Andric DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 2115e8d8bef9SDimitry Andric DynSymTabShndxRegion.EntSize = sizeof(Elf_Word); 2116e8d8bef9SDimitry Andric break; 21170b57cec5SDimitry Andric } 21180b57cec5SDimitry Andric } 21195ffd83dbSDimitry Andric 21205ffd83dbSDimitry Andric if (StringTableBegin) { 2121e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 2122e8d8bef9SDimitry Andric const uint64_t Offset = (const uint8_t *)StringTableBegin - Obj.base(); 21235ffd83dbSDimitry Andric if (StringTableSize > FileSize - Offset) 2124e8d8bef9SDimitry Andric reportUniqueWarning( 21255ffd83dbSDimitry Andric "the dynamic string table at 0x" + Twine::utohexstr(Offset) + 21265ffd83dbSDimitry Andric " goes past the end of the file (0x" + Twine::utohexstr(FileSize) + 2127e8d8bef9SDimitry Andric ") with DT_STRSZ = 0x" + Twine::utohexstr(StringTableSize)); 21285ffd83dbSDimitry Andric else 21290b57cec5SDimitry Andric DynamicStringTable = StringRef(StringTableBegin, StringTableSize); 21305ffd83dbSDimitry Andric } 21315ffd83dbSDimitry Andric 2132e8d8bef9SDimitry Andric const bool IsHashTableSupported = getHashTableEntSize() == 4; 21335ffd83dbSDimitry Andric if (DynSymRegion) { 21345ffd83dbSDimitry Andric // Often we find the information about the dynamic symbol table 21355ffd83dbSDimitry Andric // location in the SHT_DYNSYM section header. However, the value in 21365ffd83dbSDimitry Andric // DT_SYMTAB has priority, because it is used by dynamic loaders to 21375ffd83dbSDimitry Andric // locate .dynsym at runtime. The location we find in the section header 21385ffd83dbSDimitry Andric // and the location we find here should match. 21395ffd83dbSDimitry Andric if (DynSymFromTable && DynSymFromTable->Addr != DynSymRegion->Addr) 21405ffd83dbSDimitry Andric reportUniqueWarning( 21415ffd83dbSDimitry Andric createError("SHT_DYNSYM section header and DT_SYMTAB disagree about " 21425ffd83dbSDimitry Andric "the location of the dynamic symbol table")); 21435ffd83dbSDimitry Andric 21445ffd83dbSDimitry Andric // According to the ELF gABI: "The number of symbol table entries should 21455ffd83dbSDimitry Andric // equal nchain". Check to see if the DT_HASH hash table nchain value 21465ffd83dbSDimitry Andric // conflicts with the number of symbols in the dynamic symbol table 21475ffd83dbSDimitry Andric // according to the section header. 2148e8d8bef9SDimitry Andric if (HashTable && IsHashTableSupported) { 21495ffd83dbSDimitry Andric if (DynSymRegion->EntSize == 0) 2150e8d8bef9SDimitry Andric reportUniqueWarning("SHT_DYNSYM section has sh_entsize == 0"); 21515ffd83dbSDimitry Andric else if (HashTable->nchain != DynSymRegion->Size / DynSymRegion->EntSize) 2152e8d8bef9SDimitry Andric reportUniqueWarning( 21535ffd83dbSDimitry Andric "hash table nchain (" + Twine(HashTable->nchain) + 21545ffd83dbSDimitry Andric ") differs from symbol count derived from SHT_DYNSYM section " 21555ffd83dbSDimitry Andric "header (" + 2156e8d8bef9SDimitry Andric Twine(DynSymRegion->Size / DynSymRegion->EntSize) + ")"); 21575ffd83dbSDimitry Andric } 21585ffd83dbSDimitry Andric } 21595ffd83dbSDimitry Andric 21605ffd83dbSDimitry Andric // Delay the creation of the actual dynamic symbol table until now, so that 21615ffd83dbSDimitry Andric // checks can always be made against the section header-based properties, 21625ffd83dbSDimitry Andric // without worrying about tag order. 21635ffd83dbSDimitry Andric if (DynSymFromTable) { 21645ffd83dbSDimitry Andric if (!DynSymRegion) { 21655ffd83dbSDimitry Andric DynSymRegion = DynSymFromTable; 21665ffd83dbSDimitry Andric } else { 21675ffd83dbSDimitry Andric DynSymRegion->Addr = DynSymFromTable->Addr; 21685ffd83dbSDimitry Andric DynSymRegion->EntSize = DynSymFromTable->EntSize; 21695ffd83dbSDimitry Andric DynSymRegion->EntSizePrintName = DynSymFromTable->EntSizePrintName; 21705ffd83dbSDimitry Andric } 21715ffd83dbSDimitry Andric } 21725ffd83dbSDimitry Andric 21735ffd83dbSDimitry Andric // Derive the dynamic symbol table size from the DT_HASH hash table, if 21745ffd83dbSDimitry Andric // present. 2175e8d8bef9SDimitry Andric if (HashTable && IsHashTableSupported && DynSymRegion) { 2176e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 2177e8d8bef9SDimitry Andric const uint64_t DerivedSize = 2178e8d8bef9SDimitry Andric (uint64_t)HashTable->nchain * DynSymRegion->EntSize; 2179e8d8bef9SDimitry Andric const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base(); 2180e8d8bef9SDimitry Andric if (DerivedSize > FileSize - Offset) 2181e8d8bef9SDimitry Andric reportUniqueWarning( 2182e8d8bef9SDimitry Andric "the size (0x" + Twine::utohexstr(DerivedSize) + 2183e8d8bef9SDimitry Andric ") of the dynamic symbol table at 0x" + Twine::utohexstr(Offset) + 2184e8d8bef9SDimitry Andric ", derived from the hash table, goes past the end of the file (0x" + 2185e8d8bef9SDimitry Andric Twine::utohexstr(FileSize) + ") and will be ignored"); 2186e8d8bef9SDimitry Andric else 21875ffd83dbSDimitry Andric DynSymRegion->Size = HashTable->nchain * DynSymRegion->EntSize; 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric 21910b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() { 21920b57cec5SDimitry Andric // Dump version symbol section. 2193e8d8bef9SDimitry Andric printVersionSymbolSection(SymbolVersionSection); 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric // Dump version definition section. 2196e8d8bef9SDimitry Andric printVersionDefinitionSection(SymbolVersionDefSection); 21970b57cec5SDimitry Andric 21980b57cec5SDimitry Andric // Dump version dependency section. 2199e8d8bef9SDimitry Andric printVersionDependencySection(SymbolVersionNeedSection); 22008bcb0991SDimitry Andric } 22018bcb0991SDimitry Andric 22020b57cec5SDimitry Andric #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ 22030b57cec5SDimitry Andric { #enum, prefix##_##enum } 22040b57cec5SDimitry Andric 2205349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTFlags[] = { 22060b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), 22070b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), 22080b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), 22090b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), 22100b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) 22110b57cec5SDimitry Andric }; 22120b57cec5SDimitry Andric 2213349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { 22140b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), 22150b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), 22160b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), 22170b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), 22180b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), 22190b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), 22200b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), 22210b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), 22220b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), 22230b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), 22240b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), 22250b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), 22260b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), 22270b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), 22280b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), 22290b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), 22300b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND), 22310b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), 22320b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), 22330b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), 22340b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), 22350b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), 22360b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), 22370b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), 22380b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), 22394e99f454SEd Maste LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON), 22404e99f454SEd Maste LLVM_READOBJ_DT_FLAG_ENT(DF_1, PIE), 22410b57cec5SDimitry Andric }; 22420b57cec5SDimitry Andric 2243349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { 22440b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), 22450b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), 22460b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), 22470b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), 22480b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), 22490b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), 22500b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), 22510b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), 22520b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), 22530b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), 22540b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), 22550b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), 22560b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), 22570b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), 22580b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), 22590b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) 22600b57cec5SDimitry Andric }; 22610b57cec5SDimitry Andric 22620b57cec5SDimitry Andric #undef LLVM_READOBJ_DT_FLAG_ENT 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric template <typename T, typename TFlag> 22650b57cec5SDimitry Andric void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { 2266e8d8bef9SDimitry Andric SmallVector<EnumEntry<TFlag>, 10> SetFlags; 2267e8d8bef9SDimitry Andric for (const EnumEntry<TFlag> &Flag : Flags) 2268e8d8bef9SDimitry Andric if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value) 22690b57cec5SDimitry Andric SetFlags.push_back(Flag); 22700b57cec5SDimitry Andric 2271e8d8bef9SDimitry Andric for (const EnumEntry<TFlag> &Flag : SetFlags) 22720b57cec5SDimitry Andric OS << Flag.Name << " "; 22730b57cec5SDimitry Andric } 2274e8d8bef9SDimitry Andric 2275e8d8bef9SDimitry Andric template <class ELFT> 2276e8d8bef9SDimitry Andric const typename ELFT::Shdr * 2277e8d8bef9SDimitry Andric ELFDumper<ELFT>::findSectionByName(StringRef Name) const { 2278e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) { 2279e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr)) { 2280e8d8bef9SDimitry Andric if (*NameOrErr == Name) 2281e8d8bef9SDimitry Andric return &Shdr; 2282e8d8bef9SDimitry Andric } else { 2283e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the name of " + describe(Shdr) + 2284e8d8bef9SDimitry Andric ": " + toString(NameOrErr.takeError())); 2285e8d8bef9SDimitry Andric } 2286e8d8bef9SDimitry Andric } 2287e8d8bef9SDimitry Andric return nullptr; 22880b57cec5SDimitry Andric } 22890b57cec5SDimitry Andric 22900b57cec5SDimitry Andric template <class ELFT> 22915ffd83dbSDimitry Andric std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type, 22920b57cec5SDimitry Andric uint64_t Value) const { 22935ffd83dbSDimitry Andric auto FormatHexValue = [](uint64_t V) { 22945ffd83dbSDimitry Andric std::string Str; 22955ffd83dbSDimitry Andric raw_string_ostream OS(Str); 22960b57cec5SDimitry Andric const char *ConvChar = 22970b57cec5SDimitry Andric (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64; 22985ffd83dbSDimitry Andric OS << format(ConvChar, V); 22995ffd83dbSDimitry Andric return OS.str(); 23005ffd83dbSDimitry Andric }; 23015ffd83dbSDimitry Andric 23025ffd83dbSDimitry Andric auto FormatFlags = [](uint64_t V, 23035ffd83dbSDimitry Andric llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) { 23045ffd83dbSDimitry Andric std::string Str; 23055ffd83dbSDimitry Andric raw_string_ostream OS(Str); 23065ffd83dbSDimitry Andric printFlags(V, Array, OS); 23075ffd83dbSDimitry Andric return OS.str(); 23085ffd83dbSDimitry Andric }; 23090b57cec5SDimitry Andric 23100b57cec5SDimitry Andric // Handle custom printing of architecture specific tags 2311e8d8bef9SDimitry Andric switch (Obj.getHeader().e_machine) { 23120b57cec5SDimitry Andric case EM_AARCH64: 23130b57cec5SDimitry Andric switch (Type) { 23140b57cec5SDimitry Andric case DT_AARCH64_BTI_PLT: 23150b57cec5SDimitry Andric case DT_AARCH64_PAC_PLT: 2316e8d8bef9SDimitry Andric case DT_AARCH64_VARIANT_PCS: 231706c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALSSZ: 23185ffd83dbSDimitry Andric return std::to_string(Value); 231906c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_MODE: 232006c3fb27SDimitry Andric switch (Value) { 232106c3fb27SDimitry Andric case 0: 232206c3fb27SDimitry Andric return "Synchronous (0)"; 232306c3fb27SDimitry Andric case 1: 232406c3fb27SDimitry Andric return "Asynchronous (1)"; 232506c3fb27SDimitry Andric default: 232606c3fb27SDimitry Andric return (Twine("Unknown (") + Twine(Value) + ")").str(); 232706c3fb27SDimitry Andric } 232806c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_HEAP: 232906c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_STACK: 233006c3fb27SDimitry Andric switch (Value) { 233106c3fb27SDimitry Andric case 0: 233206c3fb27SDimitry Andric return "Disabled (0)"; 233306c3fb27SDimitry Andric case 1: 233406c3fb27SDimitry Andric return "Enabled (1)"; 233506c3fb27SDimitry Andric default: 233606c3fb27SDimitry Andric return (Twine("Unknown (") + Twine(Value) + ")").str(); 233706c3fb27SDimitry Andric } 233806c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALS: 233906c3fb27SDimitry Andric return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str(); 23400b57cec5SDimitry Andric default: 23410b57cec5SDimitry Andric break; 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric break; 23440b57cec5SDimitry Andric case EM_HEXAGON: 23450b57cec5SDimitry Andric switch (Type) { 23460b57cec5SDimitry Andric case DT_HEXAGON_VER: 23475ffd83dbSDimitry Andric return std::to_string(Value); 23480b57cec5SDimitry Andric case DT_HEXAGON_SYMSZ: 23490b57cec5SDimitry Andric case DT_HEXAGON_PLT: 23505ffd83dbSDimitry Andric return FormatHexValue(Value); 23510b57cec5SDimitry Andric default: 23520b57cec5SDimitry Andric break; 23530b57cec5SDimitry Andric } 23540b57cec5SDimitry Andric break; 23550b57cec5SDimitry Andric case EM_MIPS: 23560b57cec5SDimitry Andric switch (Type) { 23570b57cec5SDimitry Andric case DT_MIPS_RLD_VERSION: 23580b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTNO: 23590b57cec5SDimitry Andric case DT_MIPS_SYMTABNO: 23600b57cec5SDimitry Andric case DT_MIPS_UNREFEXTNO: 23615ffd83dbSDimitry Andric return std::to_string(Value); 23620b57cec5SDimitry Andric case DT_MIPS_TIME_STAMP: 23630b57cec5SDimitry Andric case DT_MIPS_ICHECKSUM: 23640b57cec5SDimitry Andric case DT_MIPS_IVERSION: 23650b57cec5SDimitry Andric case DT_MIPS_BASE_ADDRESS: 23660b57cec5SDimitry Andric case DT_MIPS_MSYM: 23670b57cec5SDimitry Andric case DT_MIPS_CONFLICT: 23680b57cec5SDimitry Andric case DT_MIPS_LIBLIST: 23690b57cec5SDimitry Andric case DT_MIPS_CONFLICTNO: 23700b57cec5SDimitry Andric case DT_MIPS_LIBLISTNO: 23710b57cec5SDimitry Andric case DT_MIPS_GOTSYM: 23720b57cec5SDimitry Andric case DT_MIPS_HIPAGENO: 23730b57cec5SDimitry Andric case DT_MIPS_RLD_MAP: 23740b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS: 23750b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS_NO: 23760b57cec5SDimitry Andric case DT_MIPS_DELTA_INSTANCE: 23770b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC: 23780b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC_NO: 23790b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM: 23800b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM_NO: 23810b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM: 23820b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM_NO: 23830b57cec5SDimitry Andric case DT_MIPS_CXX_FLAGS: 23840b57cec5SDimitry Andric case DT_MIPS_PIXIE_INIT: 23850b57cec5SDimitry Andric case DT_MIPS_SYMBOL_LIB: 23860b57cec5SDimitry Andric case DT_MIPS_LOCALPAGE_GOTIDX: 23870b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTIDX: 23880b57cec5SDimitry Andric case DT_MIPS_HIDDEN_GOTIDX: 23890b57cec5SDimitry Andric case DT_MIPS_PROTECTED_GOTIDX: 23900b57cec5SDimitry Andric case DT_MIPS_OPTIONS: 23910b57cec5SDimitry Andric case DT_MIPS_INTERFACE: 23920b57cec5SDimitry Andric case DT_MIPS_DYNSTR_ALIGN: 23930b57cec5SDimitry Andric case DT_MIPS_INTERFACE_SIZE: 23940b57cec5SDimitry Andric case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: 23950b57cec5SDimitry Andric case DT_MIPS_PERF_SUFFIX: 23960b57cec5SDimitry Andric case DT_MIPS_COMPACT_SIZE: 23970b57cec5SDimitry Andric case DT_MIPS_GP_VALUE: 23980b57cec5SDimitry Andric case DT_MIPS_AUX_DYNAMIC: 23990b57cec5SDimitry Andric case DT_MIPS_PLTGOT: 24000b57cec5SDimitry Andric case DT_MIPS_RWPLT: 24010b57cec5SDimitry Andric case DT_MIPS_RLD_MAP_REL: 2402d781ede6SDimitry Andric case DT_MIPS_XHASH: 24035ffd83dbSDimitry Andric return FormatHexValue(Value); 24040b57cec5SDimitry Andric case DT_MIPS_FLAGS: 2405bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags)); 24060b57cec5SDimitry Andric default: 24070b57cec5SDimitry Andric break; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric break; 24100b57cec5SDimitry Andric default: 24110b57cec5SDimitry Andric break; 24120b57cec5SDimitry Andric } 24130b57cec5SDimitry Andric 24140b57cec5SDimitry Andric switch (Type) { 24150b57cec5SDimitry Andric case DT_PLTREL: 24165ffd83dbSDimitry Andric if (Value == DT_REL) 24175ffd83dbSDimitry Andric return "REL"; 24185ffd83dbSDimitry Andric if (Value == DT_RELA) 24195ffd83dbSDimitry Andric return "RELA"; 2420bdd1243dSDimitry Andric [[fallthrough]]; 24210b57cec5SDimitry Andric case DT_PLTGOT: 24220b57cec5SDimitry Andric case DT_HASH: 24230b57cec5SDimitry Andric case DT_STRTAB: 24240b57cec5SDimitry Andric case DT_SYMTAB: 24250b57cec5SDimitry Andric case DT_RELA: 24260b57cec5SDimitry Andric case DT_INIT: 24270b57cec5SDimitry Andric case DT_FINI: 24280b57cec5SDimitry Andric case DT_REL: 24290b57cec5SDimitry Andric case DT_JMPREL: 24300b57cec5SDimitry Andric case DT_INIT_ARRAY: 24310b57cec5SDimitry Andric case DT_FINI_ARRAY: 24320b57cec5SDimitry Andric case DT_PREINIT_ARRAY: 24330b57cec5SDimitry Andric case DT_DEBUG: 24340b57cec5SDimitry Andric case DT_VERDEF: 24350b57cec5SDimitry Andric case DT_VERNEED: 24360b57cec5SDimitry Andric case DT_VERSYM: 24370b57cec5SDimitry Andric case DT_GNU_HASH: 24380b57cec5SDimitry Andric case DT_NULL: 24395ffd83dbSDimitry Andric return FormatHexValue(Value); 24400b57cec5SDimitry Andric case DT_RELACOUNT: 24410b57cec5SDimitry Andric case DT_RELCOUNT: 24420b57cec5SDimitry Andric case DT_VERDEFNUM: 24430b57cec5SDimitry Andric case DT_VERNEEDNUM: 24445ffd83dbSDimitry Andric return std::to_string(Value); 24450b57cec5SDimitry Andric case DT_PLTRELSZ: 24460b57cec5SDimitry Andric case DT_RELASZ: 24470b57cec5SDimitry Andric case DT_RELAENT: 24480b57cec5SDimitry Andric case DT_STRSZ: 24490b57cec5SDimitry Andric case DT_SYMENT: 24500b57cec5SDimitry Andric case DT_RELSZ: 24510b57cec5SDimitry Andric case DT_RELENT: 24520b57cec5SDimitry Andric case DT_INIT_ARRAYSZ: 24530b57cec5SDimitry Andric case DT_FINI_ARRAYSZ: 24540b57cec5SDimitry Andric case DT_PREINIT_ARRAYSZ: 2455349cc55cSDimitry Andric case DT_RELRSZ: 2456349cc55cSDimitry Andric case DT_RELRENT: 24570b57cec5SDimitry Andric case DT_ANDROID_RELSZ: 24580b57cec5SDimitry Andric case DT_ANDROID_RELASZ: 24595ffd83dbSDimitry Andric return std::to_string(Value) + " (bytes)"; 24600b57cec5SDimitry Andric case DT_NEEDED: 24610b57cec5SDimitry Andric case DT_SONAME: 24620b57cec5SDimitry Andric case DT_AUXILIARY: 24630b57cec5SDimitry Andric case DT_USED: 24640b57cec5SDimitry Andric case DT_FILTER: 24650b57cec5SDimitry Andric case DT_RPATH: 24660b57cec5SDimitry Andric case DT_RUNPATH: { 24670b57cec5SDimitry Andric const std::map<uint64_t, const char *> TagNames = { 24685ffd83dbSDimitry Andric {DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"}, 24695ffd83dbSDimitry Andric {DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"}, 24705ffd83dbSDimitry Andric {DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"}, 24710b57cec5SDimitry Andric {DT_RUNPATH, "Library runpath"}, 24720b57cec5SDimitry Andric }; 24735ffd83dbSDimitry Andric 24745ffd83dbSDimitry Andric return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]") 24755ffd83dbSDimitry Andric .str(); 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric case DT_FLAGS: 2478bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags)); 24790b57cec5SDimitry Andric case DT_FLAGS_1: 2480bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1)); 24810b57cec5SDimitry Andric default: 24825ffd83dbSDimitry Andric return FormatHexValue(Value); 24830b57cec5SDimitry Andric } 24840b57cec5SDimitry Andric } 24850b57cec5SDimitry Andric 24868bcb0991SDimitry Andric template <class ELFT> 24875ffd83dbSDimitry Andric StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { 24885ffd83dbSDimitry Andric if (DynamicStringTable.empty() && !DynamicStringTable.data()) { 2489e8d8bef9SDimitry Andric reportUniqueWarning("string table was not found"); 24905ffd83dbSDimitry Andric return "<?>"; 24915ffd83dbSDimitry Andric } 24925ffd83dbSDimitry Andric 24935ffd83dbSDimitry Andric auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) { 2494e8d8bef9SDimitry Andric reportUniqueWarning("string table at offset 0x" + Twine::utohexstr(Offset) + 2495e8d8bef9SDimitry Andric Msg); 24965ffd83dbSDimitry Andric return "<?>"; 24975ffd83dbSDimitry Andric }; 24985ffd83dbSDimitry Andric 2499e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 25005ffd83dbSDimitry Andric const uint64_t Offset = 2501e8d8bef9SDimitry Andric (const uint8_t *)DynamicStringTable.data() - Obj.base(); 25025ffd83dbSDimitry Andric if (DynamicStringTable.size() > FileSize - Offset) 25035ffd83dbSDimitry Andric return WarnAndReturn(" with size 0x" + 25045ffd83dbSDimitry Andric Twine::utohexstr(DynamicStringTable.size()) + 25055ffd83dbSDimitry Andric " goes past the end of the file (0x" + 25065ffd83dbSDimitry Andric Twine::utohexstr(FileSize) + ")", 25075ffd83dbSDimitry Andric Offset); 25085ffd83dbSDimitry Andric 25095ffd83dbSDimitry Andric if (Value >= DynamicStringTable.size()) 25105ffd83dbSDimitry Andric return WarnAndReturn( 25115ffd83dbSDimitry Andric ": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) + 25125ffd83dbSDimitry Andric ": it goes past the end of the table (0x" + 25135ffd83dbSDimitry Andric Twine::utohexstr(Offset + DynamicStringTable.size()) + ")", 25145ffd83dbSDimitry Andric Offset); 25155ffd83dbSDimitry Andric 25165ffd83dbSDimitry Andric if (DynamicStringTable.back() != '\0') 25175ffd83dbSDimitry Andric return WarnAndReturn(": unable to read the string at 0x" + 25185ffd83dbSDimitry Andric Twine::utohexstr(Offset + Value) + 25195ffd83dbSDimitry Andric ": the string table is not null-terminated", 25205ffd83dbSDimitry Andric Offset); 25215ffd83dbSDimitry Andric 25228bcb0991SDimitry Andric return DynamicStringTable.data() + Value; 25238bcb0991SDimitry Andric } 25248bcb0991SDimitry Andric 25250b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() { 25260b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF); 25270b57cec5SDimitry Andric Ctx.printUnwindInformation(); 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric 2530e8d8bef9SDimitry Andric // The namespace is needed to fix the compilation with GCC older than 7.0+. 25310b57cec5SDimitry Andric namespace { 25320b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printUnwindInfo() { 2533e8d8bef9SDimitry Andric if (Obj.getHeader().e_machine == EM_ARM) { 2534e8d8bef9SDimitry Andric ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF.getFileName(), 25358bcb0991SDimitry Andric DotSymtabSec); 25360b57cec5SDimitry Andric Ctx.PrintUnwindInformation(); 25370b57cec5SDimitry Andric } 25380b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF); 25390b57cec5SDimitry Andric Ctx.printUnwindInformation(); 25400b57cec5SDimitry Andric } 2541e8d8bef9SDimitry Andric } // namespace 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() { 25440b57cec5SDimitry Andric ListScope D(W, "NeededLibraries"); 25450b57cec5SDimitry Andric 25465ffd83dbSDimitry Andric std::vector<StringRef> Libs; 25470b57cec5SDimitry Andric for (const auto &Entry : dynamic_table()) 25488bcb0991SDimitry Andric if (Entry.d_tag == ELF::DT_NEEDED) 25498bcb0991SDimitry Andric Libs.push_back(getDynamicString(Entry.d_un.d_val)); 25500b57cec5SDimitry Andric 25515ffd83dbSDimitry Andric llvm::sort(Libs); 25520b57cec5SDimitry Andric 25535ffd83dbSDimitry Andric for (StringRef L : Libs) 25540b57cec5SDimitry Andric W.startLine() << L << "\n"; 25550b57cec5SDimitry Andric } 25560b57cec5SDimitry Andric 25575ffd83dbSDimitry Andric template <class ELFT> 2558e8d8bef9SDimitry Andric static Error checkHashTable(const ELFDumper<ELFT> &Dumper, 25595ffd83dbSDimitry Andric const typename ELFT::Hash *H, 25605ffd83dbSDimitry Andric bool *IsHeaderValid = nullptr) { 2561e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 2562e8d8bef9SDimitry Andric const uint64_t SecOffset = (const uint8_t *)H - Obj.base(); 2563e8d8bef9SDimitry Andric if (Dumper.getHashTableEntSize() == 8) { 2564e8d8bef9SDimitry Andric auto It = llvm::find_if(ElfMachineType, [&](const EnumEntry<unsigned> &E) { 2565e8d8bef9SDimitry Andric return E.Value == Obj.getHeader().e_machine; 2566e8d8bef9SDimitry Andric }); 2567e8d8bef9SDimitry Andric if (IsHeaderValid) 2568e8d8bef9SDimitry Andric *IsHeaderValid = false; 2569e8d8bef9SDimitry Andric return createError("the hash table at 0x" + Twine::utohexstr(SecOffset) + 2570e8d8bef9SDimitry Andric " is not supported: it contains non-standard 8 " 2571e8d8bef9SDimitry Andric "byte entries on " + 2572e8d8bef9SDimitry Andric It->AltName + " platform"); 2573e8d8bef9SDimitry Andric } 2574e8d8bef9SDimitry Andric 2575e8d8bef9SDimitry Andric auto MakeError = [&](const Twine &Msg = "") { 2576e8d8bef9SDimitry Andric return createError("the hash table at offset 0x" + 2577e8d8bef9SDimitry Andric Twine::utohexstr(SecOffset) + 25785ffd83dbSDimitry Andric " goes past the end of the file (0x" + 2579e8d8bef9SDimitry Andric Twine::utohexstr(Obj.getBufSize()) + ")" + Msg); 25805ffd83dbSDimitry Andric }; 25815ffd83dbSDimitry Andric 25825ffd83dbSDimitry Andric // Each SHT_HASH section starts from two 32-bit fields: nbucket and nchain. 25835ffd83dbSDimitry Andric const unsigned HeaderSize = 2 * sizeof(typename ELFT::Word); 25845ffd83dbSDimitry Andric 25855ffd83dbSDimitry Andric if (IsHeaderValid) 2586e8d8bef9SDimitry Andric *IsHeaderValid = Obj.getBufSize() - SecOffset >= HeaderSize; 25875ffd83dbSDimitry Andric 2588e8d8bef9SDimitry Andric if (Obj.getBufSize() - SecOffset < HeaderSize) 2589e8d8bef9SDimitry Andric return MakeError(); 25905ffd83dbSDimitry Andric 2591e8d8bef9SDimitry Andric if (Obj.getBufSize() - SecOffset - HeaderSize < 25925ffd83dbSDimitry Andric ((uint64_t)H->nbucket + H->nchain) * sizeof(typename ELFT::Word)) 2593e8d8bef9SDimitry Andric return MakeError(", nbucket = " + Twine(H->nbucket) + 25945ffd83dbSDimitry Andric ", nchain = " + Twine(H->nchain)); 25955ffd83dbSDimitry Andric return Error::success(); 25965ffd83dbSDimitry Andric } 25975ffd83dbSDimitry Andric 25985ffd83dbSDimitry Andric template <class ELFT> 2599e8d8bef9SDimitry Andric static Error checkGNUHashTable(const ELFFile<ELFT> &Obj, 26005ffd83dbSDimitry Andric const typename ELFT::GnuHash *GnuHashTable, 26015ffd83dbSDimitry Andric bool *IsHeaderValid = nullptr) { 26025ffd83dbSDimitry Andric const uint8_t *TableData = reinterpret_cast<const uint8_t *>(GnuHashTable); 2603e8d8bef9SDimitry Andric assert(TableData >= Obj.base() && TableData < Obj.base() + Obj.getBufSize() && 26045ffd83dbSDimitry Andric "GnuHashTable must always point to a location inside the file"); 26055ffd83dbSDimitry Andric 2606e8d8bef9SDimitry Andric uint64_t TableOffset = TableData - Obj.base(); 26075ffd83dbSDimitry Andric if (IsHeaderValid) 2608e8d8bef9SDimitry Andric *IsHeaderValid = TableOffset + /*Header size:*/ 16 < Obj.getBufSize(); 26095ffd83dbSDimitry Andric if (TableOffset + 16 + (uint64_t)GnuHashTable->nbuckets * 4 + 26105ffd83dbSDimitry Andric (uint64_t)GnuHashTable->maskwords * sizeof(typename ELFT::Off) >= 2611e8d8bef9SDimitry Andric Obj.getBufSize()) 26125ffd83dbSDimitry Andric return createError("unable to dump the SHT_GNU_HASH " 26135ffd83dbSDimitry Andric "section at 0x" + 26145ffd83dbSDimitry Andric Twine::utohexstr(TableOffset) + 26155ffd83dbSDimitry Andric ": it goes past the end of the file"); 26165ffd83dbSDimitry Andric return Error::success(); 26175ffd83dbSDimitry Andric } 26185ffd83dbSDimitry Andric 26190b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashTable() { 26200b57cec5SDimitry Andric DictScope D(W, "HashTable"); 26210b57cec5SDimitry Andric if (!HashTable) 26220b57cec5SDimitry Andric return; 26235ffd83dbSDimitry Andric 26245ffd83dbSDimitry Andric bool IsHeaderValid; 2625e8d8bef9SDimitry Andric Error Err = checkHashTable(*this, HashTable, &IsHeaderValid); 26265ffd83dbSDimitry Andric if (IsHeaderValid) { 26270b57cec5SDimitry Andric W.printNumber("Num Buckets", HashTable->nbucket); 26280b57cec5SDimitry Andric W.printNumber("Num Chains", HashTable->nchain); 26295ffd83dbSDimitry Andric } 26305ffd83dbSDimitry Andric 26315ffd83dbSDimitry Andric if (Err) { 26325ffd83dbSDimitry Andric reportUniqueWarning(std::move(Err)); 26335ffd83dbSDimitry Andric return; 26345ffd83dbSDimitry Andric } 26355ffd83dbSDimitry Andric 26360b57cec5SDimitry Andric W.printList("Buckets", HashTable->buckets()); 26370b57cec5SDimitry Andric W.printList("Chains", HashTable->chains()); 26380b57cec5SDimitry Andric } 26390b57cec5SDimitry Andric 26405ffd83dbSDimitry Andric template <class ELFT> 26415ffd83dbSDimitry Andric static Expected<ArrayRef<typename ELFT::Word>> 2642bdd1243dSDimitry Andric getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion, 26435ffd83dbSDimitry Andric const typename ELFT::GnuHash *GnuHashTable) { 26445ffd83dbSDimitry Andric if (!DynSymRegion) 26455ffd83dbSDimitry Andric return createError("no dynamic symbol table found"); 26465ffd83dbSDimitry Andric 26475ffd83dbSDimitry Andric ArrayRef<typename ELFT::Sym> DynSymTable = 2648e8d8bef9SDimitry Andric DynSymRegion->template getAsArrayRef<typename ELFT::Sym>(); 26495ffd83dbSDimitry Andric size_t NumSyms = DynSymTable.size(); 26505ffd83dbSDimitry Andric if (!NumSyms) 26515ffd83dbSDimitry Andric return createError("the dynamic symbol table is empty"); 26525ffd83dbSDimitry Andric 26535ffd83dbSDimitry Andric if (GnuHashTable->symndx < NumSyms) 26545ffd83dbSDimitry Andric return GnuHashTable->values(NumSyms); 26555ffd83dbSDimitry Andric 26565ffd83dbSDimitry Andric // A normal empty GNU hash table section produced by linker might have 26575ffd83dbSDimitry Andric // symndx set to the number of dynamic symbols + 1 (for the zero symbol) 26585ffd83dbSDimitry Andric // and have dummy null values in the Bloom filter and in the buckets 26595ffd83dbSDimitry Andric // vector (or no values at all). It happens because the value of symndx is not 26605ffd83dbSDimitry Andric // important for dynamic loaders when the GNU hash table is empty. They just 26615ffd83dbSDimitry Andric // skip the whole object during symbol lookup. In such cases, the symndx value 26625ffd83dbSDimitry Andric // is irrelevant and we should not report a warning. 26635ffd83dbSDimitry Andric ArrayRef<typename ELFT::Word> Buckets = GnuHashTable->buckets(); 26645ffd83dbSDimitry Andric if (!llvm::all_of(Buckets, [](typename ELFT::Word V) { return V == 0; })) 2665e8d8bef9SDimitry Andric return createError( 2666e8d8bef9SDimitry Andric "the first hashed symbol index (" + Twine(GnuHashTable->symndx) + 2667e8d8bef9SDimitry Andric ") is greater than or equal to the number of dynamic symbols (" + 26685ffd83dbSDimitry Andric Twine(NumSyms) + ")"); 26695ffd83dbSDimitry Andric // There is no way to represent an array of (dynamic symbols count - symndx) 26705ffd83dbSDimitry Andric // length. 26715ffd83dbSDimitry Andric return ArrayRef<typename ELFT::Word>(); 26725ffd83dbSDimitry Andric } 26735ffd83dbSDimitry Andric 26745ffd83dbSDimitry Andric template <typename ELFT> 2675e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printGnuHashTable() { 26760b57cec5SDimitry Andric DictScope D(W, "GnuHashTable"); 26770b57cec5SDimitry Andric if (!GnuHashTable) 26780b57cec5SDimitry Andric return; 26795ffd83dbSDimitry Andric 26805ffd83dbSDimitry Andric bool IsHeaderValid; 2681e8d8bef9SDimitry Andric Error Err = checkGNUHashTable<ELFT>(Obj, GnuHashTable, &IsHeaderValid); 26825ffd83dbSDimitry Andric if (IsHeaderValid) { 26830b57cec5SDimitry Andric W.printNumber("Num Buckets", GnuHashTable->nbuckets); 26840b57cec5SDimitry Andric W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); 26850b57cec5SDimitry Andric W.printNumber("Num Mask Words", GnuHashTable->maskwords); 26860b57cec5SDimitry Andric W.printNumber("Shift Count", GnuHashTable->shift2); 26875ffd83dbSDimitry Andric } 26885ffd83dbSDimitry Andric 26895ffd83dbSDimitry Andric if (Err) { 26905ffd83dbSDimitry Andric reportUniqueWarning(std::move(Err)); 26915ffd83dbSDimitry Andric return; 26925ffd83dbSDimitry Andric } 26935ffd83dbSDimitry Andric 26945ffd83dbSDimitry Andric ArrayRef<typename ELFT::Off> BloomFilter = GnuHashTable->filter(); 26955ffd83dbSDimitry Andric W.printHexList("Bloom Filter", BloomFilter); 26965ffd83dbSDimitry Andric 26975ffd83dbSDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets(); 26985ffd83dbSDimitry Andric W.printList("Buckets", Buckets); 26995ffd83dbSDimitry Andric 27005ffd83dbSDimitry Andric Expected<ArrayRef<Elf_Word>> Chains = 27015ffd83dbSDimitry Andric getGnuHashTableChains<ELFT>(DynSymRegion, GnuHashTable); 27025ffd83dbSDimitry Andric if (!Chains) { 2703e8d8bef9SDimitry Andric reportUniqueWarning("unable to dump 'Values' for the SHT_GNU_HASH " 27045ffd83dbSDimitry Andric "section: " + 2705e8d8bef9SDimitry Andric toString(Chains.takeError())); 27065ffd83dbSDimitry Andric return; 27075ffd83dbSDimitry Andric } 27085ffd83dbSDimitry Andric 27095ffd83dbSDimitry Andric W.printHexList("Values", *Chains); 27100b57cec5SDimitry Andric } 27110b57cec5SDimitry Andric 271206c3fb27SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() { 271306c3fb27SDimitry Andric // Print histogram for the .hash section. 271406c3fb27SDimitry Andric if (this->HashTable) { 271506c3fb27SDimitry Andric if (Error E = checkHashTable<ELFT>(*this, this->HashTable)) 271606c3fb27SDimitry Andric this->reportUniqueWarning(std::move(E)); 271706c3fb27SDimitry Andric else 271806c3fb27SDimitry Andric printHashHistogram(*this->HashTable); 271906c3fb27SDimitry Andric } 272006c3fb27SDimitry Andric 272106c3fb27SDimitry Andric // Print histogram for the .gnu.hash section. 272206c3fb27SDimitry Andric if (this->GnuHashTable) { 272306c3fb27SDimitry Andric if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable)) 272406c3fb27SDimitry Andric this->reportUniqueWarning(std::move(E)); 272506c3fb27SDimitry Andric else 272606c3fb27SDimitry Andric printGnuHashHistogram(*this->GnuHashTable); 272706c3fb27SDimitry Andric } 272806c3fb27SDimitry Andric } 272906c3fb27SDimitry Andric 273006c3fb27SDimitry Andric template <typename ELFT> 273106c3fb27SDimitry Andric void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const { 273206c3fb27SDimitry Andric size_t NBucket = HashTable.nbucket; 273306c3fb27SDimitry Andric size_t NChain = HashTable.nchain; 273406c3fb27SDimitry Andric ArrayRef<Elf_Word> Buckets = HashTable.buckets(); 273506c3fb27SDimitry Andric ArrayRef<Elf_Word> Chains = HashTable.chains(); 273606c3fb27SDimitry Andric size_t TotalSyms = 0; 273706c3fb27SDimitry Andric // If hash table is correct, we have at least chains with 0 length. 273806c3fb27SDimitry Andric size_t MaxChain = 1; 273906c3fb27SDimitry Andric 274006c3fb27SDimitry Andric if (NChain == 0 || NBucket == 0) 274106c3fb27SDimitry Andric return; 274206c3fb27SDimitry Andric 274306c3fb27SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 274406c3fb27SDimitry Andric // Go over all buckets and and note chain lengths of each bucket (total 274506c3fb27SDimitry Andric // unique chain lengths). 274606c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) { 274706c3fb27SDimitry Andric BitVector Visited(NChain); 274806c3fb27SDimitry Andric for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) { 274906c3fb27SDimitry Andric if (C == ELF::STN_UNDEF) 275006c3fb27SDimitry Andric break; 275106c3fb27SDimitry Andric if (Visited[C]) { 275206c3fb27SDimitry Andric this->reportUniqueWarning( 275306c3fb27SDimitry Andric ".hash section is invalid: bucket " + Twine(C) + 275406c3fb27SDimitry Andric ": a cycle was detected in the linked chain"); 275506c3fb27SDimitry Andric break; 275606c3fb27SDimitry Andric } 275706c3fb27SDimitry Andric Visited[C] = true; 275806c3fb27SDimitry Andric if (MaxChain <= ++ChainLen[B]) 275906c3fb27SDimitry Andric ++MaxChain; 276006c3fb27SDimitry Andric } 276106c3fb27SDimitry Andric TotalSyms += ChainLen[B]; 276206c3fb27SDimitry Andric } 276306c3fb27SDimitry Andric 276406c3fb27SDimitry Andric if (!TotalSyms) 276506c3fb27SDimitry Andric return; 276606c3fb27SDimitry Andric 276706c3fb27SDimitry Andric std::vector<size_t> Count(MaxChain, 0); 276806c3fb27SDimitry Andric // Count how long is the chain for each bucket. 276906c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; B++) 277006c3fb27SDimitry Andric ++Count[ChainLen[B]]; 277106c3fb27SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 277206c3fb27SDimitry Andric // coverage of the symbols. 277306c3fb27SDimitry Andric printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false); 277406c3fb27SDimitry Andric } 277506c3fb27SDimitry Andric 277606c3fb27SDimitry Andric template <class ELFT> 277706c3fb27SDimitry Andric void ELFDumper<ELFT>::printGnuHashHistogram( 277806c3fb27SDimitry Andric const Elf_GnuHash &GnuHashTable) const { 277906c3fb27SDimitry Andric Expected<ArrayRef<Elf_Word>> ChainsOrErr = 278006c3fb27SDimitry Andric getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable); 278106c3fb27SDimitry Andric if (!ChainsOrErr) { 278206c3fb27SDimitry Andric this->reportUniqueWarning("unable to print the GNU hash table histogram: " + 278306c3fb27SDimitry Andric toString(ChainsOrErr.takeError())); 278406c3fb27SDimitry Andric return; 278506c3fb27SDimitry Andric } 278606c3fb27SDimitry Andric 278706c3fb27SDimitry Andric ArrayRef<Elf_Word> Chains = *ChainsOrErr; 278806c3fb27SDimitry Andric size_t Symndx = GnuHashTable.symndx; 278906c3fb27SDimitry Andric size_t TotalSyms = 0; 279006c3fb27SDimitry Andric size_t MaxChain = 1; 279106c3fb27SDimitry Andric 279206c3fb27SDimitry Andric size_t NBucket = GnuHashTable.nbuckets; 279306c3fb27SDimitry Andric if (Chains.empty() || NBucket == 0) 279406c3fb27SDimitry Andric return; 279506c3fb27SDimitry Andric 279606c3fb27SDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets(); 279706c3fb27SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 279806c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) { 279906c3fb27SDimitry Andric if (!Buckets[B]) 280006c3fb27SDimitry Andric continue; 280106c3fb27SDimitry Andric size_t Len = 1; 280206c3fb27SDimitry Andric for (size_t C = Buckets[B] - Symndx; 280306c3fb27SDimitry Andric C < Chains.size() && (Chains[C] & 1) == 0; ++C) 280406c3fb27SDimitry Andric if (MaxChain < ++Len) 280506c3fb27SDimitry Andric ++MaxChain; 280606c3fb27SDimitry Andric ChainLen[B] = Len; 280706c3fb27SDimitry Andric TotalSyms += Len; 280806c3fb27SDimitry Andric } 280906c3fb27SDimitry Andric ++MaxChain; 281006c3fb27SDimitry Andric 281106c3fb27SDimitry Andric if (!TotalSyms) 281206c3fb27SDimitry Andric return; 281306c3fb27SDimitry Andric 281406c3fb27SDimitry Andric std::vector<size_t> Count(MaxChain, 0); 281506c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) 281606c3fb27SDimitry Andric ++Count[ChainLen[B]]; 281706c3fb27SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 281806c3fb27SDimitry Andric // coverage of the symbols. 281906c3fb27SDimitry Andric printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true); 282006c3fb27SDimitry Andric } 282106c3fb27SDimitry Andric 28220b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { 2823e8d8bef9SDimitry Andric StringRef SOName = "<Not found>"; 2824e8d8bef9SDimitry Andric if (SONameOffset) 2825e8d8bef9SDimitry Andric SOName = getDynamicString(*SONameOffset); 28260b57cec5SDimitry Andric W.printString("LoadName", SOName); 28270b57cec5SDimitry Andric } 28280b57cec5SDimitry Andric 28298bcb0991SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() { 2830e8d8bef9SDimitry Andric switch (Obj.getHeader().e_machine) { 28318bcb0991SDimitry Andric case EM_ARM: 2832349cc55cSDimitry Andric if (Obj.isLE()) 2833349cc55cSDimitry Andric printAttributes(ELF::SHT_ARM_ATTRIBUTES, 2834349cc55cSDimitry Andric std::make_unique<ARMAttributeParser>(&W), 2835349cc55cSDimitry Andric support::little); 2836349cc55cSDimitry Andric else 2837349cc55cSDimitry Andric reportUniqueWarning("attribute printing not implemented for big-endian " 2838349cc55cSDimitry Andric "ARM objects"); 2839349cc55cSDimitry Andric break; 28405ffd83dbSDimitry Andric case EM_RISCV: 2841349cc55cSDimitry Andric if (Obj.isLE()) 2842349cc55cSDimitry Andric printAttributes(ELF::SHT_RISCV_ATTRIBUTES, 2843349cc55cSDimitry Andric std::make_unique<RISCVAttributeParser>(&W), 2844349cc55cSDimitry Andric support::little); 2845349cc55cSDimitry Andric else 2846349cc55cSDimitry Andric reportUniqueWarning("attribute printing not implemented for big-endian " 2847349cc55cSDimitry Andric "RISC-V objects"); 2848349cc55cSDimitry Andric break; 2849349cc55cSDimitry Andric case EM_MSP430: 2850349cc55cSDimitry Andric printAttributes(ELF::SHT_MSP430_ATTRIBUTES, 2851349cc55cSDimitry Andric std::make_unique<MSP430AttributeParser>(&W), 2852349cc55cSDimitry Andric support::little); 28538bcb0991SDimitry Andric break; 28548bcb0991SDimitry Andric case EM_MIPS: { 2855e8d8bef9SDimitry Andric printMipsABIFlags(); 28568bcb0991SDimitry Andric printMipsOptions(); 28578bcb0991SDimitry Andric printMipsReginfo(); 2858e8d8bef9SDimitry Andric MipsGOTParser<ELFT> Parser(*this); 28595ffd83dbSDimitry Andric if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols())) 2860e8d8bef9SDimitry Andric reportUniqueWarning(std::move(E)); 28615ffd83dbSDimitry Andric else if (!Parser.isGotEmpty()) 2862e8d8bef9SDimitry Andric printMipsGOT(Parser); 28635ffd83dbSDimitry Andric 28645ffd83dbSDimitry Andric if (Error E = Parser.findPLT(dynamic_table())) 2865e8d8bef9SDimitry Andric reportUniqueWarning(std::move(E)); 28665ffd83dbSDimitry Andric else if (!Parser.isPltEmpty()) 2867e8d8bef9SDimitry Andric printMipsPLT(Parser); 28688bcb0991SDimitry Andric break; 28698bcb0991SDimitry Andric } 28708bcb0991SDimitry Andric default: 28718bcb0991SDimitry Andric break; 28728bcb0991SDimitry Andric } 28738bcb0991SDimitry Andric } 28748bcb0991SDimitry Andric 2875349cc55cSDimitry Andric template <class ELFT> 2876349cc55cSDimitry Andric void ELFDumper<ELFT>::printAttributes( 2877349cc55cSDimitry Andric unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser, 2878349cc55cSDimitry Andric support::endianness Endianness) { 2879349cc55cSDimitry Andric assert((AttrShType != ELF::SHT_NULL) && AttrParser && 2880349cc55cSDimitry Andric "Incomplete ELF attribute implementation"); 28810b57cec5SDimitry Andric DictScope BA(W, "BuildAttributes"); 2882e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 2883349cc55cSDimitry Andric if (Sec.sh_type != AttrShType) 28840b57cec5SDimitry Andric continue; 28850b57cec5SDimitry Andric 2886e8d8bef9SDimitry Andric ArrayRef<uint8_t> Contents; 2887e8d8bef9SDimitry Andric if (Expected<ArrayRef<uint8_t>> ContentOrErr = 2888e8d8bef9SDimitry Andric Obj.getSectionContents(Sec)) { 2889e8d8bef9SDimitry Andric Contents = *ContentOrErr; 2890e8d8bef9SDimitry Andric if (Contents.empty()) { 2891e8d8bef9SDimitry Andric reportUniqueWarning("the " + describe(Sec) + " is empty"); 28920b57cec5SDimitry Andric continue; 28930b57cec5SDimitry Andric } 2894e8d8bef9SDimitry Andric } else { 2895e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the content of the " + describe(Sec) + 2896e8d8bef9SDimitry Andric ": " + toString(ContentOrErr.takeError())); 28970b57cec5SDimitry Andric continue; 2898e8d8bef9SDimitry Andric } 28990b57cec5SDimitry Andric 2900e8d8bef9SDimitry Andric W.printHex("FormatVersion", Contents[0]); 2901e8d8bef9SDimitry Andric 2902349cc55cSDimitry Andric if (Error E = AttrParser->parse(Contents, Endianness)) 2903e8d8bef9SDimitry Andric reportUniqueWarning("unable to dump attributes from the " + 2904e8d8bef9SDimitry Andric describe(Sec) + ": " + toString(std::move(E))); 29055ffd83dbSDimitry Andric } 29060b57cec5SDimitry Andric } 2907e8d8bef9SDimitry Andric 2908e8d8bef9SDimitry Andric namespace { 29090b57cec5SDimitry Andric 29100b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser { 29110b57cec5SDimitry Andric public: 2912e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 2913e8d8bef9SDimitry Andric using Entry = typename ELFT::Addr; 29140b57cec5SDimitry Andric using Entries = ArrayRef<Entry>; 29150b57cec5SDimitry Andric 29160b57cec5SDimitry Andric const bool IsStatic; 2917e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj; 2918e8d8bef9SDimitry Andric const ELFDumper<ELFT> &Dumper; 29190b57cec5SDimitry Andric 2920e8d8bef9SDimitry Andric MipsGOTParser(const ELFDumper<ELFT> &D); 29215ffd83dbSDimitry Andric Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); 29225ffd83dbSDimitry Andric Error findPLT(Elf_Dyn_Range DynTable); 29230b57cec5SDimitry Andric 29245ffd83dbSDimitry Andric bool isGotEmpty() const { return GotEntries.empty(); } 29255ffd83dbSDimitry Andric bool isPltEmpty() const { return PltEntries.empty(); } 29260b57cec5SDimitry Andric 29270b57cec5SDimitry Andric uint64_t getGp() const; 29280b57cec5SDimitry Andric 29290b57cec5SDimitry Andric const Entry *getGotLazyResolver() const; 29300b57cec5SDimitry Andric const Entry *getGotModulePointer() const; 29310b57cec5SDimitry Andric const Entry *getPltLazyResolver() const; 29320b57cec5SDimitry Andric const Entry *getPltModulePointer() const; 29330b57cec5SDimitry Andric 29340b57cec5SDimitry Andric Entries getLocalEntries() const; 29350b57cec5SDimitry Andric Entries getGlobalEntries() const; 29360b57cec5SDimitry Andric Entries getOtherEntries() const; 29370b57cec5SDimitry Andric Entries getPltEntries() const; 29380b57cec5SDimitry Andric 29390b57cec5SDimitry Andric uint64_t getGotAddress(const Entry * E) const; 29400b57cec5SDimitry Andric int64_t getGotOffset(const Entry * E) const; 29410b57cec5SDimitry Andric const Elf_Sym *getGotSym(const Entry *E) const; 29420b57cec5SDimitry Andric 29430b57cec5SDimitry Andric uint64_t getPltAddress(const Entry * E) const; 29440b57cec5SDimitry Andric const Elf_Sym *getPltSym(const Entry *E) const; 29450b57cec5SDimitry Andric 29460b57cec5SDimitry Andric StringRef getPltStrTable() const { return PltStrTable; } 2947e8d8bef9SDimitry Andric const Elf_Shdr *getPltSymTable() const { return PltSymTable; } 29480b57cec5SDimitry Andric 29490b57cec5SDimitry Andric private: 29500b57cec5SDimitry Andric const Elf_Shdr *GotSec; 29510b57cec5SDimitry Andric size_t LocalNum; 29520b57cec5SDimitry Andric size_t GlobalNum; 29530b57cec5SDimitry Andric 29540b57cec5SDimitry Andric const Elf_Shdr *PltSec; 29550b57cec5SDimitry Andric const Elf_Shdr *PltRelSec; 29560b57cec5SDimitry Andric const Elf_Shdr *PltSymTable; 29578bcb0991SDimitry Andric StringRef FileName; 29588bcb0991SDimitry Andric 29590b57cec5SDimitry Andric Elf_Sym_Range GotDynSyms; 29600b57cec5SDimitry Andric StringRef PltStrTable; 29610b57cec5SDimitry Andric 29620b57cec5SDimitry Andric Entries GotEntries; 29630b57cec5SDimitry Andric Entries PltEntries; 29640b57cec5SDimitry Andric }; 29650b57cec5SDimitry Andric 29660b57cec5SDimitry Andric } // end anonymous namespace 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric template <class ELFT> 2969e8d8bef9SDimitry Andric MipsGOTParser<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &D) 2970e8d8bef9SDimitry Andric : IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject().getELFFile()), 2971e8d8bef9SDimitry Andric Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr), 2972e8d8bef9SDimitry Andric PltRelSec(nullptr), PltSymTable(nullptr), 2973e8d8bef9SDimitry Andric FileName(D.getElfObject().getFileName()) {} 29745ffd83dbSDimitry Andric 29755ffd83dbSDimitry Andric template <class ELFT> 29765ffd83dbSDimitry Andric Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable, 29775ffd83dbSDimitry Andric Elf_Sym_Range DynSyms) { 29780b57cec5SDimitry Andric // See "Global Offset Table" in Chapter 5 in the following document 29790b57cec5SDimitry Andric // for detailed GOT description. 29800b57cec5SDimitry Andric // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf 29810b57cec5SDimitry Andric 29820b57cec5SDimitry Andric // Find static GOT secton. 29830b57cec5SDimitry Andric if (IsStatic) { 2984e8d8bef9SDimitry Andric GotSec = Dumper.findSectionByName(".got"); 29850b57cec5SDimitry Andric if (!GotSec) 29865ffd83dbSDimitry Andric return Error::success(); 29870b57cec5SDimitry Andric 29888bcb0991SDimitry Andric ArrayRef<uint8_t> Content = 2989e8d8bef9SDimitry Andric unwrapOrError(FileName, Obj.getSectionContents(*GotSec)); 29900b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 29910b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 29920b57cec5SDimitry Andric LocalNum = GotEntries.size(); 29935ffd83dbSDimitry Andric return Error::success(); 29940b57cec5SDimitry Andric } 29950b57cec5SDimitry Andric 29965ffd83dbSDimitry Andric // Lookup dynamic table tags which define the GOT layout. 2997bdd1243dSDimitry Andric std::optional<uint64_t> DtPltGot; 2998bdd1243dSDimitry Andric std::optional<uint64_t> DtLocalGotNum; 2999bdd1243dSDimitry Andric std::optional<uint64_t> DtGotSym; 30000b57cec5SDimitry Andric for (const auto &Entry : DynTable) { 30010b57cec5SDimitry Andric switch (Entry.getTag()) { 30020b57cec5SDimitry Andric case ELF::DT_PLTGOT: 30030b57cec5SDimitry Andric DtPltGot = Entry.getVal(); 30040b57cec5SDimitry Andric break; 30050b57cec5SDimitry Andric case ELF::DT_MIPS_LOCAL_GOTNO: 30060b57cec5SDimitry Andric DtLocalGotNum = Entry.getVal(); 30070b57cec5SDimitry Andric break; 30080b57cec5SDimitry Andric case ELF::DT_MIPS_GOTSYM: 30090b57cec5SDimitry Andric DtGotSym = Entry.getVal(); 30100b57cec5SDimitry Andric break; 30110b57cec5SDimitry Andric } 30120b57cec5SDimitry Andric } 30130b57cec5SDimitry Andric 30145ffd83dbSDimitry Andric if (!DtPltGot && !DtLocalGotNum && !DtGotSym) 30155ffd83dbSDimitry Andric return Error::success(); 30165ffd83dbSDimitry Andric 30170b57cec5SDimitry Andric if (!DtPltGot) 30185ffd83dbSDimitry Andric return createError("cannot find PLTGOT dynamic tag"); 30190b57cec5SDimitry Andric if (!DtLocalGotNum) 30205ffd83dbSDimitry Andric return createError("cannot find MIPS_LOCAL_GOTNO dynamic tag"); 30210b57cec5SDimitry Andric if (!DtGotSym) 30225ffd83dbSDimitry Andric return createError("cannot find MIPS_GOTSYM dynamic tag"); 30230b57cec5SDimitry Andric 30240b57cec5SDimitry Andric size_t DynSymTotal = DynSyms.size(); 30250b57cec5SDimitry Andric if (*DtGotSym > DynSymTotal) 30265ffd83dbSDimitry Andric return createError("DT_MIPS_GOTSYM value (" + Twine(*DtGotSym) + 30275ffd83dbSDimitry Andric ") exceeds the number of dynamic symbols (" + 30285ffd83dbSDimitry Andric Twine(DynSymTotal) + ")"); 30290b57cec5SDimitry Andric 30308bcb0991SDimitry Andric GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot); 30310b57cec5SDimitry Andric if (!GotSec) 30325ffd83dbSDimitry Andric return createError("there is no non-empty GOT section at 0x" + 30335ffd83dbSDimitry Andric Twine::utohexstr(*DtPltGot)); 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric LocalNum = *DtLocalGotNum; 30360b57cec5SDimitry Andric GlobalNum = DynSymTotal - *DtGotSym; 30370b57cec5SDimitry Andric 30388bcb0991SDimitry Andric ArrayRef<uint8_t> Content = 3039e8d8bef9SDimitry Andric unwrapOrError(FileName, Obj.getSectionContents(*GotSec)); 30400b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 30410b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 30420b57cec5SDimitry Andric GotDynSyms = DynSyms.drop_front(*DtGotSym); 30435ffd83dbSDimitry Andric 30445ffd83dbSDimitry Andric return Error::success(); 30450b57cec5SDimitry Andric } 30460b57cec5SDimitry Andric 30475ffd83dbSDimitry Andric template <class ELFT> 30485ffd83dbSDimitry Andric Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) { 30495ffd83dbSDimitry Andric // Lookup dynamic table tags which define the PLT layout. 3050bdd1243dSDimitry Andric std::optional<uint64_t> DtMipsPltGot; 3051bdd1243dSDimitry Andric std::optional<uint64_t> DtJmpRel; 30525ffd83dbSDimitry Andric for (const auto &Entry : DynTable) { 30535ffd83dbSDimitry Andric switch (Entry.getTag()) { 30545ffd83dbSDimitry Andric case ELF::DT_MIPS_PLTGOT: 30555ffd83dbSDimitry Andric DtMipsPltGot = Entry.getVal(); 30565ffd83dbSDimitry Andric break; 30575ffd83dbSDimitry Andric case ELF::DT_JMPREL: 30585ffd83dbSDimitry Andric DtJmpRel = Entry.getVal(); 30595ffd83dbSDimitry Andric break; 30605ffd83dbSDimitry Andric } 30615ffd83dbSDimitry Andric } 30625ffd83dbSDimitry Andric 30635ffd83dbSDimitry Andric if (!DtMipsPltGot && !DtJmpRel) 30645ffd83dbSDimitry Andric return Error::success(); 30655ffd83dbSDimitry Andric 30660b57cec5SDimitry Andric // Find PLT section. 30670b57cec5SDimitry Andric if (!DtMipsPltGot) 30685ffd83dbSDimitry Andric return createError("cannot find MIPS_PLTGOT dynamic tag"); 30690b57cec5SDimitry Andric if (!DtJmpRel) 30705ffd83dbSDimitry Andric return createError("cannot find JMPREL dynamic tag"); 30710b57cec5SDimitry Andric 30728bcb0991SDimitry Andric PltSec = findNotEmptySectionByAddress(Obj, FileName, *DtMipsPltGot); 30730b57cec5SDimitry Andric if (!PltSec) 30745ffd83dbSDimitry Andric return createError("there is no non-empty PLTGOT section at 0x" + 30750b57cec5SDimitry Andric Twine::utohexstr(*DtMipsPltGot)); 30760b57cec5SDimitry Andric 30778bcb0991SDimitry Andric PltRelSec = findNotEmptySectionByAddress(Obj, FileName, *DtJmpRel); 30780b57cec5SDimitry Andric if (!PltRelSec) 30795ffd83dbSDimitry Andric return createError("there is no non-empty RELPLT section at 0x" + 30800b57cec5SDimitry Andric Twine::utohexstr(*DtJmpRel)); 30810b57cec5SDimitry Andric 30825ffd83dbSDimitry Andric if (Expected<ArrayRef<uint8_t>> PltContentOrErr = 3083e8d8bef9SDimitry Andric Obj.getSectionContents(*PltSec)) 30845ffd83dbSDimitry Andric PltEntries = 30855ffd83dbSDimitry Andric Entries(reinterpret_cast<const Entry *>(PltContentOrErr->data()), 30865ffd83dbSDimitry Andric PltContentOrErr->size() / sizeof(Entry)); 30875ffd83dbSDimitry Andric else 30885ffd83dbSDimitry Andric return createError("unable to read PLTGOT section content: " + 30895ffd83dbSDimitry Andric toString(PltContentOrErr.takeError())); 30900b57cec5SDimitry Andric 30915ffd83dbSDimitry Andric if (Expected<const Elf_Shdr *> PltSymTableOrErr = 3092e8d8bef9SDimitry Andric Obj.getSection(PltRelSec->sh_link)) 30935ffd83dbSDimitry Andric PltSymTable = *PltSymTableOrErr; 3094e8d8bef9SDimitry Andric else 3095e8d8bef9SDimitry Andric return createError("unable to get a symbol table linked to the " + 3096e8d8bef9SDimitry Andric describe(Obj, *PltRelSec) + ": " + 30975ffd83dbSDimitry Andric toString(PltSymTableOrErr.takeError())); 30985ffd83dbSDimitry Andric 30995ffd83dbSDimitry Andric if (Expected<StringRef> StrTabOrErr = 3100e8d8bef9SDimitry Andric Obj.getStringTableForSymtab(*PltSymTable)) 31015ffd83dbSDimitry Andric PltStrTable = *StrTabOrErr; 3102e8d8bef9SDimitry Andric else 3103e8d8bef9SDimitry Andric return createError("unable to get a string table for the " + 3104e8d8bef9SDimitry Andric describe(Obj, *PltSymTable) + ": " + 3105e8d8bef9SDimitry Andric toString(StrTabOrErr.takeError())); 31065ffd83dbSDimitry Andric 31075ffd83dbSDimitry Andric return Error::success(); 31080b57cec5SDimitry Andric } 31090b57cec5SDimitry Andric 31100b57cec5SDimitry Andric template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { 31110b57cec5SDimitry Andric return GotSec->sh_addr + 0x7ff0; 31120b57cec5SDimitry Andric } 31130b57cec5SDimitry Andric 31140b57cec5SDimitry Andric template <class ELFT> 31150b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31160b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotLazyResolver() const { 31170b57cec5SDimitry Andric return LocalNum > 0 ? &GotEntries[0] : nullptr; 31180b57cec5SDimitry Andric } 31190b57cec5SDimitry Andric 31200b57cec5SDimitry Andric template <class ELFT> 31210b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31220b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotModulePointer() const { 31230b57cec5SDimitry Andric if (LocalNum < 2) 31240b57cec5SDimitry Andric return nullptr; 31250b57cec5SDimitry Andric const Entry &E = GotEntries[1]; 31260b57cec5SDimitry Andric if ((E >> (sizeof(Entry) * 8 - 1)) == 0) 31270b57cec5SDimitry Andric return nullptr; 31280b57cec5SDimitry Andric return &E; 31290b57cec5SDimitry Andric } 31300b57cec5SDimitry Andric 31310b57cec5SDimitry Andric template <class ELFT> 31320b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31330b57cec5SDimitry Andric MipsGOTParser<ELFT>::getLocalEntries() const { 31340b57cec5SDimitry Andric size_t Skip = getGotModulePointer() ? 2 : 1; 31350b57cec5SDimitry Andric if (LocalNum - Skip <= 0) 31360b57cec5SDimitry Andric return Entries(); 31370b57cec5SDimitry Andric return GotEntries.slice(Skip, LocalNum - Skip); 31380b57cec5SDimitry Andric } 31390b57cec5SDimitry Andric 31400b57cec5SDimitry Andric template <class ELFT> 31410b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31420b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGlobalEntries() const { 31430b57cec5SDimitry Andric if (GlobalNum == 0) 31440b57cec5SDimitry Andric return Entries(); 31450b57cec5SDimitry Andric return GotEntries.slice(LocalNum, GlobalNum); 31460b57cec5SDimitry Andric } 31470b57cec5SDimitry Andric 31480b57cec5SDimitry Andric template <class ELFT> 31490b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31500b57cec5SDimitry Andric MipsGOTParser<ELFT>::getOtherEntries() const { 31510b57cec5SDimitry Andric size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; 31520b57cec5SDimitry Andric if (OtherNum == 0) 31530b57cec5SDimitry Andric return Entries(); 31540b57cec5SDimitry Andric return GotEntries.slice(LocalNum + GlobalNum, OtherNum); 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric 31570b57cec5SDimitry Andric template <class ELFT> 31580b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { 31590b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 31600b57cec5SDimitry Andric return GotSec->sh_addr + Offset; 31610b57cec5SDimitry Andric } 31620b57cec5SDimitry Andric 31630b57cec5SDimitry Andric template <class ELFT> 31640b57cec5SDimitry Andric int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { 31650b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 31660b57cec5SDimitry Andric return Offset - 0x7ff0; 31670b57cec5SDimitry Andric } 31680b57cec5SDimitry Andric 31690b57cec5SDimitry Andric template <class ELFT> 31700b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 31710b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { 31720b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E); 31730b57cec5SDimitry Andric return &GotDynSyms[Offset - LocalNum]; 31740b57cec5SDimitry Andric } 31750b57cec5SDimitry Andric 31760b57cec5SDimitry Andric template <class ELFT> 31770b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31780b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltLazyResolver() const { 31790b57cec5SDimitry Andric return PltEntries.empty() ? nullptr : &PltEntries[0]; 31800b57cec5SDimitry Andric } 31810b57cec5SDimitry Andric 31820b57cec5SDimitry Andric template <class ELFT> 31830b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31840b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltModulePointer() const { 31850b57cec5SDimitry Andric return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; 31860b57cec5SDimitry Andric } 31870b57cec5SDimitry Andric 31880b57cec5SDimitry Andric template <class ELFT> 31890b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31900b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltEntries() const { 31910b57cec5SDimitry Andric if (PltEntries.size() <= 2) 31920b57cec5SDimitry Andric return Entries(); 31930b57cec5SDimitry Andric return PltEntries.slice(2, PltEntries.size() - 2); 31940b57cec5SDimitry Andric } 31950b57cec5SDimitry Andric 31960b57cec5SDimitry Andric template <class ELFT> 31970b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { 31980b57cec5SDimitry Andric int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); 31990b57cec5SDimitry Andric return PltSec->sh_addr + Offset; 32000b57cec5SDimitry Andric } 32010b57cec5SDimitry Andric 32020b57cec5SDimitry Andric template <class ELFT> 32030b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 32040b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { 32050b57cec5SDimitry Andric int64_t Offset = std::distance(getPltEntries().data(), E); 32060b57cec5SDimitry Andric if (PltRelSec->sh_type == ELF::SHT_REL) { 3207e8d8bef9SDimitry Andric Elf_Rel_Range Rels = unwrapOrError(FileName, Obj.rels(*PltRelSec)); 32088bcb0991SDimitry Andric return unwrapOrError(FileName, 3209e8d8bef9SDimitry Andric Obj.getRelocationSymbol(Rels[Offset], PltSymTable)); 32100b57cec5SDimitry Andric } else { 3211e8d8bef9SDimitry Andric Elf_Rela_Range Rels = unwrapOrError(FileName, Obj.relas(*PltRelSec)); 32128bcb0991SDimitry Andric return unwrapOrError(FileName, 3213e8d8bef9SDimitry Andric Obj.getRelocationSymbol(Rels[Offset], PltSymTable)); 32140b57cec5SDimitry Andric } 32150b57cec5SDimitry Andric } 32160b57cec5SDimitry Andric 3217349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsISAExtType[] = { 32180b57cec5SDimitry Andric {"None", Mips::AFL_EXT_NONE}, 32190b57cec5SDimitry Andric {"Broadcom SB-1", Mips::AFL_EXT_SB1}, 32200b57cec5SDimitry Andric {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, 32210b57cec5SDimitry Andric {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, 32220b57cec5SDimitry Andric {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, 32230b57cec5SDimitry Andric {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, 32240b57cec5SDimitry Andric {"LSI R4010", Mips::AFL_EXT_4010}, 32250b57cec5SDimitry Andric {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, 32260b57cec5SDimitry Andric {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, 32270b57cec5SDimitry Andric {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, 32280b57cec5SDimitry Andric {"MIPS R4650", Mips::AFL_EXT_4650}, 32290b57cec5SDimitry Andric {"MIPS R5900", Mips::AFL_EXT_5900}, 32300b57cec5SDimitry Andric {"MIPS R10000", Mips::AFL_EXT_10000}, 32310b57cec5SDimitry Andric {"NEC VR4100", Mips::AFL_EXT_4100}, 32320b57cec5SDimitry Andric {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, 32330b57cec5SDimitry Andric {"NEC VR4120", Mips::AFL_EXT_4120}, 32340b57cec5SDimitry Andric {"NEC VR5400", Mips::AFL_EXT_5400}, 32350b57cec5SDimitry Andric {"NEC VR5500", Mips::AFL_EXT_5500}, 32360b57cec5SDimitry Andric {"RMI Xlr", Mips::AFL_EXT_XLR}, 32370b57cec5SDimitry Andric {"Toshiba R3900", Mips::AFL_EXT_3900} 32380b57cec5SDimitry Andric }; 32390b57cec5SDimitry Andric 3240349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsASEFlags[] = { 32410b57cec5SDimitry Andric {"DSP", Mips::AFL_ASE_DSP}, 32420b57cec5SDimitry Andric {"DSPR2", Mips::AFL_ASE_DSPR2}, 32430b57cec5SDimitry Andric {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, 32440b57cec5SDimitry Andric {"MCU", Mips::AFL_ASE_MCU}, 32450b57cec5SDimitry Andric {"MDMX", Mips::AFL_ASE_MDMX}, 32460b57cec5SDimitry Andric {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, 32470b57cec5SDimitry Andric {"MT", Mips::AFL_ASE_MT}, 32480b57cec5SDimitry Andric {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, 32490b57cec5SDimitry Andric {"VZ", Mips::AFL_ASE_VIRT}, 32500b57cec5SDimitry Andric {"MSA", Mips::AFL_ASE_MSA}, 32510b57cec5SDimitry Andric {"MIPS16", Mips::AFL_ASE_MIPS16}, 32520b57cec5SDimitry Andric {"microMIPS", Mips::AFL_ASE_MICROMIPS}, 32530b57cec5SDimitry Andric {"XPA", Mips::AFL_ASE_XPA}, 32540b57cec5SDimitry Andric {"CRC", Mips::AFL_ASE_CRC}, 32550b57cec5SDimitry Andric {"GINV", Mips::AFL_ASE_GINV}, 32560b57cec5SDimitry Andric }; 32570b57cec5SDimitry Andric 3258349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsFpABIType[] = { 32590b57cec5SDimitry Andric {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, 32600b57cec5SDimitry Andric {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, 32610b57cec5SDimitry Andric {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, 32620b57cec5SDimitry Andric {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, 32630b57cec5SDimitry Andric {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", 32640b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, 32650b57cec5SDimitry Andric {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, 32660b57cec5SDimitry Andric {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, 32670b57cec5SDimitry Andric {"Hard float compat (32-bit CPU, 64-bit FPU)", 32680b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_64A} 32690b57cec5SDimitry Andric }; 32700b57cec5SDimitry Andric 32710b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFlags1[] { 32720b57cec5SDimitry Andric {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, 32730b57cec5SDimitry Andric }; 32740b57cec5SDimitry Andric 32750b57cec5SDimitry Andric static int getMipsRegisterSize(uint8_t Flag) { 32760b57cec5SDimitry Andric switch (Flag) { 32770b57cec5SDimitry Andric case Mips::AFL_REG_NONE: 32780b57cec5SDimitry Andric return 0; 32790b57cec5SDimitry Andric case Mips::AFL_REG_32: 32800b57cec5SDimitry Andric return 32; 32810b57cec5SDimitry Andric case Mips::AFL_REG_64: 32820b57cec5SDimitry Andric return 64; 32830b57cec5SDimitry Andric case Mips::AFL_REG_128: 32840b57cec5SDimitry Andric return 128; 32850b57cec5SDimitry Andric default: 32860b57cec5SDimitry Andric return -1; 32870b57cec5SDimitry Andric } 32880b57cec5SDimitry Andric } 32890b57cec5SDimitry Andric 32900b57cec5SDimitry Andric template <class ELFT> 32910b57cec5SDimitry Andric static void printMipsReginfoData(ScopedPrinter &W, 32920b57cec5SDimitry Andric const Elf_Mips_RegInfo<ELFT> &Reginfo) { 32930b57cec5SDimitry Andric W.printHex("GP", Reginfo.ri_gp_value); 32940b57cec5SDimitry Andric W.printHex("General Mask", Reginfo.ri_gprmask); 32950b57cec5SDimitry Andric W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]); 32960b57cec5SDimitry Andric W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]); 32970b57cec5SDimitry Andric W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]); 32980b57cec5SDimitry Andric W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]); 32990b57cec5SDimitry Andric } 33000b57cec5SDimitry Andric 33010b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { 3302e8d8bef9SDimitry Andric const Elf_Shdr *RegInfoSec = findSectionByName(".reginfo"); 3303e8d8bef9SDimitry Andric if (!RegInfoSec) { 33040b57cec5SDimitry Andric W.startLine() << "There is no .reginfo section in the file.\n"; 33050b57cec5SDimitry Andric return; 33060b57cec5SDimitry Andric } 3307e8d8bef9SDimitry Andric 3308e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = 3309e8d8bef9SDimitry Andric Obj.getSectionContents(*RegInfoSec); 3310e8d8bef9SDimitry Andric if (!ContentsOrErr) { 3311e8d8bef9SDimitry Andric this->reportUniqueWarning( 3312e8d8bef9SDimitry Andric "unable to read the content of the .reginfo section (" + 3313e8d8bef9SDimitry Andric describe(*RegInfoSec) + "): " + toString(ContentsOrErr.takeError())); 3314e8d8bef9SDimitry Andric return; 3315e8d8bef9SDimitry Andric } 3316e8d8bef9SDimitry Andric 3317e8d8bef9SDimitry Andric if (ContentsOrErr->size() < sizeof(Elf_Mips_RegInfo<ELFT>)) { 3318e8d8bef9SDimitry Andric this->reportUniqueWarning("the .reginfo section has an invalid size (0x" + 3319e8d8bef9SDimitry Andric Twine::utohexstr(ContentsOrErr->size()) + ")"); 33200b57cec5SDimitry Andric return; 33210b57cec5SDimitry Andric } 33220b57cec5SDimitry Andric 33230b57cec5SDimitry Andric DictScope GS(W, "MIPS RegInfo"); 3324e8d8bef9SDimitry Andric printMipsReginfoData(W, *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>( 3325e8d8bef9SDimitry Andric ContentsOrErr->data())); 3326e8d8bef9SDimitry Andric } 3327e8d8bef9SDimitry Andric 3328e8d8bef9SDimitry Andric template <class ELFT> 3329e8d8bef9SDimitry Andric static Expected<const Elf_Mips_Options<ELFT> *> 3330e8d8bef9SDimitry Andric readMipsOptions(const uint8_t *SecBegin, ArrayRef<uint8_t> &SecData, 3331e8d8bef9SDimitry Andric bool &IsSupported) { 3332e8d8bef9SDimitry Andric if (SecData.size() < sizeof(Elf_Mips_Options<ELFT>)) 3333e8d8bef9SDimitry Andric return createError("the .MIPS.options section has an invalid size (0x" + 3334e8d8bef9SDimitry Andric Twine::utohexstr(SecData.size()) + ")"); 3335e8d8bef9SDimitry Andric 3336e8d8bef9SDimitry Andric const Elf_Mips_Options<ELFT> *O = 3337e8d8bef9SDimitry Andric reinterpret_cast<const Elf_Mips_Options<ELFT> *>(SecData.data()); 3338e8d8bef9SDimitry Andric const uint8_t Size = O->size; 3339e8d8bef9SDimitry Andric if (Size > SecData.size()) { 3340e8d8bef9SDimitry Andric const uint64_t Offset = SecData.data() - SecBegin; 3341e8d8bef9SDimitry Andric const uint64_t SecSize = Offset + SecData.size(); 3342e8d8bef9SDimitry Andric return createError("a descriptor of size 0x" + Twine::utohexstr(Size) + 3343e8d8bef9SDimitry Andric " at offset 0x" + Twine::utohexstr(Offset) + 3344e8d8bef9SDimitry Andric " goes past the end of the .MIPS.options " 3345e8d8bef9SDimitry Andric "section of size 0x" + 3346e8d8bef9SDimitry Andric Twine::utohexstr(SecSize)); 3347e8d8bef9SDimitry Andric } 3348e8d8bef9SDimitry Andric 3349e8d8bef9SDimitry Andric IsSupported = O->kind == ODK_REGINFO; 3350e8d8bef9SDimitry Andric const size_t ExpectedSize = 3351e8d8bef9SDimitry Andric sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>); 3352e8d8bef9SDimitry Andric 3353e8d8bef9SDimitry Andric if (IsSupported) 3354e8d8bef9SDimitry Andric if (Size < ExpectedSize) 3355e8d8bef9SDimitry Andric return createError( 3356e8d8bef9SDimitry Andric "a .MIPS.options entry of kind " + 3357e8d8bef9SDimitry Andric Twine(getElfMipsOptionsOdkType(O->kind)) + 3358e8d8bef9SDimitry Andric " has an invalid size (0x" + Twine::utohexstr(Size) + 3359e8d8bef9SDimitry Andric "), the expected size is 0x" + Twine::utohexstr(ExpectedSize)); 3360e8d8bef9SDimitry Andric 3361e8d8bef9SDimitry Andric SecData = SecData.drop_front(Size); 3362e8d8bef9SDimitry Andric return O; 33630b57cec5SDimitry Andric } 33640b57cec5SDimitry Andric 33650b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { 3366e8d8bef9SDimitry Andric const Elf_Shdr *MipsOpts = findSectionByName(".MIPS.options"); 3367e8d8bef9SDimitry Andric if (!MipsOpts) { 33680b57cec5SDimitry Andric W.startLine() << "There is no .MIPS.options section in the file.\n"; 33690b57cec5SDimitry Andric return; 33700b57cec5SDimitry Andric } 33710b57cec5SDimitry Andric 33720b57cec5SDimitry Andric DictScope GS(W, "MIPS Options"); 33730b57cec5SDimitry Andric 3374e8d8bef9SDimitry Andric ArrayRef<uint8_t> Data = 3375e8d8bef9SDimitry Andric unwrapOrError(ObjF.getFileName(), Obj.getSectionContents(*MipsOpts)); 3376e8d8bef9SDimitry Andric const uint8_t *const SecBegin = Data.begin(); 3377e8d8bef9SDimitry Andric while (!Data.empty()) { 3378e8d8bef9SDimitry Andric bool IsSupported; 3379e8d8bef9SDimitry Andric Expected<const Elf_Mips_Options<ELFT> *> OptsOrErr = 3380e8d8bef9SDimitry Andric readMipsOptions<ELFT>(SecBegin, Data, IsSupported); 3381e8d8bef9SDimitry Andric if (!OptsOrErr) { 3382e8d8bef9SDimitry Andric reportUniqueWarning(OptsOrErr.takeError()); 33830b57cec5SDimitry Andric break; 33840b57cec5SDimitry Andric } 3385e8d8bef9SDimitry Andric 3386e8d8bef9SDimitry Andric unsigned Kind = (*OptsOrErr)->kind; 3387e8d8bef9SDimitry Andric const char *Type = getElfMipsOptionsOdkType(Kind); 3388e8d8bef9SDimitry Andric if (!IsSupported) { 3389e8d8bef9SDimitry Andric W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind 3390e8d8bef9SDimitry Andric << ")\n"; 3391e8d8bef9SDimitry Andric continue; 3392e8d8bef9SDimitry Andric } 3393e8d8bef9SDimitry Andric 3394e8d8bef9SDimitry Andric DictScope GS(W, Type); 3395e8d8bef9SDimitry Andric if (Kind == ODK_REGINFO) 3396e8d8bef9SDimitry Andric printMipsReginfoData(W, (*OptsOrErr)->getRegInfo()); 3397e8d8bef9SDimitry Andric else 3398e8d8bef9SDimitry Andric llvm_unreachable("unexpected .MIPS.options section descriptor kind"); 33990b57cec5SDimitry Andric } 34000b57cec5SDimitry Andric } 34010b57cec5SDimitry Andric 34020b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { 3403e8d8bef9SDimitry Andric const Elf_Shdr *StackMapSection = findSectionByName(".llvm_stackmaps"); 34040b57cec5SDimitry Andric if (!StackMapSection) 34050b57cec5SDimitry Andric return; 34060b57cec5SDimitry Andric 3407e8d8bef9SDimitry Andric auto Warn = [&](Error &&E) { 3408e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to read the stack map from " + 3409e8d8bef9SDimitry Andric describe(*StackMapSection) + ": " + 3410e8d8bef9SDimitry Andric toString(std::move(E))); 3411e8d8bef9SDimitry Andric }; 34120b57cec5SDimitry Andric 3413e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentOrErr = 3414e8d8bef9SDimitry Andric Obj.getSectionContents(*StackMapSection); 3415e8d8bef9SDimitry Andric if (!ContentOrErr) { 3416e8d8bef9SDimitry Andric Warn(ContentOrErr.takeError()); 3417e8d8bef9SDimitry Andric return; 34180b57cec5SDimitry Andric } 34190b57cec5SDimitry Andric 3420e8d8bef9SDimitry Andric if (Error E = StackMapParser<ELFT::TargetEndianness>::validateHeader( 3421e8d8bef9SDimitry Andric *ContentOrErr)) { 3422e8d8bef9SDimitry Andric Warn(std::move(E)); 3423e8d8bef9SDimitry Andric return; 34240b57cec5SDimitry Andric } 34250b57cec5SDimitry Andric 3426e8d8bef9SDimitry Andric prettyPrintStackMap(W, StackMapParser<ELFT::TargetEndianness>(*ContentOrErr)); 3427e8d8bef9SDimitry Andric } 3428e8d8bef9SDimitry Andric 3429e8d8bef9SDimitry Andric template <class ELFT> 3430e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex, 3431e8d8bef9SDimitry Andric const Elf_Shdr &Sec, const Elf_Shdr *SymTab) { 3432e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> Target = getRelocationTarget(R, SymTab); 3433e8d8bef9SDimitry Andric if (!Target) 3434e8d8bef9SDimitry Andric reportUniqueWarning("unable to print relocation " + Twine(RelIndex) + 3435e8d8bef9SDimitry Andric " in " + describe(Sec) + ": " + 3436e8d8bef9SDimitry Andric toString(Target.takeError())); 3437e8d8bef9SDimitry Andric else 3438e8d8bef9SDimitry Andric printRelRelaReloc(R, *Target); 34390b57cec5SDimitry Andric } 34400b57cec5SDimitry Andric 344106c3fb27SDimitry Andric template <class ELFT> 344206c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> 344306c3fb27SDimitry Andric ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header, 344406c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 344506c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags), 344606c3fb27SDimitry Andric std::end(ElfSymOtherFlags)); 344706c3fb27SDimitry Andric if (Header.e_machine == EM_MIPS) { 344806c3fb27SDimitry Andric // Someone in their infinite wisdom decided to make STO_MIPS_MIPS16 344906c3fb27SDimitry Andric // flag overlap with other ST_MIPS_xxx flags. So consider both 345006c3fb27SDimitry Andric // cases separately. 345106c3fb27SDimitry Andric if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) 345206c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 345306c3fb27SDimitry Andric std::begin(ElfMips16SymOtherFlags), 345406c3fb27SDimitry Andric std::end(ElfMips16SymOtherFlags)); 345506c3fb27SDimitry Andric else 345606c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 345706c3fb27SDimitry Andric std::begin(ElfMipsSymOtherFlags), 345806c3fb27SDimitry Andric std::end(ElfMipsSymOtherFlags)); 345906c3fb27SDimitry Andric } else if (Header.e_machine == EM_AARCH64) { 346006c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 346106c3fb27SDimitry Andric std::begin(ElfAArch64SymOtherFlags), 346206c3fb27SDimitry Andric std::end(ElfAArch64SymOtherFlags)); 346306c3fb27SDimitry Andric } else if (Header.e_machine == EM_RISCV) { 346406c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags), 346506c3fb27SDimitry Andric std::end(ElfRISCVSymOtherFlags)); 346606c3fb27SDimitry Andric } 346706c3fb27SDimitry Andric return SymOtherFlags; 346806c3fb27SDimitry Andric } 346906c3fb27SDimitry Andric 34700b57cec5SDimitry Andric static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, 34710b57cec5SDimitry Andric StringRef Str2) { 34720b57cec5SDimitry Andric OS.PadToColumn(2u); 34730b57cec5SDimitry Andric OS << Str1; 34740b57cec5SDimitry Andric OS.PadToColumn(37u); 34750b57cec5SDimitry Andric OS << Str2 << "\n"; 34760b57cec5SDimitry Andric OS.flush(); 34770b57cec5SDimitry Andric } 34780b57cec5SDimitry Andric 34790b57cec5SDimitry Andric template <class ELFT> 3480e8d8bef9SDimitry Andric static std::string getSectionHeadersNumString(const ELFFile<ELFT> &Obj, 34818bcb0991SDimitry Andric StringRef FileName) { 3482e8d8bef9SDimitry Andric const typename ELFT::Ehdr &ElfHeader = Obj.getHeader(); 3483e8d8bef9SDimitry Andric if (ElfHeader.e_shnum != 0) 3484e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shnum); 34850b57cec5SDimitry Andric 3486e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections(); 3487e8d8bef9SDimitry Andric if (!ArrOrErr) { 3488e8d8bef9SDimitry Andric // In this case we can ignore an error, because we have already reported a 3489e8d8bef9SDimitry Andric // warning about the broken section header table earlier. 3490e8d8bef9SDimitry Andric consumeError(ArrOrErr.takeError()); 3491e8d8bef9SDimitry Andric return "<?>"; 3492e8d8bef9SDimitry Andric } 3493e8d8bef9SDimitry Andric 3494e8d8bef9SDimitry Andric if (ArrOrErr->empty()) 34950b57cec5SDimitry Andric return "0"; 3496e8d8bef9SDimitry Andric return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")"; 34970b57cec5SDimitry Andric } 34980b57cec5SDimitry Andric 34990b57cec5SDimitry Andric template <class ELFT> 3500e8d8bef9SDimitry Andric static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> &Obj, 35018bcb0991SDimitry Andric StringRef FileName) { 3502e8d8bef9SDimitry Andric const typename ELFT::Ehdr &ElfHeader = Obj.getHeader(); 3503e8d8bef9SDimitry Andric if (ElfHeader.e_shstrndx != SHN_XINDEX) 3504e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shstrndx); 35050b57cec5SDimitry Andric 3506e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections(); 3507e8d8bef9SDimitry Andric if (!ArrOrErr) { 3508e8d8bef9SDimitry Andric // In this case we can ignore an error, because we have already reported a 3509e8d8bef9SDimitry Andric // warning about the broken section header table earlier. 3510e8d8bef9SDimitry Andric consumeError(ArrOrErr.takeError()); 3511e8d8bef9SDimitry Andric return "<?>"; 35120b57cec5SDimitry Andric } 35130b57cec5SDimitry Andric 3514e8d8bef9SDimitry Andric if (ArrOrErr->empty()) 3515e8d8bef9SDimitry Andric return "65535 (corrupt: out of range)"; 3516e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shstrndx) + " (" + 3517e8d8bef9SDimitry Andric to_string((*ArrOrErr)[0].sh_link) + ")"; 3518e8d8bef9SDimitry Andric } 3519e8d8bef9SDimitry Andric 3520e8d8bef9SDimitry Andric static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) { 3521e8d8bef9SDimitry Andric auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) { 3522e8d8bef9SDimitry Andric return E.Value == Type; 3523e8d8bef9SDimitry Andric }); 3524bdd1243dSDimitry Andric if (It != ArrayRef(ElfObjectFileType).end()) 3525e8d8bef9SDimitry Andric return It; 3526e8d8bef9SDimitry Andric return nullptr; 3527e8d8bef9SDimitry Andric } 3528e8d8bef9SDimitry Andric 35290eae32dcSDimitry Andric template <class ELFT> 35300eae32dcSDimitry Andric void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj, 35310eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 35320eae32dcSDimitry Andric const Archive *A) { 35330eae32dcSDimitry Andric if (InputFilenames.size() > 1 || A) { 35340eae32dcSDimitry Andric this->W.startLine() << "\n"; 35350eae32dcSDimitry Andric this->W.printString("File", FileStr); 35360eae32dcSDimitry Andric } 35370eae32dcSDimitry Andric } 35380eae32dcSDimitry Andric 3539e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() { 3540e8d8bef9SDimitry Andric const Elf_Ehdr &e = this->Obj.getHeader(); 35410b57cec5SDimitry Andric OS << "ELF Header:\n"; 35420b57cec5SDimitry Andric OS << " Magic: "; 35430b57cec5SDimitry Andric std::string Str; 35440b57cec5SDimitry Andric for (int i = 0; i < ELF::EI_NIDENT; i++) 3545e8d8bef9SDimitry Andric OS << format(" %02x", static_cast<int>(e.e_ident[i])); 35460b57cec5SDimitry Andric OS << "\n"; 3547bdd1243dSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass)); 35480b57cec5SDimitry Andric printFields(OS, "Class:", Str); 3549bdd1243dSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding)); 35500b57cec5SDimitry Andric printFields(OS, "Data:", Str); 35510b57cec5SDimitry Andric OS.PadToColumn(2u); 35520b57cec5SDimitry Andric OS << "Version:"; 35530b57cec5SDimitry Andric OS.PadToColumn(37u); 355481ad6265SDimitry Andric OS << utohexstr(e.e_ident[ELF::EI_VERSION]); 3555e8d8bef9SDimitry Andric if (e.e_version == ELF::EV_CURRENT) 35560b57cec5SDimitry Andric OS << " (current)"; 35570b57cec5SDimitry Andric OS << "\n"; 3558bdd1243dSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_OSABI], ArrayRef(ElfOSABI)); 35590b57cec5SDimitry Andric printFields(OS, "OS/ABI:", Str); 3560480093f4SDimitry Andric printFields(OS, 3561e8d8bef9SDimitry Andric "ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION])); 3562e8d8bef9SDimitry Andric 3563e8d8bef9SDimitry Andric if (const EnumEntry<unsigned> *E = getObjectFileEnumEntry(e.e_type)) { 3564e8d8bef9SDimitry Andric Str = E->AltName.str(); 3565e8d8bef9SDimitry Andric } else { 3566e8d8bef9SDimitry Andric if (e.e_type >= ET_LOPROC) 356781ad6265SDimitry Andric Str = "Processor Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")"; 3568e8d8bef9SDimitry Andric else if (e.e_type >= ET_LOOS) 356981ad6265SDimitry Andric Str = "OS Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")"; 3570e8d8bef9SDimitry Andric else 357181ad6265SDimitry Andric Str = "<unknown>: " + utohexstr(e.e_type, /*LowerCase=*/true); 3572e8d8bef9SDimitry Andric } 35730b57cec5SDimitry Andric printFields(OS, "Type:", Str); 3574e8d8bef9SDimitry Andric 3575bdd1243dSDimitry Andric Str = enumToString(e.e_machine, ArrayRef(ElfMachineType)); 35760b57cec5SDimitry Andric printFields(OS, "Machine:", Str); 357781ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_version); 35780b57cec5SDimitry Andric printFields(OS, "Version:", Str); 357981ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_entry); 35800b57cec5SDimitry Andric printFields(OS, "Entry point address:", Str); 3581e8d8bef9SDimitry Andric Str = to_string(e.e_phoff) + " (bytes into file)"; 35820b57cec5SDimitry Andric printFields(OS, "Start of program headers:", Str); 3583e8d8bef9SDimitry Andric Str = to_string(e.e_shoff) + " (bytes into file)"; 35840b57cec5SDimitry Andric printFields(OS, "Start of section headers:", Str); 35850b57cec5SDimitry Andric std::string ElfFlags; 3586e8d8bef9SDimitry Andric if (e.e_machine == EM_MIPS) 3587bdd1243dSDimitry Andric ElfFlags = printFlags( 3588bdd1243dSDimitry Andric e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH), 3589bdd1243dSDimitry Andric unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH)); 3590e8d8bef9SDimitry Andric else if (e.e_machine == EM_RISCV) 3591bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags)); 3592fe6060f1SDimitry Andric else if (e.e_machine == EM_AVR) 3593bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags), 3594fe6060f1SDimitry Andric unsigned(ELF::EF_AVR_ARCH_MASK)); 3595972a253aSDimitry Andric else if (e.e_machine == EM_LOONGARCH) 3596bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags), 3597bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK), 3598bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_OBJABI_MASK)); 3599bdd1243dSDimitry Andric else if (e.e_machine == EM_XTENSA) 3600bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags), 3601bdd1243dSDimitry Andric unsigned(ELF::EF_XTENSA_MACH)); 360281ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_flags); 36030b57cec5SDimitry Andric if (!ElfFlags.empty()) 36040b57cec5SDimitry Andric Str = Str + ", " + ElfFlags; 36050b57cec5SDimitry Andric printFields(OS, "Flags:", Str); 3606e8d8bef9SDimitry Andric Str = to_string(e.e_ehsize) + " (bytes)"; 36070b57cec5SDimitry Andric printFields(OS, "Size of this header:", Str); 3608e8d8bef9SDimitry Andric Str = to_string(e.e_phentsize) + " (bytes)"; 36090b57cec5SDimitry Andric printFields(OS, "Size of program headers:", Str); 3610e8d8bef9SDimitry Andric Str = to_string(e.e_phnum); 36110b57cec5SDimitry Andric printFields(OS, "Number of program headers:", Str); 3612e8d8bef9SDimitry Andric Str = to_string(e.e_shentsize) + " (bytes)"; 36130b57cec5SDimitry Andric printFields(OS, "Size of section headers:", Str); 3614e8d8bef9SDimitry Andric Str = getSectionHeadersNumString(this->Obj, this->FileName); 36150b57cec5SDimitry Andric printFields(OS, "Number of section headers:", Str); 3616e8d8bef9SDimitry Andric Str = getSectionHeaderTableIndexString(this->Obj, this->FileName); 36170b57cec5SDimitry Andric printFields(OS, "Section header string table index:", Str); 36180b57cec5SDimitry Andric } 36190b57cec5SDimitry Andric 3620e8d8bef9SDimitry Andric template <class ELFT> std::vector<GroupSection> ELFDumper<ELFT>::getGroups() { 3621e8d8bef9SDimitry Andric auto GetSignature = [&](const Elf_Sym &Sym, unsigned SymNdx, 3622e8d8bef9SDimitry Andric const Elf_Shdr &Symtab) -> StringRef { 3623e8d8bef9SDimitry Andric Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab); 3624e8d8bef9SDimitry Andric if (!StrTableOrErr) { 3625e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the string table for " + 3626e8d8bef9SDimitry Andric describe(Symtab) + ": " + 3627e8d8bef9SDimitry Andric toString(StrTableOrErr.takeError())); 3628e8d8bef9SDimitry Andric return "<?>"; 3629e8d8bef9SDimitry Andric } 36300b57cec5SDimitry Andric 3631e8d8bef9SDimitry Andric StringRef Strings = *StrTableOrErr; 3632e8d8bef9SDimitry Andric if (Sym.st_name >= Strings.size()) { 3633e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the name of the symbol with index " + 3634e8d8bef9SDimitry Andric Twine(SymNdx) + ": st_name (0x" + 3635e8d8bef9SDimitry Andric Twine::utohexstr(Sym.st_name) + 3636e8d8bef9SDimitry Andric ") is past the end of the string table of size 0x" + 3637e8d8bef9SDimitry Andric Twine::utohexstr(Strings.size())); 3638e8d8bef9SDimitry Andric return "<?>"; 3639e8d8bef9SDimitry Andric } 36400b57cec5SDimitry Andric 3641e8d8bef9SDimitry Andric return StrTableOrErr->data() + Sym.st_name; 3642e8d8bef9SDimitry Andric }; 36430b57cec5SDimitry Andric 36440b57cec5SDimitry Andric std::vector<GroupSection> Ret; 36450b57cec5SDimitry Andric uint64_t I = 0; 3646e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 36470b57cec5SDimitry Andric ++I; 36480b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_GROUP) 36490b57cec5SDimitry Andric continue; 36500b57cec5SDimitry Andric 3651e8d8bef9SDimitry Andric StringRef Signature = "<?>"; 3652e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Sec.sh_link)) { 3653e8d8bef9SDimitry Andric if (Expected<const Elf_Sym *> SymOrErr = 3654e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Sym>(**SymtabOrErr, Sec.sh_info)) 3655e8d8bef9SDimitry Andric Signature = GetSignature(**SymOrErr, Sec.sh_info, **SymtabOrErr); 3656e8d8bef9SDimitry Andric else 3657e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the signature symbol for " + 3658e8d8bef9SDimitry Andric describe(Sec) + ": " + 3659e8d8bef9SDimitry Andric toString(SymOrErr.takeError())); 3660e8d8bef9SDimitry Andric } else { 3661e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the symbol table for " + 3662e8d8bef9SDimitry Andric describe(Sec) + ": " + 3663e8d8bef9SDimitry Andric toString(SymtabOrErr.takeError())); 3664e8d8bef9SDimitry Andric } 36650b57cec5SDimitry Andric 3666e8d8bef9SDimitry Andric ArrayRef<Elf_Word> Data; 3667e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Word>> ContentsOrErr = 3668e8d8bef9SDimitry Andric Obj.template getSectionContentsAsArray<Elf_Word>(Sec)) { 3669e8d8bef9SDimitry Andric if (ContentsOrErr->empty()) 3670e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the section group flag from the " + 3671e8d8bef9SDimitry Andric describe(Sec) + ": the section is empty"); 3672e8d8bef9SDimitry Andric else 3673e8d8bef9SDimitry Andric Data = *ContentsOrErr; 3674e8d8bef9SDimitry Andric } else { 3675e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the content of the " + describe(Sec) + 3676e8d8bef9SDimitry Andric ": " + toString(ContentsOrErr.takeError())); 3677e8d8bef9SDimitry Andric } 3678e8d8bef9SDimitry Andric 3679e8d8bef9SDimitry Andric Ret.push_back({getPrintableSectionName(Sec), 36800b57cec5SDimitry Andric maybeDemangle(Signature), 36810b57cec5SDimitry Andric Sec.sh_name, 36820b57cec5SDimitry Andric I - 1, 36830b57cec5SDimitry Andric Sec.sh_link, 36840b57cec5SDimitry Andric Sec.sh_info, 3685e8d8bef9SDimitry Andric Data.empty() ? Elf_Word(0) : Data[0], 36860b57cec5SDimitry Andric {}}); 36870b57cec5SDimitry Andric 3688e8d8bef9SDimitry Andric if (Data.empty()) 3689e8d8bef9SDimitry Andric continue; 3690e8d8bef9SDimitry Andric 36910b57cec5SDimitry Andric std::vector<GroupMember> &GM = Ret.back().Members; 36920b57cec5SDimitry Andric for (uint32_t Ndx : Data.slice(1)) { 3693e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(Ndx)) { 3694e8d8bef9SDimitry Andric GM.push_back({getPrintableSectionName(**SecOrErr), Ndx}); 3695e8d8bef9SDimitry Andric } else { 3696e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the section with index " + 3697e8d8bef9SDimitry Andric Twine(Ndx) + " when dumping the " + describe(Sec) + 3698e8d8bef9SDimitry Andric ": " + toString(SecOrErr.takeError())); 3699e8d8bef9SDimitry Andric GM.push_back({"<?>", Ndx}); 3700e8d8bef9SDimitry Andric } 37010b57cec5SDimitry Andric } 37020b57cec5SDimitry Andric } 37030b57cec5SDimitry Andric return Ret; 37040b57cec5SDimitry Andric } 37050b57cec5SDimitry Andric 3706e8d8bef9SDimitry Andric static DenseMap<uint64_t, const GroupSection *> 37070b57cec5SDimitry Andric mapSectionsToGroups(ArrayRef<GroupSection> Groups) { 37080b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Ret; 37090b57cec5SDimitry Andric for (const GroupSection &G : Groups) 37100b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) 37110b57cec5SDimitry Andric Ret.insert({GM.Index, &G}); 37120b57cec5SDimitry Andric return Ret; 37130b57cec5SDimitry Andric } 37140b57cec5SDimitry Andric 3715e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printGroupSections() { 3716e8d8bef9SDimitry Andric std::vector<GroupSection> V = this->getGroups(); 37170b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 37180b57cec5SDimitry Andric for (const GroupSection &G : V) { 37190b57cec5SDimitry Andric OS << "\n" 37200b57cec5SDimitry Andric << getGroupType(G.Type) << " group section [" 37210b57cec5SDimitry Andric << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature 37220b57cec5SDimitry Andric << "] contains " << G.Members.size() << " sections:\n" 37230b57cec5SDimitry Andric << " [Index] Name\n"; 37240b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 37250b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 3726e8d8bef9SDimitry Andric if (MainGroup != &G) 3727e8d8bef9SDimitry Andric this->reportUniqueWarning( 3728e8d8bef9SDimitry Andric "section with index " + Twine(GM.Index) + 3729e8d8bef9SDimitry Andric ", included in the group section with index " + 3730e8d8bef9SDimitry Andric Twine(MainGroup->Index) + 3731e8d8bef9SDimitry Andric ", was also found in the group section with index " + 3732e8d8bef9SDimitry Andric Twine(G.Index)); 37330b57cec5SDimitry Andric OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n"; 37340b57cec5SDimitry Andric } 37350b57cec5SDimitry Andric } 37360b57cec5SDimitry Andric 37370b57cec5SDimitry Andric if (V.empty()) 37380b57cec5SDimitry Andric OS << "There are no section groups in this file.\n"; 37390b57cec5SDimitry Andric } 37400b57cec5SDimitry Andric 37410b57cec5SDimitry Andric template <class ELFT> 3742e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printRelrReloc(const Elf_Relr &R) { 3743e8d8bef9SDimitry Andric OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) << "\n"; 37440b57cec5SDimitry Andric } 37450b57cec5SDimitry Andric 37460b57cec5SDimitry Andric template <class ELFT> 3747e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R, 3748e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) { 37490b57cec5SDimitry Andric // First two fields are bit width dependent. The rest of them are fixed width. 37500b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 37510b57cec5SDimitry Andric Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; 37520b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 16 : 8; 37530b57cec5SDimitry Andric 3754e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_hex_no_prefix(R.Offset, Width)); 3755e8d8bef9SDimitry Andric Fields[1].Str = to_string(format_hex_no_prefix(R.Info, Width)); 37560b57cec5SDimitry Andric 37570b57cec5SDimitry Andric SmallString<32> RelocName; 3758e8d8bef9SDimitry Andric this->Obj.getRelocationTypeName(R.Type, RelocName); 37590b57cec5SDimitry Andric Fields[2].Str = RelocName.c_str(); 37600b57cec5SDimitry Andric 3761e8d8bef9SDimitry Andric if (RelSym.Sym) 3762e8d8bef9SDimitry Andric Fields[3].Str = 3763e8d8bef9SDimitry Andric to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width)); 376406c3fb27SDimitry Andric if (RelSym.Sym && RelSym.Name.empty()) 376506c3fb27SDimitry Andric Fields[4].Str = "<null>"; 376606c3fb27SDimitry Andric else 3767e8d8bef9SDimitry Andric Fields[4].Str = std::string(RelSym.Name); 376806c3fb27SDimitry Andric 37690b57cec5SDimitry Andric for (const Field &F : Fields) 37700b57cec5SDimitry Andric printField(F); 37710b57cec5SDimitry Andric 37720b57cec5SDimitry Andric std::string Addend; 3773bdd1243dSDimitry Andric if (std::optional<int64_t> A = R.Addend) { 3774e8d8bef9SDimitry Andric int64_t RelAddend = *A; 377506c3fb27SDimitry Andric if (!Fields[4].Str.empty()) { 3776e8d8bef9SDimitry Andric if (RelAddend < 0) { 37770b57cec5SDimitry Andric Addend = " - "; 37780b57cec5SDimitry Andric RelAddend = std::abs(RelAddend); 3779e8d8bef9SDimitry Andric } else { 37800b57cec5SDimitry Andric Addend = " + "; 37810b57cec5SDimitry Andric } 3782e8d8bef9SDimitry Andric } 378381ad6265SDimitry Andric Addend += utohexstr(RelAddend, /*LowerCase=*/true); 37840b57cec5SDimitry Andric } 37850b57cec5SDimitry Andric OS << Addend << "\n"; 37860b57cec5SDimitry Andric } 37870b57cec5SDimitry Andric 3788e8d8bef9SDimitry Andric template <class ELFT> 3789e8d8bef9SDimitry Andric static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType) { 37900b57cec5SDimitry Andric bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; 37910b57cec5SDimitry Andric bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; 37920b57cec5SDimitry Andric if (ELFT::Is64Bits) 37930b57cec5SDimitry Andric OS << " "; 37940b57cec5SDimitry Andric else 37950b57cec5SDimitry Andric OS << " "; 37960b57cec5SDimitry Andric if (IsRelr && opts::RawRelr) 37970b57cec5SDimitry Andric OS << "Data "; 37980b57cec5SDimitry Andric else 37990b57cec5SDimitry Andric OS << "Offset"; 38000b57cec5SDimitry Andric if (ELFT::Is64Bits) 38010b57cec5SDimitry Andric OS << " Info Type" 38020b57cec5SDimitry Andric << " Symbol's Value Symbol's Name"; 38030b57cec5SDimitry Andric else 38040b57cec5SDimitry Andric OS << " Info Type Sym. Value Symbol's Name"; 38050b57cec5SDimitry Andric if (IsRela) 38060b57cec5SDimitry Andric OS << " + Addend"; 38070b57cec5SDimitry Andric OS << "\n"; 38080b57cec5SDimitry Andric } 38090b57cec5SDimitry Andric 3810e8d8bef9SDimitry Andric template <class ELFT> 3811e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name, 3812e8d8bef9SDimitry Andric const DynRegionInfo &Reg) { 3813e8d8bef9SDimitry Andric uint64_t Offset = Reg.Addr - this->Obj.base(); 3814e8d8bef9SDimitry Andric OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x" 381581ad6265SDimitry Andric << utohexstr(Offset, /*LowerCase=*/true) << " contains " << Reg.Size << " bytes:\n"; 3816e8d8bef9SDimitry Andric printRelocHeaderFields<ELFT>(OS, Type); 3817e8d8bef9SDimitry Andric } 3818e8d8bef9SDimitry Andric 3819e8d8bef9SDimitry Andric template <class ELFT> 3820e8d8bef9SDimitry Andric static bool isRelocationSec(const typename ELFT::Shdr &Sec) { 3821e8d8bef9SDimitry Andric return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA || 3822e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL || 3823e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELA || 3824e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELR; 3825e8d8bef9SDimitry Andric } 3826e8d8bef9SDimitry Andric 3827e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() { 3828e8d8bef9SDimitry Andric auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> { 38290b57cec5SDimitry Andric // Android's packed relocation section needs to be unpacked first 38300b57cec5SDimitry Andric // to get the actual number of entries. 3831e8d8bef9SDimitry Andric if (Sec.sh_type == ELF::SHT_ANDROID_REL || 3832e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELA) { 3833e8d8bef9SDimitry Andric Expected<std::vector<typename ELFT::Rela>> RelasOrErr = 3834e8d8bef9SDimitry Andric this->Obj.android_relas(Sec); 3835e8d8bef9SDimitry Andric if (!RelasOrErr) 3836e8d8bef9SDimitry Andric return RelasOrErr.takeError(); 3837e8d8bef9SDimitry Andric return RelasOrErr->size(); 38380b57cec5SDimitry Andric } 3839e8d8bef9SDimitry Andric 38400b57cec5SDimitry Andric if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || 38410b57cec5SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELR)) { 3842e8d8bef9SDimitry Andric Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec); 3843e8d8bef9SDimitry Andric if (!RelrsOrErr) 3844e8d8bef9SDimitry Andric return RelrsOrErr.takeError(); 3845e8d8bef9SDimitry Andric return this->Obj.decode_relrs(*RelrsOrErr).size(); 38460b57cec5SDimitry Andric } 38475ffd83dbSDimitry Andric 3848e8d8bef9SDimitry Andric return Sec.getEntityCount(); 3849e8d8bef9SDimitry Andric }; 3850e8d8bef9SDimitry Andric 3851e8d8bef9SDimitry Andric bool HasRelocSections = false; 3852e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 3853e8d8bef9SDimitry Andric if (!isRelocationSec<ELFT>(Sec)) 3854e8d8bef9SDimitry Andric continue; 3855e8d8bef9SDimitry Andric HasRelocSections = true; 3856e8d8bef9SDimitry Andric 3857e8d8bef9SDimitry Andric std::string EntriesNum = "<?>"; 3858e8d8bef9SDimitry Andric if (Expected<size_t> NumOrErr = GetEntriesNum(Sec)) 3859e8d8bef9SDimitry Andric EntriesNum = std::to_string(*NumOrErr); 38600b57cec5SDimitry Andric else 3861e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get the number of relocations in " + 3862e8d8bef9SDimitry Andric this->describe(Sec) + ": " + 3863e8d8bef9SDimitry Andric toString(NumOrErr.takeError())); 3864e8d8bef9SDimitry Andric 3865e8d8bef9SDimitry Andric uintX_t Offset = Sec.sh_offset; 3866e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(Sec); 3867e8d8bef9SDimitry Andric OS << "\nRelocation section '" << Name << "' at offset 0x" 386881ad6265SDimitry Andric << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum 3869e8d8bef9SDimitry Andric << " entries:\n"; 3870e8d8bef9SDimitry Andric printRelocHeaderFields<ELFT>(OS, Sec.sh_type); 3871e8d8bef9SDimitry Andric this->printRelocationsHelper(Sec); 38720b57cec5SDimitry Andric } 38730b57cec5SDimitry Andric if (!HasRelocSections) 38740b57cec5SDimitry Andric OS << "\nThere are no relocations in this file.\n"; 38750b57cec5SDimitry Andric } 38760b57cec5SDimitry Andric 38770b57cec5SDimitry Andric // Print the offset of a particular section from anyone of the ranges: 38780b57cec5SDimitry Andric // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER]. 38790b57cec5SDimitry Andric // If 'Type' does not fall within any of those ranges, then a string is 38800b57cec5SDimitry Andric // returned as '<unknown>' followed by the type value. 38810b57cec5SDimitry Andric static std::string getSectionTypeOffsetString(unsigned Type) { 38820b57cec5SDimitry Andric if (Type >= SHT_LOOS && Type <= SHT_HIOS) 388381ad6265SDimitry Andric return "LOOS+0x" + utohexstr(Type - SHT_LOOS); 38840b57cec5SDimitry Andric else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC) 388581ad6265SDimitry Andric return "LOPROC+0x" + utohexstr(Type - SHT_LOPROC); 38860b57cec5SDimitry Andric else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER) 388781ad6265SDimitry Andric return "LOUSER+0x" + utohexstr(Type - SHT_LOUSER); 388881ad6265SDimitry Andric return "0x" + utohexstr(Type) + ": <unknown>"; 38890b57cec5SDimitry Andric } 38900b57cec5SDimitry Andric 3891e8d8bef9SDimitry Andric static std::string getSectionTypeString(unsigned Machine, unsigned Type) { 3892e8d8bef9SDimitry Andric StringRef Name = getELFSectionTypeName(Machine, Type); 38930b57cec5SDimitry Andric 3894e8d8bef9SDimitry Andric // Handle SHT_GNU_* type names. 389581ad6265SDimitry Andric if (Name.consume_front("SHT_GNU_")) { 389681ad6265SDimitry Andric if (Name == "HASH") 38970b57cec5SDimitry Andric return "GNU_HASH"; 3898e8d8bef9SDimitry Andric // E.g. SHT_GNU_verneed -> VERNEED. 389981ad6265SDimitry Andric return Name.upper(); 39000b57cec5SDimitry Andric } 3901e8d8bef9SDimitry Andric 3902e8d8bef9SDimitry Andric if (Name == "SHT_SYMTAB_SHNDX") 3903e8d8bef9SDimitry Andric return "SYMTAB SECTION INDICES"; 3904e8d8bef9SDimitry Andric 390581ad6265SDimitry Andric if (Name.consume_front("SHT_")) 390681ad6265SDimitry Andric return Name.str(); 3907e8d8bef9SDimitry Andric return getSectionTypeOffsetString(Type); 39080b57cec5SDimitry Andric } 39090b57cec5SDimitry Andric 3910480093f4SDimitry Andric static void printSectionDescription(formatted_raw_ostream &OS, 3911480093f4SDimitry Andric unsigned EMachine) { 3912480093f4SDimitry Andric OS << "Key to Flags:\n"; 3913480093f4SDimitry Andric OS << " W (write), A (alloc), X (execute), M (merge), S (strings), I " 3914480093f4SDimitry Andric "(info),\n"; 3915480093f4SDimitry Andric OS << " L (link order), O (extra OS processing required), G (group), T " 3916480093f4SDimitry Andric "(TLS),\n"; 3917480093f4SDimitry Andric OS << " C (compressed), x (unknown), o (OS specific), E (exclude),\n"; 3918fe6060f1SDimitry Andric OS << " R (retain)"; 3919480093f4SDimitry Andric 3920480093f4SDimitry Andric if (EMachine == EM_X86_64) 3921fe6060f1SDimitry Andric OS << ", l (large)"; 3922480093f4SDimitry Andric else if (EMachine == EM_ARM) 3923fe6060f1SDimitry Andric OS << ", y (purecode)"; 3924480093f4SDimitry Andric 3925fe6060f1SDimitry Andric OS << ", p (processor specific)\n"; 3926480093f4SDimitry Andric } 3927480093f4SDimitry Andric 3928e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() { 3929e8d8bef9SDimitry Andric ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections()); 3930bdd1243dSDimitry Andric if (Sections.empty()) { 3931bdd1243dSDimitry Andric OS << "\nThere are no sections in this file.\n"; 3932bdd1243dSDimitry Andric Expected<StringRef> SecStrTableOrErr = 3933bdd1243dSDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler); 3934bdd1243dSDimitry Andric if (!SecStrTableOrErr) 3935bdd1243dSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 3936bdd1243dSDimitry Andric return; 3937bdd1243dSDimitry Andric } 3938bdd1243dSDimitry Andric unsigned Bias = ELFT::Is64Bits ? 0 : 8; 39390b57cec5SDimitry Andric OS << "There are " << to_string(Sections.size()) 39400b57cec5SDimitry Andric << " section headers, starting at offset " 394181ad6265SDimitry Andric << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n"; 39420b57cec5SDimitry Andric OS << "Section Headers:\n"; 39430b57cec5SDimitry Andric Field Fields[11] = { 39440b57cec5SDimitry Andric {"[Nr]", 2}, {"Name", 7}, {"Type", 25}, 39450b57cec5SDimitry Andric {"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias}, 39460b57cec5SDimitry Andric {"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias}, 39470b57cec5SDimitry Andric {"Inf", 82 - Bias}, {"Al", 86 - Bias}}; 3948e8d8bef9SDimitry Andric for (const Field &F : Fields) 39490b57cec5SDimitry Andric printField(F); 39500b57cec5SDimitry Andric OS << "\n"; 39510b57cec5SDimitry Andric 39525ffd83dbSDimitry Andric StringRef SecStrTable; 39535ffd83dbSDimitry Andric if (Expected<StringRef> SecStrTableOrErr = 3954e8d8bef9SDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler)) 39555ffd83dbSDimitry Andric SecStrTable = *SecStrTableOrErr; 39565ffd83dbSDimitry Andric else 39575ffd83dbSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 39585ffd83dbSDimitry Andric 39590b57cec5SDimitry Andric size_t SectionIndex = 0; 39600b57cec5SDimitry Andric for (const Elf_Shdr &Sec : Sections) { 39610b57cec5SDimitry Andric Fields[0].Str = to_string(SectionIndex); 39625ffd83dbSDimitry Andric if (SecStrTable.empty()) 39635ffd83dbSDimitry Andric Fields[1].Str = "<no-strings>"; 39645ffd83dbSDimitry Andric else 39655ffd83dbSDimitry Andric Fields[1].Str = std::string(unwrapOrError<StringRef>( 3966e8d8bef9SDimitry Andric this->FileName, this->Obj.getSectionName(Sec, SecStrTable))); 39670b57cec5SDimitry Andric Fields[2].Str = 3968e8d8bef9SDimitry Andric getSectionTypeString(this->Obj.getHeader().e_machine, Sec.sh_type); 39690b57cec5SDimitry Andric Fields[3].Str = 39700b57cec5SDimitry Andric to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8)); 39710b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); 39720b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6)); 39730b57cec5SDimitry Andric Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); 397481ad6265SDimitry Andric Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI], 397581ad6265SDimitry Andric this->Obj.getHeader().e_machine, Sec.sh_flags); 39760b57cec5SDimitry Andric Fields[8].Str = to_string(Sec.sh_link); 39770b57cec5SDimitry Andric Fields[9].Str = to_string(Sec.sh_info); 39780b57cec5SDimitry Andric Fields[10].Str = to_string(Sec.sh_addralign); 39790b57cec5SDimitry Andric 39800b57cec5SDimitry Andric OS.PadToColumn(Fields[0].Column); 39810b57cec5SDimitry Andric OS << "[" << right_justify(Fields[0].Str, 2) << "]"; 39820b57cec5SDimitry Andric for (int i = 1; i < 7; i++) 39830b57cec5SDimitry Andric printField(Fields[i]); 39840b57cec5SDimitry Andric OS.PadToColumn(Fields[7].Column); 39850b57cec5SDimitry Andric OS << right_justify(Fields[7].Str, 3); 39860b57cec5SDimitry Andric OS.PadToColumn(Fields[8].Column); 39870b57cec5SDimitry Andric OS << right_justify(Fields[8].Str, 2); 39880b57cec5SDimitry Andric OS.PadToColumn(Fields[9].Column); 39890b57cec5SDimitry Andric OS << right_justify(Fields[9].Str, 3); 39900b57cec5SDimitry Andric OS.PadToColumn(Fields[10].Column); 39910b57cec5SDimitry Andric OS << right_justify(Fields[10].Str, 2); 39920b57cec5SDimitry Andric OS << "\n"; 39930b57cec5SDimitry Andric ++SectionIndex; 39940b57cec5SDimitry Andric } 3995e8d8bef9SDimitry Andric printSectionDescription(OS, this->Obj.getHeader().e_machine); 39960b57cec5SDimitry Andric } 39970b57cec5SDimitry Andric 39980b57cec5SDimitry Andric template <class ELFT> 3999e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab, 40008bcb0991SDimitry Andric size_t Entries, 4001e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const { 4002e8d8bef9SDimitry Andric StringRef Name; 4003e8d8bef9SDimitry Andric if (Symtab) 4004e8d8bef9SDimitry Andric Name = this->getPrintableSectionName(*Symtab); 40050b57cec5SDimitry Andric if (!Name.empty()) 40065ffd83dbSDimitry Andric OS << "\nSymbol table '" << Name << "'"; 40070b57cec5SDimitry Andric else 40085ffd83dbSDimitry Andric OS << "\nSymbol table for image"; 40095ffd83dbSDimitry Andric OS << " contains " << Entries << " entries:\n"; 40100b57cec5SDimitry Andric 40110b57cec5SDimitry Andric if (ELFT::Is64Bits) 40128bcb0991SDimitry Andric OS << " Num: Value Size Type Bind Vis"; 40130b57cec5SDimitry Andric else 40148bcb0991SDimitry Andric OS << " Num: Value Size Type Bind Vis"; 40158bcb0991SDimitry Andric 40168bcb0991SDimitry Andric if (NonVisibilityBitsUsed) 40178bcb0991SDimitry Andric OS << " "; 40188bcb0991SDimitry Andric OS << " Ndx Name\n"; 40190b57cec5SDimitry Andric } 40200b57cec5SDimitry Andric 40210b57cec5SDimitry Andric template <class ELFT> 4022e8d8bef9SDimitry Andric std::string 4023e8d8bef9SDimitry Andric GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol, 4024e8d8bef9SDimitry Andric unsigned SymIndex, 4025e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const { 4026e8d8bef9SDimitry Andric unsigned SectionIndex = Symbol.st_shndx; 40270b57cec5SDimitry Andric switch (SectionIndex) { 40280b57cec5SDimitry Andric case ELF::SHN_UNDEF: 40290b57cec5SDimitry Andric return "UND"; 40300b57cec5SDimitry Andric case ELF::SHN_ABS: 40310b57cec5SDimitry Andric return "ABS"; 40320b57cec5SDimitry Andric case ELF::SHN_COMMON: 40330b57cec5SDimitry Andric return "COM"; 4034480093f4SDimitry Andric case ELF::SHN_XINDEX: { 4035e8d8bef9SDimitry Andric Expected<uint32_t> IndexOrErr = 4036e8d8bef9SDimitry Andric object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable); 4037480093f4SDimitry Andric if (!IndexOrErr) { 4038e8d8bef9SDimitry Andric assert(Symbol.st_shndx == SHN_XINDEX && 4039e8d8bef9SDimitry Andric "getExtendedSymbolTableIndex should only fail due to an invalid " 4040480093f4SDimitry Andric "SHT_SYMTAB_SHNDX table/reference"); 4041480093f4SDimitry Andric this->reportUniqueWarning(IndexOrErr.takeError()); 4042480093f4SDimitry Andric return "RSV[0xffff]"; 4043480093f4SDimitry Andric } 4044480093f4SDimitry Andric return to_string(format_decimal(*IndexOrErr, 3)); 4045480093f4SDimitry Andric } 40460b57cec5SDimitry Andric default: 40470b57cec5SDimitry Andric // Find if: 40480b57cec5SDimitry Andric // Processor specific 40490b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC) 40500b57cec5SDimitry Andric return std::string("PRC[0x") + 40510b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 40520b57cec5SDimitry Andric // OS specific 40530b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS) 40540b57cec5SDimitry Andric return std::string("OS[0x") + 40550b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 40560b57cec5SDimitry Andric // Architecture reserved: 40570b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LORESERVE && 40580b57cec5SDimitry Andric SectionIndex <= ELF::SHN_HIRESERVE) 40590b57cec5SDimitry Andric return std::string("RSV[0x") + 40600b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 40610b57cec5SDimitry Andric // A normal section with an index 40620b57cec5SDimitry Andric return to_string(format_decimal(SectionIndex, 3)); 40630b57cec5SDimitry Andric } 40640b57cec5SDimitry Andric } 40650b57cec5SDimitry Andric 40660b57cec5SDimitry Andric template <class ELFT> 4067e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 4068e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 4069bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 4070e8d8bef9SDimitry Andric bool IsDynamic, 4071e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed) const { 40720b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 40730b57cec5SDimitry Andric Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias, 40748bcb0991SDimitry Andric 31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias}; 4075e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(SymIndex, 6)) + ":"; 4076e8d8bef9SDimitry Andric Fields[1].Str = 4077e8d8bef9SDimitry Andric to_string(format_hex_no_prefix(Symbol.st_value, ELFT::Is64Bits ? 16 : 8)); 4078e8d8bef9SDimitry Andric Fields[2].Str = to_string(format_decimal(Symbol.st_size, 5)); 40790b57cec5SDimitry Andric 4080e8d8bef9SDimitry Andric unsigned char SymbolType = Symbol.getType(); 4081e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 40820b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 4083bdd1243dSDimitry Andric Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes)); 40840b57cec5SDimitry Andric else 4085bdd1243dSDimitry Andric Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes)); 40860b57cec5SDimitry Andric 40870b57cec5SDimitry Andric Fields[4].Str = 4088bdd1243dSDimitry Andric enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings)); 40890b57cec5SDimitry Andric Fields[5].Str = 4090bdd1243dSDimitry Andric enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities)); 4091e8d8bef9SDimitry Andric 4092e8d8bef9SDimitry Andric if (Symbol.st_other & ~0x3) { 4093e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) { 4094e8d8bef9SDimitry Andric uint8_t Other = Symbol.st_other & ~0x3; 4095e8d8bef9SDimitry Andric if (Other & STO_AARCH64_VARIANT_PCS) { 4096e8d8bef9SDimitry Andric Other &= ~STO_AARCH64_VARIANT_PCS; 4097e8d8bef9SDimitry Andric Fields[5].Str += " [VARIANT_PCS"; 4098e8d8bef9SDimitry Andric if (Other != 0) 409981ad6265SDimitry Andric Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true)); 4100e8d8bef9SDimitry Andric Fields[5].Str.append("]"); 4101e8d8bef9SDimitry Andric } 4102349cc55cSDimitry Andric } else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) { 4103349cc55cSDimitry Andric uint8_t Other = Symbol.st_other & ~0x3; 4104349cc55cSDimitry Andric if (Other & STO_RISCV_VARIANT_CC) { 4105349cc55cSDimitry Andric Other &= ~STO_RISCV_VARIANT_CC; 4106349cc55cSDimitry Andric Fields[5].Str += " [VARIANT_CC"; 4107349cc55cSDimitry Andric if (Other != 0) 410881ad6265SDimitry Andric Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true)); 4109349cc55cSDimitry Andric Fields[5].Str.append("]"); 4110349cc55cSDimitry Andric } 4111e8d8bef9SDimitry Andric } else { 41128bcb0991SDimitry Andric Fields[5].Str += 4113e8d8bef9SDimitry Andric " [<other: " + to_string(format_hex(Symbol.st_other, 2)) + ">]"; 4114e8d8bef9SDimitry Andric } 4115e8d8bef9SDimitry Andric } 41168bcb0991SDimitry Andric 41178bcb0991SDimitry Andric Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0; 4118e8d8bef9SDimitry Andric Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex, ShndxTable); 41198bcb0991SDimitry Andric 4120e8d8bef9SDimitry Andric Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable, 4121e8d8bef9SDimitry Andric StrTable, IsDynamic); 4122e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 41230b57cec5SDimitry Andric printField(Entry); 41240b57cec5SDimitry Andric OS << "\n"; 41250b57cec5SDimitry Andric } 41260b57cec5SDimitry Andric 41270b57cec5SDimitry Andric template <class ELFT> 4128e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol, 4129e8d8bef9SDimitry Andric unsigned SymIndex, 4130e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 4131e8d8bef9SDimitry Andric StringRef StrTable, 41320b57cec5SDimitry Andric uint32_t Bucket) { 41330b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 41340b57cec5SDimitry Andric Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias, 41350b57cec5SDimitry Andric 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; 4136e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(SymIndex, 5)); 41370b57cec5SDimitry Andric Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":"; 41380b57cec5SDimitry Andric 41390b57cec5SDimitry Andric Fields[2].Str = to_string( 41408bcb0991SDimitry Andric format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8)); 41410b57cec5SDimitry Andric Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5)); 41420b57cec5SDimitry Andric 41430b57cec5SDimitry Andric unsigned char SymbolType = Symbol->getType(); 4144e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 41450b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 4146bdd1243dSDimitry Andric Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes)); 41470b57cec5SDimitry Andric else 4148bdd1243dSDimitry Andric Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes)); 41490b57cec5SDimitry Andric 41500b57cec5SDimitry Andric Fields[5].Str = 4151bdd1243dSDimitry Andric enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings)); 4152bdd1243dSDimitry Andric Fields[6].Str = 4153bdd1243dSDimitry Andric enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities)); 4154e8d8bef9SDimitry Andric Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable); 4155e8d8bef9SDimitry Andric Fields[8].Str = 4156e8d8bef9SDimitry Andric this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true); 41570b57cec5SDimitry Andric 4158e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 41590b57cec5SDimitry Andric printField(Entry); 41600b57cec5SDimitry Andric OS << "\n"; 41610b57cec5SDimitry Andric } 41620b57cec5SDimitry Andric 41630b57cec5SDimitry Andric template <class ELFT> 4164e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols, 41650b57cec5SDimitry Andric bool PrintDynamicSymbols) { 41660b57cec5SDimitry Andric if (!PrintSymbols && !PrintDynamicSymbols) 41670b57cec5SDimitry Andric return; 41680b57cec5SDimitry Andric // GNU readelf prints both the .dynsym and .symtab with --symbols. 4169e8d8bef9SDimitry Andric this->printSymbolsHelper(true); 41700b57cec5SDimitry Andric if (PrintSymbols) 4171e8d8bef9SDimitry Andric this->printSymbolsHelper(false); 41720b57cec5SDimitry Andric } 41730b57cec5SDimitry Andric 41745ffd83dbSDimitry Andric template <class ELFT> 4175e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) { 4176e8d8bef9SDimitry Andric if (this->DynamicStringTable.empty()) 41770b57cec5SDimitry Andric return; 41780b57cec5SDimitry Andric 41790b57cec5SDimitry Andric if (ELFT::Is64Bits) 41800b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 41810b57cec5SDimitry Andric else 41820b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 41830b57cec5SDimitry Andric OS << "\n"; 41840b57cec5SDimitry Andric 4185e8d8bef9SDimitry Andric Elf_Sym_Range DynSyms = this->dynamic_symbols(); 41865ffd83dbSDimitry Andric const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0]; 41875ffd83dbSDimitry Andric if (!FirstSym) { 41885ffd83dbSDimitry Andric this->reportUniqueWarning( 4189e8d8bef9SDimitry Andric Twine("unable to print symbols for the .hash table: the " 41905ffd83dbSDimitry Andric "dynamic symbol table ") + 4191e8d8bef9SDimitry Andric (this->DynSymRegion ? "is empty" : "was not found")); 41925ffd83dbSDimitry Andric return; 41935ffd83dbSDimitry Andric } 41945ffd83dbSDimitry Andric 4195e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 4196e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 41975ffd83dbSDimitry Andric auto Buckets = SysVHash.buckets(); 41985ffd83dbSDimitry Andric auto Chains = SysVHash.chains(); 41995ffd83dbSDimitry Andric for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) { 42000b57cec5SDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 42010b57cec5SDimitry Andric continue; 420204eeddc0SDimitry Andric BitVector Visited(SysVHash.nchain); 42035ffd83dbSDimitry Andric for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) { 42040b57cec5SDimitry Andric if (Ch == ELF::STN_UNDEF) 42050b57cec5SDimitry Andric break; 42068bcb0991SDimitry Andric 42078bcb0991SDimitry Andric if (Visited[Ch]) { 4208e8d8bef9SDimitry Andric this->reportUniqueWarning(".hash section is invalid: bucket " + 42095ffd83dbSDimitry Andric Twine(Ch) + 4210e8d8bef9SDimitry Andric ": a cycle was detected in the linked chain"); 42118bcb0991SDimitry Andric break; 42128bcb0991SDimitry Andric } 42138bcb0991SDimitry Andric 4214e8d8bef9SDimitry Andric printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable, 4215e8d8bef9SDimitry Andric Buc); 42168bcb0991SDimitry Andric Visited[Ch] = true; 42170b57cec5SDimitry Andric } 42180b57cec5SDimitry Andric } 42190b57cec5SDimitry Andric } 42200b57cec5SDimitry Andric 42215ffd83dbSDimitry Andric template <class ELFT> 4222e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) { 4223e8d8bef9SDimitry Andric if (this->DynamicStringTable.empty()) 42245ffd83dbSDimitry Andric return; 42255ffd83dbSDimitry Andric 4226e8d8bef9SDimitry Andric Elf_Sym_Range DynSyms = this->dynamic_symbols(); 42275ffd83dbSDimitry Andric const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0]; 42285ffd83dbSDimitry Andric if (!FirstSym) { 4229e8d8bef9SDimitry Andric this->reportUniqueWarning( 42305ffd83dbSDimitry Andric Twine("unable to print symbols for the .gnu.hash table: the " 42315ffd83dbSDimitry Andric "dynamic symbol table ") + 4232e8d8bef9SDimitry Andric (this->DynSymRegion ? "is empty" : "was not found")); 42335ffd83dbSDimitry Andric return; 42345ffd83dbSDimitry Andric } 42355ffd83dbSDimitry Andric 4236e8d8bef9SDimitry Andric auto GetSymbol = [&](uint64_t SymIndex, 4237e8d8bef9SDimitry Andric uint64_t SymsTotal) -> const Elf_Sym * { 4238e8d8bef9SDimitry Andric if (SymIndex >= SymsTotal) { 4239e8d8bef9SDimitry Andric this->reportUniqueWarning( 4240e8d8bef9SDimitry Andric "unable to print hashed symbol with index " + Twine(SymIndex) + 4241e8d8bef9SDimitry Andric ", which is greater than or equal to the number of dynamic symbols " 4242e8d8bef9SDimitry Andric "(" + 4243e8d8bef9SDimitry Andric Twine::utohexstr(SymsTotal) + ")"); 4244e8d8bef9SDimitry Andric return nullptr; 4245e8d8bef9SDimitry Andric } 4246e8d8bef9SDimitry Andric return FirstSym + SymIndex; 4247e8d8bef9SDimitry Andric }; 4248e8d8bef9SDimitry Andric 4249e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Word>> ValuesOrErr = 4250e8d8bef9SDimitry Andric getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHash); 4251e8d8bef9SDimitry Andric ArrayRef<Elf_Word> Values; 4252e8d8bef9SDimitry Andric if (!ValuesOrErr) 4253e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get hash values for the SHT_GNU_HASH " 4254e8d8bef9SDimitry Andric "section: " + 4255e8d8bef9SDimitry Andric toString(ValuesOrErr.takeError())); 4256e8d8bef9SDimitry Andric else 4257e8d8bef9SDimitry Andric Values = *ValuesOrErr; 4258e8d8bef9SDimitry Andric 4259e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 4260e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 42615ffd83dbSDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHash.buckets(); 42625ffd83dbSDimitry Andric for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) { 42635ffd83dbSDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 42645ffd83dbSDimitry Andric continue; 42655ffd83dbSDimitry Andric uint32_t Index = Buckets[Buc]; 4266e8d8bef9SDimitry Andric // Print whole chain. 42675ffd83dbSDimitry Andric while (true) { 4268e8d8bef9SDimitry Andric uint32_t SymIndex = Index++; 4269e8d8bef9SDimitry Andric if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size())) 4270e8d8bef9SDimitry Andric printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable, 4271e8d8bef9SDimitry Andric Buc); 4272e8d8bef9SDimitry Andric else 4273e8d8bef9SDimitry Andric break; 4274e8d8bef9SDimitry Andric 4275e8d8bef9SDimitry Andric if (SymIndex < GnuHash.symndx) { 4276e8d8bef9SDimitry Andric this->reportUniqueWarning( 4277e8d8bef9SDimitry Andric "unable to read the hash value for symbol with index " + 4278e8d8bef9SDimitry Andric Twine(SymIndex) + 4279e8d8bef9SDimitry Andric ", which is less than the index of the first hashed symbol (" + 4280e8d8bef9SDimitry Andric Twine(GnuHash.symndx) + ")"); 4281e8d8bef9SDimitry Andric break; 4282e8d8bef9SDimitry Andric } 4283e8d8bef9SDimitry Andric 4284e8d8bef9SDimitry Andric // Chain ends at symbol with stopper bit. 4285e8d8bef9SDimitry Andric if ((Values[SymIndex - GnuHash.symndx] & 1) == 1) 42865ffd83dbSDimitry Andric break; 42875ffd83dbSDimitry Andric } 42885ffd83dbSDimitry Andric } 42895ffd83dbSDimitry Andric } 42905ffd83dbSDimitry Andric 4291e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printHashSymbols() { 4292e8d8bef9SDimitry Andric if (this->HashTable) { 42935ffd83dbSDimitry Andric OS << "\n Symbol table of .hash for image:\n"; 4294e8d8bef9SDimitry Andric if (Error E = checkHashTable<ELFT>(*this, this->HashTable)) 42955ffd83dbSDimitry Andric this->reportUniqueWarning(std::move(E)); 42965ffd83dbSDimitry Andric else 4297e8d8bef9SDimitry Andric printHashTableSymbols(*this->HashTable); 42985ffd83dbSDimitry Andric } 42995ffd83dbSDimitry Andric 43005ffd83dbSDimitry Andric // Try printing the .gnu.hash table. 4301e8d8bef9SDimitry Andric if (this->GnuHashTable) { 43020b57cec5SDimitry Andric OS << "\n Symbol table of .gnu.hash for image:\n"; 43030b57cec5SDimitry Andric if (ELFT::Is64Bits) 43040b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 43050b57cec5SDimitry Andric else 43060b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 43070b57cec5SDimitry Andric OS << "\n"; 43085ffd83dbSDimitry Andric 4309e8d8bef9SDimitry Andric if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable)) 43105ffd83dbSDimitry Andric this->reportUniqueWarning(std::move(E)); 43115ffd83dbSDimitry Andric else 4312e8d8bef9SDimitry Andric printGnuHashTableSymbols(*this->GnuHashTable); 4313e8d8bef9SDimitry Andric } 4314e8d8bef9SDimitry Andric } 4315e8d8bef9SDimitry Andric 4316e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() { 4317e8d8bef9SDimitry Andric ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections()); 4318bdd1243dSDimitry Andric if (Sections.empty()) { 4319bdd1243dSDimitry Andric OS << "\nThere are no sections in this file.\n"; 4320bdd1243dSDimitry Andric Expected<StringRef> SecStrTableOrErr = 4321bdd1243dSDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler); 4322bdd1243dSDimitry Andric if (!SecStrTableOrErr) 4323bdd1243dSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 4324bdd1243dSDimitry Andric return; 4325bdd1243dSDimitry Andric } 4326e8d8bef9SDimitry Andric OS << "There are " << to_string(Sections.size()) 4327e8d8bef9SDimitry Andric << " section headers, starting at offset " 432881ad6265SDimitry Andric << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n"; 4329e8d8bef9SDimitry Andric 4330e8d8bef9SDimitry Andric OS << "Section Headers:\n"; 4331e8d8bef9SDimitry Andric 4332e8d8bef9SDimitry Andric auto PrintFields = [&](ArrayRef<Field> V) { 4333e8d8bef9SDimitry Andric for (const Field &F : V) 4334e8d8bef9SDimitry Andric printField(F); 4335e8d8bef9SDimitry Andric OS << "\n"; 4336e8d8bef9SDimitry Andric }; 4337e8d8bef9SDimitry Andric 4338e8d8bef9SDimitry Andric PrintFields({{"[Nr]", 2}, {"Name", 7}}); 4339e8d8bef9SDimitry Andric 4340e8d8bef9SDimitry Andric constexpr bool Is64 = ELFT::Is64Bits; 4341e8d8bef9SDimitry Andric PrintFields({{"Type", 7}, 4342e8d8bef9SDimitry Andric {Is64 ? "Address" : "Addr", 23}, 4343e8d8bef9SDimitry Andric {"Off", Is64 ? 40 : 32}, 4344e8d8bef9SDimitry Andric {"Size", Is64 ? 47 : 39}, 4345e8d8bef9SDimitry Andric {"ES", Is64 ? 54 : 46}, 4346e8d8bef9SDimitry Andric {"Lk", Is64 ? 59 : 51}, 4347e8d8bef9SDimitry Andric {"Inf", Is64 ? 62 : 54}, 4348e8d8bef9SDimitry Andric {"Al", Is64 ? 66 : 57}}); 4349e8d8bef9SDimitry Andric PrintFields({{"Flags", 7}}); 4350e8d8bef9SDimitry Andric 4351e8d8bef9SDimitry Andric StringRef SecStrTable; 4352e8d8bef9SDimitry Andric if (Expected<StringRef> SecStrTableOrErr = 4353e8d8bef9SDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler)) 4354e8d8bef9SDimitry Andric SecStrTable = *SecStrTableOrErr; 4355e8d8bef9SDimitry Andric else 4356e8d8bef9SDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 4357e8d8bef9SDimitry Andric 4358e8d8bef9SDimitry Andric size_t SectionIndex = 0; 4359e8d8bef9SDimitry Andric const unsigned AddrSize = Is64 ? 16 : 8; 4360e8d8bef9SDimitry Andric for (const Elf_Shdr &S : Sections) { 4361e8d8bef9SDimitry Andric StringRef Name = "<?>"; 4362e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = 4363e8d8bef9SDimitry Andric this->Obj.getSectionName(S, SecStrTable)) 4364e8d8bef9SDimitry Andric Name = *NameOrErr; 4365e8d8bef9SDimitry Andric else 4366e8d8bef9SDimitry Andric this->reportUniqueWarning(NameOrErr.takeError()); 4367e8d8bef9SDimitry Andric 4368e8d8bef9SDimitry Andric OS.PadToColumn(2); 4369e8d8bef9SDimitry Andric OS << "[" << right_justify(to_string(SectionIndex), 2) << "]"; 4370e8d8bef9SDimitry Andric PrintFields({{Name, 7}}); 4371e8d8bef9SDimitry Andric PrintFields( 4372e8d8bef9SDimitry Andric {{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7}, 4373e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23}, 4374e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32}, 4375e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39}, 4376e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46}, 4377e8d8bef9SDimitry Andric {to_string(S.sh_link), Is64 ? 59 : 51}, 4378e8d8bef9SDimitry Andric {to_string(S.sh_info), Is64 ? 63 : 55}, 4379e8d8bef9SDimitry Andric {to_string(S.sh_addralign), Is64 ? 66 : 58}}); 4380e8d8bef9SDimitry Andric 4381e8d8bef9SDimitry Andric OS.PadToColumn(7); 4382e8d8bef9SDimitry Andric OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: "; 4383e8d8bef9SDimitry Andric 4384e8d8bef9SDimitry Andric DenseMap<unsigned, StringRef> FlagToName = { 4385e8d8bef9SDimitry Andric {SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"}, 4386e8d8bef9SDimitry Andric {SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"}, 4387e8d8bef9SDimitry Andric {SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"}, 4388e8d8bef9SDimitry Andric {SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"}, 4389e8d8bef9SDimitry Andric {SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"}, 4390e8d8bef9SDimitry Andric {SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}}; 4391e8d8bef9SDimitry Andric 4392e8d8bef9SDimitry Andric uint64_t Flags = S.sh_flags; 4393e8d8bef9SDimitry Andric uint64_t UnknownFlags = 0; 4394fe6060f1SDimitry Andric ListSeparator LS; 4395e8d8bef9SDimitry Andric while (Flags) { 4396e8d8bef9SDimitry Andric // Take the least significant bit as a flag. 4397e8d8bef9SDimitry Andric uint64_t Flag = Flags & -Flags; 4398e8d8bef9SDimitry Andric Flags -= Flag; 4399e8d8bef9SDimitry Andric 4400e8d8bef9SDimitry Andric auto It = FlagToName.find(Flag); 4401fe6060f1SDimitry Andric if (It != FlagToName.end()) 4402fe6060f1SDimitry Andric OS << LS << It->second; 4403fe6060f1SDimitry Andric else 4404e8d8bef9SDimitry Andric UnknownFlags |= Flag; 4405e8d8bef9SDimitry Andric } 4406e8d8bef9SDimitry Andric 4407e8d8bef9SDimitry Andric auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) { 4408e8d8bef9SDimitry Andric uint64_t FlagsToPrint = UnknownFlags & Mask; 4409e8d8bef9SDimitry Andric if (!FlagsToPrint) 4410e8d8bef9SDimitry Andric return; 4411e8d8bef9SDimitry Andric 4412fe6060f1SDimitry Andric OS << LS << Name << " (" 4413e8d8bef9SDimitry Andric << to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")"; 4414e8d8bef9SDimitry Andric UnknownFlags &= ~Mask; 4415e8d8bef9SDimitry Andric }; 4416e8d8bef9SDimitry Andric 4417e8d8bef9SDimitry Andric PrintUnknownFlags(SHF_MASKOS, "OS"); 4418e8d8bef9SDimitry Andric PrintUnknownFlags(SHF_MASKPROC, "PROC"); 4419e8d8bef9SDimitry Andric PrintUnknownFlags(uint64_t(-1), "UNKNOWN"); 4420e8d8bef9SDimitry Andric 4421e8d8bef9SDimitry Andric OS << "\n"; 4422e8d8bef9SDimitry Andric ++SectionIndex; 4423bdd1243dSDimitry Andric 4424bdd1243dSDimitry Andric if (!(S.sh_flags & SHF_COMPRESSED)) 4425bdd1243dSDimitry Andric continue; 4426bdd1243dSDimitry Andric Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S); 4427bdd1243dSDimitry Andric if (!Data || Data->size() < sizeof(Elf_Chdr)) { 4428bdd1243dSDimitry Andric consumeError(Data.takeError()); 4429bdd1243dSDimitry Andric reportWarning(createError("SHF_COMPRESSED section '" + Name + 4430bdd1243dSDimitry Andric "' does not have an Elf_Chdr header"), 4431bdd1243dSDimitry Andric this->FileName); 4432bdd1243dSDimitry Andric OS.indent(7); 4433bdd1243dSDimitry Andric OS << "[<corrupt>]"; 4434bdd1243dSDimitry Andric } else { 4435bdd1243dSDimitry Andric OS.indent(7); 4436bdd1243dSDimitry Andric auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data()); 4437bdd1243dSDimitry Andric if (Chdr->ch_type == ELFCOMPRESS_ZLIB) 4438bdd1243dSDimitry Andric OS << "ZLIB"; 4439bdd1243dSDimitry Andric else if (Chdr->ch_type == ELFCOMPRESS_ZSTD) 4440bdd1243dSDimitry Andric OS << "ZSTD"; 4441bdd1243dSDimitry Andric else 4442bdd1243dSDimitry Andric OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type)); 4443bdd1243dSDimitry Andric OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8) 4444bdd1243dSDimitry Andric << ", " << Chdr->ch_addralign; 4445bdd1243dSDimitry Andric } 4446bdd1243dSDimitry Andric OS << '\n'; 44470b57cec5SDimitry Andric } 44480b57cec5SDimitry Andric } 44490b57cec5SDimitry Andric 44500b57cec5SDimitry Andric static inline std::string printPhdrFlags(unsigned Flag) { 44510b57cec5SDimitry Andric std::string Str; 44520b57cec5SDimitry Andric Str = (Flag & PF_R) ? "R" : " "; 44530b57cec5SDimitry Andric Str += (Flag & PF_W) ? "W" : " "; 44540b57cec5SDimitry Andric Str += (Flag & PF_X) ? "E" : " "; 44550b57cec5SDimitry Andric return Str; 44560b57cec5SDimitry Andric } 44570b57cec5SDimitry Andric 44580b57cec5SDimitry Andric template <class ELFT> 44595ffd83dbSDimitry Andric static bool checkTLSSections(const typename ELFT::Phdr &Phdr, 44605ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 44615ffd83dbSDimitry Andric if (Sec.sh_flags & ELF::SHF_TLS) { 44625ffd83dbSDimitry Andric // .tbss must only be shown in the PT_TLS segment. 44635ffd83dbSDimitry Andric if (Sec.sh_type == ELF::SHT_NOBITS) 44645ffd83dbSDimitry Andric return Phdr.p_type == ELF::PT_TLS; 44655ffd83dbSDimitry Andric 44665ffd83dbSDimitry Andric // SHF_TLS sections are only shown in PT_TLS, PT_LOAD or PT_GNU_RELRO 44675ffd83dbSDimitry Andric // segments. 44685ffd83dbSDimitry Andric return (Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) || 44695ffd83dbSDimitry Andric (Phdr.p_type == ELF::PT_GNU_RELRO); 44700b57cec5SDimitry Andric } 44710b57cec5SDimitry Andric 44725ffd83dbSDimitry Andric // PT_TLS must only have SHF_TLS sections. 44735ffd83dbSDimitry Andric return Phdr.p_type != ELF::PT_TLS; 44745ffd83dbSDimitry Andric } 44755ffd83dbSDimitry Andric 44760b57cec5SDimitry Andric template <class ELFT> 44775ffd83dbSDimitry Andric static bool checkOffsets(const typename ELFT::Phdr &Phdr, 44785ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 44795ffd83dbSDimitry Andric // SHT_NOBITS sections don't need to have an offset inside the segment. 44800b57cec5SDimitry Andric if (Sec.sh_type == ELF::SHT_NOBITS) 44810b57cec5SDimitry Andric return true; 44825ffd83dbSDimitry Andric 44835ffd83dbSDimitry Andric if (Sec.sh_offset < Phdr.p_offset) 44840b57cec5SDimitry Andric return false; 44855ffd83dbSDimitry Andric 44865ffd83dbSDimitry Andric // Only non-empty sections can be at the end of a segment. 44875ffd83dbSDimitry Andric if (Sec.sh_size == 0) 44885ffd83dbSDimitry Andric return (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz); 44895ffd83dbSDimitry Andric return Sec.sh_offset + Sec.sh_size <= Phdr.p_offset + Phdr.p_filesz; 44900b57cec5SDimitry Andric } 44910b57cec5SDimitry Andric 44925ffd83dbSDimitry Andric // Check that an allocatable section belongs to a virtual address 44935ffd83dbSDimitry Andric // space of a segment. 44940b57cec5SDimitry Andric template <class ELFT> 44955ffd83dbSDimitry Andric static bool checkVMA(const typename ELFT::Phdr &Phdr, 44965ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 44970b57cec5SDimitry Andric if (!(Sec.sh_flags & ELF::SHF_ALLOC)) 44980b57cec5SDimitry Andric return true; 44995ffd83dbSDimitry Andric 45005ffd83dbSDimitry Andric if (Sec.sh_addr < Phdr.p_vaddr) 45010b57cec5SDimitry Andric return false; 45025ffd83dbSDimitry Andric 45035ffd83dbSDimitry Andric bool IsTbss = 45045ffd83dbSDimitry Andric (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); 45055ffd83dbSDimitry Andric // .tbss is special, it only has memory in PT_TLS and has NOBITS properties. 45065ffd83dbSDimitry Andric bool IsTbssInNonTLS = IsTbss && Phdr.p_type != ELF::PT_TLS; 45075ffd83dbSDimitry Andric // Only non-empty sections can be at the end of a segment. 45085ffd83dbSDimitry Andric if (Sec.sh_size == 0 || IsTbssInNonTLS) 45095ffd83dbSDimitry Andric return Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz; 45105ffd83dbSDimitry Andric return Sec.sh_addr + Sec.sh_size <= Phdr.p_vaddr + Phdr.p_memsz; 45110b57cec5SDimitry Andric } 45120b57cec5SDimitry Andric 45130b57cec5SDimitry Andric template <class ELFT> 45145ffd83dbSDimitry Andric static bool checkPTDynamic(const typename ELFT::Phdr &Phdr, 45155ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 45165ffd83dbSDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0) 45170b57cec5SDimitry Andric return true; 45185ffd83dbSDimitry Andric 45195ffd83dbSDimitry Andric // We get here when we have an empty section. Only non-empty sections can be 45205ffd83dbSDimitry Andric // at the start or at the end of PT_DYNAMIC. 45210b57cec5SDimitry Andric // Is section within the phdr both based on offset and VMA? 45225ffd83dbSDimitry Andric bool CheckOffset = (Sec.sh_type == ELF::SHT_NOBITS) || 45230b57cec5SDimitry Andric (Sec.sh_offset > Phdr.p_offset && 45245ffd83dbSDimitry Andric Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz); 45255ffd83dbSDimitry Andric bool CheckVA = !(Sec.sh_flags & ELF::SHF_ALLOC) || 45265ffd83dbSDimitry Andric (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz); 45275ffd83dbSDimitry Andric return CheckOffset && CheckVA; 45280b57cec5SDimitry Andric } 45290b57cec5SDimitry Andric 45300b57cec5SDimitry Andric template <class ELFT> 4531e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printProgramHeaders( 4532e8d8bef9SDimitry Andric bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) { 4533bdd1243dSDimitry Andric const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE); 4534bdd1243dSDimitry Andric // Exit early if no program header or section mapping details were requested. 4535bdd1243dSDimitry Andric if (!PrintProgramHeaders && !ShouldPrintSectionMapping) 4536bdd1243dSDimitry Andric return; 45370b57cec5SDimitry Andric 4538bdd1243dSDimitry Andric if (PrintProgramHeaders) { 4539bdd1243dSDimitry Andric const Elf_Ehdr &Header = this->Obj.getHeader(); 4540bdd1243dSDimitry Andric if (Header.e_phnum == 0) { 4541bdd1243dSDimitry Andric OS << "\nThere are no program headers in this file.\n"; 4542bdd1243dSDimitry Andric } else { 4543bdd1243dSDimitry Andric printProgramHeaders(); 4544bdd1243dSDimitry Andric } 4545bdd1243dSDimitry Andric } 4546bdd1243dSDimitry Andric 4547bdd1243dSDimitry Andric if (ShouldPrintSectionMapping) 4548e8d8bef9SDimitry Andric printSectionMapping(); 45490b57cec5SDimitry Andric } 45500b57cec5SDimitry Andric 4551e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printProgramHeaders() { 45520b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 4553e8d8bef9SDimitry Andric const Elf_Ehdr &Header = this->Obj.getHeader(); 45540b57cec5SDimitry Andric Field Fields[8] = {2, 17, 26, 37 + Bias, 45550b57cec5SDimitry Andric 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias}; 45560b57cec5SDimitry Andric OS << "\nElf file type is " 4557bdd1243dSDimitry Andric << enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n" 4558e8d8bef9SDimitry Andric << "Entry point " << format_hex(Header.e_entry, 3) << "\n" 4559e8d8bef9SDimitry Andric << "There are " << Header.e_phnum << " program headers," 4560e8d8bef9SDimitry Andric << " starting at offset " << Header.e_phoff << "\n\n" 45610b57cec5SDimitry Andric << "Program Headers:\n"; 45620b57cec5SDimitry Andric if (ELFT::Is64Bits) 45630b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr " 45640b57cec5SDimitry Andric << " FileSiz MemSiz Flg Align\n"; 45650b57cec5SDimitry Andric else 45660b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr FileSiz " 45670b57cec5SDimitry Andric << "MemSiz Flg Align\n"; 45680b57cec5SDimitry Andric 45690b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 18 : 10; 45700b57cec5SDimitry Andric unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7; 45715ffd83dbSDimitry Andric 4572e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 45735ffd83dbSDimitry Andric if (!PhdrsOrErr) { 4574e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to dump program headers: " + 4575e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 45765ffd83dbSDimitry Andric return; 45775ffd83dbSDimitry Andric } 45785ffd83dbSDimitry Andric 45795ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 4580e8d8bef9SDimitry Andric Fields[0].Str = getGNUPtType(Header.e_machine, Phdr.p_type); 45810b57cec5SDimitry Andric Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8)); 45820b57cec5SDimitry Andric Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width)); 45830b57cec5SDimitry Andric Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width)); 45840b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth)); 45850b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth)); 45860b57cec5SDimitry Andric Fields[6].Str = printPhdrFlags(Phdr.p_flags); 45870b57cec5SDimitry Andric Fields[7].Str = to_string(format_hex(Phdr.p_align, 1)); 4588e8d8bef9SDimitry Andric for (const Field &F : Fields) 4589e8d8bef9SDimitry Andric printField(F); 45900b57cec5SDimitry Andric if (Phdr.p_type == ELF::PT_INTERP) { 45915ffd83dbSDimitry Andric OS << "\n"; 45925ffd83dbSDimitry Andric auto ReportBadInterp = [&](const Twine &Msg) { 4593e8d8bef9SDimitry Andric this->reportUniqueWarning( 4594e8d8bef9SDimitry Andric "unable to read program interpreter name at offset 0x" + 4595e8d8bef9SDimitry Andric Twine::utohexstr(Phdr.p_offset) + ": " + Msg); 45965ffd83dbSDimitry Andric }; 45975ffd83dbSDimitry Andric 4598e8d8bef9SDimitry Andric if (Phdr.p_offset >= this->Obj.getBufSize()) { 45995ffd83dbSDimitry Andric ReportBadInterp("it goes past the end of the file (0x" + 4600e8d8bef9SDimitry Andric Twine::utohexstr(this->Obj.getBufSize()) + ")"); 46015ffd83dbSDimitry Andric continue; 46025ffd83dbSDimitry Andric } 46035ffd83dbSDimitry Andric 46045ffd83dbSDimitry Andric const char *Data = 4605e8d8bef9SDimitry Andric reinterpret_cast<const char *>(this->Obj.base()) + Phdr.p_offset; 4606e8d8bef9SDimitry Andric size_t MaxSize = this->Obj.getBufSize() - Phdr.p_offset; 46075ffd83dbSDimitry Andric size_t Len = strnlen(Data, MaxSize); 46085ffd83dbSDimitry Andric if (Len == MaxSize) { 46095ffd83dbSDimitry Andric ReportBadInterp("it is not null-terminated"); 46105ffd83dbSDimitry Andric continue; 46115ffd83dbSDimitry Andric } 46125ffd83dbSDimitry Andric 46135ffd83dbSDimitry Andric OS << " [Requesting program interpreter: "; 46145ffd83dbSDimitry Andric OS << StringRef(Data, Len) << "]"; 46150b57cec5SDimitry Andric } 46160b57cec5SDimitry Andric OS << "\n"; 46170b57cec5SDimitry Andric } 46180b57cec5SDimitry Andric } 46190b57cec5SDimitry Andric 4620e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionMapping() { 46210b57cec5SDimitry Andric OS << "\n Section to Segment mapping:\n Segment Sections...\n"; 46220b57cec5SDimitry Andric DenseSet<const Elf_Shdr *> BelongsToSegment; 46230b57cec5SDimitry Andric int Phnum = 0; 46245ffd83dbSDimitry Andric 4625e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 46265ffd83dbSDimitry Andric if (!PhdrsOrErr) { 4627e8d8bef9SDimitry Andric this->reportUniqueWarning( 46285ffd83dbSDimitry Andric "can't read program headers to build section to segment mapping: " + 4629e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 46305ffd83dbSDimitry Andric return; 46315ffd83dbSDimitry Andric } 46325ffd83dbSDimitry Andric 46335ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 46340b57cec5SDimitry Andric std::string Sections; 46350b57cec5SDimitry Andric OS << format(" %2.2d ", Phnum++); 46360b57cec5SDimitry Andric // Check if each section is in a segment and then print mapping. 4637e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 46385ffd83dbSDimitry Andric if (Sec.sh_type == ELF::SHT_NULL) 46395ffd83dbSDimitry Andric continue; 46405ffd83dbSDimitry Andric 46410b57cec5SDimitry Andric // readelf additionally makes sure it does not print zero sized sections 46420b57cec5SDimitry Andric // at end of segments and for PT_DYNAMIC both start and end of section 46430b57cec5SDimitry Andric // .tbss must only be shown in PT_TLS section. 46445ffd83dbSDimitry Andric if (checkTLSSections<ELFT>(Phdr, Sec) && checkOffsets<ELFT>(Phdr, Sec) && 46455ffd83dbSDimitry Andric checkVMA<ELFT>(Phdr, Sec) && checkPTDynamic<ELFT>(Phdr, Sec)) { 46468bcb0991SDimitry Andric Sections += 4647e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() + 46488bcb0991SDimitry Andric " "; 46490b57cec5SDimitry Andric BelongsToSegment.insert(&Sec); 46500b57cec5SDimitry Andric } 46510b57cec5SDimitry Andric } 46520b57cec5SDimitry Andric OS << Sections << "\n"; 46530b57cec5SDimitry Andric OS.flush(); 46540b57cec5SDimitry Andric } 46550b57cec5SDimitry Andric 46560b57cec5SDimitry Andric // Display sections that do not belong to a segment. 46570b57cec5SDimitry Andric std::string Sections; 4658e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 46590b57cec5SDimitry Andric if (BelongsToSegment.find(&Sec) == BelongsToSegment.end()) 46608bcb0991SDimitry Andric Sections += 4661e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() + 4662e8d8bef9SDimitry Andric ' '; 46630b57cec5SDimitry Andric } 46640b57cec5SDimitry Andric if (!Sections.empty()) { 46650b57cec5SDimitry Andric OS << " None " << Sections << '\n'; 46660b57cec5SDimitry Andric OS.flush(); 46670b57cec5SDimitry Andric } 46680b57cec5SDimitry Andric } 46690b57cec5SDimitry Andric 46708bcb0991SDimitry Andric namespace { 46718bcb0991SDimitry Andric 46728bcb0991SDimitry Andric template <class ELFT> 4673e8d8bef9SDimitry Andric RelSymbol<ELFT> getSymbolForReloc(const ELFDumper<ELFT> &Dumper, 4674e8d8bef9SDimitry Andric const Relocation<ELFT> &Reloc) { 4675e8d8bef9SDimitry Andric using Elf_Sym = typename ELFT::Sym; 4676e8d8bef9SDimitry Andric auto WarnAndReturn = [&](const Elf_Sym *Sym, 46775ffd83dbSDimitry Andric const Twine &Reason) -> RelSymbol<ELFT> { 4678e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 4679e8d8bef9SDimitry Andric "unable to get name of the dynamic symbol with index " + 4680e8d8bef9SDimitry Andric Twine(Reloc.Symbol) + ": " + Reason); 46815ffd83dbSDimitry Andric return {Sym, "<corrupt>"}; 46825ffd83dbSDimitry Andric }; 46838bcb0991SDimitry Andric 4684e8d8bef9SDimitry Andric ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols(); 4685e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = Symbols.begin(); 46865ffd83dbSDimitry Andric if (!FirstSym) 46875ffd83dbSDimitry Andric return WarnAndReturn(nullptr, "no dynamic symbol table found"); 46885ffd83dbSDimitry Andric 46895ffd83dbSDimitry Andric // We might have an object without a section header. In this case the size of 46905ffd83dbSDimitry Andric // Symbols is zero, because there is no way to know the size of the dynamic 46915ffd83dbSDimitry Andric // table. We should allow this case and not print a warning. 4692e8d8bef9SDimitry Andric if (!Symbols.empty() && Reloc.Symbol >= Symbols.size()) 46935ffd83dbSDimitry Andric return WarnAndReturn( 46945ffd83dbSDimitry Andric nullptr, 46955ffd83dbSDimitry Andric "index is greater than or equal to the number of dynamic symbols (" + 46965ffd83dbSDimitry Andric Twine(Symbols.size()) + ")"); 46975ffd83dbSDimitry Andric 4698e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 4699e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 4700e8d8bef9SDimitry Andric const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) + 4701e8d8bef9SDimitry Andric (uint64_t)Reloc.Symbol * sizeof(Elf_Sym); 4702e8d8bef9SDimitry Andric if (SymOffset + sizeof(Elf_Sym) > FileSize) 4703e8d8bef9SDimitry Andric return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) + 4704e8d8bef9SDimitry Andric " goes past the end of the file (0x" + 4705e8d8bef9SDimitry Andric Twine::utohexstr(FileSize) + ")"); 4706e8d8bef9SDimitry Andric 4707e8d8bef9SDimitry Andric const Elf_Sym *Sym = FirstSym + Reloc.Symbol; 4708e8d8bef9SDimitry Andric Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable()); 47095ffd83dbSDimitry Andric if (!ErrOrName) 47105ffd83dbSDimitry Andric return WarnAndReturn(Sym, toString(ErrOrName.takeError())); 47115ffd83dbSDimitry Andric 47125ffd83dbSDimitry Andric return {Sym == FirstSym ? nullptr : Sym, maybeDemangle(*ErrOrName)}; 47138bcb0991SDimitry Andric } 47148bcb0991SDimitry Andric } // namespace 47158bcb0991SDimitry Andric 47160b57cec5SDimitry Andric template <class ELFT> 4717e8d8bef9SDimitry Andric static size_t getMaxDynamicTagSize(const ELFFile<ELFT> &Obj, 47185ffd83dbSDimitry Andric typename ELFT::DynRange Tags) { 47195ffd83dbSDimitry Andric size_t Max = 0; 47205ffd83dbSDimitry Andric for (const typename ELFT::Dyn &Dyn : Tags) 4721e8d8bef9SDimitry Andric Max = std::max(Max, Obj.getDynamicTagAsString(Dyn.d_tag).size()); 47225ffd83dbSDimitry Andric return Max; 47235ffd83dbSDimitry Andric } 47245ffd83dbSDimitry Andric 4725e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDynamicTable() { 4726e8d8bef9SDimitry Andric Elf_Dyn_Range Table = this->dynamic_table(); 47270b57cec5SDimitry Andric if (Table.empty()) 47280b57cec5SDimitry Andric return; 47290b57cec5SDimitry Andric 47300b57cec5SDimitry Andric OS << "Dynamic section at offset " 4731e8d8bef9SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(this->DynamicTable.Addr) - 4732e8d8bef9SDimitry Andric this->Obj.base(), 47330b57cec5SDimitry Andric 1) 47340b57cec5SDimitry Andric << " contains " << Table.size() << " entries:\n"; 47350b57cec5SDimitry Andric 47365ffd83dbSDimitry Andric // The type name is surrounded with round brackets, hence add 2. 4737e8d8bef9SDimitry Andric size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table) + 2; 47385ffd83dbSDimitry Andric // The "Name/Value" column should be indented from the "Type" column by N 47395ffd83dbSDimitry Andric // spaces, where N = MaxTagSize - length of "Type" (4) + trailing 47405ffd83dbSDimitry Andric // space (1) = 3. 47415ffd83dbSDimitry Andric OS << " Tag" + std::string(ELFT::Is64Bits ? 16 : 8, ' ') + "Type" 47425ffd83dbSDimitry Andric << std::string(MaxTagSize - 3, ' ') << "Name/Value\n"; 47435ffd83dbSDimitry Andric 47445ffd83dbSDimitry Andric std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s "; 47450b57cec5SDimitry Andric for (auto Entry : Table) { 47460b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 47475ffd83dbSDimitry Andric std::string Type = 4748349cc55cSDimitry Andric std::string("(") + this->Obj.getDynamicTagAsString(Tag) + ")"; 4749e8d8bef9SDimitry Andric std::string Value = this->getDynamicEntry(Tag, Entry.getVal()); 47505ffd83dbSDimitry Andric OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10) 47515ffd83dbSDimitry Andric << format(ValueFmt.c_str(), Type.c_str()) << Value << "\n"; 47520b57cec5SDimitry Andric } 47530b57cec5SDimitry Andric } 47540b57cec5SDimitry Andric 4755e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDynamicRelocations() { 4756e8d8bef9SDimitry Andric this->printDynamicRelocationsHelper(); 47570b57cec5SDimitry Andric } 47585ffd83dbSDimitry Andric 4759e8d8bef9SDimitry Andric template <class ELFT> 4760e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printDynamicReloc(const Relocation<ELFT> &R) { 4761e8d8bef9SDimitry Andric printRelRelaReloc(R, getSymbolForReloc(*this, R)); 4762e8d8bef9SDimitry Andric } 4763e8d8bef9SDimitry Andric 4764e8d8bef9SDimitry Andric template <class ELFT> 4765e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) { 4766e8d8bef9SDimitry Andric this->forEachRelocationDo( 4767e8d8bef9SDimitry Andric Sec, opts::RawRelr, 4768e8d8bef9SDimitry Andric [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec, 4769e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); }, 4770e8d8bef9SDimitry Andric [&](const Elf_Relr &R) { printRelrReloc(R); }); 4771e8d8bef9SDimitry Andric } 4772e8d8bef9SDimitry Andric 4773e8d8bef9SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() { 4774e8d8bef9SDimitry Andric const bool IsMips64EL = this->Obj.isMips64EL(); 4775e8d8bef9SDimitry Andric if (this->DynRelaRegion.Size > 0) { 4776e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion); 4777e8d8bef9SDimitry Andric for (const Elf_Rela &Rela : 4778e8d8bef9SDimitry Andric this->DynRelaRegion.template getAsArrayRef<Elf_Rela>()) 4779e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL)); 4780e8d8bef9SDimitry Andric } 4781e8d8bef9SDimitry Andric 4782e8d8bef9SDimitry Andric if (this->DynRelRegion.Size > 0) { 4783e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "REL", this->DynRelRegion); 4784e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : 4785e8d8bef9SDimitry Andric this->DynRelRegion.template getAsArrayRef<Elf_Rel>()) 4786e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 4787e8d8bef9SDimitry Andric } 4788e8d8bef9SDimitry Andric 4789e8d8bef9SDimitry Andric if (this->DynRelrRegion.Size > 0) { 4790e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "RELR", this->DynRelrRegion); 4791e8d8bef9SDimitry Andric Elf_Relr_Range Relrs = 4792e8d8bef9SDimitry Andric this->DynRelrRegion.template getAsArrayRef<Elf_Relr>(); 4793e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : Obj.decode_relrs(Relrs)) 4794e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 4795e8d8bef9SDimitry Andric } 4796e8d8bef9SDimitry Andric 4797e8d8bef9SDimitry Andric if (this->DynPLTRelRegion.Size) { 4798e8d8bef9SDimitry Andric if (this->DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { 4799e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_RELA, "PLT", this->DynPLTRelRegion); 4800e8d8bef9SDimitry Andric for (const Elf_Rela &Rela : 4801e8d8bef9SDimitry Andric this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>()) 4802e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL)); 48030b57cec5SDimitry Andric } else { 4804e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion); 4805e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : 4806e8d8bef9SDimitry Andric this->DynPLTRelRegion.template getAsArrayRef<Elf_Rel>()) 4807e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 48080b57cec5SDimitry Andric } 48090b57cec5SDimitry Andric } 48105ffd83dbSDimitry Andric } 48110b57cec5SDimitry Andric 48120b57cec5SDimitry Andric template <class ELFT> 4813e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printGNUVersionSectionProlog( 4814e8d8bef9SDimitry Andric const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) { 4815e8d8bef9SDimitry Andric // Don't inline the SecName, because it might report a warning to stderr and 4816e8d8bef9SDimitry Andric // corrupt the output. 4817e8d8bef9SDimitry Andric StringRef SecName = this->getPrintableSectionName(Sec); 4818480093f4SDimitry Andric OS << Label << " section '" << SecName << "' " 48190b57cec5SDimitry Andric << "contains " << EntriesNum << " entries:\n"; 48200b57cec5SDimitry Andric 4821e8d8bef9SDimitry Andric StringRef LinkedSecName = "<corrupt>"; 4822e8d8bef9SDimitry Andric if (Expected<const typename ELFT::Shdr *> LinkedSecOrErr = 4823e8d8bef9SDimitry Andric this->Obj.getSection(Sec.sh_link)) 4824e8d8bef9SDimitry Andric LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr); 4825480093f4SDimitry Andric else 4826e8d8bef9SDimitry Andric this->reportUniqueWarning("invalid section linked to " + 4827e8d8bef9SDimitry Andric this->describe(Sec) + ": " + 4828e8d8bef9SDimitry Andric toString(LinkedSecOrErr.takeError())); 4829480093f4SDimitry Andric 4830e8d8bef9SDimitry Andric OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16) 4831e8d8bef9SDimitry Andric << " Offset: " << format_hex(Sec.sh_offset, 8) 4832e8d8bef9SDimitry Andric << " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n"; 48330b57cec5SDimitry Andric } 48340b57cec5SDimitry Andric 48350b57cec5SDimitry Andric template <class ELFT> 4836e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) { 48370b57cec5SDimitry Andric if (!Sec) 48380b57cec5SDimitry Andric return; 48390b57cec5SDimitry Andric 4840e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version symbols", 4841480093f4SDimitry Andric Sec->sh_size / sizeof(Elf_Versym)); 4842480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VerTableOrErr = 4843e8d8bef9SDimitry Andric this->getVersionTable(*Sec, /*SymTab=*/nullptr, 4844e8d8bef9SDimitry Andric /*StrTab=*/nullptr, /*SymTabSec=*/nullptr); 4845480093f4SDimitry Andric if (!VerTableOrErr) { 4846480093f4SDimitry Andric this->reportUniqueWarning(VerTableOrErr.takeError()); 4847480093f4SDimitry Andric return; 4848480093f4SDimitry Andric } 48490b57cec5SDimitry Andric 4850bdd1243dSDimitry Andric SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr; 4851bdd1243dSDimitry Andric if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr = 4852e8d8bef9SDimitry Andric this->getVersionMap()) 4853e8d8bef9SDimitry Andric VersionMap = *MapOrErr; 4854e8d8bef9SDimitry Andric else 4855e8d8bef9SDimitry Andric this->reportUniqueWarning(MapOrErr.takeError()); 4856e8d8bef9SDimitry Andric 4857480093f4SDimitry Andric ArrayRef<Elf_Versym> VerTable = *VerTableOrErr; 4858480093f4SDimitry Andric std::vector<StringRef> Versions; 4859480093f4SDimitry Andric for (size_t I = 0, E = VerTable.size(); I < E; ++I) { 4860480093f4SDimitry Andric unsigned Ndx = VerTable[I].vs_index; 4861480093f4SDimitry Andric if (Ndx == VER_NDX_LOCAL || Ndx == VER_NDX_GLOBAL) { 4862480093f4SDimitry Andric Versions.emplace_back(Ndx == VER_NDX_LOCAL ? "*local*" : "*global*"); 4863480093f4SDimitry Andric continue; 4864480093f4SDimitry Andric } 4865480093f4SDimitry Andric 4866e8d8bef9SDimitry Andric if (!VersionMap) { 4867e8d8bef9SDimitry Andric Versions.emplace_back("<corrupt>"); 4868e8d8bef9SDimitry Andric continue; 4869480093f4SDimitry Andric } 4870e8d8bef9SDimitry Andric 4871e8d8bef9SDimitry Andric bool IsDefault; 4872e8d8bef9SDimitry Andric Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex( 4873bdd1243dSDimitry Andric Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt); 4874e8d8bef9SDimitry Andric if (!NameOrErr) { 4875e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get a version for entry " + 4876e8d8bef9SDimitry Andric Twine(I) + " of " + this->describe(*Sec) + 4877e8d8bef9SDimitry Andric ": " + toString(NameOrErr.takeError())); 4878480093f4SDimitry Andric Versions.emplace_back("<corrupt>"); 4879480093f4SDimitry Andric continue; 4880480093f4SDimitry Andric } 4881480093f4SDimitry Andric Versions.emplace_back(*NameOrErr); 4882480093f4SDimitry Andric } 48830b57cec5SDimitry Andric 48840b57cec5SDimitry Andric // readelf prints 4 entries per line. 4885480093f4SDimitry Andric uint64_t Entries = VerTable.size(); 48860b57cec5SDimitry Andric for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) { 48870b57cec5SDimitry Andric OS << " " << format_hex_no_prefix(VersymRow, 3) << ":"; 4888480093f4SDimitry Andric for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) { 4889480093f4SDimitry Andric unsigned Ndx = VerTable[VersymRow + I].vs_index; 4890480093f4SDimitry Andric OS << format("%4x%c", Ndx & VERSYM_VERSION, 4891480093f4SDimitry Andric Ndx & VERSYM_HIDDEN ? 'h' : ' '); 4892480093f4SDimitry Andric OS << left_justify("(" + std::string(Versions[VersymRow + I]) + ")", 13); 48930b57cec5SDimitry Andric } 48940b57cec5SDimitry Andric OS << '\n'; 48950b57cec5SDimitry Andric } 48960b57cec5SDimitry Andric OS << '\n'; 48970b57cec5SDimitry Andric } 48980b57cec5SDimitry Andric 48990b57cec5SDimitry Andric static std::string versionFlagToString(unsigned Flags) { 49000b57cec5SDimitry Andric if (Flags == 0) 49010b57cec5SDimitry Andric return "none"; 49020b57cec5SDimitry Andric 49030b57cec5SDimitry Andric std::string Ret; 49040b57cec5SDimitry Andric auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) { 49050b57cec5SDimitry Andric if (!(Flags & Flag)) 49060b57cec5SDimitry Andric return; 49070b57cec5SDimitry Andric if (!Ret.empty()) 49080b57cec5SDimitry Andric Ret += " | "; 49090b57cec5SDimitry Andric Ret += Name; 49100b57cec5SDimitry Andric Flags &= ~Flag; 49110b57cec5SDimitry Andric }; 49120b57cec5SDimitry Andric 49130b57cec5SDimitry Andric AddFlag(VER_FLG_BASE, "BASE"); 49140b57cec5SDimitry Andric AddFlag(VER_FLG_WEAK, "WEAK"); 49150b57cec5SDimitry Andric AddFlag(VER_FLG_INFO, "INFO"); 49160b57cec5SDimitry Andric AddFlag(~0, "<unknown>"); 49170b57cec5SDimitry Andric return Ret; 49180b57cec5SDimitry Andric } 49190b57cec5SDimitry Andric 49200b57cec5SDimitry Andric template <class ELFT> 4921e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) { 49220b57cec5SDimitry Andric if (!Sec) 49230b57cec5SDimitry Andric return; 49240b57cec5SDimitry Andric 4925e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info); 49260b57cec5SDimitry Andric 4927e8d8bef9SDimitry Andric Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec); 4928480093f4SDimitry Andric if (!V) { 4929480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 4930480093f4SDimitry Andric return; 49310b57cec5SDimitry Andric } 49320b57cec5SDimitry Andric 4933480093f4SDimitry Andric for (const VerDef &Def : *V) { 4934480093f4SDimitry Andric OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u Name: %s\n", 4935480093f4SDimitry Andric Def.Offset, Def.Version, 4936480093f4SDimitry Andric versionFlagToString(Def.Flags).c_str(), Def.Ndx, Def.Cnt, 4937480093f4SDimitry Andric Def.Name.data()); 4938480093f4SDimitry Andric unsigned I = 0; 4939480093f4SDimitry Andric for (const VerdAux &Aux : Def.AuxV) 4940480093f4SDimitry Andric OS << format(" 0x%04x: Parent %u: %s\n", Aux.Offset, ++I, 4941480093f4SDimitry Andric Aux.Name.data()); 49420b57cec5SDimitry Andric } 4943480093f4SDimitry Andric 49440b57cec5SDimitry Andric OS << '\n'; 49450b57cec5SDimitry Andric } 49460b57cec5SDimitry Andric 49470b57cec5SDimitry Andric template <class ELFT> 4948e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) { 49490b57cec5SDimitry Andric if (!Sec) 49500b57cec5SDimitry Andric return; 49510b57cec5SDimitry Andric 49520b57cec5SDimitry Andric unsigned VerneedNum = Sec->sh_info; 4953e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum); 49540b57cec5SDimitry Andric 4955480093f4SDimitry Andric Expected<std::vector<VerNeed>> V = 4956e8d8bef9SDimitry Andric this->Obj.getVersionDependencies(*Sec, this->WarningHandler); 4957480093f4SDimitry Andric if (!V) { 4958480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 4959480093f4SDimitry Andric return; 49600b57cec5SDimitry Andric } 4961480093f4SDimitry Andric 4962480093f4SDimitry Andric for (const VerNeed &VN : *V) { 4963480093f4SDimitry Andric OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset, 4964480093f4SDimitry Andric VN.Version, VN.File.data(), VN.Cnt); 4965480093f4SDimitry Andric for (const VernAux &Aux : VN.AuxV) 4966480093f4SDimitry Andric OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset, 4967480093f4SDimitry Andric Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(), 4968480093f4SDimitry Andric Aux.Other); 49690b57cec5SDimitry Andric } 49700b57cec5SDimitry Andric OS << '\n'; 49710b57cec5SDimitry Andric } 49720b57cec5SDimitry Andric 49730b57cec5SDimitry Andric template <class ELFT> 497406c3fb27SDimitry Andric void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket, 497506c3fb27SDimitry Andric size_t MaxChain, 497606c3fb27SDimitry Andric size_t TotalSyms, 497706c3fb27SDimitry Andric ArrayRef<size_t> Count, 497806c3fb27SDimitry Andric bool IsGnu) const { 49790b57cec5SDimitry Andric size_t CumulativeNonZero = 0; 498006c3fb27SDimitry Andric OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "") 498106c3fb27SDimitry Andric << " bucket list length (total of " << NBucket << " buckets)\n" 49820b57cec5SDimitry Andric << " Length Number % of total Coverage\n"; 498306c3fb27SDimitry Andric for (size_t I = 0; I < MaxChain; ++I) { 49840b57cec5SDimitry Andric CumulativeNonZero += Count[I] * I; 49850b57cec5SDimitry Andric OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], 49860b57cec5SDimitry Andric (Count[I] * 100.0) / NBucket, 49870b57cec5SDimitry Andric (CumulativeNonZero * 100.0) / TotalSyms); 49880b57cec5SDimitry Andric } 49890b57cec5SDimitry Andric } 49900b57cec5SDimitry Andric 4991e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() { 49920b57cec5SDimitry Andric OS << "GNUStyle::printCGProfile not implemented\n"; 49930b57cec5SDimitry Andric } 49940b57cec5SDimitry Andric 4995fe6060f1SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printBBAddrMaps() { 4996fe6060f1SDimitry Andric OS << "GNUStyle::printBBAddrMaps not implemented\n"; 4997fe6060f1SDimitry Andric } 4998fe6060f1SDimitry Andric 4999e8d8bef9SDimitry Andric static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) { 5000e8d8bef9SDimitry Andric std::vector<uint64_t> Ret; 5001e8d8bef9SDimitry Andric const uint8_t *Cur = Data.begin(); 5002e8d8bef9SDimitry Andric const uint8_t *End = Data.end(); 5003e8d8bef9SDimitry Andric while (Cur != End) { 5004e8d8bef9SDimitry Andric unsigned Size; 5005e8d8bef9SDimitry Andric const char *Err; 5006e8d8bef9SDimitry Andric Ret.push_back(decodeULEB128(Cur, &Size, End, &Err)); 5007e8d8bef9SDimitry Andric if (Err) 5008e8d8bef9SDimitry Andric return createError(Err); 5009e8d8bef9SDimitry Andric Cur += Size; 5010e8d8bef9SDimitry Andric } 5011e8d8bef9SDimitry Andric return Ret; 5012e8d8bef9SDimitry Andric } 5013e8d8bef9SDimitry Andric 50140b57cec5SDimitry Andric template <class ELFT> 5015e8d8bef9SDimitry Andric static Expected<std::vector<uint64_t>> 5016e8d8bef9SDimitry Andric decodeAddrsigSection(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) { 5017e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Sec); 5018e8d8bef9SDimitry Andric if (!ContentsOrErr) 5019e8d8bef9SDimitry Andric return ContentsOrErr.takeError(); 5020e8d8bef9SDimitry Andric 5021e8d8bef9SDimitry Andric if (Expected<std::vector<uint64_t>> SymsOrErr = 5022e8d8bef9SDimitry Andric toULEB128Array(*ContentsOrErr)) 5023e8d8bef9SDimitry Andric return *SymsOrErr; 5024e8d8bef9SDimitry Andric else 5025e8d8bef9SDimitry Andric return createError("unable to decode " + describe(Obj, Sec) + ": " + 5026e8d8bef9SDimitry Andric toString(SymsOrErr.takeError())); 50270b57cec5SDimitry Andric } 50280b57cec5SDimitry Andric 5029e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() { 5030e8d8bef9SDimitry Andric if (!this->DotAddrsigSec) 5031e8d8bef9SDimitry Andric return; 50320b57cec5SDimitry Andric 5033e8d8bef9SDimitry Andric Expected<std::vector<uint64_t>> SymsOrErr = 5034e8d8bef9SDimitry Andric decodeAddrsigSection(this->Obj, *this->DotAddrsigSec); 5035e8d8bef9SDimitry Andric if (!SymsOrErr) { 5036e8d8bef9SDimitry Andric this->reportUniqueWarning(SymsOrErr.takeError()); 5037e8d8bef9SDimitry Andric return; 50380b57cec5SDimitry Andric } 50390b57cec5SDimitry Andric 5040e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(*this->DotAddrsigSec); 5041e8d8bef9SDimitry Andric OS << "\nAddress-significant symbols section '" << Name << "'" 5042e8d8bef9SDimitry Andric << " contains " << SymsOrErr->size() << " entries:\n"; 5043e8d8bef9SDimitry Andric OS << " Num: Name\n"; 50448bcb0991SDimitry Andric 5045e8d8bef9SDimitry Andric Field Fields[2] = {0, 8}; 5046e8d8bef9SDimitry Andric size_t SymIndex = 0; 5047e8d8bef9SDimitry Andric for (uint64_t Sym : *SymsOrErr) { 5048e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(++SymIndex, 6)) + ":"; 5049e8d8bef9SDimitry Andric Fields[1].Str = this->getStaticSymbolName(Sym); 5050e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 5051e8d8bef9SDimitry Andric printField(Entry); 5052e8d8bef9SDimitry Andric OS << "\n"; 50538bcb0991SDimitry Andric } 50540b57cec5SDimitry Andric } 50550b57cec5SDimitry Andric 50560b57cec5SDimitry Andric template <typename ELFT> 50570b57cec5SDimitry Andric static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, 50580b57cec5SDimitry Andric ArrayRef<uint8_t> Data) { 50590b57cec5SDimitry Andric std::string str; 50600b57cec5SDimitry Andric raw_string_ostream OS(str); 50610b57cec5SDimitry Andric uint32_t PrData; 50620b57cec5SDimitry Andric auto DumpBit = [&](uint32_t Flag, StringRef Name) { 50630b57cec5SDimitry Andric if (PrData & Flag) { 50640b57cec5SDimitry Andric PrData &= ~Flag; 50650b57cec5SDimitry Andric OS << Name; 50660b57cec5SDimitry Andric if (PrData) 50670b57cec5SDimitry Andric OS << ", "; 50680b57cec5SDimitry Andric } 50690b57cec5SDimitry Andric }; 50700b57cec5SDimitry Andric 50710b57cec5SDimitry Andric switch (Type) { 50720b57cec5SDimitry Andric default: 50730b57cec5SDimitry Andric OS << format("<application-specific type 0x%x>", Type); 50740b57cec5SDimitry Andric return OS.str(); 50750b57cec5SDimitry Andric case GNU_PROPERTY_STACK_SIZE: { 50760b57cec5SDimitry Andric OS << "stack size: "; 50770b57cec5SDimitry Andric if (DataSize == sizeof(typename ELFT::uint)) 50780b57cec5SDimitry Andric OS << formatv("{0:x}", 50790b57cec5SDimitry Andric (uint64_t)(*(const typename ELFT::Addr *)Data.data())); 50800b57cec5SDimitry Andric else 50810b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 50820b57cec5SDimitry Andric return OS.str(); 50830b57cec5SDimitry Andric } 50840b57cec5SDimitry Andric case GNU_PROPERTY_NO_COPY_ON_PROTECTED: 50850b57cec5SDimitry Andric OS << "no copy on protected"; 50860b57cec5SDimitry Andric if (DataSize) 50870b57cec5SDimitry Andric OS << format(" <corrupt length: 0x%x>", DataSize); 50880b57cec5SDimitry Andric return OS.str(); 50890b57cec5SDimitry Andric case GNU_PROPERTY_AARCH64_FEATURE_1_AND: 50900b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_1_AND: 50910b57cec5SDimitry Andric OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: " 50920b57cec5SDimitry Andric : "x86 feature: "); 50930b57cec5SDimitry Andric if (DataSize != 4) { 50940b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 50950b57cec5SDimitry Andric return OS.str(); 50960b57cec5SDimitry Andric } 50970b57cec5SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 50980b57cec5SDimitry Andric if (PrData == 0) { 50990b57cec5SDimitry Andric OS << "<None>"; 51000b57cec5SDimitry Andric return OS.str(); 51010b57cec5SDimitry Andric } 51020b57cec5SDimitry Andric if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { 51030b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI"); 51040b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC"); 51050b57cec5SDimitry Andric } else { 51060b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT"); 51070b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK"); 51080b57cec5SDimitry Andric } 51090b57cec5SDimitry Andric if (PrData) 51100b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 51110b57cec5SDimitry Andric return OS.str(); 51120b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_NEEDED: 51130b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_USED: 51140b57cec5SDimitry Andric OS << "x86 feature " 51150b57cec5SDimitry Andric << (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: "); 51160b57cec5SDimitry Andric if (DataSize != 4) { 51170b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 51180b57cec5SDimitry Andric return OS.str(); 51190b57cec5SDimitry Andric } 51200b57cec5SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 51210b57cec5SDimitry Andric if (PrData == 0) { 51220b57cec5SDimitry Andric OS << "<None>"; 51230b57cec5SDimitry Andric return OS.str(); 51240b57cec5SDimitry Andric } 51250b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86"); 51260b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87"); 51270b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX"); 51280b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM"); 51290b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM"); 51300b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM"); 51310b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR"); 51320b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE"); 51330b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT"); 51340b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC"); 51350b57cec5SDimitry Andric if (PrData) 51360b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 51370b57cec5SDimitry Andric return OS.str(); 5138fe6060f1SDimitry Andric case GNU_PROPERTY_X86_ISA_1_NEEDED: 5139fe6060f1SDimitry Andric case GNU_PROPERTY_X86_ISA_1_USED: 5140fe6060f1SDimitry Andric OS << "x86 ISA " 5141fe6060f1SDimitry Andric << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: "); 5142fe6060f1SDimitry Andric if (DataSize != 4) { 5143fe6060f1SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 5144fe6060f1SDimitry Andric return OS.str(); 5145fe6060f1SDimitry Andric } 5146fe6060f1SDimitry Andric PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); 5147fe6060f1SDimitry Andric if (PrData == 0) { 5148fe6060f1SDimitry Andric OS << "<None>"; 5149fe6060f1SDimitry Andric return OS.str(); 5150fe6060f1SDimitry Andric } 5151fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline"); 5152fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2"); 5153fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3"); 5154fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4"); 5155fe6060f1SDimitry Andric if (PrData) 5156fe6060f1SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 5157fe6060f1SDimitry Andric return OS.str(); 51580b57cec5SDimitry Andric } 51590b57cec5SDimitry Andric } 51600b57cec5SDimitry Andric 51610b57cec5SDimitry Andric template <typename ELFT> 51620b57cec5SDimitry Andric static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) { 51630b57cec5SDimitry Andric using Elf_Word = typename ELFT::Word; 51640b57cec5SDimitry Andric 51650b57cec5SDimitry Andric SmallVector<std::string, 4> Properties; 51660b57cec5SDimitry Andric while (Arr.size() >= 8) { 51670b57cec5SDimitry Andric uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); 51680b57cec5SDimitry Andric uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); 51690b57cec5SDimitry Andric Arr = Arr.drop_front(8); 51700b57cec5SDimitry Andric 51710b57cec5SDimitry Andric // Take padding size into account if present. 51720b57cec5SDimitry Andric uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); 51730b57cec5SDimitry Andric std::string str; 51740b57cec5SDimitry Andric raw_string_ostream OS(str); 51750b57cec5SDimitry Andric if (Arr.size() < PaddedSize) { 51760b57cec5SDimitry Andric OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize); 51770b57cec5SDimitry Andric Properties.push_back(OS.str()); 51780b57cec5SDimitry Andric break; 51790b57cec5SDimitry Andric } 51800b57cec5SDimitry Andric Properties.push_back( 51810b57cec5SDimitry Andric getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize))); 51820b57cec5SDimitry Andric Arr = Arr.drop_front(PaddedSize); 51830b57cec5SDimitry Andric } 51840b57cec5SDimitry Andric 51850b57cec5SDimitry Andric if (!Arr.empty()) 51860b57cec5SDimitry Andric Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>"); 51870b57cec5SDimitry Andric 51880b57cec5SDimitry Andric return Properties; 51890b57cec5SDimitry Andric } 51900b57cec5SDimitry Andric 51910b57cec5SDimitry Andric struct GNUAbiTag { 51920b57cec5SDimitry Andric std::string OSName; 51930b57cec5SDimitry Andric std::string ABI; 51940b57cec5SDimitry Andric bool IsValid; 51950b57cec5SDimitry Andric }; 51960b57cec5SDimitry Andric 51970b57cec5SDimitry Andric template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) { 51980b57cec5SDimitry Andric typedef typename ELFT::Word Elf_Word; 51990b57cec5SDimitry Andric 52000b57cec5SDimitry Andric ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()), 52010b57cec5SDimitry Andric reinterpret_cast<const Elf_Word *>(Desc.end())); 52020b57cec5SDimitry Andric 52030b57cec5SDimitry Andric if (Words.size() < 4) 52040b57cec5SDimitry Andric return {"", "", /*IsValid=*/false}; 52050b57cec5SDimitry Andric 52060b57cec5SDimitry Andric static const char *OSNames[] = { 52070b57cec5SDimitry Andric "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", 52080b57cec5SDimitry Andric }; 52090b57cec5SDimitry Andric StringRef OSName = "Unknown"; 5210bdd1243dSDimitry Andric if (Words[0] < std::size(OSNames)) 52110b57cec5SDimitry Andric OSName = OSNames[Words[0]]; 52120b57cec5SDimitry Andric uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; 52130b57cec5SDimitry Andric std::string str; 52140b57cec5SDimitry Andric raw_string_ostream ABI(str); 52150b57cec5SDimitry Andric ABI << Major << "." << Minor << "." << Patch; 52165ffd83dbSDimitry Andric return {std::string(OSName), ABI.str(), /*IsValid=*/true}; 52170b57cec5SDimitry Andric } 52180b57cec5SDimitry Andric 52190b57cec5SDimitry Andric static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) { 52200b57cec5SDimitry Andric std::string str; 52210b57cec5SDimitry Andric raw_string_ostream OS(str); 5222e8d8bef9SDimitry Andric for (uint8_t B : Desc) 52230b57cec5SDimitry Andric OS << format_hex_no_prefix(B, 2); 52240b57cec5SDimitry Andric return OS.str(); 52250b57cec5SDimitry Andric } 52260b57cec5SDimitry Andric 5227349cc55cSDimitry Andric static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) { 52280b57cec5SDimitry Andric return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 52290b57cec5SDimitry Andric } 52300b57cec5SDimitry Andric 52310b57cec5SDimitry Andric template <typename ELFT> 5232fe6060f1SDimitry Andric static bool printGNUNote(raw_ostream &OS, uint32_t NoteType, 52330b57cec5SDimitry Andric ArrayRef<uint8_t> Desc) { 5234fe6060f1SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 52350b57cec5SDimitry Andric switch (NoteType) { 52360b57cec5SDimitry Andric default: 5237fe6060f1SDimitry Andric return false; 52380b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 52390b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 52400b57cec5SDimitry Andric if (!AbiTag.IsValid) 52410b57cec5SDimitry Andric OS << " <corrupt GNU_ABI_TAG>"; 52420b57cec5SDimitry Andric else 52430b57cec5SDimitry Andric OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI; 52440b57cec5SDimitry Andric break; 52450b57cec5SDimitry Andric } 52460b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 52470b57cec5SDimitry Andric OS << " Build ID: " << getGNUBuildId(Desc); 52480b57cec5SDimitry Andric break; 52490b57cec5SDimitry Andric } 52500b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 5251349cc55cSDimitry Andric OS << " Version: " << getDescAsStringRef(Desc); 52520b57cec5SDimitry Andric break; 52530b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 52540b57cec5SDimitry Andric OS << " Properties:"; 5255e8d8bef9SDimitry Andric for (const std::string &Property : getGNUPropertyList<ELFT>(Desc)) 52560b57cec5SDimitry Andric OS << " " << Property << "\n"; 52570b57cec5SDimitry Andric break; 52580b57cec5SDimitry Andric } 52590b57cec5SDimitry Andric OS << '\n'; 5260fe6060f1SDimitry Andric return true; 5261fe6060f1SDimitry Andric } 5262fe6060f1SDimitry Andric 526381ad6265SDimitry Andric using AndroidNoteProperties = std::vector<std::pair<StringRef, std::string>>; 526481ad6265SDimitry Andric static AndroidNoteProperties getAndroidNoteProperties(uint32_t NoteType, 526581ad6265SDimitry Andric ArrayRef<uint8_t> Desc) { 526681ad6265SDimitry Andric AndroidNoteProperties Props; 526781ad6265SDimitry Andric switch (NoteType) { 526881ad6265SDimitry Andric case ELF::NT_ANDROID_TYPE_MEMTAG: 526981ad6265SDimitry Andric if (Desc.empty()) { 527081ad6265SDimitry Andric Props.emplace_back("Invalid .note.android.memtag", ""); 527181ad6265SDimitry Andric return Props; 527281ad6265SDimitry Andric } 527381ad6265SDimitry Andric 527481ad6265SDimitry Andric switch (Desc[0] & NT_MEMTAG_LEVEL_MASK) { 527581ad6265SDimitry Andric case NT_MEMTAG_LEVEL_NONE: 527681ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "NONE"); 527781ad6265SDimitry Andric break; 527881ad6265SDimitry Andric case NT_MEMTAG_LEVEL_ASYNC: 527981ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "ASYNC"); 528081ad6265SDimitry Andric break; 528181ad6265SDimitry Andric case NT_MEMTAG_LEVEL_SYNC: 528281ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "SYNC"); 528381ad6265SDimitry Andric break; 528481ad6265SDimitry Andric default: 528581ad6265SDimitry Andric Props.emplace_back( 528681ad6265SDimitry Andric "Tagging Mode", 528781ad6265SDimitry Andric ("Unknown (" + Twine::utohexstr(Desc[0] & NT_MEMTAG_LEVEL_MASK) + ")") 528881ad6265SDimitry Andric .str()); 528981ad6265SDimitry Andric break; 529081ad6265SDimitry Andric } 529181ad6265SDimitry Andric Props.emplace_back("Heap", 529281ad6265SDimitry Andric (Desc[0] & NT_MEMTAG_HEAP) ? "Enabled" : "Disabled"); 529381ad6265SDimitry Andric Props.emplace_back("Stack", 529481ad6265SDimitry Andric (Desc[0] & NT_MEMTAG_STACK) ? "Enabled" : "Disabled"); 529581ad6265SDimitry Andric break; 529681ad6265SDimitry Andric default: 529781ad6265SDimitry Andric return Props; 529881ad6265SDimitry Andric } 529981ad6265SDimitry Andric return Props; 530081ad6265SDimitry Andric } 530181ad6265SDimitry Andric 530281ad6265SDimitry Andric static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType, 530381ad6265SDimitry Andric ArrayRef<uint8_t> Desc) { 530481ad6265SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 530581ad6265SDimitry Andric AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc); 530681ad6265SDimitry Andric if (Props.empty()) 530781ad6265SDimitry Andric return false; 530881ad6265SDimitry Andric for (const auto &KV : Props) 530981ad6265SDimitry Andric OS << " " << KV.first << ": " << KV.second << '\n'; 531081ad6265SDimitry Andric return true; 531181ad6265SDimitry Andric } 531281ad6265SDimitry Andric 531306c3fb27SDimitry Andric template <class ELFT> 531406c3fb27SDimitry Andric void GNUELFDumper<ELFT>::printMemtag( 531506c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 531606c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 531706c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) { 531806c3fb27SDimitry Andric OS << "Memtag Dynamic Entries:\n"; 531906c3fb27SDimitry Andric if (DynamicEntries.empty()) 532006c3fb27SDimitry Andric OS << " < none found >\n"; 532106c3fb27SDimitry Andric for (const auto &DynamicEntryKV : DynamicEntries) 532206c3fb27SDimitry Andric OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second 532306c3fb27SDimitry Andric << "\n"; 532406c3fb27SDimitry Andric 532506c3fb27SDimitry Andric if (!AndroidNoteDesc.empty()) { 532606c3fb27SDimitry Andric OS << "Memtag Android Note:\n"; 532706c3fb27SDimitry Andric printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc); 532806c3fb27SDimitry Andric } 532906c3fb27SDimitry Andric 533006c3fb27SDimitry Andric if (Descriptors.empty()) 533106c3fb27SDimitry Andric return; 533206c3fb27SDimitry Andric 533306c3fb27SDimitry Andric OS << "Memtag Global Descriptors:\n"; 533406c3fb27SDimitry Andric for (const auto &[Addr, BytesToTag] : Descriptors) { 533506c3fb27SDimitry Andric OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x" 533606c3fb27SDimitry Andric << utohexstr(BytesToTag, /*LowerCase=*/true) << "\n"; 533706c3fb27SDimitry Andric } 533806c3fb27SDimitry Andric } 533906c3fb27SDimitry Andric 5340349cc55cSDimitry Andric template <typename ELFT> 5341349cc55cSDimitry Andric static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType, 5342349cc55cSDimitry Andric ArrayRef<uint8_t> Desc) { 5343349cc55cSDimitry Andric switch (NoteType) { 5344349cc55cSDimitry Andric default: 5345349cc55cSDimitry Andric return false; 5346349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION: 5347349cc55cSDimitry Andric OS << " Version: " << getDescAsStringRef(Desc); 5348349cc55cSDimitry Andric break; 5349349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER: 5350349cc55cSDimitry Andric OS << " Producer: " << getDescAsStringRef(Desc); 5351349cc55cSDimitry Andric break; 5352349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION: 5353349cc55cSDimitry Andric OS << " Producer version: " << getDescAsStringRef(Desc); 5354349cc55cSDimitry Andric break; 5355349cc55cSDimitry Andric } 5356349cc55cSDimitry Andric OS << '\n'; 5357349cc55cSDimitry Andric return true; 5358349cc55cSDimitry Andric } 5359349cc55cSDimitry Andric 5360349cc55cSDimitry Andric const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = { 5361fe6060f1SDimitry Andric {"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE}, 5362fe6060f1SDimitry Andric {"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE}, 5363fe6060f1SDimitry Andric {"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE}, 5364fe6060f1SDimitry Andric {"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED}, 5365fe6060f1SDimitry Andric {"LA48", NT_FREEBSD_FCTL_LA48}, 5366fe6060f1SDimitry Andric {"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE}, 5367fe6060f1SDimitry Andric }; 5368fe6060f1SDimitry Andric 5369fe6060f1SDimitry Andric struct FreeBSDNote { 5370fe6060f1SDimitry Andric std::string Type; 5371fe6060f1SDimitry Andric std::string Value; 5372fe6060f1SDimitry Andric }; 5373fe6060f1SDimitry Andric 5374fe6060f1SDimitry Andric template <typename ELFT> 5375bdd1243dSDimitry Andric static std::optional<FreeBSDNote> 5376fe6060f1SDimitry Andric getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) { 5377fe6060f1SDimitry Andric if (IsCore) 5378bdd1243dSDimitry Andric return std::nullopt; // No pretty-printing yet. 5379fe6060f1SDimitry Andric switch (NoteType) { 5380fe6060f1SDimitry Andric case ELF::NT_FREEBSD_ABI_TAG: 5381fe6060f1SDimitry Andric if (Desc.size() != 4) 5382bdd1243dSDimitry Andric return std::nullopt; 5383fe6060f1SDimitry Andric return FreeBSDNote{ 5384fe6060f1SDimitry Andric "ABI tag", 5385fe6060f1SDimitry Andric utostr(support::endian::read32<ELFT::TargetEndianness>(Desc.data()))}; 5386fe6060f1SDimitry Andric case ELF::NT_FREEBSD_ARCH_TAG: 5387fe6060f1SDimitry Andric return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; 5388fe6060f1SDimitry Andric case ELF::NT_FREEBSD_FEATURE_CTL: { 5389fe6060f1SDimitry Andric if (Desc.size() != 4) 5390bdd1243dSDimitry Andric return std::nullopt; 5391fe6060f1SDimitry Andric unsigned Value = 5392fe6060f1SDimitry Andric support::endian::read32<ELFT::TargetEndianness>(Desc.data()); 5393fe6060f1SDimitry Andric std::string FlagsStr; 5394fe6060f1SDimitry Andric raw_string_ostream OS(FlagsStr); 5395bdd1243dSDimitry Andric printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS); 5396fe6060f1SDimitry Andric if (OS.str().empty()) 5397fe6060f1SDimitry Andric OS << "0x" << utohexstr(Value); 5398fe6060f1SDimitry Andric else 5399fe6060f1SDimitry Andric OS << "(0x" << utohexstr(Value) << ")"; 5400fe6060f1SDimitry Andric return FreeBSDNote{"Feature flags", OS.str()}; 5401fe6060f1SDimitry Andric } 5402fe6060f1SDimitry Andric default: 5403bdd1243dSDimitry Andric return std::nullopt; 5404fe6060f1SDimitry Andric } 54050b57cec5SDimitry Andric } 54060b57cec5SDimitry Andric 54070b57cec5SDimitry Andric struct AMDNote { 54080b57cec5SDimitry Andric std::string Type; 54090b57cec5SDimitry Andric std::string Value; 54100b57cec5SDimitry Andric }; 54110b57cec5SDimitry Andric 54120b57cec5SDimitry Andric template <typename ELFT> 54130b57cec5SDimitry Andric static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 54140b57cec5SDimitry Andric switch (NoteType) { 54150b57cec5SDimitry Andric default: 54160b57cec5SDimitry Andric return {"", ""}; 5417fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: { 5418fe6060f1SDimitry Andric struct CodeObjectVersion { 5419fe6060f1SDimitry Andric uint32_t MajorVersion; 5420fe6060f1SDimitry Andric uint32_t MinorVersion; 5421fe6060f1SDimitry Andric }; 5422fe6060f1SDimitry Andric if (Desc.size() != sizeof(CodeObjectVersion)) 5423fe6060f1SDimitry Andric return {"AMD HSA Code Object Version", 5424fe6060f1SDimitry Andric "Invalid AMD HSA Code Object Version"}; 5425fe6060f1SDimitry Andric std::string VersionString; 5426fe6060f1SDimitry Andric raw_string_ostream StrOS(VersionString); 5427fe6060f1SDimitry Andric auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data()); 5428fe6060f1SDimitry Andric StrOS << "[Major: " << Version->MajorVersion 5429fe6060f1SDimitry Andric << ", Minor: " << Version->MinorVersion << "]"; 5430fe6060f1SDimitry Andric return {"AMD HSA Code Object Version", VersionString}; 5431fe6060f1SDimitry Andric } 5432fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_HSAIL: { 5433fe6060f1SDimitry Andric struct HSAILProperties { 5434fe6060f1SDimitry Andric uint32_t HSAILMajorVersion; 5435fe6060f1SDimitry Andric uint32_t HSAILMinorVersion; 5436fe6060f1SDimitry Andric uint8_t Profile; 5437fe6060f1SDimitry Andric uint8_t MachineModel; 5438fe6060f1SDimitry Andric uint8_t DefaultFloatRound; 5439fe6060f1SDimitry Andric }; 5440fe6060f1SDimitry Andric if (Desc.size() != sizeof(HSAILProperties)) 5441fe6060f1SDimitry Andric return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"}; 5442fe6060f1SDimitry Andric auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data()); 5443fe6060f1SDimitry Andric std::string HSAILPropetiesString; 5444fe6060f1SDimitry Andric raw_string_ostream StrOS(HSAILPropetiesString); 5445fe6060f1SDimitry Andric StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion 5446fe6060f1SDimitry Andric << ", HSAIL Minor: " << Properties->HSAILMinorVersion 5447fe6060f1SDimitry Andric << ", Profile: " << uint32_t(Properties->Profile) 5448fe6060f1SDimitry Andric << ", Machine Model: " << uint32_t(Properties->MachineModel) 5449fe6060f1SDimitry Andric << ", Default Float Round: " 5450fe6060f1SDimitry Andric << uint32_t(Properties->DefaultFloatRound) << "]"; 5451fe6060f1SDimitry Andric return {"AMD HSA HSAIL Properties", HSAILPropetiesString}; 5452fe6060f1SDimitry Andric } 5453fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_ISA_VERSION: { 5454fe6060f1SDimitry Andric struct IsaVersion { 5455fe6060f1SDimitry Andric uint16_t VendorNameSize; 5456fe6060f1SDimitry Andric uint16_t ArchitectureNameSize; 5457fe6060f1SDimitry Andric uint32_t Major; 5458fe6060f1SDimitry Andric uint32_t Minor; 5459fe6060f1SDimitry Andric uint32_t Stepping; 5460fe6060f1SDimitry Andric }; 5461fe6060f1SDimitry Andric if (Desc.size() < sizeof(IsaVersion)) 5462fe6060f1SDimitry Andric return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"}; 5463fe6060f1SDimitry Andric auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data()); 5464fe6060f1SDimitry Andric if (Desc.size() < sizeof(IsaVersion) + 5465fe6060f1SDimitry Andric Isa->VendorNameSize + Isa->ArchitectureNameSize || 5466fe6060f1SDimitry Andric Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0) 5467fe6060f1SDimitry Andric return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"}; 5468fe6060f1SDimitry Andric std::string IsaString; 5469fe6060f1SDimitry Andric raw_string_ostream StrOS(IsaString); 5470fe6060f1SDimitry Andric StrOS << "[Vendor: " 5471fe6060f1SDimitry Andric << StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1) 5472fe6060f1SDimitry Andric << ", Architecture: " 5473fe6060f1SDimitry Andric << StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize, 5474fe6060f1SDimitry Andric Isa->ArchitectureNameSize - 1) 5475fe6060f1SDimitry Andric << ", Major: " << Isa->Major << ", Minor: " << Isa->Minor 5476fe6060f1SDimitry Andric << ", Stepping: " << Isa->Stepping << "]"; 5477fe6060f1SDimitry Andric return {"AMD HSA ISA Version", IsaString}; 5478fe6060f1SDimitry Andric } 5479fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_METADATA: { 5480fe6060f1SDimitry Andric if (Desc.size() == 0) 5481fe6060f1SDimitry Andric return {"AMD HSA Metadata", ""}; 54820b57cec5SDimitry Andric return { 5483fe6060f1SDimitry Andric "AMD HSA Metadata", 5484fe6060f1SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)}; 5485fe6060f1SDimitry Andric } 5486fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_ISA_NAME: { 5487fe6060f1SDimitry Andric if (Desc.size() == 0) 5488fe6060f1SDimitry Andric return {"AMD HSA ISA Name", ""}; 54890b57cec5SDimitry Andric return { 5490fe6060f1SDimitry Andric "AMD HSA ISA Name", 54910b57cec5SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())}; 54920b57cec5SDimitry Andric } 5493fe6060f1SDimitry Andric case ELF::NT_AMD_PAL_METADATA: { 5494fe6060f1SDimitry Andric struct PALMetadata { 5495fe6060f1SDimitry Andric uint32_t Key; 5496fe6060f1SDimitry Andric uint32_t Value; 5497fe6060f1SDimitry Andric }; 5498fe6060f1SDimitry Andric if (Desc.size() % sizeof(PALMetadata) != 0) 5499fe6060f1SDimitry Andric return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"}; 5500fe6060f1SDimitry Andric auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data()); 5501fe6060f1SDimitry Andric std::string MetadataString; 5502fe6060f1SDimitry Andric raw_string_ostream StrOS(MetadataString); 5503fe6060f1SDimitry Andric for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) { 5504fe6060f1SDimitry Andric StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]"; 5505fe6060f1SDimitry Andric } 5506fe6060f1SDimitry Andric return {"AMD PAL Metadata", MetadataString}; 5507fe6060f1SDimitry Andric } 5508fe6060f1SDimitry Andric } 55090b57cec5SDimitry Andric } 55100b57cec5SDimitry Andric 55110b57cec5SDimitry Andric struct AMDGPUNote { 55120b57cec5SDimitry Andric std::string Type; 55130b57cec5SDimitry Andric std::string Value; 55140b57cec5SDimitry Andric }; 55150b57cec5SDimitry Andric 55160b57cec5SDimitry Andric template <typename ELFT> 55170b57cec5SDimitry Andric static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 55180b57cec5SDimitry Andric switch (NoteType) { 55190b57cec5SDimitry Andric default: 55200b57cec5SDimitry Andric return {"", ""}; 55210b57cec5SDimitry Andric case ELF::NT_AMDGPU_METADATA: { 5522e8d8bef9SDimitry Andric StringRef MsgPackString = 55230b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 55240b57cec5SDimitry Andric msgpack::Document MsgPackDoc; 55250b57cec5SDimitry Andric if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false)) 5526fe6060f1SDimitry Andric return {"", ""}; 55270b57cec5SDimitry Andric 5528fe6060f1SDimitry Andric std::string MetadataString; 552906c3fb27SDimitry Andric 553006c3fb27SDimitry Andric // FIXME: Metadata Verifier only works with AMDHSA. 553106c3fb27SDimitry Andric // This is an ugly workaround to avoid the verifier for other MD 553206c3fb27SDimitry Andric // formats (e.g. amdpal) 553306c3fb27SDimitry Andric if (MsgPackString.find("amdhsa.") != StringRef::npos) { 553406c3fb27SDimitry Andric AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true); 5535e8d8bef9SDimitry Andric if (!Verifier.verify(MsgPackDoc.getRoot())) 5536fe6060f1SDimitry Andric MetadataString = "Invalid AMDGPU Metadata\n"; 553706c3fb27SDimitry Andric } 5538e8d8bef9SDimitry Andric 5539fe6060f1SDimitry Andric raw_string_ostream StrOS(MetadataString); 5540fe6060f1SDimitry Andric if (MsgPackDoc.getRoot().isScalar()) { 5541fe6060f1SDimitry Andric // TODO: passing a scalar root to toYAML() asserts: 5542fe6060f1SDimitry Andric // (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && 5543fe6060f1SDimitry Andric // "plain scalar documents are not supported") 5544fe6060f1SDimitry Andric // To avoid this crash we print the raw data instead. 5545fe6060f1SDimitry Andric return {"", ""}; 5546fe6060f1SDimitry Andric } 55470b57cec5SDimitry Andric MsgPackDoc.toYAML(StrOS); 55480b57cec5SDimitry Andric return {"AMDGPU Metadata", StrOS.str()}; 55490b57cec5SDimitry Andric } 55500b57cec5SDimitry Andric } 55510b57cec5SDimitry Andric } 55520b57cec5SDimitry Andric 55538bcb0991SDimitry Andric struct CoreFileMapping { 55548bcb0991SDimitry Andric uint64_t Start, End, Offset; 55558bcb0991SDimitry Andric StringRef Filename; 55568bcb0991SDimitry Andric }; 55578bcb0991SDimitry Andric 55588bcb0991SDimitry Andric struct CoreNote { 55598bcb0991SDimitry Andric uint64_t PageSize; 55608bcb0991SDimitry Andric std::vector<CoreFileMapping> Mappings; 55618bcb0991SDimitry Andric }; 55628bcb0991SDimitry Andric 55638bcb0991SDimitry Andric static Expected<CoreNote> readCoreNote(DataExtractor Desc) { 55648bcb0991SDimitry Andric // Expected format of the NT_FILE note description: 55658bcb0991SDimitry Andric // 1. # of file mappings (call it N) 55668bcb0991SDimitry Andric // 2. Page size 55678bcb0991SDimitry Andric // 3. N (start, end, offset) triples 55688bcb0991SDimitry Andric // 4. N packed filenames (null delimited) 55698bcb0991SDimitry Andric // Each field is an Elf_Addr, except for filenames which are char* strings. 55708bcb0991SDimitry Andric 55718bcb0991SDimitry Andric CoreNote Ret; 55728bcb0991SDimitry Andric const int Bytes = Desc.getAddressSize(); 55738bcb0991SDimitry Andric 55748bcb0991SDimitry Andric if (!Desc.isValidOffsetForAddress(2)) 5575e8d8bef9SDimitry Andric return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) + 5576e8d8bef9SDimitry Andric " is too short, expected at least 0x" + 5577e8d8bef9SDimitry Andric Twine::utohexstr(Bytes * 2)); 55788bcb0991SDimitry Andric if (Desc.getData().back() != 0) 5579e8d8bef9SDimitry Andric return createError("the note is not NUL terminated"); 55808bcb0991SDimitry Andric 55818bcb0991SDimitry Andric uint64_t DescOffset = 0; 55828bcb0991SDimitry Andric uint64_t FileCount = Desc.getAddress(&DescOffset); 55838bcb0991SDimitry Andric Ret.PageSize = Desc.getAddress(&DescOffset); 55848bcb0991SDimitry Andric 55858bcb0991SDimitry Andric if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes)) 5586e8d8bef9SDimitry Andric return createError("unable to read file mappings (found " + 5587e8d8bef9SDimitry Andric Twine(FileCount) + "): the note of size 0x" + 5588e8d8bef9SDimitry Andric Twine::utohexstr(Desc.size()) + " is too short"); 55898bcb0991SDimitry Andric 55908bcb0991SDimitry Andric uint64_t FilenamesOffset = 0; 55918bcb0991SDimitry Andric DataExtractor Filenames( 55928bcb0991SDimitry Andric Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes), 55938bcb0991SDimitry Andric Desc.isLittleEndian(), Desc.getAddressSize()); 55948bcb0991SDimitry Andric 55958bcb0991SDimitry Andric Ret.Mappings.resize(FileCount); 5596e8d8bef9SDimitry Andric size_t I = 0; 55978bcb0991SDimitry Andric for (CoreFileMapping &Mapping : Ret.Mappings) { 5598e8d8bef9SDimitry Andric ++I; 55998bcb0991SDimitry Andric if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1)) 5600e8d8bef9SDimitry Andric return createError( 5601e8d8bef9SDimitry Andric "unable to read the file name for the mapping with index " + 5602e8d8bef9SDimitry Andric Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) + 5603e8d8bef9SDimitry Andric " is truncated"); 56048bcb0991SDimitry Andric Mapping.Start = Desc.getAddress(&DescOffset); 56058bcb0991SDimitry Andric Mapping.End = Desc.getAddress(&DescOffset); 56068bcb0991SDimitry Andric Mapping.Offset = Desc.getAddress(&DescOffset); 56078bcb0991SDimitry Andric Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset); 56088bcb0991SDimitry Andric } 56098bcb0991SDimitry Andric 56108bcb0991SDimitry Andric return Ret; 56118bcb0991SDimitry Andric } 56128bcb0991SDimitry Andric 56138bcb0991SDimitry Andric template <typename ELFT> 56148bcb0991SDimitry Andric static void printCoreNote(raw_ostream &OS, const CoreNote &Note) { 56158bcb0991SDimitry Andric // Length of "0x<address>" string. 56168bcb0991SDimitry Andric const int FieldWidth = ELFT::Is64Bits ? 18 : 10; 56178bcb0991SDimitry Andric 56188bcb0991SDimitry Andric OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n'; 56198bcb0991SDimitry Andric OS << " " << right_justify("Start", FieldWidth) << " " 56208bcb0991SDimitry Andric << right_justify("End", FieldWidth) << " " 56218bcb0991SDimitry Andric << right_justify("Page Offset", FieldWidth) << '\n'; 56228bcb0991SDimitry Andric for (const CoreFileMapping &Mapping : Note.Mappings) { 56238bcb0991SDimitry Andric OS << " " << format_hex(Mapping.Start, FieldWidth) << " " 56248bcb0991SDimitry Andric << format_hex(Mapping.End, FieldWidth) << " " 56258bcb0991SDimitry Andric << format_hex(Mapping.Offset, FieldWidth) << "\n " 56268bcb0991SDimitry Andric << Mapping.Filename << '\n'; 56278bcb0991SDimitry Andric } 56288bcb0991SDimitry Andric } 56298bcb0991SDimitry Andric 5630349cc55cSDimitry Andric const NoteType GenericNoteTypes[] = { 5631e8d8bef9SDimitry Andric {ELF::NT_VERSION, "NT_VERSION (version)"}, 5632e8d8bef9SDimitry Andric {ELF::NT_ARCH, "NT_ARCH (architecture)"}, 5633e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"}, 5634e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"}, 5635e8d8bef9SDimitry Andric }; 5636e8d8bef9SDimitry Andric 5637349cc55cSDimitry Andric const NoteType GNUNoteTypes[] = { 5638e8d8bef9SDimitry Andric {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, 5639e8d8bef9SDimitry Andric {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, 5640e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, 5641e8d8bef9SDimitry Andric {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, 5642e8d8bef9SDimitry Andric {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, 5643e8d8bef9SDimitry Andric }; 5644e8d8bef9SDimitry Andric 5645349cc55cSDimitry Andric const NoteType FreeBSDCoreNoteTypes[] = { 5646e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, 5647e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, 5648e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, 5649e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, 5650e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, 5651e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, 5652e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, 5653e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, 5654e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, 5655e8d8bef9SDimitry Andric "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, 5656e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, 5657e8d8bef9SDimitry Andric }; 5658e8d8bef9SDimitry Andric 5659349cc55cSDimitry Andric const NoteType FreeBSDNoteTypes[] = { 5660fe6060f1SDimitry Andric {ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"}, 5661fe6060f1SDimitry Andric {ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"}, 5662fe6060f1SDimitry Andric {ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"}, 5663fe6060f1SDimitry Andric {ELF::NT_FREEBSD_FEATURE_CTL, 5664fe6060f1SDimitry Andric "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"}, 5665fe6060f1SDimitry Andric }; 5666fe6060f1SDimitry Andric 56674824e7fdSDimitry Andric const NoteType NetBSDCoreNoteTypes[] = { 56684824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_PROCINFO, 56694824e7fdSDimitry Andric "NT_NETBSDCORE_PROCINFO (procinfo structure)"}, 56704824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"}, 56714824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"}, 56724824e7fdSDimitry Andric }; 56734824e7fdSDimitry Andric 5674349cc55cSDimitry Andric const NoteType OpenBSDCoreNoteTypes[] = { 5675349cc55cSDimitry Andric {ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"}, 5676349cc55cSDimitry Andric {ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"}, 5677349cc55cSDimitry Andric {ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"}, 5678349cc55cSDimitry Andric {ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"}, 5679349cc55cSDimitry Andric {ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"}, 5680349cc55cSDimitry Andric }; 5681349cc55cSDimitry Andric 5682349cc55cSDimitry Andric const NoteType AMDNoteTypes[] = { 5683fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_CODE_OBJECT_VERSION, 5684fe6060f1SDimitry Andric "NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"}, 5685fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"}, 5686fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"}, 5687fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"}, 5688fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"}, 5689fe6060f1SDimitry Andric {ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"}, 5690e8d8bef9SDimitry Andric }; 5691e8d8bef9SDimitry Andric 5692349cc55cSDimitry Andric const NoteType AMDGPUNoteTypes[] = { 5693e8d8bef9SDimitry Andric {ELF::NT_AMDGPU_METADATA, "NT_AMDGPU_METADATA (AMDGPU Metadata)"}, 5694e8d8bef9SDimitry Andric }; 5695e8d8bef9SDimitry Andric 5696349cc55cSDimitry Andric const NoteType LLVMOMPOFFLOADNoteTypes[] = { 5697349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION, 5698349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_VERSION (image format version)"}, 5699349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER, 5700349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_PRODUCER (producing toolchain)"}, 5701349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION, 5702349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION (producing toolchain version)"}, 5703349cc55cSDimitry Andric }; 5704349cc55cSDimitry Andric 570581ad6265SDimitry Andric const NoteType AndroidNoteTypes[] = { 570681ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_IDENT, "NT_ANDROID_TYPE_IDENT"}, 570781ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_KUSER, "NT_ANDROID_TYPE_KUSER"}, 570881ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_MEMTAG, 570981ad6265SDimitry Andric "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"}, 571081ad6265SDimitry Andric }; 571181ad6265SDimitry Andric 5712349cc55cSDimitry Andric const NoteType CoreNoteTypes[] = { 5713e8d8bef9SDimitry Andric {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"}, 5714e8d8bef9SDimitry Andric {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"}, 5715e8d8bef9SDimitry Andric {ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"}, 5716e8d8bef9SDimitry Andric {ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"}, 5717e8d8bef9SDimitry Andric {ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"}, 5718e8d8bef9SDimitry Andric {ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"}, 5719e8d8bef9SDimitry Andric {ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"}, 5720e8d8bef9SDimitry Andric {ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"}, 5721e8d8bef9SDimitry Andric {ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"}, 5722e8d8bef9SDimitry Andric {ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"}, 5723e8d8bef9SDimitry Andric {ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"}, 5724e8d8bef9SDimitry Andric 5725e8d8bef9SDimitry Andric {ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"}, 5726e8d8bef9SDimitry Andric {ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"}, 5727e8d8bef9SDimitry Andric {ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"}, 5728e8d8bef9SDimitry Andric {ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"}, 5729e8d8bef9SDimitry Andric {ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"}, 5730e8d8bef9SDimitry Andric {ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"}, 5731e8d8bef9SDimitry Andric {ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"}, 5732e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"}, 5733e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CFPR, 5734e8d8bef9SDimitry Andric "NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"}, 5735e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CVMX, 5736e8d8bef9SDimitry Andric "NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"}, 5737e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"}, 5738e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"}, 5739e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"}, 5740e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"}, 5741e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"}, 5742e8d8bef9SDimitry Andric 5743e8d8bef9SDimitry Andric {ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"}, 5744e8d8bef9SDimitry Andric {ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"}, 5745e8d8bef9SDimitry Andric {ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"}, 5746e8d8bef9SDimitry Andric 5747e8d8bef9SDimitry Andric {ELF::NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS (s390 upper register halves)"}, 5748e8d8bef9SDimitry Andric {ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"}, 5749e8d8bef9SDimitry Andric {ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"}, 5750e8d8bef9SDimitry Andric {ELF::NT_S390_TODPREG, "NT_S390_TODPREG (s390 TOD programmable register)"}, 5751e8d8bef9SDimitry Andric {ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"}, 5752e8d8bef9SDimitry Andric {ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"}, 5753e8d8bef9SDimitry Andric {ELF::NT_S390_LAST_BREAK, 5754e8d8bef9SDimitry Andric "NT_S390_LAST_BREAK (s390 last breaking event address)"}, 5755e8d8bef9SDimitry Andric {ELF::NT_S390_SYSTEM_CALL, 5756e8d8bef9SDimitry Andric "NT_S390_SYSTEM_CALL (s390 system call restart data)"}, 5757e8d8bef9SDimitry Andric {ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"}, 5758e8d8bef9SDimitry Andric {ELF::NT_S390_VXRS_LOW, 5759e8d8bef9SDimitry Andric "NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"}, 5760e8d8bef9SDimitry Andric {ELF::NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"}, 5761e8d8bef9SDimitry Andric {ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"}, 5762e8d8bef9SDimitry Andric {ELF::NT_S390_GS_BC, 5763e8d8bef9SDimitry Andric "NT_S390_GS_BC (s390 guarded-storage broadcast control)"}, 5764e8d8bef9SDimitry Andric 5765e8d8bef9SDimitry Andric {ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"}, 5766e8d8bef9SDimitry Andric {ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"}, 5767e8d8bef9SDimitry Andric {ELF::NT_ARM_HW_BREAK, 5768e8d8bef9SDimitry Andric "NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"}, 5769e8d8bef9SDimitry Andric {ELF::NT_ARM_HW_WATCH, 5770e8d8bef9SDimitry Andric "NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"}, 577106c3fb27SDimitry Andric {ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"}, 577206c3fb27SDimitry Andric {ELF::NT_ARM_PAC_MASK, 577306c3fb27SDimitry Andric "NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"}, 577406c3fb27SDimitry Andric {ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"}, 577506c3fb27SDimitry Andric {ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"}, 577606c3fb27SDimitry Andric {ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"}, 5777e8d8bef9SDimitry Andric 5778e8d8bef9SDimitry Andric {ELF::NT_FILE, "NT_FILE (mapped files)"}, 5779e8d8bef9SDimitry Andric {ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"}, 5780e8d8bef9SDimitry Andric {ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"}, 5781e8d8bef9SDimitry Andric }; 5782e8d8bef9SDimitry Andric 57830b57cec5SDimitry Andric template <class ELFT> 5784fe6060f1SDimitry Andric StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) { 5785e8d8bef9SDimitry Andric uint32_t Type = Note.getType(); 5786e8d8bef9SDimitry Andric auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef { 5787e8d8bef9SDimitry Andric for (const NoteType &N : V) 5788e8d8bef9SDimitry Andric if (N.ID == Type) 5789e8d8bef9SDimitry Andric return N.Name; 5790e8d8bef9SDimitry Andric return ""; 5791e8d8bef9SDimitry Andric }; 5792e8d8bef9SDimitry Andric 5793e8d8bef9SDimitry Andric StringRef Name = Note.getName(); 5794e8d8bef9SDimitry Andric if (Name == "GNU") 5795e8d8bef9SDimitry Andric return FindNote(GNUNoteTypes); 5796fe6060f1SDimitry Andric if (Name == "FreeBSD") { 5797fe6060f1SDimitry Andric if (ELFType == ELF::ET_CORE) { 5798fe6060f1SDimitry Andric // FreeBSD also places the generic core notes in the FreeBSD namespace. 5799fe6060f1SDimitry Andric StringRef Result = FindNote(FreeBSDCoreNoteTypes); 5800fe6060f1SDimitry Andric if (!Result.empty()) 5801fe6060f1SDimitry Andric return Result; 5802fe6060f1SDimitry Andric return FindNote(CoreNoteTypes); 5803fe6060f1SDimitry Andric } else { 5804e8d8bef9SDimitry Andric return FindNote(FreeBSDNoteTypes); 5805fe6060f1SDimitry Andric } 5806fe6060f1SDimitry Andric } 58074824e7fdSDimitry Andric if (ELFType == ELF::ET_CORE && Name.startswith("NetBSD-CORE")) { 58084824e7fdSDimitry Andric StringRef Result = FindNote(NetBSDCoreNoteTypes); 58094824e7fdSDimitry Andric if (!Result.empty()) 58104824e7fdSDimitry Andric return Result; 58114824e7fdSDimitry Andric return FindNote(CoreNoteTypes); 58124824e7fdSDimitry Andric } 58130eae32dcSDimitry Andric if (ELFType == ELF::ET_CORE && Name.startswith("OpenBSD")) { 5814349cc55cSDimitry Andric // OpenBSD also places the generic core notes in the OpenBSD namespace. 5815349cc55cSDimitry Andric StringRef Result = FindNote(OpenBSDCoreNoteTypes); 5816349cc55cSDimitry Andric if (!Result.empty()) 5817349cc55cSDimitry Andric return Result; 5818349cc55cSDimitry Andric return FindNote(CoreNoteTypes); 5819349cc55cSDimitry Andric } 5820e8d8bef9SDimitry Andric if (Name == "AMD") 5821e8d8bef9SDimitry Andric return FindNote(AMDNoteTypes); 5822e8d8bef9SDimitry Andric if (Name == "AMDGPU") 5823e8d8bef9SDimitry Andric return FindNote(AMDGPUNoteTypes); 5824349cc55cSDimitry Andric if (Name == "LLVMOMPOFFLOAD") 5825349cc55cSDimitry Andric return FindNote(LLVMOMPOFFLOADNoteTypes); 582681ad6265SDimitry Andric if (Name == "Android") 582781ad6265SDimitry Andric return FindNote(AndroidNoteTypes); 5828e8d8bef9SDimitry Andric 5829e8d8bef9SDimitry Andric if (ELFType == ELF::ET_CORE) 5830e8d8bef9SDimitry Andric return FindNote(CoreNoteTypes); 5831e8d8bef9SDimitry Andric return FindNote(GenericNoteTypes); 5832e8d8bef9SDimitry Andric } 5833e8d8bef9SDimitry Andric 5834e8d8bef9SDimitry Andric template <class ELFT> 583506c3fb27SDimitry Andric static void processNotesHelper( 5836e8d8bef9SDimitry Andric const ELFDumper<ELFT> &Dumper, 5837bdd1243dSDimitry Andric llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off, 583806c3fb27SDimitry Andric typename ELFT::Addr, size_t)> 5839e8d8bef9SDimitry Andric StartNotesFn, 5840fe6060f1SDimitry Andric llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn, 5841e8d8bef9SDimitry Andric llvm::function_ref<void()> FinishNotesFn) { 5842e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 5843fe6060f1SDimitry Andric bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE; 5844e8d8bef9SDimitry Andric 5845e8d8bef9SDimitry Andric ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections()); 5846fe6060f1SDimitry Andric if (!IsCoreFile && !Sections.empty()) { 5847e8d8bef9SDimitry Andric for (const typename ELFT::Shdr &S : Sections) { 5848e8d8bef9SDimitry Andric if (S.sh_type != SHT_NOTE) 5849e8d8bef9SDimitry Andric continue; 5850bdd1243dSDimitry Andric StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset, 585106c3fb27SDimitry Andric S.sh_size, S.sh_addralign); 5852e8d8bef9SDimitry Andric Error Err = Error::success(); 5853e8d8bef9SDimitry Andric size_t I = 0; 5854e8d8bef9SDimitry Andric for (const typename ELFT::Note Note : Obj.notes(S, Err)) { 5855fe6060f1SDimitry Andric if (Error E = ProcessNoteFn(Note, IsCoreFile)) 5856e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 5857e8d8bef9SDimitry Andric "unable to read note with index " + Twine(I) + " from the " + 5858e8d8bef9SDimitry Andric describe(Obj, S) + ": " + toString(std::move(E))); 5859e8d8bef9SDimitry Andric ++I; 5860e8d8bef9SDimitry Andric } 5861e8d8bef9SDimitry Andric if (Err) 5862e8d8bef9SDimitry Andric Dumper.reportUniqueWarning("unable to read notes from the " + 5863e8d8bef9SDimitry Andric describe(Obj, S) + ": " + 5864e8d8bef9SDimitry Andric toString(std::move(Err))); 5865e8d8bef9SDimitry Andric FinishNotesFn(); 5866e8d8bef9SDimitry Andric } 5867e8d8bef9SDimitry Andric return; 5868e8d8bef9SDimitry Andric } 5869e8d8bef9SDimitry Andric 5870e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Phdr>> PhdrsOrErr = Obj.program_headers(); 5871e8d8bef9SDimitry Andric if (!PhdrsOrErr) { 5872e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 5873e8d8bef9SDimitry Andric "unable to read program headers to locate the PT_NOTE segment: " + 5874e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 5875e8d8bef9SDimitry Andric return; 5876e8d8bef9SDimitry Andric } 5877e8d8bef9SDimitry Andric 5878e8d8bef9SDimitry Andric for (size_t I = 0, E = (*PhdrsOrErr).size(); I != E; ++I) { 5879e8d8bef9SDimitry Andric const typename ELFT::Phdr &P = (*PhdrsOrErr)[I]; 5880e8d8bef9SDimitry Andric if (P.p_type != PT_NOTE) 5881e8d8bef9SDimitry Andric continue; 588206c3fb27SDimitry Andric StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align); 5883e8d8bef9SDimitry Andric Error Err = Error::success(); 5884e8d8bef9SDimitry Andric size_t Index = 0; 5885e8d8bef9SDimitry Andric for (const typename ELFT::Note Note : Obj.notes(P, Err)) { 5886fe6060f1SDimitry Andric if (Error E = ProcessNoteFn(Note, IsCoreFile)) 5887e8d8bef9SDimitry Andric Dumper.reportUniqueWarning("unable to read note with index " + 5888e8d8bef9SDimitry Andric Twine(Index) + 5889e8d8bef9SDimitry Andric " from the PT_NOTE segment with index " + 5890e8d8bef9SDimitry Andric Twine(I) + ": " + toString(std::move(E))); 5891e8d8bef9SDimitry Andric ++Index; 5892e8d8bef9SDimitry Andric } 5893e8d8bef9SDimitry Andric if (Err) 5894e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 5895e8d8bef9SDimitry Andric "unable to read notes from the PT_NOTE segment with index " + 5896e8d8bef9SDimitry Andric Twine(I) + ": " + toString(std::move(Err))); 5897e8d8bef9SDimitry Andric FinishNotesFn(); 5898e8d8bef9SDimitry Andric } 5899e8d8bef9SDimitry Andric } 5900e8d8bef9SDimitry Andric 5901e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printNotes() { 590206c3fb27SDimitry Andric size_t Align = 0; 5903fe6060f1SDimitry Andric bool IsFirstHeader = true; 5904bdd1243dSDimitry Andric auto PrintHeader = [&](std::optional<StringRef> SecName, 59055ffd83dbSDimitry Andric const typename ELFT::Off Offset, 590606c3fb27SDimitry Andric const typename ELFT::Addr Size, size_t Al) { 590706c3fb27SDimitry Andric Align = std::max<size_t>(Al, 4); 5908fe6060f1SDimitry Andric // Print a newline between notes sections to match GNU readelf. 5909fe6060f1SDimitry Andric if (!IsFirstHeader) { 5910fe6060f1SDimitry Andric OS << '\n'; 5911fe6060f1SDimitry Andric } else { 5912fe6060f1SDimitry Andric IsFirstHeader = false; 5913fe6060f1SDimitry Andric } 5914fe6060f1SDimitry Andric 59155ffd83dbSDimitry Andric OS << "Displaying notes found "; 59165ffd83dbSDimitry Andric 59175ffd83dbSDimitry Andric if (SecName) 59185ffd83dbSDimitry Andric OS << "in: " << *SecName << "\n"; 59195ffd83dbSDimitry Andric else 59205ffd83dbSDimitry Andric OS << "at file offset " << format_hex(Offset, 10) << " with length " 59215ffd83dbSDimitry Andric << format_hex(Size, 10) << ":\n"; 59225ffd83dbSDimitry Andric 59235ffd83dbSDimitry Andric OS << " Owner Data size \tDescription\n"; 59240b57cec5SDimitry Andric }; 59250b57cec5SDimitry Andric 5926fe6060f1SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 59270b57cec5SDimitry Andric StringRef Name = Note.getName(); 592806c3fb27SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(Align); 59290b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 59300b57cec5SDimitry Andric 59318bcb0991SDimitry Andric // Print the note owner/type. 59328bcb0991SDimitry Andric OS << " " << left_justify(Name, 20) << ' ' 59330b57cec5SDimitry Andric << format_hex(Descriptor.size(), 10) << '\t'; 5934e8d8bef9SDimitry Andric 5935e8d8bef9SDimitry Andric StringRef NoteType = 5936e8d8bef9SDimitry Andric getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type); 59378bcb0991SDimitry Andric if (!NoteType.empty()) 59388bcb0991SDimitry Andric OS << NoteType << '\n'; 59398bcb0991SDimitry Andric else 59408bcb0991SDimitry Andric OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n"; 59418bcb0991SDimitry Andric 59428bcb0991SDimitry Andric // Print the description, or fallback to printing raw bytes for unknown 5943fe6060f1SDimitry Andric // owners/if we fail to pretty-print the contents. 59448bcb0991SDimitry Andric if (Name == "GNU") { 5945fe6060f1SDimitry Andric if (printGNUNote<ELFT>(OS, Type, Descriptor)) 5946fe6060f1SDimitry Andric return Error::success(); 5947fe6060f1SDimitry Andric } else if (Name == "FreeBSD") { 5948bdd1243dSDimitry Andric if (std::optional<FreeBSDNote> N = 5949fe6060f1SDimitry Andric getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) { 5950fe6060f1SDimitry Andric OS << " " << N->Type << ": " << N->Value << '\n'; 5951fe6060f1SDimitry Andric return Error::success(); 5952fe6060f1SDimitry Andric } 59538bcb0991SDimitry Andric } else if (Name == "AMD") { 59540b57cec5SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 5955fe6060f1SDimitry Andric if (!N.Type.empty()) { 59560b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 5957fe6060f1SDimitry Andric return Error::success(); 5958fe6060f1SDimitry Andric } 59590b57cec5SDimitry Andric } else if (Name == "AMDGPU") { 59600b57cec5SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 5961fe6060f1SDimitry Andric if (!N.Type.empty()) { 59620b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 5963fe6060f1SDimitry Andric return Error::success(); 5964fe6060f1SDimitry Andric } 5965349cc55cSDimitry Andric } else if (Name == "LLVMOMPOFFLOAD") { 5966349cc55cSDimitry Andric if (printLLVMOMPOFFLOADNote<ELFT>(OS, Type, Descriptor)) 5967349cc55cSDimitry Andric return Error::success(); 59688bcb0991SDimitry Andric } else if (Name == "CORE") { 59698bcb0991SDimitry Andric if (Type == ELF::NT_FILE) { 59708bcb0991SDimitry Andric DataExtractor DescExtractor(Descriptor, 59718bcb0991SDimitry Andric ELFT::TargetEndianness == support::little, 59728bcb0991SDimitry Andric sizeof(Elf_Addr)); 5973fe6060f1SDimitry Andric if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) { 5974e8d8bef9SDimitry Andric printCoreNote<ELFT>(OS, *NoteOrErr); 5975fe6060f1SDimitry Andric return Error::success(); 5976fe6060f1SDimitry Andric } else { 5977e8d8bef9SDimitry Andric return NoteOrErr.takeError(); 59780b57cec5SDimitry Andric } 5979fe6060f1SDimitry Andric } 598081ad6265SDimitry Andric } else if (Name == "Android") { 598181ad6265SDimitry Andric if (printAndroidNote(OS, Type, Descriptor)) 598281ad6265SDimitry Andric return Error::success(); 5983fe6060f1SDimitry Andric } 5984fe6060f1SDimitry Andric if (!Descriptor.empty()) { 59858bcb0991SDimitry Andric OS << " description data:"; 59868bcb0991SDimitry Andric for (uint8_t B : Descriptor) 59878bcb0991SDimitry Andric OS << " " << format("%02x", B); 59880b57cec5SDimitry Andric OS << '\n'; 59898bcb0991SDimitry Andric } 5990e8d8bef9SDimitry Andric return Error::success(); 59910b57cec5SDimitry Andric }; 59920b57cec5SDimitry Andric 599306c3fb27SDimitry Andric processNotesHelper(*this, /*StartNotesFn=*/PrintHeader, 599406c3fb27SDimitry Andric /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {}); 599506c3fb27SDimitry Andric } 599606c3fb27SDimitry Andric 599706c3fb27SDimitry Andric template <class ELFT> 599806c3fb27SDimitry Andric ArrayRef<uint8_t> 599906c3fb27SDimitry Andric ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) { 600006c3fb27SDimitry Andric for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) { 600106c3fb27SDimitry Andric if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC) 600206c3fb27SDimitry Andric continue; 600306c3fb27SDimitry Andric if (Sec.sh_addr != ExpectedAddr) { 600406c3fb27SDimitry Andric reportUniqueWarning( 600506c3fb27SDimitry Andric "SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" + 600606c3fb27SDimitry Andric Twine::utohexstr(Sec.sh_addr) + 600706c3fb27SDimitry Andric ", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" + 600806c3fb27SDimitry Andric Twine::utohexstr(ExpectedAddr)); 600906c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 601006c3fb27SDimitry Andric } 601106c3fb27SDimitry Andric Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec); 601206c3fb27SDimitry Andric if (auto E = Contents.takeError()) { 601306c3fb27SDimitry Andric reportUniqueWarning( 601406c3fb27SDimitry Andric "couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " + 601506c3fb27SDimitry Andric toString(std::move(E))); 601606c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 601706c3fb27SDimitry Andric } 601806c3fb27SDimitry Andric return Contents.get(); 601906c3fb27SDimitry Andric } 602006c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 602106c3fb27SDimitry Andric } 602206c3fb27SDimitry Andric 602306c3fb27SDimitry Andric // Reserve the lower three bits of the first byte of the step distance when 602406c3fb27SDimitry Andric // encoding the memtag descriptors. Found to be the best overall size tradeoff 602506c3fb27SDimitry Andric // when compiling Android T with full MTE globals enabled. 602606c3fb27SDimitry Andric constexpr uint64_t MemtagStepVarintReservedBits = 3; 602706c3fb27SDimitry Andric constexpr uint64_t MemtagGranuleSize = 16; 602806c3fb27SDimitry Andric 602906c3fb27SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printMemtag() { 603006c3fb27SDimitry Andric if (Obj.getHeader().e_machine != EM_AARCH64) return; 603106c3fb27SDimitry Andric std::vector<std::pair<std::string, std::string>> DynamicEntries; 603206c3fb27SDimitry Andric uint64_t MemtagGlobalsSz = 0; 603306c3fb27SDimitry Andric uint64_t MemtagGlobals = 0; 603406c3fb27SDimitry Andric for (const typename ELFT::Dyn &Entry : dynamic_table()) { 603506c3fb27SDimitry Andric uintX_t Tag = Entry.getTag(); 603606c3fb27SDimitry Andric switch (Tag) { 603706c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALSSZ: 603806c3fb27SDimitry Andric MemtagGlobalsSz = Entry.getVal(); 603906c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 604006c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 604106c3fb27SDimitry Andric break; 604206c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALS: 604306c3fb27SDimitry Andric MemtagGlobals = Entry.getVal(); 604406c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 604506c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 604606c3fb27SDimitry Andric break; 604706c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_MODE: 604806c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_HEAP: 604906c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_STACK: 605006c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 605106c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 605206c3fb27SDimitry Andric break; 605306c3fb27SDimitry Andric } 605406c3fb27SDimitry Andric } 605506c3fb27SDimitry Andric 605606c3fb27SDimitry Andric ArrayRef<uint8_t> AndroidNoteDesc; 605706c3fb27SDimitry Andric auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 605806c3fb27SDimitry Andric if (Note.getName() == "Android" && 605906c3fb27SDimitry Andric Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG) 606006c3fb27SDimitry Andric AndroidNoteDesc = Note.getDesc(4); 606106c3fb27SDimitry Andric return Error::success(); 606206c3fb27SDimitry Andric }; 606306c3fb27SDimitry Andric 606406c3fb27SDimitry Andric processNotesHelper( 606506c3fb27SDimitry Andric *this, 606606c3fb27SDimitry Andric /*StartNotesFn=*/ 606706c3fb27SDimitry Andric [](std::optional<StringRef>, const typename ELFT::Off, 606806c3fb27SDimitry Andric const typename ELFT::Addr, size_t) {}, 606906c3fb27SDimitry Andric /*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {}); 607006c3fb27SDimitry Andric 607106c3fb27SDimitry Andric ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals); 607206c3fb27SDimitry Andric if (Contents.size() != MemtagGlobalsSz) { 607306c3fb27SDimitry Andric reportUniqueWarning( 607406c3fb27SDimitry Andric "mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" + 607506c3fb27SDimitry Andric Twine::utohexstr(MemtagGlobalsSz) + 607606c3fb27SDimitry Andric ") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" + 607706c3fb27SDimitry Andric Twine::utohexstr(Contents.size()) + ")"); 607806c3fb27SDimitry Andric Contents = ArrayRef<uint8_t>(); 607906c3fb27SDimitry Andric } 608006c3fb27SDimitry Andric 608106c3fb27SDimitry Andric std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors; 608206c3fb27SDimitry Andric uint64_t Address = 0; 608306c3fb27SDimitry Andric // See the AArch64 MemtagABI document for a description of encoding scheme: 608406c3fb27SDimitry Andric // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic 608506c3fb27SDimitry Andric for (size_t I = 0; I < Contents.size();) { 608606c3fb27SDimitry Andric const char *Error = nullptr; 608706c3fb27SDimitry Andric unsigned DecodedBytes = 0; 608806c3fb27SDimitry Andric uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes, 608906c3fb27SDimitry Andric Contents.end(), &Error); 609006c3fb27SDimitry Andric I += DecodedBytes; 609106c3fb27SDimitry Andric if (Error) { 609206c3fb27SDimitry Andric reportUniqueWarning( 609306c3fb27SDimitry Andric "error decoding distance uleb, " + Twine(DecodedBytes) + 609406c3fb27SDimitry Andric " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error)); 609506c3fb27SDimitry Andric GlobalDescriptors.clear(); 609606c3fb27SDimitry Andric break; 609706c3fb27SDimitry Andric } 609806c3fb27SDimitry Andric uint64_t Distance = Value >> MemtagStepVarintReservedBits; 609906c3fb27SDimitry Andric uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1); 610006c3fb27SDimitry Andric if (GranulesToTag == 0) { 610106c3fb27SDimitry Andric GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes, 610206c3fb27SDimitry Andric Contents.end(), &Error) + 610306c3fb27SDimitry Andric 1; 610406c3fb27SDimitry Andric I += DecodedBytes; 610506c3fb27SDimitry Andric if (Error) { 610606c3fb27SDimitry Andric reportUniqueWarning( 610706c3fb27SDimitry Andric "error decoding size-only uleb, " + Twine(DecodedBytes) + 610806c3fb27SDimitry Andric " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error)); 610906c3fb27SDimitry Andric GlobalDescriptors.clear(); 611006c3fb27SDimitry Andric break; 611106c3fb27SDimitry Andric } 611206c3fb27SDimitry Andric } 611306c3fb27SDimitry Andric Address += Distance * MemtagGranuleSize; 611406c3fb27SDimitry Andric GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize); 611506c3fb27SDimitry Andric Address += GranulesToTag * MemtagGranuleSize; 611606c3fb27SDimitry Andric } 611706c3fb27SDimitry Andric 611806c3fb27SDimitry Andric printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors); 61195ffd83dbSDimitry Andric } 61205ffd83dbSDimitry Andric 6121e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() { 61220b57cec5SDimitry Andric OS << "printELFLinkerOptions not implemented!\n"; 61230b57cec5SDimitry Andric } 61240b57cec5SDimitry Andric 6125480093f4SDimitry Andric template <class ELFT> 6126e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printDependentLibsHelper( 61275ffd83dbSDimitry Andric function_ref<void(const Elf_Shdr &)> OnSectionStart, 61285ffd83dbSDimitry Andric function_ref<void(StringRef, uint64_t)> OnLibEntry) { 61295ffd83dbSDimitry Andric auto Warn = [this](unsigned SecNdx, StringRef Msg) { 6130e8d8bef9SDimitry Andric this->reportUniqueWarning("SHT_LLVM_DEPENDENT_LIBRARIES section at index " + 6131e8d8bef9SDimitry Andric Twine(SecNdx) + " is broken: " + Msg); 61325ffd83dbSDimitry Andric }; 61335ffd83dbSDimitry Andric 61345ffd83dbSDimitry Andric unsigned I = -1; 6135e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) { 61365ffd83dbSDimitry Andric ++I; 61375ffd83dbSDimitry Andric if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES) 61385ffd83dbSDimitry Andric continue; 61395ffd83dbSDimitry Andric 61405ffd83dbSDimitry Andric OnSectionStart(Shdr); 61415ffd83dbSDimitry Andric 6142e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Shdr); 61435ffd83dbSDimitry Andric if (!ContentsOrErr) { 61445ffd83dbSDimitry Andric Warn(I, toString(ContentsOrErr.takeError())); 61455ffd83dbSDimitry Andric continue; 61465ffd83dbSDimitry Andric } 61475ffd83dbSDimitry Andric 61485ffd83dbSDimitry Andric ArrayRef<uint8_t> Contents = *ContentsOrErr; 61495ffd83dbSDimitry Andric if (!Contents.empty() && Contents.back() != 0) { 61505ffd83dbSDimitry Andric Warn(I, "the content is not null-terminated"); 61515ffd83dbSDimitry Andric continue; 61525ffd83dbSDimitry Andric } 61535ffd83dbSDimitry Andric 61545ffd83dbSDimitry Andric for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) { 61555ffd83dbSDimitry Andric StringRef Lib((const char *)I); 61565ffd83dbSDimitry Andric OnLibEntry(Lib, I - Contents.begin()); 61575ffd83dbSDimitry Andric I += Lib.size() + 1; 61585ffd83dbSDimitry Andric } 61595ffd83dbSDimitry Andric } 61605ffd83dbSDimitry Andric } 61615ffd83dbSDimitry Andric 61625ffd83dbSDimitry Andric template <class ELFT> 6163e8d8bef9SDimitry Andric void ELFDumper<ELFT>::forEachRelocationDo( 6164e8d8bef9SDimitry Andric const Elf_Shdr &Sec, bool RawRelr, 6165e8d8bef9SDimitry Andric llvm::function_ref<void(const Relocation<ELFT> &, unsigned, 6166e8d8bef9SDimitry Andric const Elf_Shdr &, const Elf_Shdr *)> 6167e8d8bef9SDimitry Andric RelRelaFn, 6168e8d8bef9SDimitry Andric llvm::function_ref<void(const Elf_Relr &)> RelrFn) { 6169e8d8bef9SDimitry Andric auto Warn = [&](Error &&E, 6170e8d8bef9SDimitry Andric const Twine &Prefix = "unable to read relocations from") { 6171e8d8bef9SDimitry Andric this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " + 6172e8d8bef9SDimitry Andric toString(std::move(E))); 6173e8d8bef9SDimitry Andric }; 6174e8d8bef9SDimitry Andric 6175e8d8bef9SDimitry Andric // SHT_RELR/SHT_ANDROID_RELR sections do not have an associated symbol table. 6176e8d8bef9SDimitry Andric // For them we should not treat the value of the sh_link field as an index of 6177e8d8bef9SDimitry Andric // a symbol table. 6178e8d8bef9SDimitry Andric const Elf_Shdr *SymTab; 6179e8d8bef9SDimitry Andric if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR) { 6180e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link); 6181e8d8bef9SDimitry Andric if (!SymTabOrErr) { 6182e8d8bef9SDimitry Andric Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for"); 6183e8d8bef9SDimitry Andric return; 6184e8d8bef9SDimitry Andric } 6185e8d8bef9SDimitry Andric SymTab = *SymTabOrErr; 6186e8d8bef9SDimitry Andric } 6187e8d8bef9SDimitry Andric 6188e8d8bef9SDimitry Andric unsigned RelNdx = 0; 6189e8d8bef9SDimitry Andric const bool IsMips64EL = this->Obj.isMips64EL(); 6190e8d8bef9SDimitry Andric switch (Sec.sh_type) { 6191e8d8bef9SDimitry Andric case ELF::SHT_REL: 6192e8d8bef9SDimitry Andric if (Expected<Elf_Rel_Range> RangeOrErr = Obj.rels(Sec)) { 6193e8d8bef9SDimitry Andric for (const Elf_Rel &R : *RangeOrErr) 6194e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6195e8d8bef9SDimitry Andric } else { 6196e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6197e8d8bef9SDimitry Andric } 6198e8d8bef9SDimitry Andric break; 6199e8d8bef9SDimitry Andric case ELF::SHT_RELA: 6200e8d8bef9SDimitry Andric if (Expected<Elf_Rela_Range> RangeOrErr = Obj.relas(Sec)) { 6201e8d8bef9SDimitry Andric for (const Elf_Rela &R : *RangeOrErr) 6202e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6203e8d8bef9SDimitry Andric } else { 6204e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6205e8d8bef9SDimitry Andric } 6206e8d8bef9SDimitry Andric break; 6207e8d8bef9SDimitry Andric case ELF::SHT_RELR: 6208e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_RELR: { 6209e8d8bef9SDimitry Andric Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec); 6210e8d8bef9SDimitry Andric if (!RangeOrErr) { 6211e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6212e8d8bef9SDimitry Andric break; 6213e8d8bef9SDimitry Andric } 6214e8d8bef9SDimitry Andric if (RawRelr) { 6215e8d8bef9SDimitry Andric for (const Elf_Relr &R : *RangeOrErr) 6216e8d8bef9SDimitry Andric RelrFn(R); 6217e8d8bef9SDimitry Andric break; 6218e8d8bef9SDimitry Andric } 6219e8d8bef9SDimitry Andric 6220e8d8bef9SDimitry Andric for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr)) 6221e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, 6222e8d8bef9SDimitry Andric /*SymTab=*/nullptr); 6223e8d8bef9SDimitry Andric break; 6224e8d8bef9SDimitry Andric } 6225e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_REL: 6226e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_RELA: 6227e8d8bef9SDimitry Andric if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) { 6228e8d8bef9SDimitry Andric for (const Elf_Rela &R : *RelasOrErr) 6229e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6230e8d8bef9SDimitry Andric } else { 6231e8d8bef9SDimitry Andric Warn(RelasOrErr.takeError()); 6232e8d8bef9SDimitry Andric } 6233e8d8bef9SDimitry Andric break; 6234e8d8bef9SDimitry Andric } 6235e8d8bef9SDimitry Andric } 6236e8d8bef9SDimitry Andric 6237e8d8bef9SDimitry Andric template <class ELFT> 6238e8d8bef9SDimitry Andric StringRef ELFDumper<ELFT>::getPrintableSectionName(const Elf_Shdr &Sec) const { 6239e8d8bef9SDimitry Andric StringRef Name = "<?>"; 6240e8d8bef9SDimitry Andric if (Expected<StringRef> SecNameOrErr = 6241e8d8bef9SDimitry Andric Obj.getSectionName(Sec, this->WarningHandler)) 6242e8d8bef9SDimitry Andric Name = *SecNameOrErr; 6243e8d8bef9SDimitry Andric else 6244e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get the name of " + describe(Sec) + 6245e8d8bef9SDimitry Andric ": " + toString(SecNameOrErr.takeError())); 6246e8d8bef9SDimitry Andric return Name; 6247e8d8bef9SDimitry Andric } 6248e8d8bef9SDimitry Andric 6249e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDependentLibs() { 62505ffd83dbSDimitry Andric bool SectionStarted = false; 62515ffd83dbSDimitry Andric struct NameOffset { 62525ffd83dbSDimitry Andric StringRef Name; 62535ffd83dbSDimitry Andric uint64_t Offset; 62545ffd83dbSDimitry Andric }; 62555ffd83dbSDimitry Andric std::vector<NameOffset> SecEntries; 62565ffd83dbSDimitry Andric NameOffset Current; 62575ffd83dbSDimitry Andric auto PrintSection = [&]() { 62585ffd83dbSDimitry Andric OS << "Dependent libraries section " << Current.Name << " at offset " 62595ffd83dbSDimitry Andric << format_hex(Current.Offset, 1) << " contains " << SecEntries.size() 62605ffd83dbSDimitry Andric << " entries:\n"; 62615ffd83dbSDimitry Andric for (NameOffset Entry : SecEntries) 6262e8d8bef9SDimitry Andric OS << " [" << format("%6" PRIx64, Entry.Offset) << "] " << Entry.Name 62635ffd83dbSDimitry Andric << "\n"; 62645ffd83dbSDimitry Andric OS << "\n"; 62655ffd83dbSDimitry Andric SecEntries.clear(); 62665ffd83dbSDimitry Andric }; 62675ffd83dbSDimitry Andric 62685ffd83dbSDimitry Andric auto OnSectionStart = [&](const Elf_Shdr &Shdr) { 62695ffd83dbSDimitry Andric if (SectionStarted) 62705ffd83dbSDimitry Andric PrintSection(); 62715ffd83dbSDimitry Andric SectionStarted = true; 62725ffd83dbSDimitry Andric Current.Offset = Shdr.sh_offset; 6273e8d8bef9SDimitry Andric Current.Name = this->getPrintableSectionName(Shdr); 62745ffd83dbSDimitry Andric }; 62755ffd83dbSDimitry Andric auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) { 62765ffd83dbSDimitry Andric SecEntries.push_back(NameOffset{Lib, Offset}); 62775ffd83dbSDimitry Andric }; 62785ffd83dbSDimitry Andric 6279e8d8bef9SDimitry Andric this->printDependentLibsHelper(OnSectionStart, OnLibEntry); 62805ffd83dbSDimitry Andric if (SectionStarted) 62815ffd83dbSDimitry Andric PrintSection(); 6282480093f4SDimitry Andric } 6283480093f4SDimitry Andric 62848bcb0991SDimitry Andric template <class ELFT> 6285fe6060f1SDimitry Andric SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress( 6286bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) { 6287fe6060f1SDimitry Andric SmallVector<uint32_t> SymbolIndexes; 628881ad6265SDimitry Andric if (!this->AddressToIndexMap) { 6289fe6060f1SDimitry Andric // Populate the address to index map upon the first invocation of this 6290fe6060f1SDimitry Andric // function. 6291fe6060f1SDimitry Andric this->AddressToIndexMap.emplace(); 6292e8d8bef9SDimitry Andric if (this->DotSymtabSec) { 6293fe6060f1SDimitry Andric if (Expected<Elf_Sym_Range> SymsOrError = 6294fe6060f1SDimitry Andric Obj.symbols(this->DotSymtabSec)) { 6295e8d8bef9SDimitry Andric uint32_t Index = (uint32_t)-1; 6296e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : *SymsOrError) { 6297e8d8bef9SDimitry Andric ++Index; 6298e8d8bef9SDimitry Andric 6299e8d8bef9SDimitry Andric if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC) 63008bcb0991SDimitry Andric continue; 6301e8d8bef9SDimitry Andric 6302fe6060f1SDimitry Andric Expected<uint64_t> SymAddrOrErr = 6303fe6060f1SDimitry Andric ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress(); 6304fe6060f1SDimitry Andric if (!SymAddrOrErr) { 6305e8d8bef9SDimitry Andric std::string Name = this->getStaticSymbolName(Index); 6306e8d8bef9SDimitry Andric reportUniqueWarning("unable to get address of symbol '" + Name + 6307e8d8bef9SDimitry Andric "': " + toString(SymAddrOrErr.takeError())); 6308fe6060f1SDimitry Andric return SymbolIndexes; 63098bcb0991SDimitry Andric } 6310e8d8bef9SDimitry Andric 6311fe6060f1SDimitry Andric (*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index); 6312fe6060f1SDimitry Andric } 6313fe6060f1SDimitry Andric } else { 6314fe6060f1SDimitry Andric reportUniqueWarning("unable to read the symbol table: " + 6315fe6060f1SDimitry Andric toString(SymsOrError.takeError())); 6316fe6060f1SDimitry Andric } 6317fe6060f1SDimitry Andric } 6318fe6060f1SDimitry Andric } 6319fe6060f1SDimitry Andric 6320fe6060f1SDimitry Andric auto Symbols = this->AddressToIndexMap->find(SymValue); 6321fe6060f1SDimitry Andric if (Symbols == this->AddressToIndexMap->end()) 6322fe6060f1SDimitry Andric return SymbolIndexes; 6323fe6060f1SDimitry Andric 6324fe6060f1SDimitry Andric for (uint32_t Index : Symbols->second) { 6325e8d8bef9SDimitry Andric // Check if the symbol is in the right section. FunctionSec == None 6326e8d8bef9SDimitry Andric // means "any section". 6327e8d8bef9SDimitry Andric if (FunctionSec) { 6328fe6060f1SDimitry Andric const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index)); 6329e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SecOrErr = 6330e8d8bef9SDimitry Andric Obj.getSection(Sym, this->DotSymtabSec, 6331e8d8bef9SDimitry Andric this->getShndxTable(this->DotSymtabSec))) { 6332e8d8bef9SDimitry Andric if (*FunctionSec != *SecOrErr) 6333e8d8bef9SDimitry Andric continue; 6334e8d8bef9SDimitry Andric } else { 6335e8d8bef9SDimitry Andric std::string Name = this->getStaticSymbolName(Index); 6336e8d8bef9SDimitry Andric // Note: it is impossible to trigger this error currently, it is 6337e8d8bef9SDimitry Andric // untested. 6338e8d8bef9SDimitry Andric reportUniqueWarning("unable to get section of symbol '" + Name + 6339e8d8bef9SDimitry Andric "': " + toString(SecOrErr.takeError())); 6340fe6060f1SDimitry Andric return SymbolIndexes; 6341e8d8bef9SDimitry Andric } 6342e8d8bef9SDimitry Andric } 6343e8d8bef9SDimitry Andric 6344fe6060f1SDimitry Andric SymbolIndexes.push_back(Index); 63458bcb0991SDimitry Andric } 63468bcb0991SDimitry Andric 6347fe6060f1SDimitry Andric return SymbolIndexes; 6348fe6060f1SDimitry Andric } 6349fe6060f1SDimitry Andric 6350fe6060f1SDimitry Andric template <class ELFT> 6351fe6060f1SDimitry Andric bool ELFDumper<ELFT>::printFunctionStackSize( 6352bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec, 6353fe6060f1SDimitry Andric const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) { 6354fe6060f1SDimitry Andric SmallVector<uint32_t> FuncSymIndexes = 6355fe6060f1SDimitry Andric this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec); 6356fe6060f1SDimitry Andric if (FuncSymIndexes.empty()) 6357e8d8bef9SDimitry Andric reportUniqueWarning( 6358e8d8bef9SDimitry Andric "could not identify function symbol for stack size entry in " + 6359e8d8bef9SDimitry Andric describe(StackSizeSec)); 63608bcb0991SDimitry Andric 63618bcb0991SDimitry Andric // Extract the size. The expectation is that Offset is pointing to the right 63628bcb0991SDimitry Andric // place, i.e. past the function address. 6363e8d8bef9SDimitry Andric Error Err = Error::success(); 6364e8d8bef9SDimitry Andric uint64_t StackSize = Data.getULEB128(Offset, &Err); 6365e8d8bef9SDimitry Andric if (Err) { 6366e8d8bef9SDimitry Andric reportUniqueWarning("could not extract a valid stack size from " + 6367e8d8bef9SDimitry Andric describe(StackSizeSec) + ": " + 6368e8d8bef9SDimitry Andric toString(std::move(Err))); 6369e8d8bef9SDimitry Andric return false; 6370e8d8bef9SDimitry Andric } 6371fe6060f1SDimitry Andric 6372fe6060f1SDimitry Andric if (FuncSymIndexes.empty()) { 6373fe6060f1SDimitry Andric printStackSizeEntry(StackSize, {"?"}); 6374fe6060f1SDimitry Andric } else { 6375fe6060f1SDimitry Andric SmallVector<std::string> FuncSymNames; 6376fe6060f1SDimitry Andric for (uint32_t Index : FuncSymIndexes) 6377fe6060f1SDimitry Andric FuncSymNames.push_back(this->getStaticSymbolName(Index)); 6378fe6060f1SDimitry Andric printStackSizeEntry(StackSize, FuncSymNames); 6379fe6060f1SDimitry Andric } 6380fe6060f1SDimitry Andric 6381e8d8bef9SDimitry Andric return true; 63828bcb0991SDimitry Andric } 63838bcb0991SDimitry Andric 63848bcb0991SDimitry Andric template <class ELFT> 6385e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size, 6386fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) { 63878bcb0991SDimitry Andric OS.PadToColumn(2); 63888bcb0991SDimitry Andric OS << format_decimal(Size, 11); 63898bcb0991SDimitry Andric OS.PadToColumn(18); 6390fe6060f1SDimitry Andric 6391fe6060f1SDimitry Andric OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n"; 63928bcb0991SDimitry Andric } 63938bcb0991SDimitry Andric 63948bcb0991SDimitry Andric template <class ELFT> 6395e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R, 6396e8d8bef9SDimitry Andric const Elf_Shdr &RelocSec, unsigned Ndx, 6397e8d8bef9SDimitry Andric const Elf_Shdr *SymTab, 6398e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec, 6399e8d8bef9SDimitry Andric const Elf_Shdr &StackSizeSec, 64008bcb0991SDimitry Andric const RelocationResolver &Resolver, 64018bcb0991SDimitry Andric DataExtractor Data) { 64028bcb0991SDimitry Andric // This function ignores potentially erroneous input, unless it is directly 64038bcb0991SDimitry Andric // related to stack size reporting. 6404e8d8bef9SDimitry Andric const Elf_Sym *Sym = nullptr; 6405e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> TargetOrErr = this->getRelocationTarget(R, SymTab); 6406e8d8bef9SDimitry Andric if (!TargetOrErr) 6407e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the target of relocation with index " + 6408e8d8bef9SDimitry Andric Twine(Ndx) + " in " + describe(RelocSec) + ": " + 6409e8d8bef9SDimitry Andric toString(TargetOrErr.takeError())); 6410e8d8bef9SDimitry Andric else 6411e8d8bef9SDimitry Andric Sym = TargetOrErr->Sym; 6412e8d8bef9SDimitry Andric 64138bcb0991SDimitry Andric uint64_t RelocSymValue = 0; 6414e8d8bef9SDimitry Andric if (Sym) { 6415e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SectionOrErr = 6416e8d8bef9SDimitry Andric this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab)); 64178bcb0991SDimitry Andric if (!SectionOrErr) { 6418e8d8bef9SDimitry Andric reportUniqueWarning( 6419e8d8bef9SDimitry Andric "cannot identify the section for relocation symbol '" + 6420e8d8bef9SDimitry Andric (*TargetOrErr).Name + "': " + toString(SectionOrErr.takeError())); 64218bcb0991SDimitry Andric } else if (*SectionOrErr != FunctionSec) { 6422e8d8bef9SDimitry Andric reportUniqueWarning("relocation symbol '" + (*TargetOrErr).Name + 6423e8d8bef9SDimitry Andric "' is not in the expected section"); 64248bcb0991SDimitry Andric // Pretend that the symbol is in the correct section and report its 64258bcb0991SDimitry Andric // stack size anyway. 6426e8d8bef9SDimitry Andric FunctionSec = *SectionOrErr; 64278bcb0991SDimitry Andric } 64288bcb0991SDimitry Andric 6429e8d8bef9SDimitry Andric RelocSymValue = Sym->st_value; 64308bcb0991SDimitry Andric } 64318bcb0991SDimitry Andric 6432e8d8bef9SDimitry Andric uint64_t Offset = R.Offset; 6433e8d8bef9SDimitry Andric if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) { 6434e8d8bef9SDimitry Andric reportUniqueWarning("found invalid relocation offset (0x" + 6435e8d8bef9SDimitry Andric Twine::utohexstr(Offset) + ") into " + 6436e8d8bef9SDimitry Andric describe(StackSizeSec) + 6437e8d8bef9SDimitry Andric " while trying to extract a stack size entry"); 6438e8d8bef9SDimitry Andric return; 6439e8d8bef9SDimitry Andric } 64408bcb0991SDimitry Andric 644181ad6265SDimitry Andric uint64_t SymValue = Resolver(R.Type, Offset, RelocSymValue, 644281ad6265SDimitry Andric Data.getAddress(&Offset), R.Addend.value_or(0)); 6443e8d8bef9SDimitry Andric this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data, 6444e8d8bef9SDimitry Andric &Offset); 64458bcb0991SDimitry Andric } 64468bcb0991SDimitry Andric 64478bcb0991SDimitry Andric template <class ELFT> 6448e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printNonRelocatableStackSizes( 6449e8d8bef9SDimitry Andric std::function<void()> PrintHeader) { 64508bcb0991SDimitry Andric // This function ignores potentially erroneous input, unless it is directly 64518bcb0991SDimitry Andric // related to stack size reporting. 6452e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 6453e8d8bef9SDimitry Andric if (this->getPrintableSectionName(Sec) != ".stack_sizes") 64548bcb0991SDimitry Andric continue; 64558bcb0991SDimitry Andric PrintHeader(); 64568bcb0991SDimitry Andric ArrayRef<uint8_t> Contents = 6457e8d8bef9SDimitry Andric unwrapOrError(this->FileName, Obj.getSectionContents(Sec)); 6458e8d8bef9SDimitry Andric DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr)); 64598bcb0991SDimitry Andric uint64_t Offset = 0; 64608bcb0991SDimitry Andric while (Offset < Contents.size()) { 64618bcb0991SDimitry Andric // The function address is followed by a ULEB representing the stack 64628bcb0991SDimitry Andric // size. Check for an extra byte before we try to process the entry. 64638bcb0991SDimitry Andric if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) { 6464e8d8bef9SDimitry Andric reportUniqueWarning( 6465e8d8bef9SDimitry Andric describe(Sec) + 6466e8d8bef9SDimitry Andric " ended while trying to extract a stack size entry"); 6467e8d8bef9SDimitry Andric break; 64688bcb0991SDimitry Andric } 64698bcb0991SDimitry Andric uint64_t SymValue = Data.getAddress(&Offset); 6470bdd1243dSDimitry Andric if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec, 6471bdd1243dSDimitry Andric Data, &Offset)) 6472e8d8bef9SDimitry Andric break; 64738bcb0991SDimitry Andric } 64748bcb0991SDimitry Andric } 64758bcb0991SDimitry Andric } 64768bcb0991SDimitry Andric 64778bcb0991SDimitry Andric template <class ELFT> 6478fe6060f1SDimitry Andric void ELFDumper<ELFT>::printRelocatableStackSizes( 6479fe6060f1SDimitry Andric std::function<void()> PrintHeader) { 6480fe6060f1SDimitry Andric // Build a map between stack size sections and their corresponding relocation 6481fe6060f1SDimitry Andric // sections. 6482fe6060f1SDimitry Andric auto IsMatch = [&](const Elf_Shdr &Sec) -> bool { 6483fe6060f1SDimitry Andric StringRef SectionName; 6484fe6060f1SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec)) 6485fe6060f1SDimitry Andric SectionName = *NameOrErr; 6486fe6060f1SDimitry Andric else 6487fe6060f1SDimitry Andric consumeError(NameOrErr.takeError()); 6488fe6060f1SDimitry Andric 6489fe6060f1SDimitry Andric return SectionName == ".stack_sizes"; 6490fe6060f1SDimitry Andric }; 64918bcb0991SDimitry Andric 649206c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> 649306c3fb27SDimitry Andric StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch); 649406c3fb27SDimitry Andric if (!StackSizeRelocMapOrErr) { 649506c3fb27SDimitry Andric reportUniqueWarning("unable to get stack size map section(s): " + 649606c3fb27SDimitry Andric toString(StackSizeRelocMapOrErr.takeError())); 649706c3fb27SDimitry Andric return; 649806c3fb27SDimitry Andric } 649906c3fb27SDimitry Andric 650006c3fb27SDimitry Andric for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) { 65018bcb0991SDimitry Andric PrintHeader(); 6502e8d8bef9SDimitry Andric const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first; 6503e8d8bef9SDimitry Andric const Elf_Shdr *RelocSec = StackSizeMapEntry.second; 65048bcb0991SDimitry Andric 65058bcb0991SDimitry Andric // Warn about stack size sections without a relocation section. 6506e8d8bef9SDimitry Andric if (!RelocSec) { 6507e8d8bef9SDimitry Andric reportWarning(createError(".stack_sizes (" + describe(*StackSizesELFSec) + 6508e8d8bef9SDimitry Andric ") does not have a corresponding " 65098bcb0991SDimitry Andric "relocation section"), 6510e8d8bef9SDimitry Andric FileName); 65118bcb0991SDimitry Andric continue; 65128bcb0991SDimitry Andric } 65138bcb0991SDimitry Andric 65148bcb0991SDimitry Andric // A .stack_sizes section header's sh_link field is supposed to point 65158bcb0991SDimitry Andric // to the section that contains the functions whose stack sizes are 65168bcb0991SDimitry Andric // described in it. 6517e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec = unwrapOrError( 6518e8d8bef9SDimitry Andric this->FileName, Obj.getSection(StackSizesELFSec->sh_link)); 65198bcb0991SDimitry Andric 6520e8d8bef9SDimitry Andric SupportsRelocation IsSupportedFn; 65218bcb0991SDimitry Andric RelocationResolver Resolver; 6522e8d8bef9SDimitry Andric std::tie(IsSupportedFn, Resolver) = getRelocationResolver(this->ObjF); 6523e8d8bef9SDimitry Andric ArrayRef<uint8_t> Contents = 6524e8d8bef9SDimitry Andric unwrapOrError(this->FileName, Obj.getSectionContents(*StackSizesELFSec)); 6525e8d8bef9SDimitry Andric DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr)); 6526e8d8bef9SDimitry Andric 6527e8d8bef9SDimitry Andric forEachRelocationDo( 6528e8d8bef9SDimitry Andric *RelocSec, /*RawRelr=*/false, 6529e8d8bef9SDimitry Andric [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec, 6530e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) { 6531e8d8bef9SDimitry Andric if (!IsSupportedFn || !IsSupportedFn(R.Type)) { 6532e8d8bef9SDimitry Andric reportUniqueWarning( 6533e8d8bef9SDimitry Andric describe(*RelocSec) + 6534e8d8bef9SDimitry Andric " contains an unsupported relocation with index " + Twine(Ndx) + 6535e8d8bef9SDimitry Andric ": " + Obj.getRelocationTypeName(R.Type)); 6536e8d8bef9SDimitry Andric return; 65378bcb0991SDimitry Andric } 6538e8d8bef9SDimitry Andric 6539e8d8bef9SDimitry Andric this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec, 6540e8d8bef9SDimitry Andric *StackSizesELFSec, Resolver, Data); 6541e8d8bef9SDimitry Andric }, 6542e8d8bef9SDimitry Andric [](const Elf_Relr &) { 6543e8d8bef9SDimitry Andric llvm_unreachable("can't get here, because we only support " 6544e8d8bef9SDimitry Andric "SHT_REL/SHT_RELA sections"); 6545e8d8bef9SDimitry Andric }); 65468bcb0991SDimitry Andric } 65478bcb0991SDimitry Andric } 65488bcb0991SDimitry Andric 65498bcb0991SDimitry Andric template <class ELFT> 6550e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printStackSizes() { 65518bcb0991SDimitry Andric bool HeaderHasBeenPrinted = false; 65528bcb0991SDimitry Andric auto PrintHeader = [&]() { 65538bcb0991SDimitry Andric if (HeaderHasBeenPrinted) 65548bcb0991SDimitry Andric return; 65558bcb0991SDimitry Andric OS << "\nStack Sizes:\n"; 65568bcb0991SDimitry Andric OS.PadToColumn(9); 65578bcb0991SDimitry Andric OS << "Size"; 65588bcb0991SDimitry Andric OS.PadToColumn(18); 6559fe6060f1SDimitry Andric OS << "Functions\n"; 65608bcb0991SDimitry Andric HeaderHasBeenPrinted = true; 65618bcb0991SDimitry Andric }; 65628bcb0991SDimitry Andric 65638bcb0991SDimitry Andric // For non-relocatable objects, look directly for sections whose name starts 65648bcb0991SDimitry Andric // with .stack_sizes and process the contents. 6565e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_type == ELF::ET_REL) 6566e8d8bef9SDimitry Andric this->printRelocatableStackSizes(PrintHeader); 65678bcb0991SDimitry Andric else 6568e8d8bef9SDimitry Andric this->printNonRelocatableStackSizes(PrintHeader); 65698bcb0991SDimitry Andric } 65708bcb0991SDimitry Andric 65710b57cec5SDimitry Andric template <class ELFT> 6572e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 65730b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 65740b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 65750b57cec5SDimitry Andric OS.PadToColumn(2); 65760b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); 65770b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 65780b57cec5SDimitry Andric OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; 65790b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 65800b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 65810b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 65820b57cec5SDimitry Andric OS << Purpose << "\n"; 65830b57cec5SDimitry Andric }; 65840b57cec5SDimitry Andric 65850b57cec5SDimitry Andric OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); 65860b57cec5SDimitry Andric OS << " Canonical gp value: " 65870b57cec5SDimitry Andric << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; 65880b57cec5SDimitry Andric 65890b57cec5SDimitry Andric OS << " Reserved entries:\n"; 65900b57cec5SDimitry Andric if (ELFT::Is64Bits) 65910b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 65920b57cec5SDimitry Andric else 65930b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 65940b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); 65950b57cec5SDimitry Andric if (Parser.getGotModulePointer()) 65960b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); 65970b57cec5SDimitry Andric 65980b57cec5SDimitry Andric if (!Parser.getLocalEntries().empty()) { 65990b57cec5SDimitry Andric OS << "\n"; 66000b57cec5SDimitry Andric OS << " Local entries:\n"; 66010b57cec5SDimitry Andric if (ELFT::Is64Bits) 66020b57cec5SDimitry Andric OS << " Address Access Initial\n"; 66030b57cec5SDimitry Andric else 66040b57cec5SDimitry Andric OS << " Address Access Initial\n"; 66050b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) 66060b57cec5SDimitry Andric PrintEntry(&E, ""); 66070b57cec5SDimitry Andric } 66080b57cec5SDimitry Andric 66090b57cec5SDimitry Andric if (Parser.IsStatic) 66100b57cec5SDimitry Andric return; 66110b57cec5SDimitry Andric 66120b57cec5SDimitry Andric if (!Parser.getGlobalEntries().empty()) { 66130b57cec5SDimitry Andric OS << "\n"; 66140b57cec5SDimitry Andric OS << " Global entries:\n"; 66150b57cec5SDimitry Andric if (ELFT::Is64Bits) 66160b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val." 66170b57cec5SDimitry Andric << " Type Ndx Name\n"; 66180b57cec5SDimitry Andric else 66190b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; 6620e8d8bef9SDimitry Andric 6621e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 6622e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 66230b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 6624e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getGotSym(&E); 6625e8d8bef9SDimitry Andric const Elf_Sym &FirstSym = this->dynamic_symbols()[0]; 6626e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 6627e8d8bef9SDimitry Andric Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false); 66280b57cec5SDimitry Andric 66290b57cec5SDimitry Andric OS.PadToColumn(2); 66300b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); 66310b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 66320b57cec5SDimitry Andric OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; 66330b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 66340b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 66350b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 6636e8d8bef9SDimitry Andric OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias)); 66370b57cec5SDimitry Andric OS.PadToColumn(40 + 3 * Bias); 6638bdd1243dSDimitry Andric OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes)); 66390b57cec5SDimitry Andric OS.PadToColumn(48 + 3 * Bias); 6640e8d8bef9SDimitry Andric OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(), 6641e8d8bef9SDimitry Andric ShndxTable); 66420b57cec5SDimitry Andric OS.PadToColumn(52 + 3 * Bias); 66430b57cec5SDimitry Andric OS << SymName << "\n"; 66440b57cec5SDimitry Andric } 66450b57cec5SDimitry Andric } 66460b57cec5SDimitry Andric 66470b57cec5SDimitry Andric if (!Parser.getOtherEntries().empty()) 66480b57cec5SDimitry Andric OS << "\n Number of TLS and multi-GOT entries " 66490b57cec5SDimitry Andric << Parser.getOtherEntries().size() << "\n"; 66500b57cec5SDimitry Andric } 66510b57cec5SDimitry Andric 66520b57cec5SDimitry Andric template <class ELFT> 6653e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 66540b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 66550b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 66560b57cec5SDimitry Andric OS.PadToColumn(2); 66570b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias); 66580b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 66590b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 66600b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 66610b57cec5SDimitry Andric OS << Purpose << "\n"; 66620b57cec5SDimitry Andric }; 66630b57cec5SDimitry Andric 66640b57cec5SDimitry Andric OS << "PLT GOT:\n\n"; 66650b57cec5SDimitry Andric 66660b57cec5SDimitry Andric OS << " Reserved entries:\n"; 66670b57cec5SDimitry Andric OS << " Address Initial Purpose\n"; 66680b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); 66690b57cec5SDimitry Andric if (Parser.getPltModulePointer()) 66700b57cec5SDimitry Andric PrintEntry(Parser.getPltModulePointer(), "Module pointer"); 66710b57cec5SDimitry Andric 66720b57cec5SDimitry Andric if (!Parser.getPltEntries().empty()) { 66730b57cec5SDimitry Andric OS << "\n"; 66740b57cec5SDimitry Andric OS << " Entries:\n"; 66750b57cec5SDimitry Andric OS << " Address Initial Sym.Val. Type Ndx Name\n"; 6676e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 6677e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 66780b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 6679e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getPltSym(&E); 6680e8d8bef9SDimitry Andric const Elf_Sym &FirstSym = *cantFail( 6681e8d8bef9SDimitry Andric this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0)); 6682e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 6683e8d8bef9SDimitry Andric Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false); 66840b57cec5SDimitry Andric 66850b57cec5SDimitry Andric OS.PadToColumn(2); 66860b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias)); 66870b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 66880b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 66890b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 6690e8d8bef9SDimitry Andric OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias)); 66910b57cec5SDimitry Andric OS.PadToColumn(29 + 3 * Bias); 6692bdd1243dSDimitry Andric OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes)); 66930b57cec5SDimitry Andric OS.PadToColumn(37 + 3 * Bias); 6694e8d8bef9SDimitry Andric OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(), 6695e8d8bef9SDimitry Andric ShndxTable); 66960b57cec5SDimitry Andric OS.PadToColumn(41 + 3 * Bias); 66970b57cec5SDimitry Andric OS << SymName << "\n"; 66980b57cec5SDimitry Andric } 66990b57cec5SDimitry Andric } 67000b57cec5SDimitry Andric } 67010b57cec5SDimitry Andric 67028bcb0991SDimitry Andric template <class ELFT> 6703e8d8bef9SDimitry Andric Expected<const Elf_Mips_ABIFlags<ELFT> *> 6704e8d8bef9SDimitry Andric getMipsAbiFlagsSection(const ELFDumper<ELFT> &Dumper) { 6705e8d8bef9SDimitry Andric const typename ELFT::Shdr *Sec = Dumper.findSectionByName(".MIPS.abiflags"); 6706e8d8bef9SDimitry Andric if (Sec == nullptr) 6707e8d8bef9SDimitry Andric return nullptr; 6708e8d8bef9SDimitry Andric 6709e8d8bef9SDimitry Andric constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: "; 6710e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> DataOrErr = 6711e8d8bef9SDimitry Andric Dumper.getElfObject().getELFFile().getSectionContents(*Sec); 6712e8d8bef9SDimitry Andric if (!DataOrErr) 6713e8d8bef9SDimitry Andric return createError(ErrPrefix + toString(DataOrErr.takeError())); 6714e8d8bef9SDimitry Andric 6715e8d8bef9SDimitry Andric if (DataOrErr->size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) 6716e8d8bef9SDimitry Andric return createError(ErrPrefix + "it has a wrong size (" + 6717e8d8bef9SDimitry Andric Twine(DataOrErr->size()) + ")"); 6718e8d8bef9SDimitry Andric return reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(DataOrErr->data()); 6719e8d8bef9SDimitry Andric } 6720e8d8bef9SDimitry Andric 6721e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printMipsABIFlags() { 6722e8d8bef9SDimitry Andric const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr; 6723e8d8bef9SDimitry Andric if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr = 6724e8d8bef9SDimitry Andric getMipsAbiFlagsSection(*this)) 6725e8d8bef9SDimitry Andric Flags = *SecOrErr; 6726e8d8bef9SDimitry Andric else 6727e8d8bef9SDimitry Andric this->reportUniqueWarning(SecOrErr.takeError()); 6728e8d8bef9SDimitry Andric if (!Flags) 67298bcb0991SDimitry Andric return; 67308bcb0991SDimitry Andric 67318bcb0991SDimitry Andric OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n"; 67328bcb0991SDimitry Andric OS << "ISA: MIPS" << int(Flags->isa_level); 67338bcb0991SDimitry Andric if (Flags->isa_rev > 1) 67348bcb0991SDimitry Andric OS << "r" << int(Flags->isa_rev); 67358bcb0991SDimitry Andric OS << "\n"; 67368bcb0991SDimitry Andric OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n"; 67378bcb0991SDimitry Andric OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n"; 67388bcb0991SDimitry Andric OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n"; 6739bdd1243dSDimitry Andric OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType)) 6740bdd1243dSDimitry Andric << "\n"; 67418bcb0991SDimitry Andric OS << "ISA Extension: " 6742bdd1243dSDimitry Andric << enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n"; 67438bcb0991SDimitry Andric if (Flags->ases == 0) 67448bcb0991SDimitry Andric OS << "ASEs: None\n"; 67458bcb0991SDimitry Andric else 67468bcb0991SDimitry Andric // FIXME: Print each flag on a separate line. 6747bdd1243dSDimitry Andric OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags)) 67488bcb0991SDimitry Andric << "\n"; 67498bcb0991SDimitry Andric OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n"; 67508bcb0991SDimitry Andric OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n"; 67518bcb0991SDimitry Andric OS << "\n"; 67528bcb0991SDimitry Andric } 67538bcb0991SDimitry Andric 6754e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printFileHeaders() { 6755e8d8bef9SDimitry Andric const Elf_Ehdr &E = this->Obj.getHeader(); 67560b57cec5SDimitry Andric { 67570b57cec5SDimitry Andric DictScope D(W, "ElfHeader"); 67580b57cec5SDimitry Andric { 67590b57cec5SDimitry Andric DictScope D(W, "Ident"); 6760bdd1243dSDimitry Andric W.printBinary("Magic", 6761bdd1243dSDimitry Andric ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4)); 6762bdd1243dSDimitry Andric W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass)); 6763e8d8bef9SDimitry Andric W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA], 6764bdd1243dSDimitry Andric ArrayRef(ElfDataEncoding)); 6765e8d8bef9SDimitry Andric W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]); 67660b57cec5SDimitry Andric 6767bdd1243dSDimitry Andric auto OSABI = ArrayRef(ElfOSABI); 6768e8d8bef9SDimitry Andric if (E.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && 6769e8d8bef9SDimitry Andric E.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { 6770e8d8bef9SDimitry Andric switch (E.e_machine) { 67710b57cec5SDimitry Andric case ELF::EM_AMDGPU: 6772bdd1243dSDimitry Andric OSABI = ArrayRef(AMDGPUElfOSABI); 67730b57cec5SDimitry Andric break; 67740b57cec5SDimitry Andric case ELF::EM_ARM: 6775bdd1243dSDimitry Andric OSABI = ArrayRef(ARMElfOSABI); 67760b57cec5SDimitry Andric break; 67770b57cec5SDimitry Andric case ELF::EM_TI_C6000: 6778bdd1243dSDimitry Andric OSABI = ArrayRef(C6000ElfOSABI); 67790b57cec5SDimitry Andric break; 67800b57cec5SDimitry Andric } 67810b57cec5SDimitry Andric } 6782e8d8bef9SDimitry Andric W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI); 6783e8d8bef9SDimitry Andric W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]); 6784bdd1243dSDimitry Andric W.printBinary("Unused", 6785bdd1243dSDimitry Andric ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD)); 67860b57cec5SDimitry Andric } 67870b57cec5SDimitry Andric 6788e8d8bef9SDimitry Andric std::string TypeStr; 6789e8d8bef9SDimitry Andric if (const EnumEntry<unsigned> *Ent = getObjectFileEnumEntry(E.e_type)) { 6790e8d8bef9SDimitry Andric TypeStr = Ent->Name.str(); 6791e8d8bef9SDimitry Andric } else { 6792e8d8bef9SDimitry Andric if (E.e_type >= ET_LOPROC) 6793e8d8bef9SDimitry Andric TypeStr = "Processor Specific"; 6794e8d8bef9SDimitry Andric else if (E.e_type >= ET_LOOS) 6795e8d8bef9SDimitry Andric TypeStr = "OS Specific"; 6796e8d8bef9SDimitry Andric else 6797e8d8bef9SDimitry Andric TypeStr = "Unknown"; 6798e8d8bef9SDimitry Andric } 679981ad6265SDimitry Andric W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")"); 6800e8d8bef9SDimitry Andric 6801bdd1243dSDimitry Andric W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType)); 6802e8d8bef9SDimitry Andric W.printNumber("Version", E.e_version); 6803e8d8bef9SDimitry Andric W.printHex("Entry", E.e_entry); 6804e8d8bef9SDimitry Andric W.printHex("ProgramHeaderOffset", E.e_phoff); 6805e8d8bef9SDimitry Andric W.printHex("SectionHeaderOffset", E.e_shoff); 6806e8d8bef9SDimitry Andric if (E.e_machine == EM_MIPS) 6807bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags), 68080b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), 68090b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_MACH)); 6810fe6060f1SDimitry Andric else if (E.e_machine == EM_AMDGPU) { 6811fe6060f1SDimitry Andric switch (E.e_ident[ELF::EI_ABIVERSION]) { 6812fe6060f1SDimitry Andric default: 6813fe6060f1SDimitry Andric W.printHex("Flags", E.e_flags); 6814fe6060f1SDimitry Andric break; 6815fe6060f1SDimitry Andric case 0: 6816fe6060f1SDimitry Andric // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags. 6817bdd1243dSDimitry Andric [[fallthrough]]; 6818fe6060f1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V3: 6819fe6060f1SDimitry Andric W.printFlags("Flags", E.e_flags, 6820bdd1243dSDimitry Andric ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3), 68210b57cec5SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH)); 6822fe6060f1SDimitry Andric break; 6823fe6060f1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V4: 68241fd87a68SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V5: 6825fe6060f1SDimitry Andric W.printFlags("Flags", E.e_flags, 6826bdd1243dSDimitry Andric ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4), 6827fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH), 6828fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4), 6829fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4)); 6830fe6060f1SDimitry Andric break; 6831fe6060f1SDimitry Andric } 6832fe6060f1SDimitry Andric } else if (E.e_machine == EM_RISCV) 6833bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags)); 6834fe6060f1SDimitry Andric else if (E.e_machine == EM_AVR) 6835bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags), 6836fe6060f1SDimitry Andric unsigned(ELF::EF_AVR_ARCH_MASK)); 6837972a253aSDimitry Andric else if (E.e_machine == EM_LOONGARCH) 6838bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags), 6839bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK), 6840bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_OBJABI_MASK)); 6841bdd1243dSDimitry Andric else if (E.e_machine == EM_XTENSA) 6842bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags), 6843bdd1243dSDimitry Andric unsigned(ELF::EF_XTENSA_MACH)); 68440b57cec5SDimitry Andric else 6845e8d8bef9SDimitry Andric W.printFlags("Flags", E.e_flags); 6846e8d8bef9SDimitry Andric W.printNumber("HeaderSize", E.e_ehsize); 6847e8d8bef9SDimitry Andric W.printNumber("ProgramHeaderEntrySize", E.e_phentsize); 6848e8d8bef9SDimitry Andric W.printNumber("ProgramHeaderCount", E.e_phnum); 6849e8d8bef9SDimitry Andric W.printNumber("SectionHeaderEntrySize", E.e_shentsize); 68508bcb0991SDimitry Andric W.printString("SectionHeaderCount", 6851e8d8bef9SDimitry Andric getSectionHeadersNumString(this->Obj, this->FileName)); 68520b57cec5SDimitry Andric W.printString("StringTableSectionIndex", 6853e8d8bef9SDimitry Andric getSectionHeaderTableIndexString(this->Obj, this->FileName)); 68540b57cec5SDimitry Andric } 68550b57cec5SDimitry Andric } 68560b57cec5SDimitry Andric 6857e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() { 68580b57cec5SDimitry Andric DictScope Lists(W, "Groups"); 6859e8d8bef9SDimitry Andric std::vector<GroupSection> V = this->getGroups(); 68600b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 68610b57cec5SDimitry Andric for (const GroupSection &G : V) { 68620b57cec5SDimitry Andric DictScope D(W, "Group"); 68630b57cec5SDimitry Andric W.printNumber("Name", G.Name, G.ShName); 68640b57cec5SDimitry Andric W.printNumber("Index", G.Index); 68650b57cec5SDimitry Andric W.printNumber("Link", G.Link); 68660b57cec5SDimitry Andric W.printNumber("Info", G.Info); 68670b57cec5SDimitry Andric W.printHex("Type", getGroupType(G.Type), G.Type); 686806c3fb27SDimitry Andric W.printString("Signature", G.Signature); 68690b57cec5SDimitry Andric 687006c3fb27SDimitry Andric ListScope L(W, getGroupSectionHeaderName()); 68710b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 68720b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 6873e8d8bef9SDimitry Andric if (MainGroup != &G) 6874e8d8bef9SDimitry Andric this->reportUniqueWarning( 6875e8d8bef9SDimitry Andric "section with index " + Twine(GM.Index) + 6876e8d8bef9SDimitry Andric ", included in the group section with index " + 6877e8d8bef9SDimitry Andric Twine(MainGroup->Index) + 6878e8d8bef9SDimitry Andric ", was also found in the group section with index " + 6879e8d8bef9SDimitry Andric Twine(G.Index)); 688006c3fb27SDimitry Andric printSectionGroupMembers(GM.Name, GM.Index); 68810b57cec5SDimitry Andric } 68820b57cec5SDimitry Andric } 68830b57cec5SDimitry Andric 68840b57cec5SDimitry Andric if (V.empty()) 688506c3fb27SDimitry Andric printEmptyGroupMessage(); 688606c3fb27SDimitry Andric } 688706c3fb27SDimitry Andric 688806c3fb27SDimitry Andric template <class ELFT> 688906c3fb27SDimitry Andric std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const { 689006c3fb27SDimitry Andric return "Section(s) in group"; 689106c3fb27SDimitry Andric } 689206c3fb27SDimitry Andric 689306c3fb27SDimitry Andric template <class ELFT> 689406c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name, 689506c3fb27SDimitry Andric uint64_t Idx) const { 689606c3fb27SDimitry Andric W.startLine() << Name << " (" << Idx << ")\n"; 68970b57cec5SDimitry Andric } 68980b57cec5SDimitry Andric 6899e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() { 69000b57cec5SDimitry Andric ListScope D(W, "Relocations"); 69010b57cec5SDimitry Andric 6902e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 6903e8d8bef9SDimitry Andric if (!isRelocationSec<ELFT>(Sec)) 69040b57cec5SDimitry Andric continue; 69050b57cec5SDimitry Andric 6906e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(Sec); 6907e8d8bef9SDimitry Andric unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front(); 690806c3fb27SDimitry Andric printRelocationSectionInfo(Sec, Name, SecNdx); 69090b57cec5SDimitry Andric } 69100b57cec5SDimitry Andric } 69110b57cec5SDimitry Andric 69120b57cec5SDimitry Andric template <class ELFT> 6913e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printRelrReloc(const Elf_Relr &R) { 69140b57cec5SDimitry Andric W.startLine() << W.hex(R) << "\n"; 69150b57cec5SDimitry Andric } 69160b57cec5SDimitry Andric 69170b57cec5SDimitry Andric template <class ELFT> 691806c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R, 691906c3fb27SDimitry Andric StringRef SymbolName, 692006c3fb27SDimitry Andric StringRef RelocName) { 69210b57cec5SDimitry Andric DictScope Group(W, "Relocation"); 6922e8d8bef9SDimitry Andric W.printHex("Offset", R.Offset); 6923e8d8bef9SDimitry Andric W.printNumber("Type", RelocName, R.Type); 6924e8d8bef9SDimitry Andric W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol); 6925e8d8bef9SDimitry Andric if (R.Addend) 6926e8d8bef9SDimitry Andric W.printHex("Addend", (uintX_t)*R.Addend); 692706c3fb27SDimitry Andric } 692806c3fb27SDimitry Andric 692906c3fb27SDimitry Andric template <class ELFT> 693006c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R, 693106c3fb27SDimitry Andric StringRef SymbolName, 693206c3fb27SDimitry Andric StringRef RelocName) { 69330b57cec5SDimitry Andric raw_ostream &OS = W.startLine(); 6934e8d8bef9SDimitry Andric OS << W.hex(R.Offset) << " " << RelocName << " " 6935e8d8bef9SDimitry Andric << (!SymbolName.empty() ? SymbolName : "-"); 6936e8d8bef9SDimitry Andric if (R.Addend) 6937e8d8bef9SDimitry Andric OS << " " << W.hex((uintX_t)*R.Addend); 6938e8d8bef9SDimitry Andric OS << "\n"; 69390b57cec5SDimitry Andric } 694006c3fb27SDimitry Andric 694106c3fb27SDimitry Andric template <class ELFT> 694206c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec, 694306c3fb27SDimitry Andric StringRef Name, 694406c3fb27SDimitry Andric const unsigned SecNdx) { 694506c3fb27SDimitry Andric DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str()); 694606c3fb27SDimitry Andric this->printRelocationsHelper(Sec); 694706c3fb27SDimitry Andric } 694806c3fb27SDimitry Andric 694906c3fb27SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const { 695006c3fb27SDimitry Andric W.startLine() << "There are no group sections in the file.\n"; 695106c3fb27SDimitry Andric } 695206c3fb27SDimitry Andric 695306c3fb27SDimitry Andric template <class ELFT> 695406c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R, 695506c3fb27SDimitry Andric const RelSymbol<ELFT> &RelSym) { 695606c3fb27SDimitry Andric StringRef SymbolName = RelSym.Name; 695706c3fb27SDimitry Andric if (RelSym.Sym && RelSym.Name.empty()) 695806c3fb27SDimitry Andric SymbolName = "<null>"; 695906c3fb27SDimitry Andric SmallString<32> RelocName; 696006c3fb27SDimitry Andric this->Obj.getRelocationTypeName(R.Type, RelocName); 696106c3fb27SDimitry Andric 696206c3fb27SDimitry Andric if (opts::ExpandRelocs) { 696306c3fb27SDimitry Andric printExpandedRelRelaReloc(R, SymbolName, RelocName); 696406c3fb27SDimitry Andric } else { 696506c3fb27SDimitry Andric printDefaultRelRelaReloc(R, SymbolName, RelocName); 696606c3fb27SDimitry Andric } 69670b57cec5SDimitry Andric } 69680b57cec5SDimitry Andric 6969e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() { 69700b57cec5SDimitry Andric ListScope SectionsD(W, "Sections"); 69710b57cec5SDimitry Andric 69720b57cec5SDimitry Andric int SectionIndex = -1; 6973480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> FlagsList = 697481ad6265SDimitry Andric getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI], 697581ad6265SDimitry Andric this->Obj.getHeader().e_machine); 6976e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 69770b57cec5SDimitry Andric DictScope SectionD(W, "Section"); 69780b57cec5SDimitry Andric W.printNumber("Index", ++SectionIndex); 6979e8d8bef9SDimitry Andric W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name); 6980e8d8bef9SDimitry Andric W.printHex("Type", 6981e8d8bef9SDimitry Andric object::getELFSectionTypeName(this->Obj.getHeader().e_machine, 6982e8d8bef9SDimitry Andric Sec.sh_type), 69830b57cec5SDimitry Andric Sec.sh_type); 6984bdd1243dSDimitry Andric W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList)); 69850b57cec5SDimitry Andric W.printHex("Address", Sec.sh_addr); 69860b57cec5SDimitry Andric W.printHex("Offset", Sec.sh_offset); 69870b57cec5SDimitry Andric W.printNumber("Size", Sec.sh_size); 69880b57cec5SDimitry Andric W.printNumber("Link", Sec.sh_link); 69890b57cec5SDimitry Andric W.printNumber("Info", Sec.sh_info); 69900b57cec5SDimitry Andric W.printNumber("AddressAlignment", Sec.sh_addralign); 69910b57cec5SDimitry Andric W.printNumber("EntrySize", Sec.sh_entsize); 69920b57cec5SDimitry Andric 69930b57cec5SDimitry Andric if (opts::SectionRelocations) { 69940b57cec5SDimitry Andric ListScope D(W, "Relocations"); 6995e8d8bef9SDimitry Andric this->printRelocationsHelper(Sec); 69960b57cec5SDimitry Andric } 69970b57cec5SDimitry Andric 69980b57cec5SDimitry Andric if (opts::SectionSymbols) { 69990b57cec5SDimitry Andric ListScope D(W, "Symbols"); 7000e8d8bef9SDimitry Andric if (this->DotSymtabSec) { 7001e8d8bef9SDimitry Andric StringRef StrTable = unwrapOrError( 7002e8d8bef9SDimitry Andric this->FileName, 7003e8d8bef9SDimitry Andric this->Obj.getStringTableForSymtab(*this->DotSymtabSec)); 7004e8d8bef9SDimitry Andric ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec); 70050b57cec5SDimitry Andric 7006e8d8bef9SDimitry Andric typename ELFT::SymRange Symbols = unwrapOrError( 7007e8d8bef9SDimitry Andric this->FileName, this->Obj.symbols(this->DotSymtabSec)); 7008e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : Symbols) { 70090b57cec5SDimitry Andric const Elf_Shdr *SymSec = unwrapOrError( 70108bcb0991SDimitry Andric this->FileName, 7011e8d8bef9SDimitry Andric this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable)); 70120b57cec5SDimitry Andric if (SymSec == &Sec) 7013e8d8bef9SDimitry Andric printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false, 7014e8d8bef9SDimitry Andric false); 7015e8d8bef9SDimitry Andric } 70160b57cec5SDimitry Andric } 70170b57cec5SDimitry Andric } 70180b57cec5SDimitry Andric 70190b57cec5SDimitry Andric if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { 70208bcb0991SDimitry Andric ArrayRef<uint8_t> Data = 7021e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec)); 70220b57cec5SDimitry Andric W.printBinaryBlock( 70230b57cec5SDimitry Andric "SectionData", 70240b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Data.data()), Data.size())); 70250b57cec5SDimitry Andric } 70260b57cec5SDimitry Andric } 70270b57cec5SDimitry Andric } 70280b57cec5SDimitry Andric 70290b57cec5SDimitry Andric template <class ELFT> 7030e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbolSection( 7031e8d8bef9SDimitry Andric const Elf_Sym &Symbol, unsigned SymIndex, 7032e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const { 7033bdd1243dSDimitry Andric auto GetSectionSpecialType = [&]() -> std::optional<StringRef> { 7034e8d8bef9SDimitry Andric if (Symbol.isUndefined()) 7035e8d8bef9SDimitry Andric return StringRef("Undefined"); 7036e8d8bef9SDimitry Andric if (Symbol.isProcessorSpecific()) 7037e8d8bef9SDimitry Andric return StringRef("Processor Specific"); 7038e8d8bef9SDimitry Andric if (Symbol.isOSSpecific()) 7039e8d8bef9SDimitry Andric return StringRef("Operating System Specific"); 7040e8d8bef9SDimitry Andric if (Symbol.isAbsolute()) 7041e8d8bef9SDimitry Andric return StringRef("Absolute"); 7042e8d8bef9SDimitry Andric if (Symbol.isCommon()) 7043e8d8bef9SDimitry Andric return StringRef("Common"); 7044e8d8bef9SDimitry Andric if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX) 7045e8d8bef9SDimitry Andric return StringRef("Reserved"); 7046bdd1243dSDimitry Andric return std::nullopt; 7047e8d8bef9SDimitry Andric }; 7048e8d8bef9SDimitry Andric 7049bdd1243dSDimitry Andric if (std::optional<StringRef> Type = GetSectionSpecialType()) { 7050e8d8bef9SDimitry Andric W.printHex("Section", *Type, Symbol.st_shndx); 7051e8d8bef9SDimitry Andric return; 7052e8d8bef9SDimitry Andric } 7053e8d8bef9SDimitry Andric 7054480093f4SDimitry Andric Expected<unsigned> SectionIndex = 7055e8d8bef9SDimitry Andric this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable); 7056480093f4SDimitry Andric if (!SectionIndex) { 7057e8d8bef9SDimitry Andric assert(Symbol.st_shndx == SHN_XINDEX && 7058480093f4SDimitry Andric "getSymbolSectionIndex should only fail due to an invalid " 7059480093f4SDimitry Andric "SHT_SYMTAB_SHNDX table/reference"); 7060480093f4SDimitry Andric this->reportUniqueWarning(SectionIndex.takeError()); 7061480093f4SDimitry Andric W.printHex("Section", "Reserved", SHN_XINDEX); 7062480093f4SDimitry Andric return; 7063480093f4SDimitry Andric } 7064480093f4SDimitry Andric 7065480093f4SDimitry Andric Expected<StringRef> SectionName = 7066e8d8bef9SDimitry Andric this->getSymbolSectionName(Symbol, *SectionIndex); 7067480093f4SDimitry Andric if (!SectionName) { 70685ffd83dbSDimitry Andric // Don't report an invalid section name if the section headers are missing. 70695ffd83dbSDimitry Andric // In such situations, all sections will be "invalid". 7070e8d8bef9SDimitry Andric if (!this->ObjF.sections().empty()) 7071480093f4SDimitry Andric this->reportUniqueWarning(SectionName.takeError()); 70725ffd83dbSDimitry Andric else 70735ffd83dbSDimitry Andric consumeError(SectionName.takeError()); 7074480093f4SDimitry Andric W.printHex("Section", "<?>", *SectionIndex); 7075480093f4SDimitry Andric } else { 7076480093f4SDimitry Andric W.printHex("Section", *SectionName, *SectionIndex); 7077480093f4SDimitry Andric } 7078480093f4SDimitry Andric } 7079480093f4SDimitry Andric 7080480093f4SDimitry Andric template <class ELFT> 708106c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const { 708206c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> SymOtherFlags = 708306c3fb27SDimitry Andric this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol); 708406c3fb27SDimitry Andric W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u); 708506c3fb27SDimitry Andric } 708606c3fb27SDimitry Andric 708706c3fb27SDimitry Andric template <class ELFT> 708806c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printZeroSymbolOtherField( 708906c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 709006c3fb27SDimitry Andric assert(Symbol.st_other == 0 && "non-zero Other Field"); 709106c3fb27SDimitry Andric // Usually st_other flag is zero. Do not pollute the output 709206c3fb27SDimitry Andric // by flags enumeration in that case. 709306c3fb27SDimitry Andric W.printNumber("Other", 0); 709406c3fb27SDimitry Andric } 709506c3fb27SDimitry Andric 709606c3fb27SDimitry Andric template <class ELFT> 7097e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 7098e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 7099bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 7100e8d8bef9SDimitry Andric bool IsDynamic, 7101e8d8bef9SDimitry Andric bool /*NonVisibilityBitsUsed*/) const { 7102e8d8bef9SDimitry Andric std::string FullSymbolName = this->getFullSymbolName( 7103e8d8bef9SDimitry Andric Symbol, SymIndex, ShndxTable, StrTable, IsDynamic); 7104e8d8bef9SDimitry Andric unsigned char SymbolType = Symbol.getType(); 71050b57cec5SDimitry Andric 71060b57cec5SDimitry Andric DictScope D(W, "Symbol"); 7107e8d8bef9SDimitry Andric W.printNumber("Name", FullSymbolName, Symbol.st_name); 7108e8d8bef9SDimitry Andric W.printHex("Value", Symbol.st_value); 7109e8d8bef9SDimitry Andric W.printNumber("Size", Symbol.st_size); 7110bdd1243dSDimitry Andric W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings)); 7111e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 71120b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 7113bdd1243dSDimitry Andric W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes)); 71140b57cec5SDimitry Andric else 7115bdd1243dSDimitry Andric W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes)); 7116e8d8bef9SDimitry Andric if (Symbol.st_other == 0) 711706c3fb27SDimitry Andric printZeroSymbolOtherField(Symbol); 71180b57cec5SDimitry Andric else 711906c3fb27SDimitry Andric printSymbolOtherField(Symbol); 7120e8d8bef9SDimitry Andric printSymbolSection(Symbol, SymIndex, ShndxTable); 71210b57cec5SDimitry Andric } 71220b57cec5SDimitry Andric 71230b57cec5SDimitry Andric template <class ELFT> 7124e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols, 71250b57cec5SDimitry Andric bool PrintDynamicSymbols) { 7126e8d8bef9SDimitry Andric if (PrintSymbols) { 71270b57cec5SDimitry Andric ListScope Group(W, "Symbols"); 7128e8d8bef9SDimitry Andric this->printSymbolsHelper(false); 71290b57cec5SDimitry Andric } 7130e8d8bef9SDimitry Andric if (PrintDynamicSymbols) { 71310b57cec5SDimitry Andric ListScope Group(W, "DynamicSymbols"); 7132e8d8bef9SDimitry Andric this->printSymbolsHelper(true); 7133e8d8bef9SDimitry Andric } 71340b57cec5SDimitry Andric } 71350b57cec5SDimitry Andric 7136e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() { 7137e8d8bef9SDimitry Andric Elf_Dyn_Range Table = this->dynamic_table(); 71380b57cec5SDimitry Andric if (Table.empty()) 71390b57cec5SDimitry Andric return; 71400b57cec5SDimitry Andric 71410b57cec5SDimitry Andric W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n"; 71420b57cec5SDimitry Andric 7143e8d8bef9SDimitry Andric size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table); 71445ffd83dbSDimitry Andric // The "Name/Value" column should be indented from the "Type" column by N 71455ffd83dbSDimitry Andric // spaces, where N = MaxTagSize - length of "Type" (4) + trailing 71465ffd83dbSDimitry Andric // space (1) = -3. 71475ffd83dbSDimitry Andric W.startLine() << " Tag" << std::string(ELFT::Is64Bits ? 16 : 8, ' ') 71485ffd83dbSDimitry Andric << "Type" << std::string(MaxTagSize - 3, ' ') << "Name/Value\n"; 71495ffd83dbSDimitry Andric 71505ffd83dbSDimitry Andric std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s "; 71510b57cec5SDimitry Andric for (auto Entry : Table) { 71520b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 7153e8d8bef9SDimitry Andric std::string Value = this->getDynamicEntry(Tag, Entry.getVal()); 71545ffd83dbSDimitry Andric W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true) 71555ffd83dbSDimitry Andric << " " 71565ffd83dbSDimitry Andric << format(ValueFmt.c_str(), 7157e8d8bef9SDimitry Andric this->Obj.getDynamicTagAsString(Tag).c_str()) 71585ffd83dbSDimitry Andric << Value << "\n"; 71590b57cec5SDimitry Andric } 71600b57cec5SDimitry Andric W.startLine() << "]\n"; 71610b57cec5SDimitry Andric } 71620b57cec5SDimitry Andric 7163e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() { 71640b57cec5SDimitry Andric W.startLine() << "Dynamic Relocations {\n"; 71650b57cec5SDimitry Andric W.indent(); 7166e8d8bef9SDimitry Andric this->printDynamicRelocationsHelper(); 71670b57cec5SDimitry Andric W.unindent(); 71680b57cec5SDimitry Andric W.startLine() << "}\n"; 71690b57cec5SDimitry Andric } 71700b57cec5SDimitry Andric 71710b57cec5SDimitry Andric template <class ELFT> 7172e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printProgramHeaders( 7173e8d8bef9SDimitry Andric bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) { 71740b57cec5SDimitry Andric if (PrintProgramHeaders) 7175e8d8bef9SDimitry Andric printProgramHeaders(); 71760b57cec5SDimitry Andric if (PrintSectionMapping == cl::BOU_TRUE) 7177e8d8bef9SDimitry Andric printSectionMapping(); 71780b57cec5SDimitry Andric } 71790b57cec5SDimitry Andric 7180e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printProgramHeaders() { 71810b57cec5SDimitry Andric ListScope L(W, "ProgramHeaders"); 71820b57cec5SDimitry Andric 7183e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 71845ffd83dbSDimitry Andric if (!PhdrsOrErr) { 7185e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to dump program headers: " + 7186e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 71875ffd83dbSDimitry Andric return; 71885ffd83dbSDimitry Andric } 71895ffd83dbSDimitry Andric 71905ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 71910b57cec5SDimitry Andric DictScope P(W, "ProgramHeader"); 7192e8d8bef9SDimitry Andric StringRef Type = 7193e8d8bef9SDimitry Andric segmentTypeToString(this->Obj.getHeader().e_machine, Phdr.p_type); 7194e8d8bef9SDimitry Andric 7195e8d8bef9SDimitry Andric W.printHex("Type", Type.empty() ? "Unknown" : Type, Phdr.p_type); 71960b57cec5SDimitry Andric W.printHex("Offset", Phdr.p_offset); 71970b57cec5SDimitry Andric W.printHex("VirtualAddress", Phdr.p_vaddr); 71980b57cec5SDimitry Andric W.printHex("PhysicalAddress", Phdr.p_paddr); 71990b57cec5SDimitry Andric W.printNumber("FileSize", Phdr.p_filesz); 72000b57cec5SDimitry Andric W.printNumber("MemSize", Phdr.p_memsz); 7201bdd1243dSDimitry Andric W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags)); 72020b57cec5SDimitry Andric W.printNumber("Alignment", Phdr.p_align); 72030b57cec5SDimitry Andric } 72040b57cec5SDimitry Andric } 72050b57cec5SDimitry Andric 72060b57cec5SDimitry Andric template <class ELFT> 7207e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) { 72088bcb0991SDimitry Andric ListScope SS(W, "VersionSymbols"); 72090b57cec5SDimitry Andric if (!Sec) 72100b57cec5SDimitry Andric return; 72110b57cec5SDimitry Andric 7212480093f4SDimitry Andric StringRef StrTable; 7213480093f4SDimitry Andric ArrayRef<Elf_Sym> Syms; 7214e8d8bef9SDimitry Andric const Elf_Shdr *SymTabSec; 7215480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VerTableOrErr = 7216e8d8bef9SDimitry Andric this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec); 7217480093f4SDimitry Andric if (!VerTableOrErr) { 7218480093f4SDimitry Andric this->reportUniqueWarning(VerTableOrErr.takeError()); 7219480093f4SDimitry Andric return; 7220480093f4SDimitry Andric } 72210b57cec5SDimitry Andric 7222480093f4SDimitry Andric if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size()) 7223480093f4SDimitry Andric return; 7224480093f4SDimitry Andric 7225e8d8bef9SDimitry Andric ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec); 7226480093f4SDimitry Andric for (size_t I = 0, E = Syms.size(); I < E; ++I) { 72270b57cec5SDimitry Andric DictScope S(W, "Symbol"); 7228480093f4SDimitry Andric W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION); 7229e8d8bef9SDimitry Andric W.printString("Name", 7230e8d8bef9SDimitry Andric this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable, 7231e8d8bef9SDimitry Andric /*IsDynamic=*/true)); 72320b57cec5SDimitry Andric } 72330b57cec5SDimitry Andric } 72340b57cec5SDimitry Andric 7235349cc55cSDimitry Andric const EnumEntry<unsigned> SymVersionFlags[] = { 7236e8d8bef9SDimitry Andric {"Base", "BASE", VER_FLG_BASE}, 7237e8d8bef9SDimitry Andric {"Weak", "WEAK", VER_FLG_WEAK}, 7238e8d8bef9SDimitry Andric {"Info", "INFO", VER_FLG_INFO}}; 7239e8d8bef9SDimitry Andric 72400b57cec5SDimitry Andric template <class ELFT> 7241e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) { 72428bcb0991SDimitry Andric ListScope SD(W, "VersionDefinitions"); 72430b57cec5SDimitry Andric if (!Sec) 72440b57cec5SDimitry Andric return; 72450b57cec5SDimitry Andric 7246e8d8bef9SDimitry Andric Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec); 7247480093f4SDimitry Andric if (!V) { 7248480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 7249480093f4SDimitry Andric return; 72500b57cec5SDimitry Andric } 7251480093f4SDimitry Andric 7252480093f4SDimitry Andric for (const VerDef &D : *V) { 7253480093f4SDimitry Andric DictScope Def(W, "Definition"); 7254480093f4SDimitry Andric W.printNumber("Version", D.Version); 7255bdd1243dSDimitry Andric W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags)); 7256480093f4SDimitry Andric W.printNumber("Index", D.Ndx); 7257480093f4SDimitry Andric W.printNumber("Hash", D.Hash); 7258480093f4SDimitry Andric W.printString("Name", D.Name.c_str()); 7259480093f4SDimitry Andric W.printList( 7260480093f4SDimitry Andric "Predecessors", D.AuxV, 7261480093f4SDimitry Andric [](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); }); 72620b57cec5SDimitry Andric } 72630b57cec5SDimitry Andric } 72640b57cec5SDimitry Andric 72650b57cec5SDimitry Andric template <class ELFT> 7266e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) { 72678bcb0991SDimitry Andric ListScope SD(W, "VersionRequirements"); 72680b57cec5SDimitry Andric if (!Sec) 72690b57cec5SDimitry Andric return; 72700b57cec5SDimitry Andric 7271480093f4SDimitry Andric Expected<std::vector<VerNeed>> V = 7272e8d8bef9SDimitry Andric this->Obj.getVersionDependencies(*Sec, this->WarningHandler); 7273480093f4SDimitry Andric if (!V) { 7274480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 7275480093f4SDimitry Andric return; 72760b57cec5SDimitry Andric } 7277480093f4SDimitry Andric 7278480093f4SDimitry Andric for (const VerNeed &VN : *V) { 7279480093f4SDimitry Andric DictScope Entry(W, "Dependency"); 7280480093f4SDimitry Andric W.printNumber("Version", VN.Version); 7281480093f4SDimitry Andric W.printNumber("Count", VN.Cnt); 7282480093f4SDimitry Andric W.printString("FileName", VN.File.c_str()); 7283480093f4SDimitry Andric 7284480093f4SDimitry Andric ListScope L(W, "Entries"); 7285480093f4SDimitry Andric for (const VernAux &Aux : VN.AuxV) { 7286480093f4SDimitry Andric DictScope Entry(W, "Entry"); 7287480093f4SDimitry Andric W.printNumber("Hash", Aux.Hash); 7288bdd1243dSDimitry Andric W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags)); 7289480093f4SDimitry Andric W.printNumber("Index", Aux.Other); 7290480093f4SDimitry Andric W.printString("Name", Aux.Name.c_str()); 7291480093f4SDimitry Andric } 72920b57cec5SDimitry Andric } 72930b57cec5SDimitry Andric } 72940b57cec5SDimitry Andric 729506c3fb27SDimitry Andric template <class ELFT> 729606c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket, 729706c3fb27SDimitry Andric size_t MaxChain, 729806c3fb27SDimitry Andric size_t TotalSyms, 729906c3fb27SDimitry Andric ArrayRef<size_t> Count, 730006c3fb27SDimitry Andric bool IsGnu) const { 730106c3fb27SDimitry Andric StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram"; 730206c3fb27SDimitry Andric StringRef BucketName = IsGnu ? "Bucket" : "Chain"; 730306c3fb27SDimitry Andric StringRef ListName = IsGnu ? "Buckets" : "Chains"; 730406c3fb27SDimitry Andric DictScope Outer(W, HistName); 730506c3fb27SDimitry Andric W.printNumber("TotalBuckets", NBucket); 730606c3fb27SDimitry Andric ListScope Buckets(W, ListName); 730706c3fb27SDimitry Andric size_t CumulativeNonZero = 0; 730806c3fb27SDimitry Andric for (size_t I = 0; I < MaxChain; ++I) { 730906c3fb27SDimitry Andric CumulativeNonZero += Count[I] * I; 731006c3fb27SDimitry Andric DictScope Bucket(W, BucketName); 731106c3fb27SDimitry Andric W.printNumber("Length", I); 731206c3fb27SDimitry Andric W.printNumber("Count", Count[I]); 731306c3fb27SDimitry Andric W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket); 731406c3fb27SDimitry Andric W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms); 731506c3fb27SDimitry Andric } 73160b57cec5SDimitry Andric } 73170b57cec5SDimitry Andric 7318fe6060f1SDimitry Andric // Returns true if rel/rela section exists, and populates SymbolIndices. 7319fe6060f1SDimitry Andric // Otherwise returns false. 7320fe6060f1SDimitry Andric template <class ELFT> 7321fe6060f1SDimitry Andric static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection, 7322fe6060f1SDimitry Andric const ELFFile<ELFT> &Obj, 7323fe6060f1SDimitry Andric const LLVMELFDumper<ELFT> *Dumper, 7324fe6060f1SDimitry Andric SmallVector<uint32_t, 128> &SymbolIndices) { 7325fe6060f1SDimitry Andric if (!CGRelSection) { 7326fe6060f1SDimitry Andric Dumper->reportUniqueWarning( 7327fe6060f1SDimitry Andric "relocation section for a call graph section doesn't exist"); 7328fe6060f1SDimitry Andric return false; 7329fe6060f1SDimitry Andric } 7330fe6060f1SDimitry Andric 7331fe6060f1SDimitry Andric if (CGRelSection->sh_type == SHT_REL) { 7332fe6060f1SDimitry Andric typename ELFT::RelRange CGProfileRel; 7333fe6060f1SDimitry Andric Expected<typename ELFT::RelRange> CGProfileRelOrError = 7334fe6060f1SDimitry Andric Obj.rels(*CGRelSection); 7335fe6060f1SDimitry Andric if (!CGProfileRelOrError) { 7336fe6060f1SDimitry Andric Dumper->reportUniqueWarning("unable to load relocations for " 7337fe6060f1SDimitry Andric "SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7338fe6060f1SDimitry Andric toString(CGProfileRelOrError.takeError())); 7339fe6060f1SDimitry Andric return false; 7340fe6060f1SDimitry Andric } 7341fe6060f1SDimitry Andric 7342fe6060f1SDimitry Andric CGProfileRel = *CGProfileRelOrError; 7343fe6060f1SDimitry Andric for (const typename ELFT::Rel &Rel : CGProfileRel) 7344fe6060f1SDimitry Andric SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL())); 7345fe6060f1SDimitry Andric } else { 7346fe6060f1SDimitry Andric // MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert 7347fe6060f1SDimitry Andric // the format to SHT_RELA 7348fe6060f1SDimitry Andric // (https://sourceware.org/bugzilla/show_bug.cgi?id=28035) 7349fe6060f1SDimitry Andric typename ELFT::RelaRange CGProfileRela; 7350fe6060f1SDimitry Andric Expected<typename ELFT::RelaRange> CGProfileRelaOrError = 7351fe6060f1SDimitry Andric Obj.relas(*CGRelSection); 7352fe6060f1SDimitry Andric if (!CGProfileRelaOrError) { 7353fe6060f1SDimitry Andric Dumper->reportUniqueWarning("unable to load relocations for " 7354fe6060f1SDimitry Andric "SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7355fe6060f1SDimitry Andric toString(CGProfileRelaOrError.takeError())); 7356fe6060f1SDimitry Andric return false; 7357fe6060f1SDimitry Andric } 7358fe6060f1SDimitry Andric 7359fe6060f1SDimitry Andric CGProfileRela = *CGProfileRelaOrError; 7360fe6060f1SDimitry Andric for (const typename ELFT::Rela &Rela : CGProfileRela) 7361fe6060f1SDimitry Andric SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL())); 7362fe6060f1SDimitry Andric } 7363fe6060f1SDimitry Andric 7364fe6060f1SDimitry Andric return true; 7365fe6060f1SDimitry Andric } 7366fe6060f1SDimitry Andric 7367e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() { 7368fe6060f1SDimitry Andric auto IsMatch = [](const Elf_Shdr &Sec) -> bool { 7369fe6060f1SDimitry Andric return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE; 7370fe6060f1SDimitry Andric }; 7371fe6060f1SDimitry Andric 737206c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 737306c3fb27SDimitry Andric this->Obj.getSectionAndRelocations(IsMatch); 737406c3fb27SDimitry Andric if (!SecToRelocMapOrErr) { 737506c3fb27SDimitry Andric this->reportUniqueWarning("unable to get CG Profile section(s): " + 737606c3fb27SDimitry Andric toString(SecToRelocMapOrErr.takeError())); 737706c3fb27SDimitry Andric return; 737806c3fb27SDimitry Andric } 737906c3fb27SDimitry Andric 738006c3fb27SDimitry Andric for (const auto &CGMapEntry : *SecToRelocMapOrErr) { 7381fe6060f1SDimitry Andric const Elf_Shdr *CGSection = CGMapEntry.first; 7382fe6060f1SDimitry Andric const Elf_Shdr *CGRelSection = CGMapEntry.second; 73835ffd83dbSDimitry Andric 73845ffd83dbSDimitry Andric Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr = 7385fe6060f1SDimitry Andric this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection); 73865ffd83dbSDimitry Andric if (!CGProfileOrErr) { 73875ffd83dbSDimitry Andric this->reportUniqueWarning( 7388fe6060f1SDimitry Andric "unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7389e8d8bef9SDimitry Andric toString(CGProfileOrErr.takeError())); 73905ffd83dbSDimitry Andric return; 73915ffd83dbSDimitry Andric } 73925ffd83dbSDimitry Andric 7393fe6060f1SDimitry Andric SmallVector<uint32_t, 128> SymbolIndices; 7394fe6060f1SDimitry Andric bool UseReloc = 7395fe6060f1SDimitry Andric getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices); 7396fe6060f1SDimitry Andric if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) { 7397fe6060f1SDimitry Andric this->reportUniqueWarning( 7398fe6060f1SDimitry Andric "number of from/to pairs does not match number of frequencies"); 7399fe6060f1SDimitry Andric UseReloc = false; 7400fe6060f1SDimitry Andric } 7401fe6060f1SDimitry Andric 7402fe6060f1SDimitry Andric ListScope L(W, "CGProfile"); 7403fe6060f1SDimitry Andric for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) { 7404fe6060f1SDimitry Andric const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I]; 74050b57cec5SDimitry Andric DictScope D(W, "CGProfileEntry"); 7406fe6060f1SDimitry Andric if (UseReloc) { 7407fe6060f1SDimitry Andric uint32_t From = SymbolIndices[I * 2]; 7408fe6060f1SDimitry Andric uint32_t To = SymbolIndices[I * 2 + 1]; 7409fe6060f1SDimitry Andric W.printNumber("From", this->getStaticSymbolName(From), From); 7410fe6060f1SDimitry Andric W.printNumber("To", this->getStaticSymbolName(To), To); 7411fe6060f1SDimitry Andric } 74120b57cec5SDimitry Andric W.printNumber("Weight", CGPE.cgp_weight); 74130b57cec5SDimitry Andric } 74140b57cec5SDimitry Andric } 7415fe6060f1SDimitry Andric } 7416fe6060f1SDimitry Andric 7417fe6060f1SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() { 7418fe6060f1SDimitry Andric bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; 741906c3fb27SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 742006c3fb27SDimitry Andric auto IsMatch = [](const Elf_Shdr &Sec) -> bool { 742106c3fb27SDimitry Andric return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP || 742206c3fb27SDimitry Andric Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP_V0; 742306c3fb27SDimitry Andric }; 742406c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr = 742506c3fb27SDimitry Andric this->Obj.getSectionAndRelocations(IsMatch); 742606c3fb27SDimitry Andric if (!SecRelocMapOrErr) { 742706c3fb27SDimitry Andric this->reportUniqueWarning( 742806c3fb27SDimitry Andric "failed to get SHT_LLVM_BB_ADDR_MAP section(s): " + 742906c3fb27SDimitry Andric toString(SecRelocMapOrErr.takeError())); 743006c3fb27SDimitry Andric return; 743181ad6265SDimitry Andric } 743206c3fb27SDimitry Andric for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) { 7433bdd1243dSDimitry Andric std::optional<const Elf_Shdr *> FunctionSec; 7434fe6060f1SDimitry Andric if (IsRelocatable) 7435fe6060f1SDimitry Andric FunctionSec = 743606c3fb27SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link)); 7437fe6060f1SDimitry Andric ListScope L(W, "BBAddrMap"); 743806c3fb27SDimitry Andric if (IsRelocatable && !RelocSec) { 743906c3fb27SDimitry Andric this->reportUniqueWarning("unable to get relocation section for " + 744006c3fb27SDimitry Andric this->describe(*Sec)); 744106c3fb27SDimitry Andric continue; 744206c3fb27SDimitry Andric } 7443349cc55cSDimitry Andric Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = 744406c3fb27SDimitry Andric this->Obj.decodeBBAddrMap(*Sec, RelocSec); 7445fe6060f1SDimitry Andric if (!BBAddrMapOrErr) { 744606c3fb27SDimitry Andric this->reportUniqueWarning("unable to dump " + this->describe(*Sec) + 744706c3fb27SDimitry Andric ": " + toString(BBAddrMapOrErr.takeError())); 7448fe6060f1SDimitry Andric continue; 7449fe6060f1SDimitry Andric } 7450349cc55cSDimitry Andric for (const BBAddrMap &AM : *BBAddrMapOrErr) { 7451fe6060f1SDimitry Andric DictScope D(W, "Function"); 7452fe6060f1SDimitry Andric W.printHex("At", AM.Addr); 7453fe6060f1SDimitry Andric SmallVector<uint32_t> FuncSymIndex = 7454fe6060f1SDimitry Andric this->getSymbolIndexesForFunctionAddress(AM.Addr, FunctionSec); 7455fe6060f1SDimitry Andric std::string FuncName = "<?>"; 7456fe6060f1SDimitry Andric if (FuncSymIndex.empty()) 7457fe6060f1SDimitry Andric this->reportUniqueWarning( 7458fe6060f1SDimitry Andric "could not identify function symbol for address (0x" + 745906c3fb27SDimitry Andric Twine::utohexstr(AM.Addr) + ") in " + this->describe(*Sec)); 7460fe6060f1SDimitry Andric else 7461fe6060f1SDimitry Andric FuncName = this->getStaticSymbolName(FuncSymIndex.front()); 7462fe6060f1SDimitry Andric W.printString("Name", FuncName); 7463fe6060f1SDimitry Andric 7464fe6060f1SDimitry Andric ListScope L(W, "BB entries"); 7465349cc55cSDimitry Andric for (const BBAddrMap::BBEntry &BBE : AM.BBEntries) { 7466fe6060f1SDimitry Andric DictScope L(W); 7467bdd1243dSDimitry Andric W.printNumber("ID", BBE.ID); 7468fe6060f1SDimitry Andric W.printHex("Offset", BBE.Offset); 7469fe6060f1SDimitry Andric W.printHex("Size", BBE.Size); 747006c3fb27SDimitry Andric W.printBoolean("HasReturn", BBE.hasReturn()); 747106c3fb27SDimitry Andric W.printBoolean("HasTailCall", BBE.hasTailCall()); 747206c3fb27SDimitry Andric W.printBoolean("IsEHPad", BBE.isEHPad()); 747306c3fb27SDimitry Andric W.printBoolean("CanFallThrough", BBE.canFallThrough()); 747406c3fb27SDimitry Andric W.printBoolean("HasIndirectBranch", BBE.MD.HasIndirectBranch); 7475fe6060f1SDimitry Andric } 7476fe6060f1SDimitry Andric } 7477fe6060f1SDimitry Andric } 7478fe6060f1SDimitry Andric } 74790b57cec5SDimitry Andric 7480e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() { 74810b57cec5SDimitry Andric ListScope L(W, "Addrsig"); 7482e8d8bef9SDimitry Andric if (!this->DotAddrsigSec) 74830b57cec5SDimitry Andric return; 7484e8d8bef9SDimitry Andric 7485e8d8bef9SDimitry Andric Expected<std::vector<uint64_t>> SymsOrErr = 7486e8d8bef9SDimitry Andric decodeAddrsigSection(this->Obj, *this->DotAddrsigSec); 7487e8d8bef9SDimitry Andric if (!SymsOrErr) { 7488e8d8bef9SDimitry Andric this->reportUniqueWarning(SymsOrErr.takeError()); 74898bcb0991SDimitry Andric return; 74908bcb0991SDimitry Andric } 74918bcb0991SDimitry Andric 7492e8d8bef9SDimitry Andric for (uint64_t Sym : *SymsOrErr) 7493e8d8bef9SDimitry Andric W.printNumber("Sym", this->getStaticSymbolName(Sym), Sym); 74940b57cec5SDimitry Andric } 74950b57cec5SDimitry Andric 74960b57cec5SDimitry Andric template <typename ELFT> 7497fe6060f1SDimitry Andric static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, 74980b57cec5SDimitry Andric ScopedPrinter &W) { 7499fe6060f1SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 75000b57cec5SDimitry Andric switch (NoteType) { 75010b57cec5SDimitry Andric default: 7502fe6060f1SDimitry Andric return false; 75030b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 75040b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 75050b57cec5SDimitry Andric if (!AbiTag.IsValid) { 75060b57cec5SDimitry Andric W.printString("ABI", "<corrupt GNU_ABI_TAG>"); 7507fe6060f1SDimitry Andric return false; 75080b57cec5SDimitry Andric } else { 75090b57cec5SDimitry Andric W.printString("OS", AbiTag.OSName); 75100b57cec5SDimitry Andric W.printString("ABI", AbiTag.ABI); 75110b57cec5SDimitry Andric } 75120b57cec5SDimitry Andric break; 75130b57cec5SDimitry Andric } 75140b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 75150b57cec5SDimitry Andric W.printString("Build ID", getGNUBuildId(Desc)); 75160b57cec5SDimitry Andric break; 75170b57cec5SDimitry Andric } 75180b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 7519349cc55cSDimitry Andric W.printString("Version", getDescAsStringRef(Desc)); 75200b57cec5SDimitry Andric break; 75210b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 75220b57cec5SDimitry Andric ListScope D(W, "Property"); 7523e8d8bef9SDimitry Andric for (const std::string &Property : getGNUPropertyList<ELFT>(Desc)) 75240b57cec5SDimitry Andric W.printString(Property); 75250b57cec5SDimitry Andric break; 75260b57cec5SDimitry Andric } 7527fe6060f1SDimitry Andric return true; 75280b57cec5SDimitry Andric } 75290b57cec5SDimitry Andric 753081ad6265SDimitry Andric static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, 753181ad6265SDimitry Andric ScopedPrinter &W) { 753281ad6265SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 753381ad6265SDimitry Andric AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc); 753481ad6265SDimitry Andric if (Props.empty()) 753581ad6265SDimitry Andric return false; 753681ad6265SDimitry Andric for (const auto &KV : Props) 753781ad6265SDimitry Andric W.printString(KV.first, KV.second); 753881ad6265SDimitry Andric return true; 753981ad6265SDimitry Andric } 754081ad6265SDimitry Andric 754106c3fb27SDimitry Andric template <class ELFT> 754206c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printMemtag( 754306c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 754406c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 754506c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) { 754606c3fb27SDimitry Andric { 754706c3fb27SDimitry Andric ListScope L(W, "Memtag Dynamic Entries:"); 754806c3fb27SDimitry Andric if (DynamicEntries.empty()) 754906c3fb27SDimitry Andric W.printString("< none found >"); 755006c3fb27SDimitry Andric for (const auto &DynamicEntryKV : DynamicEntries) 755106c3fb27SDimitry Andric W.printString(DynamicEntryKV.first, DynamicEntryKV.second); 755206c3fb27SDimitry Andric } 755306c3fb27SDimitry Andric 755406c3fb27SDimitry Andric if (!AndroidNoteDesc.empty()) { 755506c3fb27SDimitry Andric ListScope L(W, "Memtag Android Note:"); 755606c3fb27SDimitry Andric printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W); 755706c3fb27SDimitry Andric } 755806c3fb27SDimitry Andric 755906c3fb27SDimitry Andric if (Descriptors.empty()) 756006c3fb27SDimitry Andric return; 756106c3fb27SDimitry Andric 756206c3fb27SDimitry Andric { 756306c3fb27SDimitry Andric ListScope L(W, "Memtag Global Descriptors:"); 756406c3fb27SDimitry Andric for (const auto &[Addr, BytesToTag] : Descriptors) { 756506c3fb27SDimitry Andric W.printHex("0x" + utohexstr(Addr), BytesToTag); 756606c3fb27SDimitry Andric } 756706c3fb27SDimitry Andric } 756806c3fb27SDimitry Andric } 756906c3fb27SDimitry Andric 7570349cc55cSDimitry Andric template <typename ELFT> 7571349cc55cSDimitry Andric static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType, 7572349cc55cSDimitry Andric ArrayRef<uint8_t> Desc, 7573349cc55cSDimitry Andric ScopedPrinter &W) { 7574349cc55cSDimitry Andric switch (NoteType) { 7575349cc55cSDimitry Andric default: 7576349cc55cSDimitry Andric return false; 7577349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION: 7578349cc55cSDimitry Andric W.printString("Version", getDescAsStringRef(Desc)); 7579349cc55cSDimitry Andric break; 7580349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER: 7581349cc55cSDimitry Andric W.printString("Producer", getDescAsStringRef(Desc)); 7582349cc55cSDimitry Andric break; 7583349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION: 7584349cc55cSDimitry Andric W.printString("Producer version", getDescAsStringRef(Desc)); 7585349cc55cSDimitry Andric break; 7586349cc55cSDimitry Andric } 7587349cc55cSDimitry Andric return true; 7588349cc55cSDimitry Andric } 7589349cc55cSDimitry Andric 75908bcb0991SDimitry Andric static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) { 75918bcb0991SDimitry Andric W.printNumber("Page Size", Note.PageSize); 75928bcb0991SDimitry Andric for (const CoreFileMapping &Mapping : Note.Mappings) { 75938bcb0991SDimitry Andric ListScope D(W, "Mapping"); 75948bcb0991SDimitry Andric W.printHex("Start", Mapping.Start); 75958bcb0991SDimitry Andric W.printHex("End", Mapping.End); 75968bcb0991SDimitry Andric W.printHex("Offset", Mapping.Offset); 75978bcb0991SDimitry Andric W.printString("Filename", Mapping.Filename); 75988bcb0991SDimitry Andric } 75998bcb0991SDimitry Andric } 76008bcb0991SDimitry Andric 7601e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() { 76020b57cec5SDimitry Andric ListScope L(W, "Notes"); 76030b57cec5SDimitry Andric 7604e8d8bef9SDimitry Andric std::unique_ptr<DictScope> NoteScope; 760506c3fb27SDimitry Andric size_t Align = 0; 7606bdd1243dSDimitry Andric auto StartNotes = [&](std::optional<StringRef> SecName, 76075ffd83dbSDimitry Andric const typename ELFT::Off Offset, 760806c3fb27SDimitry Andric const typename ELFT::Addr Size, size_t Al) { 760906c3fb27SDimitry Andric Align = std::max<size_t>(Al, 4); 7610e8d8bef9SDimitry Andric NoteScope = std::make_unique<DictScope>(W, "NoteSection"); 76115ffd83dbSDimitry Andric W.printString("Name", SecName ? *SecName : "<?>"); 76120b57cec5SDimitry Andric W.printHex("Offset", Offset); 76130b57cec5SDimitry Andric W.printHex("Size", Size); 76140b57cec5SDimitry Andric }; 76150b57cec5SDimitry Andric 7616e8d8bef9SDimitry Andric auto EndNotes = [&] { NoteScope.reset(); }; 7617e8d8bef9SDimitry Andric 7618fe6060f1SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 76190b57cec5SDimitry Andric DictScope D2(W, "Note"); 76200b57cec5SDimitry Andric StringRef Name = Note.getName(); 762106c3fb27SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(Align); 76220b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 76230b57cec5SDimitry Andric 76248bcb0991SDimitry Andric // Print the note owner/type. 76250b57cec5SDimitry Andric W.printString("Owner", Name); 76260b57cec5SDimitry Andric W.printHex("Data size", Descriptor.size()); 7627e8d8bef9SDimitry Andric 7628e8d8bef9SDimitry Andric StringRef NoteType = 7629e8d8bef9SDimitry Andric getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type); 76300b57cec5SDimitry Andric if (!NoteType.empty()) 76310b57cec5SDimitry Andric W.printString("Type", NoteType); 76320b57cec5SDimitry Andric else 76330b57cec5SDimitry Andric W.printString("Type", 76340b57cec5SDimitry Andric "Unknown (" + to_string(format_hex(Type, 10)) + ")"); 76358bcb0991SDimitry Andric 76368bcb0991SDimitry Andric // Print the description, or fallback to printing raw bytes for unknown 7637fe6060f1SDimitry Andric // owners/if we fail to pretty-print the contents. 76388bcb0991SDimitry Andric if (Name == "GNU") { 7639fe6060f1SDimitry Andric if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W)) 7640fe6060f1SDimitry Andric return Error::success(); 7641fe6060f1SDimitry Andric } else if (Name == "FreeBSD") { 7642bdd1243dSDimitry Andric if (std::optional<FreeBSDNote> N = 7643fe6060f1SDimitry Andric getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) { 7644fe6060f1SDimitry Andric W.printString(N->Type, N->Value); 7645fe6060f1SDimitry Andric return Error::success(); 7646fe6060f1SDimitry Andric } 76478bcb0991SDimitry Andric } else if (Name == "AMD") { 76488bcb0991SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 7649fe6060f1SDimitry Andric if (!N.Type.empty()) { 76508bcb0991SDimitry Andric W.printString(N.Type, N.Value); 7651fe6060f1SDimitry Andric return Error::success(); 7652fe6060f1SDimitry Andric } 76538bcb0991SDimitry Andric } else if (Name == "AMDGPU") { 76548bcb0991SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 7655fe6060f1SDimitry Andric if (!N.Type.empty()) { 76568bcb0991SDimitry Andric W.printString(N.Type, N.Value); 7657fe6060f1SDimitry Andric return Error::success(); 7658fe6060f1SDimitry Andric } 7659349cc55cSDimitry Andric } else if (Name == "LLVMOMPOFFLOAD") { 7660349cc55cSDimitry Andric if (printLLVMOMPOFFLOADNoteLLVMStyle<ELFT>(Type, Descriptor, W)) 7661349cc55cSDimitry Andric return Error::success(); 76628bcb0991SDimitry Andric } else if (Name == "CORE") { 76638bcb0991SDimitry Andric if (Type == ELF::NT_FILE) { 76648bcb0991SDimitry Andric DataExtractor DescExtractor(Descriptor, 76658bcb0991SDimitry Andric ELFT::TargetEndianness == support::little, 76668bcb0991SDimitry Andric sizeof(Elf_Addr)); 7667fe6060f1SDimitry Andric if (Expected<CoreNote> N = readCoreNote(DescExtractor)) { 7668fe6060f1SDimitry Andric printCoreNoteLLVMStyle(*N, W); 7669fe6060f1SDimitry Andric return Error::success(); 7670fe6060f1SDimitry Andric } else { 7671fe6060f1SDimitry Andric return N.takeError(); 76728bcb0991SDimitry Andric } 7673fe6060f1SDimitry Andric } 767481ad6265SDimitry Andric } else if (Name == "Android") { 767581ad6265SDimitry Andric if (printAndroidNoteLLVMStyle(Type, Descriptor, W)) 767681ad6265SDimitry Andric return Error::success(); 7677fe6060f1SDimitry Andric } 7678fe6060f1SDimitry Andric if (!Descriptor.empty()) { 76798bcb0991SDimitry Andric W.printBinaryBlock("Description data", Descriptor); 76808bcb0991SDimitry Andric } 7681e8d8bef9SDimitry Andric return Error::success(); 76820b57cec5SDimitry Andric }; 76830b57cec5SDimitry Andric 768406c3fb27SDimitry Andric processNotesHelper(*this, /*StartNotesFn=*/StartNotes, 768506c3fb27SDimitry Andric /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes); 76865ffd83dbSDimitry Andric } 76875ffd83dbSDimitry Andric 7688e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() { 76890b57cec5SDimitry Andric ListScope L(W, "LinkerOptions"); 76900b57cec5SDimitry Andric 7691480093f4SDimitry Andric unsigned I = -1; 7692e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(this->Obj.sections())) { 7693480093f4SDimitry Andric ++I; 76940b57cec5SDimitry Andric if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) 76950b57cec5SDimitry Andric continue; 76960b57cec5SDimitry Andric 7697e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = 7698e8d8bef9SDimitry Andric this->Obj.getSectionContents(Shdr); 76995ffd83dbSDimitry Andric if (!ContentsOrErr) { 7700e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to read the content of the " 77015ffd83dbSDimitry Andric "SHT_LLVM_LINKER_OPTIONS section: " + 7702e8d8bef9SDimitry Andric toString(ContentsOrErr.takeError())); 77035ffd83dbSDimitry Andric continue; 77045ffd83dbSDimitry Andric } 77055ffd83dbSDimitry Andric if (ContentsOrErr->empty()) 7706480093f4SDimitry Andric continue; 77070b57cec5SDimitry Andric 77085ffd83dbSDimitry Andric if (ContentsOrErr->back() != 0) { 7709e8d8bef9SDimitry Andric this->reportUniqueWarning("SHT_LLVM_LINKER_OPTIONS section at index " + 7710e8d8bef9SDimitry Andric Twine(I) + 7711480093f4SDimitry Andric " is broken: the " 7712e8d8bef9SDimitry Andric "content is not null-terminated"); 7713480093f4SDimitry Andric continue; 7714480093f4SDimitry Andric } 77150b57cec5SDimitry Andric 7716480093f4SDimitry Andric SmallVector<StringRef, 16> Strings; 77175ffd83dbSDimitry Andric toStringRef(ContentsOrErr->drop_back()).split(Strings, '\0'); 7718480093f4SDimitry Andric if (Strings.size() % 2 != 0) { 7719e8d8bef9SDimitry Andric this->reportUniqueWarning( 7720480093f4SDimitry Andric "SHT_LLVM_LINKER_OPTIONS section at index " + Twine(I) + 7721480093f4SDimitry Andric " is broken: an incomplete " 7722480093f4SDimitry Andric "key-value pair was found. The last possible key was: \"" + 7723e8d8bef9SDimitry Andric Strings.back() + "\""); 7724480093f4SDimitry Andric continue; 7725480093f4SDimitry Andric } 7726480093f4SDimitry Andric 7727480093f4SDimitry Andric for (size_t I = 0; I < Strings.size(); I += 2) 7728480093f4SDimitry Andric W.printString(Strings[I], Strings[I + 1]); 7729480093f4SDimitry Andric } 7730480093f4SDimitry Andric } 7731480093f4SDimitry Andric 7732e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDependentLibs() { 7733480093f4SDimitry Andric ListScope L(W, "DependentLibs"); 77345ffd83dbSDimitry Andric this->printDependentLibsHelper( 7735e8d8bef9SDimitry Andric [](const Elf_Shdr &) {}, 77365ffd83dbSDimitry Andric [this](StringRef Lib, uint64_t) { W.printString(Lib); }); 77370b57cec5SDimitry Andric } 77380b57cec5SDimitry Andric 7739e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() { 77408bcb0991SDimitry Andric ListScope L(W, "StackSizes"); 7741e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_type == ELF::ET_REL) 7742e8d8bef9SDimitry Andric this->printRelocatableStackSizes([]() {}); 77438bcb0991SDimitry Andric else 7744e8d8bef9SDimitry Andric this->printNonRelocatableStackSizes([]() {}); 77458bcb0991SDimitry Andric } 77468bcb0991SDimitry Andric 77478bcb0991SDimitry Andric template <class ELFT> 7748fe6060f1SDimitry Andric void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size, 7749fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) { 77508bcb0991SDimitry Andric DictScope D(W, "Entry"); 7751fe6060f1SDimitry Andric W.printList("Functions", FuncNames); 77528bcb0991SDimitry Andric W.printHex("Size", Size); 77538bcb0991SDimitry Andric } 77548bcb0991SDimitry Andric 77558bcb0991SDimitry Andric template <class ELFT> 7756e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 77570b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 77580b57cec5SDimitry Andric W.printHex("Address", Parser.getGotAddress(E)); 77590b57cec5SDimitry Andric W.printNumber("Access", Parser.getGotOffset(E)); 77600b57cec5SDimitry Andric W.printHex("Initial", *E); 77610b57cec5SDimitry Andric }; 77620b57cec5SDimitry Andric 77630b57cec5SDimitry Andric DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); 77640b57cec5SDimitry Andric 77650b57cec5SDimitry Andric W.printHex("Canonical gp value", Parser.getGp()); 77660b57cec5SDimitry Andric { 77670b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 77680b57cec5SDimitry Andric { 77690b57cec5SDimitry Andric DictScope D(W, "Entry"); 77700b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver()); 77710b57cec5SDimitry Andric W.printString("Purpose", StringRef("Lazy resolver")); 77720b57cec5SDimitry Andric } 77730b57cec5SDimitry Andric 77740b57cec5SDimitry Andric if (Parser.getGotModulePointer()) { 77750b57cec5SDimitry Andric DictScope D(W, "Entry"); 77760b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer()); 77770b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer (GNU extension)")); 77780b57cec5SDimitry Andric } 77790b57cec5SDimitry Andric } 77800b57cec5SDimitry Andric { 77810b57cec5SDimitry Andric ListScope LS(W, "Local entries"); 77820b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) { 77830b57cec5SDimitry Andric DictScope D(W, "Entry"); 77840b57cec5SDimitry Andric PrintEntry(&E); 77850b57cec5SDimitry Andric } 77860b57cec5SDimitry Andric } 77870b57cec5SDimitry Andric 77880b57cec5SDimitry Andric if (Parser.IsStatic) 77890b57cec5SDimitry Andric return; 77900b57cec5SDimitry Andric 77910b57cec5SDimitry Andric { 77920b57cec5SDimitry Andric ListScope GS(W, "Global entries"); 77930b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 77940b57cec5SDimitry Andric DictScope D(W, "Entry"); 77950b57cec5SDimitry Andric 77960b57cec5SDimitry Andric PrintEntry(&E); 77970b57cec5SDimitry Andric 7798e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getGotSym(&E); 7799e8d8bef9SDimitry Andric W.printHex("Value", Sym.st_value); 7800bdd1243dSDimitry Andric W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes)); 78010b57cec5SDimitry Andric 7802e8d8bef9SDimitry Andric const unsigned SymIndex = &Sym - this->dynamic_symbols().begin(); 7803e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 7804e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 7805e8d8bef9SDimitry Andric printSymbolSection(Sym, SymIndex, ShndxTable); 7806e8d8bef9SDimitry Andric 7807e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 7808e8d8bef9SDimitry Andric Sym, SymIndex, ShndxTable, this->DynamicStringTable, true); 7809e8d8bef9SDimitry Andric W.printNumber("Name", SymName, Sym.st_name); 78100b57cec5SDimitry Andric } 78110b57cec5SDimitry Andric } 78120b57cec5SDimitry Andric 78130b57cec5SDimitry Andric W.printNumber("Number of TLS and multi-GOT entries", 78140b57cec5SDimitry Andric uint64_t(Parser.getOtherEntries().size())); 78150b57cec5SDimitry Andric } 78160b57cec5SDimitry Andric 78170b57cec5SDimitry Andric template <class ELFT> 7818e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 78190b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 78200b57cec5SDimitry Andric W.printHex("Address", Parser.getPltAddress(E)); 78210b57cec5SDimitry Andric W.printHex("Initial", *E); 78220b57cec5SDimitry Andric }; 78230b57cec5SDimitry Andric 78240b57cec5SDimitry Andric DictScope GS(W, "PLT GOT"); 78250b57cec5SDimitry Andric 78260b57cec5SDimitry Andric { 78270b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 78280b57cec5SDimitry Andric { 78290b57cec5SDimitry Andric DictScope D(W, "Entry"); 78300b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver()); 78310b57cec5SDimitry Andric W.printString("Purpose", StringRef("PLT lazy resolver")); 78320b57cec5SDimitry Andric } 78330b57cec5SDimitry Andric 78340b57cec5SDimitry Andric if (auto E = Parser.getPltModulePointer()) { 78350b57cec5SDimitry Andric DictScope D(W, "Entry"); 78360b57cec5SDimitry Andric PrintEntry(E); 78370b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer")); 78380b57cec5SDimitry Andric } 78390b57cec5SDimitry Andric } 78400b57cec5SDimitry Andric { 78410b57cec5SDimitry Andric ListScope LS(W, "Entries"); 7842e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 7843e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 78440b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 78450b57cec5SDimitry Andric DictScope D(W, "Entry"); 78460b57cec5SDimitry Andric PrintEntry(&E); 78470b57cec5SDimitry Andric 7848e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getPltSym(&E); 7849e8d8bef9SDimitry Andric W.printHex("Value", Sym.st_value); 7850bdd1243dSDimitry Andric W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes)); 7851e8d8bef9SDimitry Andric printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(), 7852e8d8bef9SDimitry Andric ShndxTable); 78530b57cec5SDimitry Andric 7854e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = cantFail( 7855e8d8bef9SDimitry Andric this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0)); 7856e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 7857e8d8bef9SDimitry Andric Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true); 7858e8d8bef9SDimitry Andric W.printNumber("Name", SymName, Sym.st_name); 78590b57cec5SDimitry Andric } 78600b57cec5SDimitry Andric } 78610b57cec5SDimitry Andric } 78628bcb0991SDimitry Andric 7863e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() { 7864e8d8bef9SDimitry Andric const Elf_Mips_ABIFlags<ELFT> *Flags; 7865e8d8bef9SDimitry Andric if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr = 7866e8d8bef9SDimitry Andric getMipsAbiFlagsSection(*this)) { 7867e8d8bef9SDimitry Andric Flags = *SecOrErr; 7868e8d8bef9SDimitry Andric if (!Flags) { 78698bcb0991SDimitry Andric W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; 78708bcb0991SDimitry Andric return; 78718bcb0991SDimitry Andric } 7872e8d8bef9SDimitry Andric } else { 7873e8d8bef9SDimitry Andric this->reportUniqueWarning(SecOrErr.takeError()); 78748bcb0991SDimitry Andric return; 78758bcb0991SDimitry Andric } 78768bcb0991SDimitry Andric 78778bcb0991SDimitry Andric raw_ostream &OS = W.getOStream(); 78788bcb0991SDimitry Andric DictScope GS(W, "MIPS ABI Flags"); 78798bcb0991SDimitry Andric 78808bcb0991SDimitry Andric W.printNumber("Version", Flags->version); 78818bcb0991SDimitry Andric W.startLine() << "ISA: "; 78828bcb0991SDimitry Andric if (Flags->isa_rev <= 1) 78838bcb0991SDimitry Andric OS << format("MIPS%u", Flags->isa_level); 78848bcb0991SDimitry Andric else 78858bcb0991SDimitry Andric OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); 78868bcb0991SDimitry Andric OS << "\n"; 7887bdd1243dSDimitry Andric W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType)); 7888bdd1243dSDimitry Andric W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags)); 7889bdd1243dSDimitry Andric W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType)); 78908bcb0991SDimitry Andric W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); 78918bcb0991SDimitry Andric W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); 78928bcb0991SDimitry Andric W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); 7893bdd1243dSDimitry Andric W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1)); 78948bcb0991SDimitry Andric W.printHex("Flags 2", Flags->flags2); 78958bcb0991SDimitry Andric } 78960eae32dcSDimitry Andric 78970eae32dcSDimitry Andric template <class ELFT> 78980eae32dcSDimitry Andric void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj, 78990eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 79000eae32dcSDimitry Andric const Archive *A) { 7901bdd1243dSDimitry Andric FileScope = std::make_unique<DictScope>(this->W); 79020eae32dcSDimitry Andric DictScope D(this->W, "FileSummary"); 79030eae32dcSDimitry Andric this->W.printString("File", FileStr); 79040eae32dcSDimitry Andric this->W.printString("Format", Obj.getFileFormatName()); 79050eae32dcSDimitry Andric this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch())); 79060eae32dcSDimitry Andric this->W.printString( 79070eae32dcSDimitry Andric "AddressSize", 79080eae32dcSDimitry Andric std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); 79090eae32dcSDimitry Andric this->printLoadName(); 79100eae32dcSDimitry Andric } 791106c3fb27SDimitry Andric 791206c3fb27SDimitry Andric template <class ELFT> 791306c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printZeroSymbolOtherField( 791406c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 791506c3fb27SDimitry Andric // We want the JSON format to be uniform, since it is machine readable, so 791606c3fb27SDimitry Andric // always print the `Other` field the same way. 791706c3fb27SDimitry Andric this->printSymbolOtherField(Symbol); 791806c3fb27SDimitry Andric } 791906c3fb27SDimitry Andric 792006c3fb27SDimitry Andric template <class ELFT> 792106c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R, 792206c3fb27SDimitry Andric StringRef SymbolName, 792306c3fb27SDimitry Andric StringRef RelocName) { 792406c3fb27SDimitry Andric this->printExpandedRelRelaReloc(R, SymbolName, RelocName); 792506c3fb27SDimitry Andric } 792606c3fb27SDimitry Andric 792706c3fb27SDimitry Andric template <class ELFT> 792806c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec, 792906c3fb27SDimitry Andric StringRef Name, 793006c3fb27SDimitry Andric const unsigned SecNdx) { 793106c3fb27SDimitry Andric DictScope Group(this->W); 793206c3fb27SDimitry Andric this->W.printNumber("SectionIndex", SecNdx); 793306c3fb27SDimitry Andric ListScope D(this->W, "Relocs"); 793406c3fb27SDimitry Andric this->printRelocationsHelper(Sec); 793506c3fb27SDimitry Andric } 793606c3fb27SDimitry Andric 793706c3fb27SDimitry Andric template <class ELFT> 793806c3fb27SDimitry Andric std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const { 793906c3fb27SDimitry Andric return "GroupSections"; 794006c3fb27SDimitry Andric } 794106c3fb27SDimitry Andric 794206c3fb27SDimitry Andric template <class ELFT> 794306c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name, 794406c3fb27SDimitry Andric uint64_t Idx) const { 794506c3fb27SDimitry Andric DictScope Grp(this->W); 794606c3fb27SDimitry Andric this->W.printString("Name", Name); 794706c3fb27SDimitry Andric this->W.printNumber("Index", Idx); 794806c3fb27SDimitry Andric } 794906c3fb27SDimitry Andric 795006c3fb27SDimitry Andric template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const { 795106c3fb27SDimitry Andric // JSON output does not need to print anything for empty groups 795206c3fb27SDimitry Andric } 7953