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/STLExtras.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 270b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 280b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 290b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 300b57cec5SDimitry Andric #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" 310b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 3204eeddc0SDimitry Andric #include "llvm/BinaryFormat/MsgPackDocument.h" 330b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h" 340eae32dcSDimitry Andric #include "llvm/Object/Archive.h" 350b57cec5SDimitry Andric #include "llvm/Object/ELF.h" 360b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 370b57cec5SDimitry Andric #include "llvm/Object/ELFTypes.h" 380b57cec5SDimitry Andric #include "llvm/Object/Error.h" 390b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 408bcb0991SDimitry Andric #include "llvm/Object/RelocationResolver.h" 410b57cec5SDimitry Andric #include "llvm/Object/StackMapParser.h" 420b57cec5SDimitry Andric #include "llvm/Support/AMDGPUMetadata.h" 430b57cec5SDimitry Andric #include "llvm/Support/ARMAttributeParser.h" 440b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 450b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 460b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 470b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 480b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 490b57cec5SDimitry Andric #include "llvm/Support/Format.h" 500b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 510b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 52*0fca6ea1SDimitry Andric #include "llvm/Support/HexagonAttributeParser.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" 615f757f3fSDimitry Andric #include "llvm/Support/SystemZ/zOSSupport.h" 620b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 630b57cec5SDimitry Andric #include <algorithm> 64*0fca6ea1SDimitry Andric #include <array> 650b57cec5SDimitry Andric #include <cinttypes> 660b57cec5SDimitry Andric #include <cstddef> 670b57cec5SDimitry Andric #include <cstdint> 680b57cec5SDimitry Andric #include <cstdlib> 690b57cec5SDimitry Andric #include <iterator> 700b57cec5SDimitry Andric #include <memory> 71bdd1243dSDimitry Andric #include <optional> 720b57cec5SDimitry Andric #include <string> 730b57cec5SDimitry Andric #include <system_error> 740b57cec5SDimitry Andric #include <vector> 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric using namespace llvm; 770b57cec5SDimitry Andric using namespace llvm::object; 78*0fca6ea1SDimitry Andric using namespace llvm::support; 790b57cec5SDimitry Andric using namespace ELF; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ 820b57cec5SDimitry Andric case ns::enum: \ 830b57cec5SDimitry Andric return #enum; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric #define ENUM_ENT(enum, altName) \ 860b57cec5SDimitry Andric { #enum, altName, ELF::enum } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric #define ENUM_ENT_1(enum) \ 890b57cec5SDimitry Andric { #enum, #enum, ELF::enum } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric namespace { 920b57cec5SDimitry Andric 93e8d8bef9SDimitry Andric template <class ELFT> struct RelSymbol { 94e8d8bef9SDimitry Andric RelSymbol(const typename ELFT::Sym *S, StringRef N) 95e8d8bef9SDimitry Andric : Sym(S), Name(N.str()) {} 96e8d8bef9SDimitry Andric const typename ELFT::Sym *Sym; 97e8d8bef9SDimitry Andric std::string Name; 98e8d8bef9SDimitry Andric }; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric /// Represents a contiguous uniform range in the file. We cannot just create a 1010b57cec5SDimitry Andric /// range directly because when creating one of these from the .dynamic table 1020b57cec5SDimitry Andric /// the size, entity size and virtual address are different entries in arbitrary 1030b57cec5SDimitry Andric /// order (DT_REL, DT_RELSZ, DT_RELENT for example). 1040b57cec5SDimitry Andric struct DynRegionInfo { 105e8d8bef9SDimitry Andric DynRegionInfo(const Binary &Owner, const ObjDumper &D) 106e8d8bef9SDimitry Andric : Obj(&Owner), Dumper(&D) {} 107e8d8bef9SDimitry Andric DynRegionInfo(const Binary &Owner, const ObjDumper &D, const uint8_t *A, 108e8d8bef9SDimitry Andric uint64_t S, uint64_t ES) 109e8d8bef9SDimitry Andric : Addr(A), Size(S), EntSize(ES), Obj(&Owner), Dumper(&D) {} 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric /// Address in current address space. 112e8d8bef9SDimitry Andric const uint8_t *Addr = nullptr; 1130b57cec5SDimitry Andric /// Size in bytes of the region. 1140b57cec5SDimitry Andric uint64_t Size = 0; 1150b57cec5SDimitry Andric /// Size of each entity in the region. 1160b57cec5SDimitry Andric uint64_t EntSize = 0; 1170b57cec5SDimitry Andric 118e8d8bef9SDimitry Andric /// Owner object. Used for error reporting. 119e8d8bef9SDimitry Andric const Binary *Obj; 120e8d8bef9SDimitry Andric /// Dumper used for error reporting. 121e8d8bef9SDimitry Andric const ObjDumper *Dumper; 1225ffd83dbSDimitry Andric /// Error prefix. Used for error reporting to provide more information. 1235ffd83dbSDimitry Andric std::string Context; 1245ffd83dbSDimitry Andric /// Region size name. Used for error reporting. 1255ffd83dbSDimitry Andric StringRef SizePrintName = "size"; 1265ffd83dbSDimitry Andric /// Entry size name. Used for error reporting. If this field is empty, errors 1275ffd83dbSDimitry Andric /// will not mention the entry size. 1285ffd83dbSDimitry Andric StringRef EntSizePrintName = "entry size"; 1298bcb0991SDimitry Andric 1300b57cec5SDimitry Andric template <typename Type> ArrayRef<Type> getAsArrayRef() const { 1310b57cec5SDimitry Andric const Type *Start = reinterpret_cast<const Type *>(Addr); 1320b57cec5SDimitry Andric if (!Start) 1330b57cec5SDimitry Andric return {Start, Start}; 134e8d8bef9SDimitry Andric 135e8d8bef9SDimitry Andric const uint64_t Offset = 136e8d8bef9SDimitry Andric Addr - (const uint8_t *)Obj->getMemoryBufferRef().getBufferStart(); 137e8d8bef9SDimitry Andric const uint64_t ObjSize = Obj->getMemoryBufferRef().getBufferSize(); 138e8d8bef9SDimitry Andric 139e8d8bef9SDimitry Andric if (Size > ObjSize - Offset) { 140e8d8bef9SDimitry Andric Dumper->reportUniqueWarning( 141e8d8bef9SDimitry Andric "unable to read data at 0x" + Twine::utohexstr(Offset) + 142e8d8bef9SDimitry Andric " of size 0x" + Twine::utohexstr(Size) + " (" + SizePrintName + 143e8d8bef9SDimitry Andric "): it goes past the end of the file of size 0x" + 144e8d8bef9SDimitry Andric Twine::utohexstr(ObjSize)); 145e8d8bef9SDimitry Andric return {Start, Start}; 146e8d8bef9SDimitry Andric } 147e8d8bef9SDimitry Andric 1485ffd83dbSDimitry Andric if (EntSize == sizeof(Type) && (Size % EntSize == 0)) 1490b57cec5SDimitry Andric return {Start, Start + (Size / EntSize)}; 1505ffd83dbSDimitry Andric 1515ffd83dbSDimitry Andric std::string Msg; 1525ffd83dbSDimitry Andric if (!Context.empty()) 1535ffd83dbSDimitry Andric Msg += Context + " has "; 1545ffd83dbSDimitry Andric 1555ffd83dbSDimitry Andric Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")") 1565ffd83dbSDimitry Andric .str(); 1575ffd83dbSDimitry Andric if (!EntSizePrintName.empty()) 1585ffd83dbSDimitry Andric Msg += 1595ffd83dbSDimitry Andric (" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")") 1605ffd83dbSDimitry Andric .str(); 1615ffd83dbSDimitry Andric 162e8d8bef9SDimitry Andric Dumper->reportUniqueWarning(Msg); 1635ffd83dbSDimitry Andric return {Start, Start}; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric }; 1660b57cec5SDimitry Andric 167e8d8bef9SDimitry Andric struct GroupMember { 168e8d8bef9SDimitry Andric StringRef Name; 169e8d8bef9SDimitry Andric uint64_t Index; 170e8d8bef9SDimitry Andric }; 171e8d8bef9SDimitry Andric 172e8d8bef9SDimitry Andric struct GroupSection { 173e8d8bef9SDimitry Andric StringRef Name; 174e8d8bef9SDimitry Andric std::string Signature; 175e8d8bef9SDimitry Andric uint64_t ShName; 176e8d8bef9SDimitry Andric uint64_t Index; 177e8d8bef9SDimitry Andric uint32_t Link; 178e8d8bef9SDimitry Andric uint32_t Info; 179e8d8bef9SDimitry Andric uint32_t Type; 180e8d8bef9SDimitry Andric std::vector<GroupMember> Members; 181e8d8bef9SDimitry Andric }; 182e8d8bef9SDimitry Andric 183480093f4SDimitry Andric namespace { 184480093f4SDimitry Andric 185e8d8bef9SDimitry Andric struct NoteType { 186e8d8bef9SDimitry Andric uint32_t ID; 187e8d8bef9SDimitry Andric StringRef Name; 188480093f4SDimitry Andric }; 189480093f4SDimitry Andric 190480093f4SDimitry Andric } // namespace 191480093f4SDimitry Andric 192e8d8bef9SDimitry Andric template <class ELFT> class Relocation { 1930b57cec5SDimitry Andric public: 194e8d8bef9SDimitry Andric Relocation(const typename ELFT::Rel &R, bool IsMips64EL) 195e8d8bef9SDimitry Andric : Type(R.getType(IsMips64EL)), Symbol(R.getSymbol(IsMips64EL)), 196e8d8bef9SDimitry Andric Offset(R.r_offset), Info(R.r_info) {} 1970b57cec5SDimitry Andric 198e8d8bef9SDimitry Andric Relocation(const typename ELFT::Rela &R, bool IsMips64EL) 199e8d8bef9SDimitry Andric : Relocation((const typename ELFT::Rel &)R, IsMips64EL) { 200e8d8bef9SDimitry Andric Addend = R.r_addend; 201e8d8bef9SDimitry Andric } 202e8d8bef9SDimitry Andric 203e8d8bef9SDimitry Andric uint32_t Type; 204e8d8bef9SDimitry Andric uint32_t Symbol; 205e8d8bef9SDimitry Andric typename ELFT::uint Offset; 206e8d8bef9SDimitry Andric typename ELFT::uint Info; 207bdd1243dSDimitry Andric std::optional<int64_t> Addend; 208e8d8bef9SDimitry Andric }; 209e8d8bef9SDimitry Andric 210e8d8bef9SDimitry Andric template <class ELFT> class MipsGOTParser; 211e8d8bef9SDimitry Andric 212e8d8bef9SDimitry Andric template <typename ELFT> class ELFDumper : public ObjDumper { 213e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 214e8d8bef9SDimitry Andric 215e8d8bef9SDimitry Andric public: 216e8d8bef9SDimitry Andric ELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer); 217e8d8bef9SDimitry Andric 2180b57cec5SDimitry Andric void printUnwindInfo() override; 2190b57cec5SDimitry Andric void printNeededLibraries() override; 2200b57cec5SDimitry Andric void printHashTable() override; 221e8d8bef9SDimitry Andric void printGnuHashTable() override; 2220b57cec5SDimitry Andric void printLoadName() override; 2230b57cec5SDimitry Andric void printVersionInfo() override; 2248bcb0991SDimitry Andric void printArchSpecificInfo() override; 2250b57cec5SDimitry Andric void printStackMap() const override; 22606c3fb27SDimitry Andric void printMemtag() override; 22706c3fb27SDimitry Andric ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr); 22806c3fb27SDimitry Andric 22906c3fb27SDimitry Andric // Hash histogram shows statistics of how efficient the hash was for the 23006c3fb27SDimitry Andric // dynamic symbol table. The table shows the number of hash buckets for 23106c3fb27SDimitry Andric // different lengths of chains as an absolute number and percentage of the 23206c3fb27SDimitry Andric // total buckets, and the cumulative coverage of symbols for each set of 23306c3fb27SDimitry Andric // buckets. 23406c3fb27SDimitry Andric void printHashHistograms() override; 2350b57cec5SDimitry Andric 236e8d8bef9SDimitry Andric const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; }; 2370b57cec5SDimitry Andric 238e8d8bef9SDimitry Andric std::string describe(const Elf_Shdr &Sec) const; 2390b57cec5SDimitry Andric 240e8d8bef9SDimitry Andric unsigned getHashTableEntSize() const { 241e8d8bef9SDimitry Andric // EM_S390 and ELF::EM_ALPHA platforms use 8-bytes entries in SHT_HASH 242e8d8bef9SDimitry Andric // sections. This violates the ELF specification. 243e8d8bef9SDimitry Andric if (Obj.getHeader().e_machine == ELF::EM_S390 || 244e8d8bef9SDimitry Andric Obj.getHeader().e_machine == ELF::EM_ALPHA) 245e8d8bef9SDimitry Andric return 8; 246e8d8bef9SDimitry Andric return 4; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 24906c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> 25006c3fb27SDimitry Andric getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const; 25106c3fb27SDimitry Andric 2520b57cec5SDimitry Andric Elf_Dyn_Range dynamic_table() const { 2530b57cec5SDimitry Andric // A valid .dynamic section contains an array of entries terminated 2540b57cec5SDimitry Andric // with a DT_NULL entry. However, sometimes the section content may 2550b57cec5SDimitry Andric // continue past the DT_NULL entry, so to dump the section correctly, 2560b57cec5SDimitry Andric // we first find the end of the entries by iterating over them. 257e8d8bef9SDimitry Andric Elf_Dyn_Range Table = DynamicTable.template getAsArrayRef<Elf_Dyn>(); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric size_t Size = 0; 2600b57cec5SDimitry Andric while (Size < Table.size()) 2610b57cec5SDimitry Andric if (Table[Size++].getTag() == DT_NULL) 2620b57cec5SDimitry Andric break; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric return Table.slice(0, Size); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric Elf_Sym_Range dynamic_symbols() const { 2685ffd83dbSDimitry Andric if (!DynSymRegion) 2695ffd83dbSDimitry Andric return Elf_Sym_Range(); 270e8d8bef9SDimitry Andric return DynSymRegion->template getAsArrayRef<Elf_Sym>(); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 273e8d8bef9SDimitry Andric const Elf_Shdr *findSectionByName(StringRef Name) const; 274e8d8bef9SDimitry Andric 275e8d8bef9SDimitry Andric StringRef getDynamicStringTable() const { return DynamicStringTable; } 276e8d8bef9SDimitry Andric 277e8d8bef9SDimitry Andric protected: 278e8d8bef9SDimitry Andric virtual void printVersionSymbolSection(const Elf_Shdr *Sec) = 0; 279e8d8bef9SDimitry Andric virtual void printVersionDefinitionSection(const Elf_Shdr *Sec) = 0; 280e8d8bef9SDimitry Andric virtual void printVersionDependencySection(const Elf_Shdr *Sec) = 0; 281e8d8bef9SDimitry Andric 282e8d8bef9SDimitry Andric void 283e8d8bef9SDimitry Andric printDependentLibsHelper(function_ref<void(const Elf_Shdr &)> OnSectionStart, 284e8d8bef9SDimitry Andric function_ref<void(StringRef, uint64_t)> OnLibEntry); 285e8d8bef9SDimitry Andric 286e8d8bef9SDimitry Andric virtual void printRelRelaReloc(const Relocation<ELFT> &R, 287e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) = 0; 288e8d8bef9SDimitry Andric virtual void printDynamicRelocHeader(unsigned Type, StringRef Name, 289e8d8bef9SDimitry Andric const DynRegionInfo &Reg) {} 290e8d8bef9SDimitry Andric void printReloc(const Relocation<ELFT> &R, unsigned RelIndex, 291e8d8bef9SDimitry Andric const Elf_Shdr &Sec, const Elf_Shdr *SymTab); 292e8d8bef9SDimitry Andric void printDynamicReloc(const Relocation<ELFT> &R); 293e8d8bef9SDimitry Andric void printDynamicRelocationsHelper(); 294e8d8bef9SDimitry Andric void printRelocationsHelper(const Elf_Shdr &Sec); 295e8d8bef9SDimitry Andric void forEachRelocationDo( 296*0fca6ea1SDimitry Andric const Elf_Shdr &Sec, 297e8d8bef9SDimitry Andric llvm::function_ref<void(const Relocation<ELFT> &, unsigned, 298e8d8bef9SDimitry Andric const Elf_Shdr &, const Elf_Shdr *)> 299*0fca6ea1SDimitry Andric RelRelaFn); 300e8d8bef9SDimitry Andric 301e8d8bef9SDimitry Andric virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset, 3025f757f3fSDimitry Andric bool NonVisibilityBitsUsed, 3035f757f3fSDimitry Andric bool ExtraSymInfo) const {}; 304e8d8bef9SDimitry Andric virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 305e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 306bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 3075f757f3fSDimitry Andric bool NonVisibilityBitsUsed, 3085f757f3fSDimitry Andric bool ExtraSymInfo) const = 0; 309e8d8bef9SDimitry Andric 310e8d8bef9SDimitry Andric virtual void printMipsABIFlags() = 0; 311e8d8bef9SDimitry Andric virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; 312e8d8bef9SDimitry Andric virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0; 313e8d8bef9SDimitry Andric 31406c3fb27SDimitry Andric virtual void printMemtag( 31506c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 31606c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 31706c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0; 31806c3fb27SDimitry Andric 31906c3fb27SDimitry Andric virtual void printHashHistogram(const Elf_Hash &HashTable) const; 32006c3fb27SDimitry Andric virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const; 32106c3fb27SDimitry Andric virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain, 32206c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 32306c3fb27SDimitry Andric bool IsGnu) const = 0; 32406c3fb27SDimitry Andric 325e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Versym>> 326e8d8bef9SDimitry Andric getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab, 327e8d8bef9SDimitry Andric StringRef *StrTab, const Elf_Shdr **SymTabSec) const; 328e8d8bef9SDimitry Andric StringRef getPrintableSectionName(const Elf_Shdr &Sec) const; 329e8d8bef9SDimitry Andric 330e8d8bef9SDimitry Andric std::vector<GroupSection> getGroups(); 331e8d8bef9SDimitry Andric 332fe6060f1SDimitry Andric // Returns the function symbol index for the given address. Matches the 333fe6060f1SDimitry Andric // symbol's section with FunctionSec when specified. 334bdd1243dSDimitry Andric // Returns std::nullopt if no function symbol can be found for the address or 335bdd1243dSDimitry Andric // in case it is not defined in the specified section. 336bdd1243dSDimitry Andric SmallVector<uint32_t> getSymbolIndexesForFunctionAddress( 337bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec); 338e8d8bef9SDimitry Andric bool printFunctionStackSize(uint64_t SymValue, 339bdd1243dSDimitry Andric std::optional<const Elf_Shdr *> FunctionSec, 340e8d8bef9SDimitry Andric const Elf_Shdr &StackSizeSec, DataExtractor Data, 341e8d8bef9SDimitry Andric uint64_t *Offset); 342e8d8bef9SDimitry Andric void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec, 343e8d8bef9SDimitry Andric unsigned Ndx, const Elf_Shdr *SymTab, 344e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec, 345e8d8bef9SDimitry Andric const RelocationResolver &Resolver, DataExtractor Data); 346fe6060f1SDimitry Andric virtual void printStackSizeEntry(uint64_t Size, 347fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) = 0; 348e8d8bef9SDimitry Andric 349e8d8bef9SDimitry Andric void printRelocatableStackSizes(std::function<void()> PrintHeader); 350e8d8bef9SDimitry Andric void printNonRelocatableStackSizes(std::function<void()> PrintHeader); 351e8d8bef9SDimitry Andric 352e8d8bef9SDimitry Andric const object::ELFObjectFile<ELFT> &ObjF; 353e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj; 354e8d8bef9SDimitry Andric StringRef FileName; 355e8d8bef9SDimitry Andric 356e8d8bef9SDimitry Andric Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size, 357e8d8bef9SDimitry Andric uint64_t EntSize) { 358e8d8bef9SDimitry Andric if (Offset + Size < Offset || Offset + Size > Obj.getBufSize()) 359e8d8bef9SDimitry Andric return createError("offset (0x" + Twine::utohexstr(Offset) + 360e8d8bef9SDimitry Andric ") + size (0x" + Twine::utohexstr(Size) + 361e8d8bef9SDimitry Andric ") is greater than the file size (0x" + 362e8d8bef9SDimitry Andric Twine::utohexstr(Obj.getBufSize()) + ")"); 363e8d8bef9SDimitry Andric return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize); 364e8d8bef9SDimitry Andric } 365e8d8bef9SDimitry Andric 366349cc55cSDimitry Andric void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>, 3675f757f3fSDimitry Andric llvm::endianness); 368e8d8bef9SDimitry Andric void printMipsReginfo(); 369e8d8bef9SDimitry Andric void printMipsOptions(); 370e8d8bef9SDimitry Andric 371e8d8bef9SDimitry Andric std::pair<const Elf_Phdr *, const Elf_Shdr *> findDynamic(); 372e8d8bef9SDimitry Andric void loadDynamicTable(); 373e8d8bef9SDimitry Andric void parseDynamicTable(); 374e8d8bef9SDimitry Andric 375e8d8bef9SDimitry Andric Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym, 376e8d8bef9SDimitry Andric bool &IsDefault) const; 377bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const; 378e8d8bef9SDimitry Andric 379e8d8bef9SDimitry Andric DynRegionInfo DynRelRegion; 380e8d8bef9SDimitry Andric DynRegionInfo DynRelaRegion; 381*0fca6ea1SDimitry Andric DynRegionInfo DynCrelRegion; 382e8d8bef9SDimitry Andric DynRegionInfo DynRelrRegion; 383e8d8bef9SDimitry Andric DynRegionInfo DynPLTRelRegion; 384bdd1243dSDimitry Andric std::optional<DynRegionInfo> DynSymRegion; 385e8d8bef9SDimitry Andric DynRegionInfo DynSymTabShndxRegion; 386e8d8bef9SDimitry Andric DynRegionInfo DynamicTable; 387e8d8bef9SDimitry Andric StringRef DynamicStringTable; 388e8d8bef9SDimitry Andric const Elf_Hash *HashTable = nullptr; 389e8d8bef9SDimitry Andric const Elf_GnuHash *GnuHashTable = nullptr; 390e8d8bef9SDimitry Andric const Elf_Shdr *DotSymtabSec = nullptr; 391e8d8bef9SDimitry Andric const Elf_Shdr *DotDynsymSec = nullptr; 392e8d8bef9SDimitry Andric const Elf_Shdr *DotAddrsigSec = nullptr; 393e8d8bef9SDimitry Andric DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables; 394bdd1243dSDimitry Andric std::optional<uint64_t> SONameOffset; 395bdd1243dSDimitry Andric std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap; 396e8d8bef9SDimitry Andric 397e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version 398e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r 399e8d8bef9SDimitry Andric const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d 400e8d8bef9SDimitry Andric 401e8d8bef9SDimitry Andric std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex, 402e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 403bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 4040b57cec5SDimitry Andric bool IsDynamic) const; 405e8d8bef9SDimitry Andric Expected<unsigned> 406e8d8bef9SDimitry Andric getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex, 407e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const; 408e8d8bef9SDimitry Andric Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol, 409480093f4SDimitry Andric unsigned SectionIndex) const; 4105ffd83dbSDimitry Andric std::string getStaticSymbolName(uint32_t Index) const; 4115ffd83dbSDimitry Andric StringRef getDynamicString(uint64_t Value) const; 4120b57cec5SDimitry Andric 413*0fca6ea1SDimitry Andric std::pair<Elf_Sym_Range, std::optional<StringRef>> getSymtabAndStrtab() const; 4145f757f3fSDimitry Andric void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const; 4155ffd83dbSDimitry Andric std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; 4160b57cec5SDimitry Andric 417e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R, 418e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) const; 419480093f4SDimitry Andric 420e8d8bef9SDimitry Andric ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const; 4215ffd83dbSDimitry Andric 422e8d8bef9SDimitry Andric private: 423bdd1243dSDimitry Andric mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap; 4240b57cec5SDimitry Andric }; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric template <class ELFT> 427e8d8bef9SDimitry Andric std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const { 428e8d8bef9SDimitry Andric return ::describe(Obj, Sec); 429480093f4SDimitry Andric } 430480093f4SDimitry Andric 431e8d8bef9SDimitry Andric namespace { 432e8d8bef9SDimitry Andric 433e8d8bef9SDimitry Andric template <class ELFT> struct SymtabLink { 434e8d8bef9SDimitry Andric typename ELFT::SymRange Symbols; 435e8d8bef9SDimitry Andric StringRef StringTable; 436e8d8bef9SDimitry Andric const typename ELFT::Shdr *SymTab; 437e8d8bef9SDimitry Andric }; 438e8d8bef9SDimitry Andric 439e8d8bef9SDimitry Andric // Returns the linked symbol table, symbols and associated string table for a 440e8d8bef9SDimitry Andric // given section. 441480093f4SDimitry Andric template <class ELFT> 442e8d8bef9SDimitry Andric Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj, 443e8d8bef9SDimitry Andric const typename ELFT::Shdr &Sec, 444e8d8bef9SDimitry Andric unsigned ExpectedType) { 445480093f4SDimitry Andric Expected<const typename ELFT::Shdr *> SymtabOrErr = 446e8d8bef9SDimitry Andric Obj.getSection(Sec.sh_link); 447480093f4SDimitry Andric if (!SymtabOrErr) 448e8d8bef9SDimitry Andric return createError("invalid section linked to " + describe(Obj, Sec) + 449e8d8bef9SDimitry Andric ": " + toString(SymtabOrErr.takeError())); 450480093f4SDimitry Andric 451480093f4SDimitry Andric if ((*SymtabOrErr)->sh_type != ExpectedType) 452480093f4SDimitry Andric return createError( 453e8d8bef9SDimitry Andric "invalid section linked to " + describe(Obj, Sec) + ": expected " + 454e8d8bef9SDimitry Andric object::getELFSectionTypeName(Obj.getHeader().e_machine, ExpectedType) + 455480093f4SDimitry Andric ", but got " + 456e8d8bef9SDimitry Andric object::getELFSectionTypeName(Obj.getHeader().e_machine, 457480093f4SDimitry Andric (*SymtabOrErr)->sh_type)); 458480093f4SDimitry Andric 459e8d8bef9SDimitry Andric Expected<StringRef> StrTabOrErr = Obj.getLinkAsStrtab(**SymtabOrErr); 460480093f4SDimitry Andric if (!StrTabOrErr) 461480093f4SDimitry Andric return createError( 462480093f4SDimitry Andric "can't get a string table for the symbol table linked to " + 463e8d8bef9SDimitry Andric describe(Obj, Sec) + ": " + toString(StrTabOrErr.takeError())); 464480093f4SDimitry Andric 465e8d8bef9SDimitry Andric Expected<typename ELFT::SymRange> SymsOrErr = Obj.symbols(*SymtabOrErr); 466480093f4SDimitry Andric if (!SymsOrErr) 467e8d8bef9SDimitry Andric return createError("unable to read symbols from the " + describe(Obj, Sec) + 468e8d8bef9SDimitry Andric ": " + toString(SymsOrErr.takeError())); 469480093f4SDimitry Andric 470e8d8bef9SDimitry Andric return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr}; 471480093f4SDimitry Andric } 472480093f4SDimitry Andric 473e8d8bef9SDimitry Andric } // namespace 474e8d8bef9SDimitry Andric 475480093f4SDimitry Andric template <class ELFT> 476480093f4SDimitry Andric Expected<ArrayRef<typename ELFT::Versym>> 477e8d8bef9SDimitry Andric ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab, 478e8d8bef9SDimitry Andric StringRef *StrTab, 479e8d8bef9SDimitry Andric const Elf_Shdr **SymTabSec) const { 480e8d8bef9SDimitry Andric assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec)); 481e8d8bef9SDimitry Andric if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) % 482e8d8bef9SDimitry Andric sizeof(uint16_t) != 483e8d8bef9SDimitry Andric 0) 484e8d8bef9SDimitry Andric return createError("the " + describe(Sec) + " is misaligned"); 485480093f4SDimitry Andric 486480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VersionsOrErr = 487e8d8bef9SDimitry Andric Obj.template getSectionContentsAsArray<Elf_Versym>(Sec); 488480093f4SDimitry Andric if (!VersionsOrErr) 489e8d8bef9SDimitry Andric return createError("cannot read content of " + describe(Sec) + ": " + 490e8d8bef9SDimitry Andric toString(VersionsOrErr.takeError())); 491480093f4SDimitry Andric 492e8d8bef9SDimitry Andric Expected<SymtabLink<ELFT>> SymTabOrErr = 493e8d8bef9SDimitry Andric getLinkAsSymtab(Obj, Sec, SHT_DYNSYM); 494480093f4SDimitry Andric if (!SymTabOrErr) { 4955ffd83dbSDimitry Andric reportUniqueWarning(SymTabOrErr.takeError()); 496480093f4SDimitry Andric return *VersionsOrErr; 497480093f4SDimitry Andric } 498480093f4SDimitry Andric 499e8d8bef9SDimitry Andric if (SymTabOrErr->Symbols.size() != VersionsOrErr->size()) 500e8d8bef9SDimitry Andric reportUniqueWarning(describe(Sec) + ": the number of entries (" + 501e8d8bef9SDimitry Andric Twine(VersionsOrErr->size()) + 502480093f4SDimitry Andric ") does not match the number of symbols (" + 503e8d8bef9SDimitry Andric Twine(SymTabOrErr->Symbols.size()) + 504e8d8bef9SDimitry Andric ") in the symbol table with index " + 505e8d8bef9SDimitry Andric Twine(Sec.sh_link)); 506480093f4SDimitry Andric 507e8d8bef9SDimitry Andric if (SymTab) { 508e8d8bef9SDimitry Andric *SymTab = SymTabOrErr->Symbols; 509e8d8bef9SDimitry Andric *StrTab = SymTabOrErr->StringTable; 510e8d8bef9SDimitry Andric *SymTabSec = SymTabOrErr->SymTab; 511e8d8bef9SDimitry Andric } 512480093f4SDimitry Andric return *VersionsOrErr; 513480093f4SDimitry Andric } 514480093f4SDimitry Andric 515480093f4SDimitry Andric template <class ELFT> 516*0fca6ea1SDimitry Andric std::pair<typename ELFDumper<ELFT>::Elf_Sym_Range, std::optional<StringRef>> 517*0fca6ea1SDimitry Andric ELFDumper<ELFT>::getSymtabAndStrtab() const { 518*0fca6ea1SDimitry Andric assert(DotSymtabSec); 519*0fca6ea1SDimitry Andric Elf_Sym_Range Syms(nullptr, nullptr); 520*0fca6ea1SDimitry Andric std::optional<StringRef> StrTable; 521*0fca6ea1SDimitry Andric if (Expected<StringRef> StrTableOrErr = 522*0fca6ea1SDimitry Andric Obj.getStringTableForSymtab(*DotSymtabSec)) 523*0fca6ea1SDimitry Andric StrTable = *StrTableOrErr; 524*0fca6ea1SDimitry Andric else 525*0fca6ea1SDimitry Andric reportUniqueWarning( 526*0fca6ea1SDimitry Andric "unable to get the string table for the SHT_SYMTAB section: " + 527*0fca6ea1SDimitry Andric toString(StrTableOrErr.takeError())); 528*0fca6ea1SDimitry Andric 529*0fca6ea1SDimitry Andric if (Expected<Elf_Sym_Range> SymsOrErr = Obj.symbols(DotSymtabSec)) 530*0fca6ea1SDimitry Andric Syms = *SymsOrErr; 531*0fca6ea1SDimitry Andric else 532*0fca6ea1SDimitry Andric reportUniqueWarning("unable to read symbols from the SHT_SYMTAB section: " + 533*0fca6ea1SDimitry Andric toString(SymsOrErr.takeError())); 534*0fca6ea1SDimitry Andric return {Syms, StrTable}; 535*0fca6ea1SDimitry Andric } 536*0fca6ea1SDimitry Andric 537*0fca6ea1SDimitry Andric template <class ELFT> 5385f757f3fSDimitry Andric void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic, 5395f757f3fSDimitry Andric bool ExtraSymInfo) const { 540bdd1243dSDimitry Andric std::optional<StringRef> StrTable; 5410b57cec5SDimitry Andric size_t Entries = 0; 5420b57cec5SDimitry Andric Elf_Sym_Range Syms(nullptr, nullptr); 543e8d8bef9SDimitry Andric const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec; 544e8d8bef9SDimitry Andric 5450b57cec5SDimitry Andric if (IsDynamic) { 5460b57cec5SDimitry Andric StrTable = DynamicStringTable; 5470b57cec5SDimitry Andric Syms = dynamic_symbols(); 5485ffd83dbSDimitry Andric Entries = Syms.size(); 549e8d8bef9SDimitry Andric } else if (DotSymtabSec) { 550*0fca6ea1SDimitry Andric std::tie(Syms, StrTable) = getSymtabAndStrtab(); 5510b57cec5SDimitry Andric Entries = DotSymtabSec->getEntityCount(); 5520b57cec5SDimitry Andric } 553e8d8bef9SDimitry Andric if (Syms.empty()) 5540b57cec5SDimitry Andric return; 5558bcb0991SDimitry Andric 5568bcb0991SDimitry Andric // The st_other field has 2 logical parts. The first two bits hold the symbol 5578bcb0991SDimitry Andric // visibility (STV_*) and the remainder hold other platform-specific values. 558e8d8bef9SDimitry Andric bool NonVisibilityBitsUsed = 559e8d8bef9SDimitry Andric llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; }); 5608bcb0991SDimitry Andric 561e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable = 562e8d8bef9SDimitry Andric IsDynamic ? DataRegion<Elf_Word>( 563e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, 564e8d8bef9SDimitry Andric this->getElfObject().getELFFile().end()) 565e8d8bef9SDimitry Andric : DataRegion<Elf_Word>(this->getShndxTable(SymtabSec)); 566e8d8bef9SDimitry Andric 5675f757f3fSDimitry Andric printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo); 568e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : Syms) 569e8d8bef9SDimitry Andric printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic, 5705f757f3fSDimitry Andric NonVisibilityBitsUsed, ExtraSymInfo); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 573e8d8bef9SDimitry Andric template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> { 5740b57cec5SDimitry Andric formatted_raw_ostream &OS; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric public: 577e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 5780b57cec5SDimitry Andric 579e8d8bef9SDimitry Andric GNUELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 580e8d8bef9SDimitry Andric : ELFDumper<ELFT>(ObjF, Writer), 581e8d8bef9SDimitry Andric OS(static_cast<formatted_raw_ostream &>(Writer.getOStream())) { 582e8d8bef9SDimitry Andric assert(&this->W.getOStream() == &llvm::fouts()); 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850eae32dcSDimitry Andric void printFileSummary(StringRef FileStr, ObjectFile &Obj, 5860eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 5870eae32dcSDimitry Andric const Archive *A) override; 588e8d8bef9SDimitry Andric void printFileHeaders() override; 589e8d8bef9SDimitry Andric void printGroupSections() override; 590e8d8bef9SDimitry Andric void printRelocations() override; 591e8d8bef9SDimitry Andric void printSectionHeaders() override; 5925f757f3fSDimitry Andric void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols, 5935f757f3fSDimitry Andric bool ExtraSymInfo) override; 594e8d8bef9SDimitry Andric void printHashSymbols() override; 595e8d8bef9SDimitry Andric void printSectionDetails() override; 596e8d8bef9SDimitry Andric void printDependentLibs() override; 597e8d8bef9SDimitry Andric void printDynamicTable() override; 598e8d8bef9SDimitry Andric void printDynamicRelocations() override; 599e8d8bef9SDimitry Andric void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset, 6005f757f3fSDimitry Andric bool NonVisibilityBitsUsed, 6015f757f3fSDimitry Andric bool ExtraSymInfo) const override; 602e8d8bef9SDimitry Andric void printProgramHeaders(bool PrintProgramHeaders, 6030b57cec5SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 604e8d8bef9SDimitry Andric void printVersionSymbolSection(const Elf_Shdr *Sec) override; 605e8d8bef9SDimitry Andric void printVersionDefinitionSection(const Elf_Shdr *Sec) override; 606e8d8bef9SDimitry Andric void printVersionDependencySection(const Elf_Shdr *Sec) override; 607e8d8bef9SDimitry Andric void printCGProfile() override; 608*0fca6ea1SDimitry Andric void printBBAddrMaps(bool PrettyPGOAnalysis) override; 609e8d8bef9SDimitry Andric void printAddrsig() override; 610e8d8bef9SDimitry Andric void printNotes() override; 611e8d8bef9SDimitry Andric void printELFLinkerOptions() override; 612e8d8bef9SDimitry Andric void printStackSizes() override; 61306c3fb27SDimitry Andric void printMemtag( 61406c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 61506c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 61606c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override; 61706c3fb27SDimitry Andric void printHashHistogramStats(size_t NBucket, size_t MaxChain, 61806c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 61906c3fb27SDimitry Andric bool IsGnu) const override; 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric private: 622e8d8bef9SDimitry Andric void printHashTableSymbols(const Elf_Hash &HashTable); 623e8d8bef9SDimitry Andric void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable); 6245ffd83dbSDimitry Andric 6250b57cec5SDimitry Andric struct Field { 6260b57cec5SDimitry Andric std::string Str; 6270b57cec5SDimitry Andric unsigned Column; 6280b57cec5SDimitry Andric 6295ffd83dbSDimitry Andric Field(StringRef S, unsigned Col) : Str(std::string(S)), Column(Col) {} 6300b57cec5SDimitry Andric Field(unsigned Col) : Column(Col) {} 6310b57cec5SDimitry Andric }; 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric template <typename T, typename TEnum> 6340b57cec5SDimitry Andric std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues, 6350b57cec5SDimitry Andric TEnum EnumMask1 = {}, TEnum EnumMask2 = {}, 636e8d8bef9SDimitry Andric TEnum EnumMask3 = {}) const { 6370b57cec5SDimitry Andric std::string Str; 638e8d8bef9SDimitry Andric for (const EnumEntry<TEnum> &Flag : EnumValues) { 6390b57cec5SDimitry Andric if (Flag.Value == 0) 6400b57cec5SDimitry Andric continue; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric TEnum EnumMask{}; 6430b57cec5SDimitry Andric if (Flag.Value & EnumMask1) 6440b57cec5SDimitry Andric EnumMask = EnumMask1; 6450b57cec5SDimitry Andric else if (Flag.Value & EnumMask2) 6460b57cec5SDimitry Andric EnumMask = EnumMask2; 6470b57cec5SDimitry Andric else if (Flag.Value & EnumMask3) 6480b57cec5SDimitry Andric EnumMask = EnumMask3; 6490b57cec5SDimitry Andric bool IsEnum = (Flag.Value & EnumMask) != 0; 6500b57cec5SDimitry Andric if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 6510b57cec5SDimitry Andric (IsEnum && (Value & EnumMask) == Flag.Value)) { 6520b57cec5SDimitry Andric if (!Str.empty()) 6530b57cec5SDimitry Andric Str += ", "; 6540b57cec5SDimitry Andric Str += Flag.AltName; 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric return Str; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 660e8d8bef9SDimitry Andric formatted_raw_ostream &printField(struct Field F) const { 6610b57cec5SDimitry Andric if (F.Column != 0) 6620b57cec5SDimitry Andric OS.PadToColumn(F.Column); 6630b57cec5SDimitry Andric OS << F.Str; 6640b57cec5SDimitry Andric OS.flush(); 6650b57cec5SDimitry Andric return OS; 6660b57cec5SDimitry Andric } 667e8d8bef9SDimitry Andric void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex, 668e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, StringRef StrTable, 669e8d8bef9SDimitry Andric uint32_t Bucket); 670*0fca6ea1SDimitry Andric void printRelr(const Elf_Shdr &Sec); 671e8d8bef9SDimitry Andric void printRelRelaReloc(const Relocation<ELFT> &R, 672e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) override; 673e8d8bef9SDimitry Andric void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 674e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 675bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 6765f757f3fSDimitry Andric bool NonVisibilityBitsUsed, 6775f757f3fSDimitry Andric bool ExtraSymInfo) const override; 678e8d8bef9SDimitry Andric void printDynamicRelocHeader(unsigned Type, StringRef Name, 679e8d8bef9SDimitry Andric const DynRegionInfo &Reg) override; 680e8d8bef9SDimitry Andric 681e8d8bef9SDimitry Andric std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex, 6825f757f3fSDimitry Andric DataRegion<Elf_Word> ShndxTable, 6835f757f3fSDimitry Andric bool ExtraSymInfo = false) const; 684e8d8bef9SDimitry Andric void printProgramHeaders() override; 685e8d8bef9SDimitry Andric void printSectionMapping() override; 686e8d8bef9SDimitry Andric void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec, 687480093f4SDimitry Andric const Twine &Label, unsigned EntriesNum); 6880b57cec5SDimitry Andric 689fe6060f1SDimitry Andric void printStackSizeEntry(uint64_t Size, 690fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) override; 691e8d8bef9SDimitry Andric 6920b57cec5SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 6930b57cec5SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 694e8d8bef9SDimitry Andric void printMipsABIFlags() override; 695e8d8bef9SDimitry Andric }; 696e8d8bef9SDimitry Andric 697e8d8bef9SDimitry Andric template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> { 698e8d8bef9SDimitry Andric public: 699e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 700e8d8bef9SDimitry Andric 701e8d8bef9SDimitry Andric LLVMELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 702e8d8bef9SDimitry Andric : ELFDumper<ELFT>(ObjF, Writer), W(Writer) {} 703e8d8bef9SDimitry Andric 704e8d8bef9SDimitry Andric void printFileHeaders() override; 705e8d8bef9SDimitry Andric void printGroupSections() override; 706e8d8bef9SDimitry Andric void printRelocations() override; 707e8d8bef9SDimitry Andric void printSectionHeaders() override; 7085f757f3fSDimitry Andric void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols, 7095f757f3fSDimitry Andric bool ExtraSymInfo) override; 710e8d8bef9SDimitry Andric void printDependentLibs() override; 711e8d8bef9SDimitry Andric void printDynamicTable() override; 712e8d8bef9SDimitry Andric void printDynamicRelocations() override; 713e8d8bef9SDimitry Andric void printProgramHeaders(bool PrintProgramHeaders, 714e8d8bef9SDimitry Andric cl::boolOrDefault PrintSectionMapping) override; 715e8d8bef9SDimitry Andric void printVersionSymbolSection(const Elf_Shdr *Sec) override; 716e8d8bef9SDimitry Andric void printVersionDefinitionSection(const Elf_Shdr *Sec) override; 717e8d8bef9SDimitry Andric void printVersionDependencySection(const Elf_Shdr *Sec) override; 718e8d8bef9SDimitry Andric void printCGProfile() override; 719*0fca6ea1SDimitry Andric void printBBAddrMaps(bool PrettyPGOAnalysis) override; 720e8d8bef9SDimitry Andric void printAddrsig() override; 721e8d8bef9SDimitry Andric void printNotes() override; 722e8d8bef9SDimitry Andric void printELFLinkerOptions() override; 723e8d8bef9SDimitry Andric void printStackSizes() override; 72406c3fb27SDimitry Andric void printMemtag( 72506c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 72606c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 72706c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override; 72806c3fb27SDimitry Andric void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex, 72906c3fb27SDimitry Andric DataRegion<Elf_Word> ShndxTable) const; 73006c3fb27SDimitry Andric void printHashHistogramStats(size_t NBucket, size_t MaxChain, 73106c3fb27SDimitry Andric size_t TotalSyms, ArrayRef<size_t> Count, 73206c3fb27SDimitry Andric bool IsGnu) const override; 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric private: 735e8d8bef9SDimitry Andric void printRelRelaReloc(const Relocation<ELFT> &R, 736e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) override; 737e8d8bef9SDimitry Andric 738e8d8bef9SDimitry Andric void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 739e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 740bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic, 7415f757f3fSDimitry Andric bool /*NonVisibilityBitsUsed*/, 7425f757f3fSDimitry Andric bool /*ExtraSymInfo*/) const override; 743e8d8bef9SDimitry Andric void printProgramHeaders() override; 744e8d8bef9SDimitry Andric void printSectionMapping() override {} 745fe6060f1SDimitry Andric void printStackSizeEntry(uint64_t Size, 746fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) override; 747e8d8bef9SDimitry Andric 748e8d8bef9SDimitry Andric void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; 749e8d8bef9SDimitry Andric void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; 750e8d8bef9SDimitry Andric void printMipsABIFlags() override; 75106c3fb27SDimitry Andric virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; 7520b57cec5SDimitry Andric 7530eae32dcSDimitry Andric protected: 75406c3fb27SDimitry Andric virtual std::string getGroupSectionHeaderName() const; 75506c3fb27SDimitry Andric void printSymbolOtherField(const Elf_Sym &Symbol) const; 75606c3fb27SDimitry Andric virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R, 75706c3fb27SDimitry Andric StringRef SymbolName, 75806c3fb27SDimitry Andric StringRef RelocName); 75906c3fb27SDimitry Andric virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R, 76006c3fb27SDimitry Andric StringRef SymbolName, 76106c3fb27SDimitry Andric StringRef RelocName); 76206c3fb27SDimitry Andric virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, 76306c3fb27SDimitry Andric const unsigned SecNdx); 76406c3fb27SDimitry Andric virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const; 76506c3fb27SDimitry Andric virtual void printEmptyGroupMessage() const; 76606c3fb27SDimitry Andric 7670b57cec5SDimitry Andric ScopedPrinter &W; 7680b57cec5SDimitry Andric }; 7690b57cec5SDimitry Andric 7700eae32dcSDimitry Andric // JSONELFDumper shares most of the same implementation as LLVMELFDumper except 7710eae32dcSDimitry Andric // it uses a JSONScopedPrinter. 7720eae32dcSDimitry Andric template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> { 7730eae32dcSDimitry Andric public: 7740eae32dcSDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 7750eae32dcSDimitry Andric 7760eae32dcSDimitry Andric JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer) 7770eae32dcSDimitry Andric : LLVMELFDumper<ELFT>(ObjF, Writer) {} 7780eae32dcSDimitry Andric 77906c3fb27SDimitry Andric std::string getGroupSectionHeaderName() const override; 78006c3fb27SDimitry Andric 7810eae32dcSDimitry Andric void printFileSummary(StringRef FileStr, ObjectFile &Obj, 7820eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 7830eae32dcSDimitry Andric const Archive *A) override; 78406c3fb27SDimitry Andric virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override; 78506c3fb27SDimitry Andric 78606c3fb27SDimitry Andric void printDefaultRelRelaReloc(const Relocation<ELFT> &R, 78706c3fb27SDimitry Andric StringRef SymbolName, 78806c3fb27SDimitry Andric StringRef RelocName) override; 78906c3fb27SDimitry Andric 79006c3fb27SDimitry Andric void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, 79106c3fb27SDimitry Andric const unsigned SecNdx) override; 79206c3fb27SDimitry Andric 79306c3fb27SDimitry Andric void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override; 79406c3fb27SDimitry Andric 79506c3fb27SDimitry Andric void printEmptyGroupMessage() const override; 7960eae32dcSDimitry Andric 797*0fca6ea1SDimitry Andric void printDynamicTable() override; 798*0fca6ea1SDimitry Andric 7990eae32dcSDimitry Andric private: 800*0fca6ea1SDimitry Andric void printAuxillaryDynamicTableEntryInfo(const Elf_Dyn &Entry); 801*0fca6ea1SDimitry Andric 8020eae32dcSDimitry Andric std::unique_ptr<DictScope> FileScope; 8030eae32dcSDimitry Andric }; 8040eae32dcSDimitry Andric 8050b57cec5SDimitry Andric } // end anonymous namespace 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric namespace llvm { 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric template <class ELFT> 810e8d8bef9SDimitry Andric static std::unique_ptr<ObjDumper> 811e8d8bef9SDimitry Andric createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) { 812e8d8bef9SDimitry Andric if (opts::Output == opts::GNU) 813e8d8bef9SDimitry Andric return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer); 8140eae32dcSDimitry Andric else if (opts::Output == opts::JSON) 8150eae32dcSDimitry Andric return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer); 816e8d8bef9SDimitry Andric return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 819e8d8bef9SDimitry Andric std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj, 820e8d8bef9SDimitry Andric ScopedPrinter &Writer) { 8210b57cec5SDimitry Andric // Little-endian 32-bit 822e8d8bef9SDimitry Andric if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(&Obj)) 823e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric // Big-endian 32-bit 826e8d8bef9SDimitry Andric if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(&Obj)) 827e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // Little-endian 64-bit 830e8d8bef9SDimitry Andric if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj)) 831e8d8bef9SDimitry Andric return createELFDumper(*ELFObj, Writer); 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric // Big-endian 64-bit 834e8d8bef9SDimitry Andric return createELFDumper(*cast<ELF64BEObjectFile>(&Obj), Writer); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric } // end namespace llvm 8380b57cec5SDimitry Andric 839e8d8bef9SDimitry Andric template <class ELFT> 840bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> 841e8d8bef9SDimitry Andric ELFDumper<ELFT>::getVersionMap() const { 842e8d8bef9SDimitry Andric // If the VersionMap has already been loaded or if there is no dynamic symtab 843e8d8bef9SDimitry Andric // or version table, there is nothing to do. 844e8d8bef9SDimitry Andric if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection) 845e8d8bef9SDimitry Andric return &VersionMap; 8460b57cec5SDimitry Andric 847bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr = 848e8d8bef9SDimitry Andric Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection); 849e8d8bef9SDimitry Andric if (MapOrErr) 850e8d8bef9SDimitry Andric VersionMap = *MapOrErr; 851e8d8bef9SDimitry Andric else 852e8d8bef9SDimitry Andric return MapOrErr.takeError(); 8530b57cec5SDimitry Andric 854e8d8bef9SDimitry Andric return &VersionMap; 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric template <typename ELFT> 858e8d8bef9SDimitry Andric Expected<StringRef> ELFDumper<ELFT>::getSymbolVersion(const Elf_Sym &Sym, 8590b57cec5SDimitry Andric bool &IsDefault) const { 8600b57cec5SDimitry Andric // This is a dynamic symbol. Look in the GNU symbol version table. 8610b57cec5SDimitry Andric if (!SymbolVersionSection) { 8620b57cec5SDimitry Andric // No version table. 8630b57cec5SDimitry Andric IsDefault = false; 8640b57cec5SDimitry Andric return ""; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8675ffd83dbSDimitry Andric assert(DynSymRegion && "DynSymRegion has not been initialised"); 8680b57cec5SDimitry Andric // Determine the position in the symbol table of this entry. 869e8d8bef9SDimitry Andric size_t EntryIndex = (reinterpret_cast<uintptr_t>(&Sym) - 8705ffd83dbSDimitry Andric reinterpret_cast<uintptr_t>(DynSymRegion->Addr)) / 8710b57cec5SDimitry Andric sizeof(Elf_Sym); 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric // Get the corresponding version index entry. 874e8d8bef9SDimitry Andric Expected<const Elf_Versym *> EntryOrErr = 875e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Versym>(*SymbolVersionSection, EntryIndex); 876e8d8bef9SDimitry Andric if (!EntryOrErr) 8775ffd83dbSDimitry Andric return EntryOrErr.takeError(); 878e8d8bef9SDimitry Andric 879e8d8bef9SDimitry Andric unsigned Version = (*EntryOrErr)->vs_index; 880e8d8bef9SDimitry Andric if (Version == VER_NDX_LOCAL || Version == VER_NDX_GLOBAL) { 881e8d8bef9SDimitry Andric IsDefault = false; 882e8d8bef9SDimitry Andric return ""; 883e8d8bef9SDimitry Andric } 884e8d8bef9SDimitry Andric 885bdd1243dSDimitry Andric Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr = 886e8d8bef9SDimitry Andric getVersionMap(); 887e8d8bef9SDimitry Andric if (!MapOrErr) 888e8d8bef9SDimitry Andric return MapOrErr.takeError(); 889e8d8bef9SDimitry Andric 890e8d8bef9SDimitry Andric return Obj.getSymbolVersionByIndex(Version, IsDefault, **MapOrErr, 891e8d8bef9SDimitry Andric Sym.st_shndx == ELF::SHN_UNDEF); 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric template <typename ELFT> 895e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> 896e8d8bef9SDimitry Andric ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R, 897e8d8bef9SDimitry Andric const Elf_Shdr *SymTab) const { 898e8d8bef9SDimitry Andric if (R.Symbol == 0) 899e8d8bef9SDimitry Andric return RelSymbol<ELFT>(nullptr, ""); 900e8d8bef9SDimitry Andric 901e8d8bef9SDimitry Andric Expected<const Elf_Sym *> SymOrErr = 902e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Sym>(*SymTab, R.Symbol); 9035ffd83dbSDimitry Andric if (!SymOrErr) 904e8d8bef9SDimitry Andric return createError("unable to read an entry with index " + Twine(R.Symbol) + 905e8d8bef9SDimitry Andric " from " + describe(*SymTab) + ": " + 906e8d8bef9SDimitry Andric toString(SymOrErr.takeError())); 9075ffd83dbSDimitry Andric const Elf_Sym *Sym = *SymOrErr; 9085ffd83dbSDimitry Andric if (!Sym) 909e8d8bef9SDimitry Andric return RelSymbol<ELFT>(nullptr, ""); 9105ffd83dbSDimitry Andric 911e8d8bef9SDimitry Andric Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*SymTab); 9125ffd83dbSDimitry Andric if (!StrTableOrErr) 9135ffd83dbSDimitry Andric return StrTableOrErr.takeError(); 9145ffd83dbSDimitry Andric 915e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = 916e8d8bef9SDimitry Andric cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0)); 9175ffd83dbSDimitry Andric std::string SymbolName = 918e8d8bef9SDimitry Andric getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab), 919e8d8bef9SDimitry Andric *StrTableOrErr, SymTab->sh_type == SHT_DYNSYM); 920e8d8bef9SDimitry Andric return RelSymbol<ELFT>(Sym, SymbolName); 921e8d8bef9SDimitry Andric } 922e8d8bef9SDimitry Andric 923e8d8bef9SDimitry Andric template <typename ELFT> 924e8d8bef9SDimitry Andric ArrayRef<typename ELFT::Word> 925e8d8bef9SDimitry Andric ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const { 926e8d8bef9SDimitry Andric if (Symtab) { 927e8d8bef9SDimitry Andric auto It = ShndxTables.find(Symtab); 928e8d8bef9SDimitry Andric if (It != ShndxTables.end()) 929e8d8bef9SDimitry Andric return It->second; 930e8d8bef9SDimitry Andric } 931e8d8bef9SDimitry Andric return {}; 9325ffd83dbSDimitry Andric } 9335ffd83dbSDimitry Andric 9345ffd83dbSDimitry Andric static std::string maybeDemangle(StringRef Name) { 93506c3fb27SDimitry Andric return opts::Demangle ? demangle(Name) : Name.str(); 9365ffd83dbSDimitry Andric } 9375ffd83dbSDimitry Andric 9385ffd83dbSDimitry Andric template <typename ELFT> 9395ffd83dbSDimitry Andric std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { 9405ffd83dbSDimitry Andric auto Warn = [&](Error E) -> std::string { 941e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the name of symbol with index " + 942e8d8bef9SDimitry Andric Twine(Index) + ": " + toString(std::move(E))); 9435ffd83dbSDimitry Andric return "<?>"; 9445ffd83dbSDimitry Andric }; 9455ffd83dbSDimitry Andric 9468bcb0991SDimitry Andric Expected<const typename ELFT::Sym *> SymOrErr = 947e8d8bef9SDimitry Andric Obj.getSymbol(DotSymtabSec, Index); 9488bcb0991SDimitry Andric if (!SymOrErr) 9495ffd83dbSDimitry Andric return Warn(SymOrErr.takeError()); 9508bcb0991SDimitry Andric 951e8d8bef9SDimitry Andric Expected<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*DotSymtabSec); 9528bcb0991SDimitry Andric if (!StrTabOrErr) 9535ffd83dbSDimitry Andric return Warn(StrTabOrErr.takeError()); 9548bcb0991SDimitry Andric 9558bcb0991SDimitry Andric Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr); 9568bcb0991SDimitry Andric if (!NameOrErr) 9575ffd83dbSDimitry Andric return Warn(NameOrErr.takeError()); 9588bcb0991SDimitry Andric return maybeDemangle(*NameOrErr); 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric template <typename ELFT> 962bdd1243dSDimitry Andric std::string ELFDumper<ELFT>::getFullSymbolName( 963bdd1243dSDimitry Andric const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable, 964bdd1243dSDimitry Andric std::optional<StringRef> StrTable, bool IsDynamic) const { 9655ffd83dbSDimitry Andric if (!StrTable) 9665ffd83dbSDimitry Andric return "<?>"; 9675ffd83dbSDimitry Andric 9685ffd83dbSDimitry Andric std::string SymbolName; 969e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = Symbol.getName(*StrTable)) { 9705ffd83dbSDimitry Andric SymbolName = maybeDemangle(*NameOrErr); 9715ffd83dbSDimitry Andric } else { 9725ffd83dbSDimitry Andric reportUniqueWarning(NameOrErr.takeError()); 9735ffd83dbSDimitry Andric return "<?>"; 9745ffd83dbSDimitry Andric } 9750b57cec5SDimitry Andric 976e8d8bef9SDimitry Andric if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) { 977480093f4SDimitry Andric Expected<unsigned> SectionIndex = 978e8d8bef9SDimitry Andric getSymbolSectionIndex(Symbol, SymIndex, ShndxTable); 979480093f4SDimitry Andric if (!SectionIndex) { 9805ffd83dbSDimitry Andric reportUniqueWarning(SectionIndex.takeError()); 981480093f4SDimitry Andric return "<?>"; 982480093f4SDimitry Andric } 983480093f4SDimitry Andric Expected<StringRef> NameOrErr = getSymbolSectionName(Symbol, *SectionIndex); 984480093f4SDimitry Andric if (!NameOrErr) { 9855ffd83dbSDimitry Andric reportUniqueWarning(NameOrErr.takeError()); 986480093f4SDimitry Andric return ("<section " + Twine(*SectionIndex) + ">").str(); 987480093f4SDimitry Andric } 9885ffd83dbSDimitry Andric return std::string(*NameOrErr); 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric if (!IsDynamic) 9920b57cec5SDimitry Andric return SymbolName; 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric bool IsDefault; 995e8d8bef9SDimitry Andric Expected<StringRef> VersionOrErr = getSymbolVersion(Symbol, IsDefault); 996480093f4SDimitry Andric if (!VersionOrErr) { 9975ffd83dbSDimitry Andric reportUniqueWarning(VersionOrErr.takeError()); 998480093f4SDimitry Andric return SymbolName + "@<corrupt>"; 999480093f4SDimitry Andric } 1000480093f4SDimitry Andric 1001480093f4SDimitry Andric if (!VersionOrErr->empty()) { 10020b57cec5SDimitry Andric SymbolName += (IsDefault ? "@@" : "@"); 1003480093f4SDimitry Andric SymbolName += *VersionOrErr; 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric return SymbolName; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric template <typename ELFT> 1009480093f4SDimitry Andric Expected<unsigned> 1010e8d8bef9SDimitry Andric ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex, 1011e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const { 1012e8d8bef9SDimitry Andric unsigned Ndx = Symbol.st_shndx; 1013e8d8bef9SDimitry Andric if (Ndx == SHN_XINDEX) 1014e8d8bef9SDimitry Andric return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, 1015e8d8bef9SDimitry Andric ShndxTable); 1016e8d8bef9SDimitry Andric if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE) 1017e8d8bef9SDimitry Andric return Ndx; 1018e8d8bef9SDimitry Andric 1019bdd1243dSDimitry Andric auto CreateErr = [&](const Twine &Name, 1020bdd1243dSDimitry Andric std::optional<unsigned> Offset = std::nullopt) { 1021e8d8bef9SDimitry Andric std::string Desc; 1022e8d8bef9SDimitry Andric if (Offset) 1023e8d8bef9SDimitry Andric Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str(); 1024e8d8bef9SDimitry Andric else 1025e8d8bef9SDimitry Andric Desc = Name.str(); 1026e8d8bef9SDimitry Andric return createError( 1027e8d8bef9SDimitry Andric "unable to get section index for symbol with st_shndx = 0x" + 1028e8d8bef9SDimitry Andric Twine::utohexstr(Ndx) + " (" + Desc + ")"); 1029e8d8bef9SDimitry Andric }; 1030e8d8bef9SDimitry Andric 1031e8d8bef9SDimitry Andric if (Ndx >= ELF::SHN_LOPROC && Ndx <= ELF::SHN_HIPROC) 1032e8d8bef9SDimitry Andric return CreateErr("SHN_LOPROC", Ndx - ELF::SHN_LOPROC); 1033e8d8bef9SDimitry Andric if (Ndx >= ELF::SHN_LOOS && Ndx <= ELF::SHN_HIOS) 1034e8d8bef9SDimitry Andric return CreateErr("SHN_LOOS", Ndx - ELF::SHN_LOOS); 1035e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_UNDEF) 1036e8d8bef9SDimitry Andric return CreateErr("SHN_UNDEF"); 1037e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_ABS) 1038e8d8bef9SDimitry Andric return CreateErr("SHN_ABS"); 1039e8d8bef9SDimitry Andric if (Ndx == ELF::SHN_COMMON) 1040e8d8bef9SDimitry Andric return CreateErr("SHN_COMMON"); 1041e8d8bef9SDimitry Andric return CreateErr("SHN_LORESERVE", Ndx - SHN_LORESERVE); 10420b57cec5SDimitry Andric } 1043480093f4SDimitry Andric 1044480093f4SDimitry Andric template <typename ELFT> 1045480093f4SDimitry Andric Expected<StringRef> 1046e8d8bef9SDimitry Andric ELFDumper<ELFT>::getSymbolSectionName(const Elf_Sym &Symbol, 1047480093f4SDimitry Andric unsigned SectionIndex) const { 1048e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(SectionIndex); 1049480093f4SDimitry Andric if (!SecOrErr) 1050480093f4SDimitry Andric return SecOrErr.takeError(); 1051e8d8bef9SDimitry Andric return Obj.getSectionName(**SecOrErr); 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric template <class ELFO> 10550b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr * 1056e8d8bef9SDimitry Andric findNotEmptySectionByAddress(const ELFO &Obj, StringRef FileName, 10578bcb0991SDimitry Andric uint64_t Addr) { 10585ffd83dbSDimitry Andric for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections())) 1059e8d8bef9SDimitry Andric if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) 10600b57cec5SDimitry Andric return &Shdr; 10610b57cec5SDimitry Andric return nullptr; 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 1064349cc55cSDimitry Andric const EnumEntry<unsigned> ElfClass[] = { 10650b57cec5SDimitry Andric {"None", "none", ELF::ELFCLASSNONE}, 10660b57cec5SDimitry Andric {"32-bit", "ELF32", ELF::ELFCLASS32}, 10670b57cec5SDimitry Andric {"64-bit", "ELF64", ELF::ELFCLASS64}, 10680b57cec5SDimitry Andric }; 10690b57cec5SDimitry Andric 1070349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDataEncoding[] = { 10710b57cec5SDimitry Andric {"None", "none", ELF::ELFDATANONE}, 10720b57cec5SDimitry Andric {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB}, 10730b57cec5SDimitry Andric {"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB}, 10740b57cec5SDimitry Andric }; 10750b57cec5SDimitry Andric 1076349cc55cSDimitry Andric const EnumEntry<unsigned> ElfObjectFileType[] = { 10770b57cec5SDimitry Andric {"None", "NONE (none)", ELF::ET_NONE}, 10780b57cec5SDimitry Andric {"Relocatable", "REL (Relocatable file)", ELF::ET_REL}, 10790b57cec5SDimitry Andric {"Executable", "EXEC (Executable file)", ELF::ET_EXEC}, 10800b57cec5SDimitry Andric {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN}, 10810b57cec5SDimitry Andric {"Core", "CORE (Core file)", ELF::ET_CORE}, 10820b57cec5SDimitry Andric }; 10830b57cec5SDimitry Andric 1084349cc55cSDimitry Andric const EnumEntry<unsigned> ElfOSABI[] = { 10850b57cec5SDimitry Andric {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, 10860b57cec5SDimitry Andric {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, 10870b57cec5SDimitry Andric {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, 10880b57cec5SDimitry Andric {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, 10890b57cec5SDimitry Andric {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, 10900b57cec5SDimitry Andric {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, 10910b57cec5SDimitry Andric {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, 10920b57cec5SDimitry Andric {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, 10930b57cec5SDimitry Andric {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, 10940b57cec5SDimitry Andric {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, 10950b57cec5SDimitry Andric {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, 10960b57cec5SDimitry Andric {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, 10970b57cec5SDimitry Andric {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, 10980b57cec5SDimitry Andric {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, 10990b57cec5SDimitry Andric {"AROS", "AROS", ELF::ELFOSABI_AROS}, 11000b57cec5SDimitry Andric {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, 11010b57cec5SDimitry Andric {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, 11021db9f3b2SDimitry Andric {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA}, 11030b57cec5SDimitry Andric {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} 11040b57cec5SDimitry Andric }; 11050b57cec5SDimitry Andric 1106349cc55cSDimitry Andric const EnumEntry<unsigned> AMDGPUElfOSABI[] = { 11070b57cec5SDimitry Andric {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, 11080b57cec5SDimitry Andric {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL}, 11090b57cec5SDimitry Andric {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D} 11100b57cec5SDimitry Andric }; 11110b57cec5SDimitry Andric 1112349cc55cSDimitry Andric const EnumEntry<unsigned> ARMElfOSABI[] = { 1113*0fca6ea1SDimitry Andric {"ARM", "ARM", ELF::ELFOSABI_ARM}, 1114*0fca6ea1SDimitry Andric {"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC}, 11150b57cec5SDimitry Andric }; 11160b57cec5SDimitry Andric 1117349cc55cSDimitry Andric const EnumEntry<unsigned> C6000ElfOSABI[] = { 11180b57cec5SDimitry Andric {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI}, 11190b57cec5SDimitry Andric {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX} 11200b57cec5SDimitry Andric }; 11210b57cec5SDimitry Andric 1122349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMachineType[] = { 11230b57cec5SDimitry Andric ENUM_ENT(EM_NONE, "None"), 11240b57cec5SDimitry Andric ENUM_ENT(EM_M32, "WE32100"), 11250b57cec5SDimitry Andric ENUM_ENT(EM_SPARC, "Sparc"), 11260b57cec5SDimitry Andric ENUM_ENT(EM_386, "Intel 80386"), 11270b57cec5SDimitry Andric ENUM_ENT(EM_68K, "MC68000"), 11280b57cec5SDimitry Andric ENUM_ENT(EM_88K, "MC88000"), 11290b57cec5SDimitry Andric ENUM_ENT(EM_IAMCU, "EM_IAMCU"), 11300b57cec5SDimitry Andric ENUM_ENT(EM_860, "Intel 80860"), 11310b57cec5SDimitry Andric ENUM_ENT(EM_MIPS, "MIPS R3000"), 11320b57cec5SDimitry Andric ENUM_ENT(EM_S370, "IBM System/370"), 11330b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"), 11340b57cec5SDimitry Andric ENUM_ENT(EM_PARISC, "HPPA"), 11350b57cec5SDimitry Andric ENUM_ENT(EM_VPP500, "Fujitsu VPP500"), 11360b57cec5SDimitry Andric ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"), 11370b57cec5SDimitry Andric ENUM_ENT(EM_960, "Intel 80960"), 11380b57cec5SDimitry Andric ENUM_ENT(EM_PPC, "PowerPC"), 11390b57cec5SDimitry Andric ENUM_ENT(EM_PPC64, "PowerPC64"), 11400b57cec5SDimitry Andric ENUM_ENT(EM_S390, "IBM S/390"), 11410b57cec5SDimitry Andric ENUM_ENT(EM_SPU, "SPU"), 11420b57cec5SDimitry Andric ENUM_ENT(EM_V800, "NEC V800 series"), 11430b57cec5SDimitry Andric ENUM_ENT(EM_FR20, "Fujistsu FR20"), 11440b57cec5SDimitry Andric ENUM_ENT(EM_RH32, "TRW RH-32"), 11450b57cec5SDimitry Andric ENUM_ENT(EM_RCE, "Motorola RCE"), 11460b57cec5SDimitry Andric ENUM_ENT(EM_ARM, "ARM"), 11470b57cec5SDimitry Andric ENUM_ENT(EM_ALPHA, "EM_ALPHA"), 11480b57cec5SDimitry Andric ENUM_ENT(EM_SH, "Hitachi SH"), 11490b57cec5SDimitry Andric ENUM_ENT(EM_SPARCV9, "Sparc v9"), 11500b57cec5SDimitry Andric ENUM_ENT(EM_TRICORE, "Siemens Tricore"), 11510b57cec5SDimitry Andric ENUM_ENT(EM_ARC, "ARC"), 11520b57cec5SDimitry Andric ENUM_ENT(EM_H8_300, "Hitachi H8/300"), 11530b57cec5SDimitry Andric ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"), 11540b57cec5SDimitry Andric ENUM_ENT(EM_H8S, "Hitachi H8S"), 11550b57cec5SDimitry Andric ENUM_ENT(EM_H8_500, "Hitachi H8/500"), 11560b57cec5SDimitry Andric ENUM_ENT(EM_IA_64, "Intel IA-64"), 11570b57cec5SDimitry Andric ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"), 11580b57cec5SDimitry Andric ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"), 11590b57cec5SDimitry Andric ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"), 11600b57cec5SDimitry Andric ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"), 11610b57cec5SDimitry Andric ENUM_ENT(EM_PCP, "Siemens PCP"), 11620b57cec5SDimitry Andric ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"), 11630b57cec5SDimitry Andric ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"), 11640b57cec5SDimitry Andric ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"), 11650b57cec5SDimitry Andric ENUM_ENT(EM_ME16, "Toyota ME16 processor"), 11660b57cec5SDimitry Andric ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"), 11670b57cec5SDimitry Andric ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"), 11680b57cec5SDimitry Andric ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"), 11690b57cec5SDimitry Andric ENUM_ENT(EM_PDSP, "Sony DSP processor"), 11700b57cec5SDimitry Andric ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"), 11710b57cec5SDimitry Andric ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"), 11720b57cec5SDimitry Andric ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"), 11730b57cec5SDimitry Andric ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"), 11740b57cec5SDimitry Andric ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"), 11750b57cec5SDimitry Andric ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"), 11760b57cec5SDimitry Andric ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"), 11770b57cec5SDimitry Andric ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"), 11780b57cec5SDimitry Andric ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"), 11790b57cec5SDimitry Andric ENUM_ENT(EM_SVX, "Silicon Graphics SVx"), 11800b57cec5SDimitry Andric ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"), 11810b57cec5SDimitry Andric ENUM_ENT(EM_VAX, "Digital VAX"), 11820b57cec5SDimitry Andric ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"), 11830b57cec5SDimitry Andric ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"), 11840b57cec5SDimitry Andric ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"), 11850b57cec5SDimitry Andric ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"), 11860b57cec5SDimitry Andric ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"), 11870b57cec5SDimitry Andric ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"), 11880b57cec5SDimitry Andric ENUM_ENT(EM_PRISM, "Vitesse Prism"), 11890b57cec5SDimitry Andric ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"), 11900b57cec5SDimitry Andric ENUM_ENT(EM_FR30, "Fujitsu FR30"), 11910b57cec5SDimitry Andric ENUM_ENT(EM_D10V, "Mitsubishi D10V"), 11920b57cec5SDimitry Andric ENUM_ENT(EM_D30V, "Mitsubishi D30V"), 11930b57cec5SDimitry Andric ENUM_ENT(EM_V850, "NEC v850"), 11940b57cec5SDimitry Andric ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"), 11950b57cec5SDimitry Andric ENUM_ENT(EM_MN10300, "Matsushita MN10300"), 11960b57cec5SDimitry Andric ENUM_ENT(EM_MN10200, "Matsushita MN10200"), 11970b57cec5SDimitry Andric ENUM_ENT(EM_PJ, "picoJava"), 11980b57cec5SDimitry Andric ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"), 11990b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"), 12000b57cec5SDimitry Andric ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"), 12010b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"), 12020b57cec5SDimitry Andric ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"), 12030b57cec5SDimitry Andric ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"), 12040b57cec5SDimitry Andric ENUM_ENT(EM_TPC, "Tenor Network TPC processor"), 12050b57cec5SDimitry Andric ENUM_ENT(EM_SNP1K, "EM_SNP1K"), 12060b57cec5SDimitry Andric ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"), 12070b57cec5SDimitry Andric ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"), 12080b57cec5SDimitry Andric ENUM_ENT(EM_MAX, "MAX Processor"), 12090b57cec5SDimitry Andric ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"), 12100b57cec5SDimitry Andric ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"), 12110b57cec5SDimitry Andric ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"), 12120b57cec5SDimitry Andric ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"), 12130b57cec5SDimitry Andric ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"), 12140b57cec5SDimitry Andric ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"), 12150b57cec5SDimitry Andric ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"), 12160b57cec5SDimitry Andric ENUM_ENT(EM_UNICORE, "Unicore"), 12170b57cec5SDimitry Andric ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"), 12180b57cec5SDimitry Andric ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"), 12190b57cec5SDimitry Andric ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"), 12200b57cec5SDimitry Andric ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"), 12210b57cec5SDimitry Andric ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"), 12220b57cec5SDimitry Andric ENUM_ENT(EM_C166, "Infineon Technologies xc16x"), 12230b57cec5SDimitry Andric ENUM_ENT(EM_M16C, "Renesas M16C"), 12240b57cec5SDimitry Andric ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"), 12250b57cec5SDimitry Andric ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"), 12260b57cec5SDimitry Andric ENUM_ENT(EM_M32C, "Renesas M32C"), 12270b57cec5SDimitry Andric ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"), 12280b57cec5SDimitry Andric ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"), 12290b57cec5SDimitry Andric ENUM_ENT(EM_SHARC, "EM_SHARC"), 12300b57cec5SDimitry Andric ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"), 12310b57cec5SDimitry Andric ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"), 12320b57cec5SDimitry Andric ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"), 12330b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"), 12340b57cec5SDimitry Andric ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"), 12350b57cec5SDimitry Andric ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"), 12360b57cec5SDimitry Andric ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"), 12370b57cec5SDimitry Andric ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"), 12380b57cec5SDimitry Andric ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"), 12390b57cec5SDimitry Andric ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"), 12400b57cec5SDimitry Andric ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"), 12410b57cec5SDimitry Andric ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"), 12420b57cec5SDimitry Andric ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"), 12430b57cec5SDimitry Andric ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"), 12440b57cec5SDimitry Andric ENUM_ENT(EM_8051, "Intel 8051 and variants"), 12450b57cec5SDimitry Andric ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"), 12460b57cec5SDimitry Andric ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"), 12470b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"), 12485ffd83dbSDimitry Andric // FIXME: Following EM_ECOG1X definitions is dead code since EM_ECOG1X has 12495ffd83dbSDimitry Andric // an identical number to EM_ECOG1. 12500b57cec5SDimitry Andric ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"), 12510b57cec5SDimitry Andric ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"), 12520b57cec5SDimitry Andric ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"), 12530b57cec5SDimitry Andric ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"), 12540b57cec5SDimitry Andric ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"), 12550b57cec5SDimitry Andric ENUM_ENT(EM_RX, "Renesas RX"), 12560b57cec5SDimitry Andric ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"), 12570b57cec5SDimitry Andric ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"), 12580b57cec5SDimitry Andric ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"), 1259fe6060f1SDimitry Andric ENUM_ENT(EM_CR16, "National Semiconductor CompactRISC 16-bit processor"), 12600b57cec5SDimitry Andric ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"), 12610b57cec5SDimitry Andric ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"), 12620b57cec5SDimitry Andric ENUM_ENT(EM_L10M, "EM_L10M"), 12630b57cec5SDimitry Andric ENUM_ENT(EM_K10M, "EM_K10M"), 12640b57cec5SDimitry Andric ENUM_ENT(EM_AARCH64, "AArch64"), 12650b57cec5SDimitry Andric ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"), 12660b57cec5SDimitry Andric ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"), 12670b57cec5SDimitry Andric ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"), 12680b57cec5SDimitry Andric ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"), 1269fe6060f1SDimitry Andric ENUM_ENT(EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core"), 12700b57cec5SDimitry Andric ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"), 12710b57cec5SDimitry Andric ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"), 12720b57cec5SDimitry Andric ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"), 12730b57cec5SDimitry Andric ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"), 12740b57cec5SDimitry Andric ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"), 12750b57cec5SDimitry Andric ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"), 12760b57cec5SDimitry Andric ENUM_ENT(EM_OPEN8, "EM_OPEN8"), 12770b57cec5SDimitry Andric ENUM_ENT(EM_RL78, "Renesas RL78"), 12780b57cec5SDimitry Andric ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"), 12790b57cec5SDimitry Andric ENUM_ENT(EM_78KOR, "EM_78KOR"), 12800b57cec5SDimitry Andric ENUM_ENT(EM_56800EX, "EM_56800EX"), 12810b57cec5SDimitry Andric ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"), 12820b57cec5SDimitry Andric ENUM_ENT(EM_RISCV, "RISC-V"), 12830b57cec5SDimitry Andric ENUM_ENT(EM_LANAI, "EM_LANAI"), 12840b57cec5SDimitry Andric ENUM_ENT(EM_BPF, "EM_BPF"), 12855ffd83dbSDimitry Andric ENUM_ENT(EM_VE, "NEC SX-Aurora Vector Engine"), 128681ad6265SDimitry Andric ENUM_ENT(EM_LOONGARCH, "LoongArch"), 12870b57cec5SDimitry Andric }; 12880b57cec5SDimitry Andric 1289349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymbolBindings[] = { 12900b57cec5SDimitry Andric {"Local", "LOCAL", ELF::STB_LOCAL}, 12910b57cec5SDimitry Andric {"Global", "GLOBAL", ELF::STB_GLOBAL}, 12920b57cec5SDimitry Andric {"Weak", "WEAK", ELF::STB_WEAK}, 12930b57cec5SDimitry Andric {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}}; 12940b57cec5SDimitry Andric 1295349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymbolVisibilities[] = { 12960b57cec5SDimitry Andric {"DEFAULT", "DEFAULT", ELF::STV_DEFAULT}, 12970b57cec5SDimitry Andric {"INTERNAL", "INTERNAL", ELF::STV_INTERNAL}, 12980b57cec5SDimitry Andric {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN}, 12990b57cec5SDimitry Andric {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; 13000b57cec5SDimitry Andric 1301349cc55cSDimitry Andric const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { 13020b57cec5SDimitry Andric { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } 13030b57cec5SDimitry Andric }; 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric static const char *getGroupType(uint32_t Flag) { 13060b57cec5SDimitry Andric if (Flag & ELF::GRP_COMDAT) 13070b57cec5SDimitry Andric return "COMDAT"; 13080b57cec5SDimitry Andric else 13090b57cec5SDimitry Andric return "(unknown)"; 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 1312349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSectionFlags[] = { 13130b57cec5SDimitry Andric ENUM_ENT(SHF_WRITE, "W"), 13140b57cec5SDimitry Andric ENUM_ENT(SHF_ALLOC, "A"), 13150b57cec5SDimitry Andric ENUM_ENT(SHF_EXECINSTR, "X"), 13160b57cec5SDimitry Andric ENUM_ENT(SHF_MERGE, "M"), 13170b57cec5SDimitry Andric ENUM_ENT(SHF_STRINGS, "S"), 13180b57cec5SDimitry Andric ENUM_ENT(SHF_INFO_LINK, "I"), 13190b57cec5SDimitry Andric ENUM_ENT(SHF_LINK_ORDER, "L"), 1320480093f4SDimitry Andric ENUM_ENT(SHF_OS_NONCONFORMING, "O"), 13210b57cec5SDimitry Andric ENUM_ENT(SHF_GROUP, "G"), 13220b57cec5SDimitry Andric ENUM_ENT(SHF_TLS, "T"), 1323480093f4SDimitry Andric ENUM_ENT(SHF_COMPRESSED, "C"), 1324480093f4SDimitry Andric ENUM_ENT(SHF_EXCLUDE, "E"), 13250b57cec5SDimitry Andric }; 13260b57cec5SDimitry Andric 132781ad6265SDimitry Andric const EnumEntry<unsigned> ElfGNUSectionFlags[] = { 132881ad6265SDimitry Andric ENUM_ENT(SHF_GNU_RETAIN, "R") 132981ad6265SDimitry Andric }; 133081ad6265SDimitry Andric 133181ad6265SDimitry Andric const EnumEntry<unsigned> ElfSolarisSectionFlags[] = { 133281ad6265SDimitry Andric ENUM_ENT(SHF_SUNW_NODISCARD, "R") 133381ad6265SDimitry Andric }; 133481ad6265SDimitry Andric 1335349cc55cSDimitry Andric const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { 1336480093f4SDimitry Andric ENUM_ENT(XCORE_SHF_CP_SECTION, ""), 1337480093f4SDimitry Andric ENUM_ENT(XCORE_SHF_DP_SECTION, "") 13380b57cec5SDimitry Andric }; 13390b57cec5SDimitry Andric 1340349cc55cSDimitry Andric const EnumEntry<unsigned> ElfARMSectionFlags[] = { 1341480093f4SDimitry Andric ENUM_ENT(SHF_ARM_PURECODE, "y") 13420b57cec5SDimitry Andric }; 13430b57cec5SDimitry Andric 1344349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { 1345480093f4SDimitry Andric ENUM_ENT(SHF_HEX_GPREL, "") 13460b57cec5SDimitry Andric }; 13470b57cec5SDimitry Andric 1348349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsSectionFlags[] = { 1349480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NODUPES, ""), 1350480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NAMES, ""), 1351480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_LOCAL, ""), 1352480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_NOSTRIP, ""), 1353480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_GPREL, ""), 1354480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_MERGE, ""), 1355480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_ADDR, ""), 1356480093f4SDimitry Andric ENUM_ENT(SHF_MIPS_STRING, "") 13570b57cec5SDimitry Andric }; 13580b57cec5SDimitry Andric 1359349cc55cSDimitry Andric const EnumEntry<unsigned> ElfX86_64SectionFlags[] = { 1360480093f4SDimitry Andric ENUM_ENT(SHF_X86_64_LARGE, "l") 13610b57cec5SDimitry Andric }; 13620b57cec5SDimitry Andric 1363480093f4SDimitry Andric static std::vector<EnumEntry<unsigned>> 136481ad6265SDimitry Andric getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) { 1365480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags), 1366480093f4SDimitry Andric std::end(ElfSectionFlags)); 136781ad6265SDimitry Andric switch (EOSAbi) { 136881ad6265SDimitry Andric case ELFOSABI_SOLARIS: 136981ad6265SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags), 137081ad6265SDimitry Andric std::end(ElfSolarisSectionFlags)); 137181ad6265SDimitry Andric break; 137281ad6265SDimitry Andric default: 137381ad6265SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags), 137481ad6265SDimitry Andric std::end(ElfGNUSectionFlags)); 137581ad6265SDimitry Andric break; 137681ad6265SDimitry Andric } 1377480093f4SDimitry Andric switch (EMachine) { 1378480093f4SDimitry Andric case EM_ARM: 1379480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags), 1380480093f4SDimitry Andric std::end(ElfARMSectionFlags)); 1381480093f4SDimitry Andric break; 1382480093f4SDimitry Andric case EM_HEXAGON: 1383480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfHexagonSectionFlags), 1384480093f4SDimitry Andric std::end(ElfHexagonSectionFlags)); 1385480093f4SDimitry Andric break; 1386480093f4SDimitry Andric case EM_MIPS: 1387480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfMipsSectionFlags), 1388480093f4SDimitry Andric std::end(ElfMipsSectionFlags)); 1389480093f4SDimitry Andric break; 1390480093f4SDimitry Andric case EM_X86_64: 1391480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfX86_64SectionFlags), 1392480093f4SDimitry Andric std::end(ElfX86_64SectionFlags)); 1393480093f4SDimitry Andric break; 1394480093f4SDimitry Andric case EM_XCORE: 1395480093f4SDimitry Andric Ret.insert(Ret.end(), std::begin(ElfXCoreSectionFlags), 1396480093f4SDimitry Andric std::end(ElfXCoreSectionFlags)); 13970b57cec5SDimitry Andric break; 13980b57cec5SDimitry Andric default: 1399480093f4SDimitry Andric break; 1400480093f4SDimitry Andric } 1401480093f4SDimitry Andric return Ret; 1402480093f4SDimitry Andric } 1403480093f4SDimitry Andric 140481ad6265SDimitry Andric static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine, 140581ad6265SDimitry Andric uint64_t Flags) { 1406480093f4SDimitry Andric // Here we are trying to build the flags string in the same way as GNU does. 1407480093f4SDimitry Andric // It is not that straightforward. Imagine we have sh_flags == 0x90000000. 1408480093f4SDimitry Andric // SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000. 1409480093f4SDimitry Andric // GNU readelf will not print "E" or "Ep" in this case, but will print just 1410480093f4SDimitry Andric // "p". It only will print "E" when no other processor flag is set. 1411480093f4SDimitry Andric std::string Str; 1412480093f4SDimitry Andric bool HasUnknownFlag = false; 1413480093f4SDimitry Andric bool HasOSFlag = false; 1414480093f4SDimitry Andric bool HasProcFlag = false; 1415480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> FlagsList = 141681ad6265SDimitry Andric getSectionFlagsForTarget(EOSAbi, EMachine); 1417480093f4SDimitry Andric while (Flags) { 1418480093f4SDimitry Andric // Take the least significant bit as a flag. 1419480093f4SDimitry Andric uint64_t Flag = Flags & -Flags; 1420480093f4SDimitry Andric Flags -= Flag; 1421480093f4SDimitry Andric 1422480093f4SDimitry Andric // Find the flag in the known flags list. 1423480093f4SDimitry Andric auto I = llvm::find_if(FlagsList, [=](const EnumEntry<unsigned> &E) { 1424480093f4SDimitry Andric // Flags with empty names are not printed in GNU style output. 1425480093f4SDimitry Andric return E.Value == Flag && !E.AltName.empty(); 1426480093f4SDimitry Andric }); 1427480093f4SDimitry Andric if (I != FlagsList.end()) { 1428480093f4SDimitry Andric Str += I->AltName; 1429480093f4SDimitry Andric continue; 1430480093f4SDimitry Andric } 1431480093f4SDimitry Andric 1432480093f4SDimitry Andric // If we did not find a matching regular flag, then we deal with an OS 1433480093f4SDimitry Andric // specific flag, processor specific flag or an unknown flag. 1434480093f4SDimitry Andric if (Flag & ELF::SHF_MASKOS) { 1435480093f4SDimitry Andric HasOSFlag = true; 1436480093f4SDimitry Andric Flags &= ~ELF::SHF_MASKOS; 1437480093f4SDimitry Andric } else if (Flag & ELF::SHF_MASKPROC) { 1438480093f4SDimitry Andric HasProcFlag = true; 1439480093f4SDimitry Andric // Mask off all the processor-specific bits. This removes the SHF_EXCLUDE 1440480093f4SDimitry Andric // bit if set so that it doesn't also get printed. 1441480093f4SDimitry Andric Flags &= ~ELF::SHF_MASKPROC; 1442480093f4SDimitry Andric } else { 1443480093f4SDimitry Andric HasUnknownFlag = true; 1444480093f4SDimitry Andric } 1445480093f4SDimitry Andric } 1446480093f4SDimitry Andric 1447480093f4SDimitry Andric // "o", "p" and "x" are printed last. 1448480093f4SDimitry Andric if (HasOSFlag) 14490b57cec5SDimitry Andric Str += "o"; 1450480093f4SDimitry Andric if (HasProcFlag) 14510b57cec5SDimitry Andric Str += "p"; 1452480093f4SDimitry Andric if (HasUnknownFlag) 14530b57cec5SDimitry Andric Str += "x"; 14540b57cec5SDimitry Andric return Str; 14550b57cec5SDimitry Andric } 14560b57cec5SDimitry Andric 1457e8d8bef9SDimitry Andric static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { 1458e8d8bef9SDimitry Andric // Check potentially overlapped processor-specific program header type. 14590b57cec5SDimitry Andric switch (Arch) { 14600b57cec5SDimitry Andric case ELF::EM_ARM: 14610b57cec5SDimitry Andric switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); } 14620b57cec5SDimitry Andric break; 14630b57cec5SDimitry Andric case ELF::EM_MIPS: 14640b57cec5SDimitry Andric case ELF::EM_MIPS_RS3_LE: 14650b57cec5SDimitry Andric switch (Type) { 14660b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); 14670b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); 14680b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); 14690b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS); 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric break; 147281ad6265SDimitry Andric case ELF::EM_RISCV: 147381ad6265SDimitry Andric switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_RISCV_ATTRIBUTES); } 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric switch (Type) { 14770b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL); 14780b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD); 14790b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC); 14800b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP); 14810b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE); 14820b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB); 14830b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR); 14840b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS); 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME); 14870b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND); 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); 14900b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); 1491480093f4SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY); 14920b57cec5SDimitry Andric 1493bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE); 14940b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); 14950b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); 14965f757f3fSDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI); 149756727255SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS); 14980b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); 14990b57cec5SDimitry Andric default: 15000b57cec5SDimitry Andric return ""; 15010b57cec5SDimitry Andric } 15020b57cec5SDimitry Andric } 15030b57cec5SDimitry Andric 1504e8d8bef9SDimitry Andric static std::string getGNUPtType(unsigned Arch, unsigned Type) { 1505e8d8bef9SDimitry Andric StringRef Seg = segmentTypeToString(Arch, Type); 1506e8d8bef9SDimitry Andric if (Seg.empty()) 15070b57cec5SDimitry Andric return std::string("<unknown>: ") + to_string(format_hex(Type, 1)); 1508e8d8bef9SDimitry Andric 1509e8d8bef9SDimitry Andric // E.g. "PT_ARM_EXIDX" -> "EXIDX". 151081ad6265SDimitry Andric if (Seg.consume_front("PT_ARM_")) 151181ad6265SDimitry Andric return Seg.str(); 1512e8d8bef9SDimitry Andric 1513e8d8bef9SDimitry Andric // E.g. "PT_MIPS_REGINFO" -> "REGINFO". 151481ad6265SDimitry Andric if (Seg.consume_front("PT_MIPS_")) 151581ad6265SDimitry Andric return Seg.str(); 151681ad6265SDimitry Andric 151781ad6265SDimitry Andric // E.g. "PT_RISCV_ATTRIBUTES" 151881ad6265SDimitry Andric if (Seg.consume_front("PT_RISCV_")) 151981ad6265SDimitry Andric return Seg.str(); 1520e8d8bef9SDimitry Andric 1521e8d8bef9SDimitry Andric // E.g. "PT_LOAD" -> "LOAD". 15225f757f3fSDimitry Andric assert(Seg.starts_with("PT_")); 1523e8d8bef9SDimitry Andric return Seg.drop_front(3).str(); 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric 1526349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSegmentFlags[] = { 15270b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_X), 15280b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_W), 15290b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, PF_R) 15300b57cec5SDimitry Andric }; 15310b57cec5SDimitry Andric 1532349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { 15330b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"), 15340b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_PIC, "pic"), 15350b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_CPIC, "cpic"), 15360b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI2, "abi2"), 15370b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"), 15380b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_FP64, "fp64"), 15390b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_NAN2008, "nan2008"), 15400b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O32, "o32"), 15410b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_O64, "o64"), 15420b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"), 15430b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"), 15440b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_3900, "3900"), 15450b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4010, "4010"), 15460b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4100, "4100"), 15470b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4650, "4650"), 15480b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4120, "4120"), 15490b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_4111, "4111"), 15500b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"), 15510b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"), 15520b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"), 15530b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"), 15540b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"), 15550b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5400, "5400"), 15560b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5900, "5900"), 15570b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_5500, "5500"), 15580b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_9000, "9000"), 15590b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"), 15600b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"), 15610b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"), 15620b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"), 15630b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"), 15640b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"), 15650b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_1, "mips1"), 15660b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_2, "mips2"), 15670b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_3, "mips3"), 15680b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_4, "mips4"), 15690b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_5, "mips5"), 15700b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32, "mips32"), 15710b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64, "mips64"), 15720b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"), 15730b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"), 15740b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"), 15750b57cec5SDimitry Andric ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6") 15760b57cec5SDimitry Andric }; 15770b57cec5SDimitry Andric 1578*0fca6ea1SDimitry Andric // clang-format off 1579*0fca6ea1SDimitry Andric #define AMDGPU_MACH_ENUM_ENTS \ 1580*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"), \ 1581*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"), \ 1582*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"), \ 1583*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"), \ 1584*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"), \ 1585*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"), \ 1586*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"), \ 1587*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"), \ 1588*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"), \ 1589*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"), \ 1590*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"), \ 1591*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"), \ 1592*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"), \ 1593*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"), \ 1594*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"), \ 1595*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"), \ 1596*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"), \ 1597*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"), \ 1598*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"), \ 1599*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"), \ 1600*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"), \ 1601*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"), \ 1602*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"), \ 1603*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"), \ 1604*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"), \ 1605*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"), \ 1606*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"), \ 1607*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"), \ 1608*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"), \ 1609*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"), \ 1610*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"), \ 1611*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"), \ 1612*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"), \ 1613*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"), \ 1614*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"), \ 1615*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"), \ 1616*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"), \ 1617*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"), \ 1618*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"), \ 1619*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"), \ 1620*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"), \ 1621*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"), \ 1622*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"), \ 1623*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"), \ 1624*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"), \ 1625*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"), \ 1626*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"), \ 1627*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"), \ 1628*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"), \ 1629*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"), \ 1630*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"), \ 1631*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"), \ 1632*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"), \ 1633*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"), \ 1634*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"), \ 1635*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"), \ 1636*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"), \ 1637*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"), \ 1638*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"), \ 1639*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1152, "gfx1152"), \ 1640*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"), \ 1641*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"), \ 1642*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC, "gfx9-generic"), \ 1643*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC, "gfx10-1-generic"), \ 1644*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC, "gfx10-3-generic"), \ 1645*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC, "gfx11-generic"), \ 1646*0fca6ea1SDimitry Andric ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC, "gfx12-generic") 1647*0fca6ea1SDimitry Andric // clang-format on 1648*0fca6ea1SDimitry Andric 1649349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = { 1650*0fca6ea1SDimitry Andric AMDGPU_MACH_ENUM_ENTS, 1651cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_V3, "xnack"), 1652cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_V3, "sramecc"), 1653fe6060f1SDimitry Andric }; 1654fe6060f1SDimitry Andric 1655349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = { 1656*0fca6ea1SDimitry Andric AMDGPU_MACH_ENUM_ENTS, 1657cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ANY_V4, "xnack"), 1658cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_OFF_V4, "xnack-"), 1659cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ON_V4, "xnack+"), 1660cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ANY_V4, "sramecc"), 1661cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_OFF_V4, "sramecc-"), 1662cb14a3feSDimitry Andric ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ON_V4, "sramecc+"), 16635f757f3fSDimitry Andric }; 16645f757f3fSDimitry Andric 16655f757f3fSDimitry Andric const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = { 16665f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"), 16675f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"), 16685f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"), 16695f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"), 16705f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"), 16715f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"), 16725f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"), 16735f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"), 16745f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"), 16755f757f3fSDimitry Andric ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"), 16760b57cec5SDimitry Andric }; 16770b57cec5SDimitry Andric 1678349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { 16790b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_RVC, "RVC"), 16800b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"), 16810b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"), 16820b57cec5SDimitry Andric ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"), 168304eeddc0SDimitry Andric ENUM_ENT(EF_RISCV_RVE, "RVE"), 168404eeddc0SDimitry Andric ENUM_ENT(EF_RISCV_TSO, "TSO"), 16850b57cec5SDimitry Andric }; 16860b57cec5SDimitry Andric 1687349cc55cSDimitry Andric const EnumEntry<unsigned> ElfHeaderAVRFlags[] = { 1688fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1), 1689fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2), 1690fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25), 1691fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3), 1692fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31), 1693fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35), 1694fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4), 1695fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5), 1696fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51), 1697fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6), 1698fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY), 1699fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1), 1700fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2), 1701fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3), 1702fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4), 1703fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5), 1704fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6), 1705fe6060f1SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7), 1706fe6060f1SDimitry Andric ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"), 1707fe6060f1SDimitry Andric }; 1708fe6060f1SDimitry Andric 1709972a253aSDimitry Andric const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = { 1710bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"), 1711bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"), 1712bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"), 1713bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"), 1714bdd1243dSDimitry Andric ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"), 1715972a253aSDimitry Andric }; 1716972a253aSDimitry Andric 1717bdd1243dSDimitry Andric static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = { 1718bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE), 1719bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN), 1720bdd1243dSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT) 1721bdd1243dSDimitry Andric }; 1722fe6060f1SDimitry Andric 1723349cc55cSDimitry Andric const EnumEntry<unsigned> ElfSymOtherFlags[] = { 17240b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), 17250b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN), 17260b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED) 17270b57cec5SDimitry Andric }; 17280b57cec5SDimitry Andric 1729349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = { 17300b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 17310b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 17320b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC), 17330b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS) 17340b57cec5SDimitry Andric }; 17350b57cec5SDimitry Andric 1736349cc55cSDimitry Andric const EnumEntry<unsigned> ElfAArch64SymOtherFlags[] = { 1737e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS) 1738e8d8bef9SDimitry Andric }; 1739e8d8bef9SDimitry Andric 1740349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = { 17410b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), 17420b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), 17430b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16) 17440b57cec5SDimitry Andric }; 17450b57cec5SDimitry Andric 1746349cc55cSDimitry Andric const EnumEntry<unsigned> ElfRISCVSymOtherFlags[] = { 1747349cc55cSDimitry Andric LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)}; 1748349cc55cSDimitry Andric 17490b57cec5SDimitry Andric static const char *getElfMipsOptionsOdkType(unsigned Odk) { 17500b57cec5SDimitry Andric switch (Odk) { 17510b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL); 17520b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO); 17530b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS); 17540b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD); 17550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH); 17560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL); 17570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS); 17580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND); 17590b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR); 17600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP); 17610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT); 17620b57cec5SDimitry Andric LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE); 17630b57cec5SDimitry Andric default: 17640b57cec5SDimitry Andric return "Unknown"; 17650b57cec5SDimitry Andric } 17660b57cec5SDimitry Andric } 17670b57cec5SDimitry Andric 17680b57cec5SDimitry Andric template <typename ELFT> 17698bcb0991SDimitry Andric std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *> 1770e8d8bef9SDimitry Andric ELFDumper<ELFT>::findDynamic() { 17710b57cec5SDimitry Andric // Try to locate the PT_DYNAMIC header. 17720b57cec5SDimitry Andric const Elf_Phdr *DynamicPhdr = nullptr; 1773e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = Obj.program_headers()) { 17745ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 17750b57cec5SDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC) 17760b57cec5SDimitry Andric continue; 17770b57cec5SDimitry Andric DynamicPhdr = &Phdr; 17780b57cec5SDimitry Andric break; 17790b57cec5SDimitry Andric } 17805ffd83dbSDimitry Andric } else { 1781e8d8bef9SDimitry Andric reportUniqueWarning( 17825ffd83dbSDimitry Andric "unable to read program headers to locate the PT_DYNAMIC segment: " + 1783e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 17845ffd83dbSDimitry Andric } 17850b57cec5SDimitry Andric 17860b57cec5SDimitry Andric // Try to locate the .dynamic section in the sections header table. 17870b57cec5SDimitry Andric const Elf_Shdr *DynamicSec = nullptr; 1788e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 17890b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_DYNAMIC) 17900b57cec5SDimitry Andric continue; 17910b57cec5SDimitry Andric DynamicSec = &Sec; 17920b57cec5SDimitry Andric break; 17930b57cec5SDimitry Andric } 17940b57cec5SDimitry Andric 1795e8d8bef9SDimitry Andric if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz > 1796e8d8bef9SDimitry Andric ObjF.getMemoryBufferRef().getBufferSize()) || 1797e8d8bef9SDimitry Andric (DynamicPhdr->p_offset + DynamicPhdr->p_filesz < 1798e8d8bef9SDimitry Andric DynamicPhdr->p_offset))) { 1799e8d8bef9SDimitry Andric reportUniqueWarning( 1800e8d8bef9SDimitry Andric "PT_DYNAMIC segment offset (0x" + 1801e8d8bef9SDimitry Andric Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" + 1802e8d8bef9SDimitry Andric Twine::utohexstr(DynamicPhdr->p_filesz) + 1803e8d8bef9SDimitry Andric ") exceeds the size of the file (0x" + 1804e8d8bef9SDimitry Andric Twine::utohexstr(ObjF.getMemoryBufferRef().getBufferSize()) + ")"); 18058bcb0991SDimitry Andric // Don't use the broken dynamic header. 18068bcb0991SDimitry Andric DynamicPhdr = nullptr; 18070b57cec5SDimitry Andric } 18080b57cec5SDimitry Andric 18098bcb0991SDimitry Andric if (DynamicPhdr && DynamicSec) { 18100b57cec5SDimitry Andric if (DynamicSec->sh_addr + DynamicSec->sh_size > 18110b57cec5SDimitry Andric DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || 18120b57cec5SDimitry Andric DynamicSec->sh_addr < DynamicPhdr->p_vaddr) 1813e8d8bef9SDimitry Andric reportUniqueWarning(describe(*DynamicSec) + 1814e8d8bef9SDimitry Andric " is not contained within the " 1815e8d8bef9SDimitry Andric "PT_DYNAMIC segment"); 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr) 1818e8d8bef9SDimitry Andric reportUniqueWarning(describe(*DynamicSec) + " is not at the start of " 1819e8d8bef9SDimitry Andric "PT_DYNAMIC segment"); 18208bcb0991SDimitry Andric } 18218bcb0991SDimitry Andric 18228bcb0991SDimitry Andric return std::make_pair(DynamicPhdr, DynamicSec); 18238bcb0991SDimitry Andric } 18248bcb0991SDimitry Andric 18258bcb0991SDimitry Andric template <typename ELFT> 1826e8d8bef9SDimitry Andric void ELFDumper<ELFT>::loadDynamicTable() { 18278bcb0991SDimitry Andric const Elf_Phdr *DynamicPhdr; 18288bcb0991SDimitry Andric const Elf_Shdr *DynamicSec; 1829e8d8bef9SDimitry Andric std::tie(DynamicPhdr, DynamicSec) = findDynamic(); 18308bcb0991SDimitry Andric if (!DynamicPhdr && !DynamicSec) 18318bcb0991SDimitry Andric return; 18328bcb0991SDimitry Andric 1833e8d8bef9SDimitry Andric DynRegionInfo FromPhdr(ObjF, *this); 18348bcb0991SDimitry Andric bool IsPhdrTableValid = false; 18358bcb0991SDimitry Andric if (DynamicPhdr) { 1836e8d8bef9SDimitry Andric // Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are 1837e8d8bef9SDimitry Andric // validated in findDynamic() and so createDRI() is not expected to fail. 1838e8d8bef9SDimitry Andric FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz, 1839e8d8bef9SDimitry Andric sizeof(Elf_Dyn))); 18405ffd83dbSDimitry Andric FromPhdr.SizePrintName = "PT_DYNAMIC size"; 18415ffd83dbSDimitry Andric FromPhdr.EntSizePrintName = ""; 1842e8d8bef9SDimitry Andric IsPhdrTableValid = !FromPhdr.template getAsArrayRef<Elf_Dyn>().empty(); 18438bcb0991SDimitry Andric } 18448bcb0991SDimitry Andric 18458bcb0991SDimitry Andric // Locate the dynamic table described in a section header. 18468bcb0991SDimitry Andric // Ignore sh_entsize and use the expected value for entry size explicitly. 18478bcb0991SDimitry Andric // This allows us to dump dynamic sections with a broken sh_entsize 18488bcb0991SDimitry Andric // field. 1849e8d8bef9SDimitry Andric DynRegionInfo FromSec(ObjF, *this); 18508bcb0991SDimitry Andric bool IsSecTableValid = false; 18518bcb0991SDimitry Andric if (DynamicSec) { 1852e8d8bef9SDimitry Andric Expected<DynRegionInfo> RegOrErr = 1853e8d8bef9SDimitry Andric createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn)); 1854e8d8bef9SDimitry Andric if (RegOrErr) { 1855e8d8bef9SDimitry Andric FromSec = *RegOrErr; 1856e8d8bef9SDimitry Andric FromSec.Context = describe(*DynamicSec); 18575ffd83dbSDimitry Andric FromSec.EntSizePrintName = ""; 1858e8d8bef9SDimitry Andric IsSecTableValid = !FromSec.template getAsArrayRef<Elf_Dyn>().empty(); 1859e8d8bef9SDimitry Andric } else { 1860e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the dynamic table from " + 1861e8d8bef9SDimitry Andric describe(*DynamicSec) + ": " + 1862e8d8bef9SDimitry Andric toString(RegOrErr.takeError())); 1863e8d8bef9SDimitry Andric } 18648bcb0991SDimitry Andric } 18658bcb0991SDimitry Andric 18668bcb0991SDimitry Andric // When we only have information from one of the SHT_DYNAMIC section header or 18678bcb0991SDimitry Andric // PT_DYNAMIC program header, just use that. 18688bcb0991SDimitry Andric if (!DynamicPhdr || !DynamicSec) { 18698bcb0991SDimitry Andric if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) { 18708bcb0991SDimitry Andric DynamicTable = DynamicPhdr ? FromPhdr : FromSec; 1871e8d8bef9SDimitry Andric parseDynamicTable(); 18728bcb0991SDimitry Andric } else { 1873e8d8bef9SDimitry Andric reportUniqueWarning("no valid dynamic table was found"); 18748bcb0991SDimitry Andric } 18758bcb0991SDimitry Andric return; 18768bcb0991SDimitry Andric } 18778bcb0991SDimitry Andric 18788bcb0991SDimitry Andric // At this point we have tables found from the section header and from the 18798bcb0991SDimitry Andric // dynamic segment. Usually they match, but we have to do sanity checks to 18808bcb0991SDimitry Andric // verify that. 18818bcb0991SDimitry Andric 18828bcb0991SDimitry Andric if (FromPhdr.Addr != FromSec.Addr) 1883e8d8bef9SDimitry Andric reportUniqueWarning("SHT_DYNAMIC section header and PT_DYNAMIC " 18848bcb0991SDimitry Andric "program header disagree about " 1885e8d8bef9SDimitry Andric "the location of the dynamic table"); 18868bcb0991SDimitry Andric 18878bcb0991SDimitry Andric if (!IsPhdrTableValid && !IsSecTableValid) { 1888e8d8bef9SDimitry Andric reportUniqueWarning("no valid dynamic table was found"); 18898bcb0991SDimitry Andric return; 18908bcb0991SDimitry Andric } 18918bcb0991SDimitry Andric 1892e8d8bef9SDimitry Andric // Information in the PT_DYNAMIC program header has priority over the 1893e8d8bef9SDimitry Andric // information in a section header. 18948bcb0991SDimitry Andric if (IsPhdrTableValid) { 18958bcb0991SDimitry Andric if (!IsSecTableValid) 1896e8d8bef9SDimitry Andric reportUniqueWarning( 1897e8d8bef9SDimitry Andric "SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used"); 18988bcb0991SDimitry Andric DynamicTable = FromPhdr; 18998bcb0991SDimitry Andric } else { 1900e8d8bef9SDimitry Andric reportUniqueWarning( 1901e8d8bef9SDimitry Andric "PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used"); 19028bcb0991SDimitry Andric DynamicTable = FromSec; 19038bcb0991SDimitry Andric } 19048bcb0991SDimitry Andric 1905e8d8bef9SDimitry Andric parseDynamicTable(); 19060b57cec5SDimitry Andric } 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric template <typename ELFT> 1909e8d8bef9SDimitry Andric ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O, 19100b57cec5SDimitry Andric ScopedPrinter &Writer) 1911e8d8bef9SDimitry Andric : ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()), 1912e8d8bef9SDimitry Andric FileName(O.getFileName()), DynRelRegion(O, *this), 1913*0fca6ea1SDimitry Andric DynRelaRegion(O, *this), DynCrelRegion(O, *this), DynRelrRegion(O, *this), 1914e8d8bef9SDimitry Andric DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this), 1915e8d8bef9SDimitry Andric DynamicTable(O, *this) { 1916e8d8bef9SDimitry Andric if (!O.IsContentValid()) 1917e8d8bef9SDimitry Andric return; 19185ffd83dbSDimitry Andric 1919e8d8bef9SDimitry Andric typename ELFT::ShdrRange Sections = cantFail(Obj.sections()); 19205ffd83dbSDimitry Andric for (const Elf_Shdr &Sec : Sections) { 19210b57cec5SDimitry Andric switch (Sec.sh_type) { 19220b57cec5SDimitry Andric case ELF::SHT_SYMTAB: 19230b57cec5SDimitry Andric if (!DotSymtabSec) 19240b57cec5SDimitry Andric DotSymtabSec = &Sec; 19250b57cec5SDimitry Andric break; 19260b57cec5SDimitry Andric case ELF::SHT_DYNSYM: 1927e8d8bef9SDimitry Andric if (!DotDynsymSec) 1928e8d8bef9SDimitry Andric DotDynsymSec = &Sec; 19290b57cec5SDimitry Andric 1930e8d8bef9SDimitry Andric if (!DynSymRegion) { 1931e8d8bef9SDimitry Andric Expected<DynRegionInfo> RegOrErr = 1932e8d8bef9SDimitry Andric createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize); 1933e8d8bef9SDimitry Andric if (RegOrErr) { 1934e8d8bef9SDimitry Andric DynSymRegion = *RegOrErr; 1935e8d8bef9SDimitry Andric DynSymRegion->Context = describe(Sec); 1936e8d8bef9SDimitry Andric 1937e8d8bef9SDimitry Andric if (Expected<StringRef> E = Obj.getStringTableForSymtab(Sec)) 19380b57cec5SDimitry Andric DynamicStringTable = *E; 19390b57cec5SDimitry Andric else 1940e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the string table for the " + 1941e8d8bef9SDimitry Andric describe(Sec) + ": " + toString(E.takeError())); 1942e8d8bef9SDimitry Andric } else { 1943e8d8bef9SDimitry Andric reportUniqueWarning("unable to read dynamic symbols from " + 1944e8d8bef9SDimitry Andric describe(Sec) + ": " + 1945e8d8bef9SDimitry Andric toString(RegOrErr.takeError())); 1946e8d8bef9SDimitry Andric } 19470b57cec5SDimitry Andric } 19480b57cec5SDimitry Andric break; 1949e8d8bef9SDimitry Andric case ELF::SHT_SYMTAB_SHNDX: { 1950e8d8bef9SDimitry Andric uint32_t SymtabNdx = Sec.sh_link; 1951e8d8bef9SDimitry Andric if (SymtabNdx >= Sections.size()) { 1952e8d8bef9SDimitry Andric reportUniqueWarning( 1953e8d8bef9SDimitry Andric "unable to get the associated symbol table for " + describe(Sec) + 1954e8d8bef9SDimitry Andric ": sh_link (" + Twine(SymtabNdx) + 1955e8d8bef9SDimitry Andric ") is greater than or equal to the total number of sections (" + 1956e8d8bef9SDimitry Andric Twine(Sections.size()) + ")"); 1957e8d8bef9SDimitry Andric continue; 1958e8d8bef9SDimitry Andric } 1959e8d8bef9SDimitry Andric 1960e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr = 1961e8d8bef9SDimitry Andric Obj.getSHNDXTable(Sec)) { 1962e8d8bef9SDimitry Andric if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr}) 1963e8d8bef9SDimitry Andric .second) 1964e8d8bef9SDimitry Andric reportUniqueWarning( 1965e8d8bef9SDimitry Andric "multiple SHT_SYMTAB_SHNDX sections are linked to " + 1966e8d8bef9SDimitry Andric describe(Sec)); 1967e8d8bef9SDimitry Andric } else { 1968e8d8bef9SDimitry Andric reportUniqueWarning(ShndxTableOrErr.takeError()); 1969e8d8bef9SDimitry Andric } 19700b57cec5SDimitry Andric break; 1971e8d8bef9SDimitry Andric } 19720b57cec5SDimitry Andric case ELF::SHT_GNU_versym: 19730b57cec5SDimitry Andric if (!SymbolVersionSection) 19740b57cec5SDimitry Andric SymbolVersionSection = &Sec; 19750b57cec5SDimitry Andric break; 19760b57cec5SDimitry Andric case ELF::SHT_GNU_verdef: 19770b57cec5SDimitry Andric if (!SymbolVersionDefSection) 19780b57cec5SDimitry Andric SymbolVersionDefSection = &Sec; 19790b57cec5SDimitry Andric break; 19800b57cec5SDimitry Andric case ELF::SHT_GNU_verneed: 19810b57cec5SDimitry Andric if (!SymbolVersionNeedSection) 19820b57cec5SDimitry Andric SymbolVersionNeedSection = &Sec; 19830b57cec5SDimitry Andric break; 19840b57cec5SDimitry Andric case ELF::SHT_LLVM_ADDRSIG: 19850b57cec5SDimitry Andric if (!DotAddrsigSec) 19860b57cec5SDimitry Andric DotAddrsigSec = &Sec; 19870b57cec5SDimitry Andric break; 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric } 19900b57cec5SDimitry Andric 1991e8d8bef9SDimitry Andric loadDynamicTable(); 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric 1994e8d8bef9SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() { 19950b57cec5SDimitry Andric auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * { 1996e8d8bef9SDimitry Andric auto MappedAddrOrError = Obj.toMappedAddr(VAddr, [&](const Twine &Msg) { 1997e8d8bef9SDimitry Andric this->reportUniqueWarning(Msg); 1998e8d8bef9SDimitry Andric return Error::success(); 1999e8d8bef9SDimitry Andric }); 20000b57cec5SDimitry Andric if (!MappedAddrOrError) { 2001e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to parse DT_" + 2002e8d8bef9SDimitry Andric Obj.getDynamicTagAsString(Tag) + ": " + 2003e8d8bef9SDimitry Andric llvm::toString(MappedAddrOrError.takeError())); 20040b57cec5SDimitry Andric return nullptr; 20050b57cec5SDimitry Andric } 20060b57cec5SDimitry Andric return MappedAddrOrError.get(); 20070b57cec5SDimitry Andric }; 20080b57cec5SDimitry Andric 20090b57cec5SDimitry Andric const char *StringTableBegin = nullptr; 20100b57cec5SDimitry Andric uint64_t StringTableSize = 0; 2011bdd1243dSDimitry Andric std::optional<DynRegionInfo> DynSymFromTable; 20120b57cec5SDimitry Andric for (const Elf_Dyn &Dyn : dynamic_table()) { 20135f757f3fSDimitry Andric if (Obj.getHeader().e_machine == EM_AARCH64) { 20145f757f3fSDimitry Andric switch (Dyn.d_tag) { 20155f757f3fSDimitry Andric case ELF::DT_AARCH64_AUTH_RELRSZ: 20165f757f3fSDimitry Andric DynRelrRegion.Size = Dyn.getVal(); 20175f757f3fSDimitry Andric DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value"; 20185f757f3fSDimitry Andric continue; 20195f757f3fSDimitry Andric case ELF::DT_AARCH64_AUTH_RELRENT: 20205f757f3fSDimitry Andric DynRelrRegion.EntSize = Dyn.getVal(); 20215f757f3fSDimitry Andric DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value"; 20225f757f3fSDimitry Andric continue; 20235f757f3fSDimitry Andric } 20245f757f3fSDimitry Andric } 20250b57cec5SDimitry Andric switch (Dyn.d_tag) { 20260b57cec5SDimitry Andric case ELF::DT_HASH: 20270b57cec5SDimitry Andric HashTable = reinterpret_cast<const Elf_Hash *>( 20280b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20290b57cec5SDimitry Andric break; 20300b57cec5SDimitry Andric case ELF::DT_GNU_HASH: 20310b57cec5SDimitry Andric GnuHashTable = reinterpret_cast<const Elf_GnuHash *>( 20320b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20330b57cec5SDimitry Andric break; 20340b57cec5SDimitry Andric case ELF::DT_STRTAB: 20350b57cec5SDimitry Andric StringTableBegin = reinterpret_cast<const char *>( 20360b57cec5SDimitry Andric toMappedAddr(Dyn.getTag(), Dyn.getPtr())); 20370b57cec5SDimitry Andric break; 20380b57cec5SDimitry Andric case ELF::DT_STRSZ: 20390b57cec5SDimitry Andric StringTableSize = Dyn.getVal(); 20400b57cec5SDimitry Andric break; 20418bcb0991SDimitry Andric case ELF::DT_SYMTAB: { 20425ffd83dbSDimitry Andric // If we can't map the DT_SYMTAB value to an address (e.g. when there are 20435ffd83dbSDimitry Andric // no program headers), we ignore its value. 20448bcb0991SDimitry Andric if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) { 2045e8d8bef9SDimitry Andric DynSymFromTable.emplace(ObjF, *this); 20465ffd83dbSDimitry Andric DynSymFromTable->Addr = VA; 20475ffd83dbSDimitry Andric DynSymFromTable->EntSize = sizeof(Elf_Sym); 20485ffd83dbSDimitry Andric DynSymFromTable->EntSizePrintName = ""; 20498bcb0991SDimitry Andric } 20500b57cec5SDimitry Andric break; 20518bcb0991SDimitry Andric } 20525ffd83dbSDimitry Andric case ELF::DT_SYMENT: { 20535ffd83dbSDimitry Andric uint64_t Val = Dyn.getVal(); 20545ffd83dbSDimitry Andric if (Val != sizeof(Elf_Sym)) 2055e8d8bef9SDimitry Andric this->reportUniqueWarning("DT_SYMENT value of 0x" + 20565ffd83dbSDimitry Andric Twine::utohexstr(Val) + 20575ffd83dbSDimitry Andric " is not the size of a symbol (0x" + 2058e8d8bef9SDimitry Andric Twine::utohexstr(sizeof(Elf_Sym)) + ")"); 20595ffd83dbSDimitry Andric break; 20605ffd83dbSDimitry Andric } 20610b57cec5SDimitry Andric case ELF::DT_RELA: 20620b57cec5SDimitry Andric DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20630b57cec5SDimitry Andric break; 20640b57cec5SDimitry Andric case ELF::DT_RELASZ: 20650b57cec5SDimitry Andric DynRelaRegion.Size = Dyn.getVal(); 20665ffd83dbSDimitry Andric DynRelaRegion.SizePrintName = "DT_RELASZ value"; 20670b57cec5SDimitry Andric break; 20680b57cec5SDimitry Andric case ELF::DT_RELAENT: 20690b57cec5SDimitry Andric DynRelaRegion.EntSize = Dyn.getVal(); 20705ffd83dbSDimitry Andric DynRelaRegion.EntSizePrintName = "DT_RELAENT value"; 20710b57cec5SDimitry Andric break; 2072*0fca6ea1SDimitry Andric case ELF::DT_CREL: 2073*0fca6ea1SDimitry Andric DynCrelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 2074*0fca6ea1SDimitry Andric break; 20750b57cec5SDimitry Andric case ELF::DT_SONAME: 20760b57cec5SDimitry Andric SONameOffset = Dyn.getVal(); 20770b57cec5SDimitry Andric break; 20780b57cec5SDimitry Andric case ELF::DT_REL: 20790b57cec5SDimitry Andric DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20800b57cec5SDimitry Andric break; 20810b57cec5SDimitry Andric case ELF::DT_RELSZ: 20820b57cec5SDimitry Andric DynRelRegion.Size = Dyn.getVal(); 20835ffd83dbSDimitry Andric DynRelRegion.SizePrintName = "DT_RELSZ value"; 20840b57cec5SDimitry Andric break; 20850b57cec5SDimitry Andric case ELF::DT_RELENT: 20860b57cec5SDimitry Andric DynRelRegion.EntSize = Dyn.getVal(); 20875ffd83dbSDimitry Andric DynRelRegion.EntSizePrintName = "DT_RELENT value"; 20880b57cec5SDimitry Andric break; 20890b57cec5SDimitry Andric case ELF::DT_RELR: 20900b57cec5SDimitry Andric case ELF::DT_ANDROID_RELR: 20915f757f3fSDimitry Andric case ELF::DT_AARCH64_AUTH_RELR: 20920b57cec5SDimitry Andric DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 20930b57cec5SDimitry Andric break; 20940b57cec5SDimitry Andric case ELF::DT_RELRSZ: 20950b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRSZ: 20965f757f3fSDimitry Andric case ELF::DT_AARCH64_AUTH_RELRSZ: 20970b57cec5SDimitry Andric DynRelrRegion.Size = Dyn.getVal(); 20985ffd83dbSDimitry Andric DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ 20995ffd83dbSDimitry Andric ? "DT_RELRSZ value" 21005ffd83dbSDimitry Andric : "DT_ANDROID_RELRSZ value"; 21010b57cec5SDimitry Andric break; 21020b57cec5SDimitry Andric case ELF::DT_RELRENT: 21030b57cec5SDimitry Andric case ELF::DT_ANDROID_RELRENT: 21045f757f3fSDimitry Andric case ELF::DT_AARCH64_AUTH_RELRENT: 21050b57cec5SDimitry Andric DynRelrRegion.EntSize = Dyn.getVal(); 21065ffd83dbSDimitry Andric DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT 21075ffd83dbSDimitry Andric ? "DT_RELRENT value" 21085ffd83dbSDimitry Andric : "DT_ANDROID_RELRENT value"; 21090b57cec5SDimitry Andric break; 21100b57cec5SDimitry Andric case ELF::DT_PLTREL: 21110b57cec5SDimitry Andric if (Dyn.getVal() == DT_REL) 21120b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rel); 21130b57cec5SDimitry Andric else if (Dyn.getVal() == DT_RELA) 21140b57cec5SDimitry Andric DynPLTRelRegion.EntSize = sizeof(Elf_Rela); 2115*0fca6ea1SDimitry Andric else if (Dyn.getVal() == DT_CREL) 2116*0fca6ea1SDimitry Andric DynPLTRelRegion.EntSize = 1; 21170b57cec5SDimitry Andric else 2118e8d8bef9SDimitry Andric reportUniqueWarning(Twine("unknown DT_PLTREL value of ") + 2119e8d8bef9SDimitry Andric Twine((uint64_t)Dyn.getVal())); 2120e8d8bef9SDimitry Andric DynPLTRelRegion.EntSizePrintName = "PLTREL entry size"; 21210b57cec5SDimitry Andric break; 21220b57cec5SDimitry Andric case ELF::DT_JMPREL: 21230b57cec5SDimitry Andric DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 21240b57cec5SDimitry Andric break; 21250b57cec5SDimitry Andric case ELF::DT_PLTRELSZ: 21260b57cec5SDimitry Andric DynPLTRelRegion.Size = Dyn.getVal(); 21275ffd83dbSDimitry Andric DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value"; 21280b57cec5SDimitry Andric break; 2129e8d8bef9SDimitry Andric case ELF::DT_SYMTAB_SHNDX: 2130e8d8bef9SDimitry Andric DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); 2131e8d8bef9SDimitry Andric DynSymTabShndxRegion.EntSize = sizeof(Elf_Word); 2132e8d8bef9SDimitry Andric break; 21330b57cec5SDimitry Andric } 21340b57cec5SDimitry Andric } 21355ffd83dbSDimitry Andric 21365ffd83dbSDimitry Andric if (StringTableBegin) { 2137e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 2138e8d8bef9SDimitry Andric const uint64_t Offset = (const uint8_t *)StringTableBegin - Obj.base(); 21395ffd83dbSDimitry Andric if (StringTableSize > FileSize - Offset) 2140e8d8bef9SDimitry Andric reportUniqueWarning( 21415ffd83dbSDimitry Andric "the dynamic string table at 0x" + Twine::utohexstr(Offset) + 21425ffd83dbSDimitry Andric " goes past the end of the file (0x" + Twine::utohexstr(FileSize) + 2143e8d8bef9SDimitry Andric ") with DT_STRSZ = 0x" + Twine::utohexstr(StringTableSize)); 21445ffd83dbSDimitry Andric else 21450b57cec5SDimitry Andric DynamicStringTable = StringRef(StringTableBegin, StringTableSize); 21465ffd83dbSDimitry Andric } 21475ffd83dbSDimitry Andric 2148e8d8bef9SDimitry Andric const bool IsHashTableSupported = getHashTableEntSize() == 4; 21495ffd83dbSDimitry Andric if (DynSymRegion) { 21505ffd83dbSDimitry Andric // Often we find the information about the dynamic symbol table 21515ffd83dbSDimitry Andric // location in the SHT_DYNSYM section header. However, the value in 21525ffd83dbSDimitry Andric // DT_SYMTAB has priority, because it is used by dynamic loaders to 21535ffd83dbSDimitry Andric // locate .dynsym at runtime. The location we find in the section header 21545ffd83dbSDimitry Andric // and the location we find here should match. 21555ffd83dbSDimitry Andric if (DynSymFromTable && DynSymFromTable->Addr != DynSymRegion->Addr) 21565ffd83dbSDimitry Andric reportUniqueWarning( 21575ffd83dbSDimitry Andric createError("SHT_DYNSYM section header and DT_SYMTAB disagree about " 21585ffd83dbSDimitry Andric "the location of the dynamic symbol table")); 21595ffd83dbSDimitry Andric 21605ffd83dbSDimitry Andric // According to the ELF gABI: "The number of symbol table entries should 21615ffd83dbSDimitry Andric // equal nchain". Check to see if the DT_HASH hash table nchain value 21625ffd83dbSDimitry Andric // conflicts with the number of symbols in the dynamic symbol table 21635ffd83dbSDimitry Andric // according to the section header. 2164e8d8bef9SDimitry Andric if (HashTable && IsHashTableSupported) { 21655ffd83dbSDimitry Andric if (DynSymRegion->EntSize == 0) 2166e8d8bef9SDimitry Andric reportUniqueWarning("SHT_DYNSYM section has sh_entsize == 0"); 21675ffd83dbSDimitry Andric else if (HashTable->nchain != DynSymRegion->Size / DynSymRegion->EntSize) 2168e8d8bef9SDimitry Andric reportUniqueWarning( 21695ffd83dbSDimitry Andric "hash table nchain (" + Twine(HashTable->nchain) + 21705ffd83dbSDimitry Andric ") differs from symbol count derived from SHT_DYNSYM section " 21715ffd83dbSDimitry Andric "header (" + 2172e8d8bef9SDimitry Andric Twine(DynSymRegion->Size / DynSymRegion->EntSize) + ")"); 21735ffd83dbSDimitry Andric } 21745ffd83dbSDimitry Andric } 21755ffd83dbSDimitry Andric 21765ffd83dbSDimitry Andric // Delay the creation of the actual dynamic symbol table until now, so that 21775ffd83dbSDimitry Andric // checks can always be made against the section header-based properties, 21785ffd83dbSDimitry Andric // without worrying about tag order. 21795ffd83dbSDimitry Andric if (DynSymFromTable) { 21805ffd83dbSDimitry Andric if (!DynSymRegion) { 21815ffd83dbSDimitry Andric DynSymRegion = DynSymFromTable; 21825ffd83dbSDimitry Andric } else { 21835ffd83dbSDimitry Andric DynSymRegion->Addr = DynSymFromTable->Addr; 21845ffd83dbSDimitry Andric DynSymRegion->EntSize = DynSymFromTable->EntSize; 21855ffd83dbSDimitry Andric DynSymRegion->EntSizePrintName = DynSymFromTable->EntSizePrintName; 21865ffd83dbSDimitry Andric } 21875ffd83dbSDimitry Andric } 21885ffd83dbSDimitry Andric 21895ffd83dbSDimitry Andric // Derive the dynamic symbol table size from the DT_HASH hash table, if 21905ffd83dbSDimitry Andric // present. 2191e8d8bef9SDimitry Andric if (HashTable && IsHashTableSupported && DynSymRegion) { 2192e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 2193e8d8bef9SDimitry Andric const uint64_t DerivedSize = 2194e8d8bef9SDimitry Andric (uint64_t)HashTable->nchain * DynSymRegion->EntSize; 2195e8d8bef9SDimitry Andric const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base(); 2196e8d8bef9SDimitry Andric if (DerivedSize > FileSize - Offset) 2197e8d8bef9SDimitry Andric reportUniqueWarning( 2198e8d8bef9SDimitry Andric "the size (0x" + Twine::utohexstr(DerivedSize) + 2199e8d8bef9SDimitry Andric ") of the dynamic symbol table at 0x" + Twine::utohexstr(Offset) + 2200e8d8bef9SDimitry Andric ", derived from the hash table, goes past the end of the file (0x" + 2201e8d8bef9SDimitry Andric Twine::utohexstr(FileSize) + ") and will be ignored"); 2202e8d8bef9SDimitry Andric else 22035ffd83dbSDimitry Andric DynSymRegion->Size = HashTable->nchain * DynSymRegion->EntSize; 22040b57cec5SDimitry Andric } 22050b57cec5SDimitry Andric } 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() { 22080b57cec5SDimitry Andric // Dump version symbol section. 2209e8d8bef9SDimitry Andric printVersionSymbolSection(SymbolVersionSection); 22100b57cec5SDimitry Andric 22110b57cec5SDimitry Andric // Dump version definition section. 2212e8d8bef9SDimitry Andric printVersionDefinitionSection(SymbolVersionDefSection); 22130b57cec5SDimitry Andric 22140b57cec5SDimitry Andric // Dump version dependency section. 2215e8d8bef9SDimitry Andric printVersionDependencySection(SymbolVersionNeedSection); 22168bcb0991SDimitry Andric } 22178bcb0991SDimitry Andric 22180b57cec5SDimitry Andric #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ 22190b57cec5SDimitry Andric { #enum, prefix##_##enum } 22200b57cec5SDimitry Andric 2221349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTFlags[] = { 22220b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), 22230b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), 22240b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), 22250b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), 22260b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) 22270b57cec5SDimitry Andric }; 22280b57cec5SDimitry Andric 2229349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { 22300b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), 22310b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), 22320b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), 22330b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), 22340b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), 22350b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), 22360b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), 22370b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), 22380b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), 22390b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), 22400b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), 22410b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), 22420b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), 22430b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), 22440b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), 22450b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), 22460b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND), 22470b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), 22480b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), 22490b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), 22500b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), 22510b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), 22520b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), 22530b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), 22540b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), 22554e99f454SEd Maste LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON), 22564e99f454SEd Maste LLVM_READOBJ_DT_FLAG_ENT(DF_1, PIE), 22570b57cec5SDimitry Andric }; 22580b57cec5SDimitry Andric 2259349cc55cSDimitry Andric const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { 22600b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), 22610b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), 22620b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), 22630b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), 22640b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), 22650b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), 22660b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), 22670b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), 22680b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), 22690b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), 22700b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), 22710b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), 22720b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), 22730b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), 22740b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), 22750b57cec5SDimitry Andric LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) 22760b57cec5SDimitry Andric }; 22770b57cec5SDimitry Andric 22780b57cec5SDimitry Andric #undef LLVM_READOBJ_DT_FLAG_ENT 22790b57cec5SDimitry Andric 22800b57cec5SDimitry Andric template <typename T, typename TFlag> 22810b57cec5SDimitry Andric void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { 2282e8d8bef9SDimitry Andric SmallVector<EnumEntry<TFlag>, 10> SetFlags; 2283e8d8bef9SDimitry Andric for (const EnumEntry<TFlag> &Flag : Flags) 2284e8d8bef9SDimitry Andric if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value) 22850b57cec5SDimitry Andric SetFlags.push_back(Flag); 22860b57cec5SDimitry Andric 2287e8d8bef9SDimitry Andric for (const EnumEntry<TFlag> &Flag : SetFlags) 22880b57cec5SDimitry Andric OS << Flag.Name << " "; 22890b57cec5SDimitry Andric } 2290e8d8bef9SDimitry Andric 2291e8d8bef9SDimitry Andric template <class ELFT> 2292e8d8bef9SDimitry Andric const typename ELFT::Shdr * 2293e8d8bef9SDimitry Andric ELFDumper<ELFT>::findSectionByName(StringRef Name) const { 2294e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) { 2295e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr)) { 2296e8d8bef9SDimitry Andric if (*NameOrErr == Name) 2297e8d8bef9SDimitry Andric return &Shdr; 2298e8d8bef9SDimitry Andric } else { 2299e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the name of " + describe(Shdr) + 2300e8d8bef9SDimitry Andric ": " + toString(NameOrErr.takeError())); 2301e8d8bef9SDimitry Andric } 2302e8d8bef9SDimitry Andric } 2303e8d8bef9SDimitry Andric return nullptr; 23040b57cec5SDimitry Andric } 23050b57cec5SDimitry Andric 23060b57cec5SDimitry Andric template <class ELFT> 23075ffd83dbSDimitry Andric std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type, 23080b57cec5SDimitry Andric uint64_t Value) const { 23095ffd83dbSDimitry Andric auto FormatHexValue = [](uint64_t V) { 23105ffd83dbSDimitry Andric std::string Str; 23115ffd83dbSDimitry Andric raw_string_ostream OS(Str); 23120b57cec5SDimitry Andric const char *ConvChar = 23130b57cec5SDimitry Andric (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64; 23145ffd83dbSDimitry Andric OS << format(ConvChar, V); 23155ffd83dbSDimitry Andric return OS.str(); 23165ffd83dbSDimitry Andric }; 23175ffd83dbSDimitry Andric 23185ffd83dbSDimitry Andric auto FormatFlags = [](uint64_t V, 23195ffd83dbSDimitry Andric llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) { 23205ffd83dbSDimitry Andric std::string Str; 23215ffd83dbSDimitry Andric raw_string_ostream OS(Str); 23225ffd83dbSDimitry Andric printFlags(V, Array, OS); 23235ffd83dbSDimitry Andric return OS.str(); 23245ffd83dbSDimitry Andric }; 23250b57cec5SDimitry Andric 23260b57cec5SDimitry Andric // Handle custom printing of architecture specific tags 2327e8d8bef9SDimitry Andric switch (Obj.getHeader().e_machine) { 23280b57cec5SDimitry Andric case EM_AARCH64: 23290b57cec5SDimitry Andric switch (Type) { 23300b57cec5SDimitry Andric case DT_AARCH64_BTI_PLT: 23310b57cec5SDimitry Andric case DT_AARCH64_PAC_PLT: 2332e8d8bef9SDimitry Andric case DT_AARCH64_VARIANT_PCS: 233306c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALSSZ: 23345ffd83dbSDimitry Andric return std::to_string(Value); 233506c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_MODE: 233606c3fb27SDimitry Andric switch (Value) { 233706c3fb27SDimitry Andric case 0: 233806c3fb27SDimitry Andric return "Synchronous (0)"; 233906c3fb27SDimitry Andric case 1: 234006c3fb27SDimitry Andric return "Asynchronous (1)"; 234106c3fb27SDimitry Andric default: 234206c3fb27SDimitry Andric return (Twine("Unknown (") + Twine(Value) + ")").str(); 234306c3fb27SDimitry Andric } 234406c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_HEAP: 234506c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_STACK: 234606c3fb27SDimitry Andric switch (Value) { 234706c3fb27SDimitry Andric case 0: 234806c3fb27SDimitry Andric return "Disabled (0)"; 234906c3fb27SDimitry Andric case 1: 235006c3fb27SDimitry Andric return "Enabled (1)"; 235106c3fb27SDimitry Andric default: 235206c3fb27SDimitry Andric return (Twine("Unknown (") + Twine(Value) + ")").str(); 235306c3fb27SDimitry Andric } 235406c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALS: 235506c3fb27SDimitry Andric return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str(); 23560b57cec5SDimitry Andric default: 23570b57cec5SDimitry Andric break; 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric break; 23600b57cec5SDimitry Andric case EM_HEXAGON: 23610b57cec5SDimitry Andric switch (Type) { 23620b57cec5SDimitry Andric case DT_HEXAGON_VER: 23635ffd83dbSDimitry Andric return std::to_string(Value); 23640b57cec5SDimitry Andric case DT_HEXAGON_SYMSZ: 23650b57cec5SDimitry Andric case DT_HEXAGON_PLT: 23665ffd83dbSDimitry Andric return FormatHexValue(Value); 23670b57cec5SDimitry Andric default: 23680b57cec5SDimitry Andric break; 23690b57cec5SDimitry Andric } 23700b57cec5SDimitry Andric break; 23710b57cec5SDimitry Andric case EM_MIPS: 23720b57cec5SDimitry Andric switch (Type) { 23730b57cec5SDimitry Andric case DT_MIPS_RLD_VERSION: 23740b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTNO: 23750b57cec5SDimitry Andric case DT_MIPS_SYMTABNO: 23760b57cec5SDimitry Andric case DT_MIPS_UNREFEXTNO: 23775ffd83dbSDimitry Andric return std::to_string(Value); 23780b57cec5SDimitry Andric case DT_MIPS_TIME_STAMP: 23790b57cec5SDimitry Andric case DT_MIPS_ICHECKSUM: 23800b57cec5SDimitry Andric case DT_MIPS_IVERSION: 23810b57cec5SDimitry Andric case DT_MIPS_BASE_ADDRESS: 23820b57cec5SDimitry Andric case DT_MIPS_MSYM: 23830b57cec5SDimitry Andric case DT_MIPS_CONFLICT: 23840b57cec5SDimitry Andric case DT_MIPS_LIBLIST: 23850b57cec5SDimitry Andric case DT_MIPS_CONFLICTNO: 23860b57cec5SDimitry Andric case DT_MIPS_LIBLISTNO: 23870b57cec5SDimitry Andric case DT_MIPS_GOTSYM: 23880b57cec5SDimitry Andric case DT_MIPS_HIPAGENO: 23890b57cec5SDimitry Andric case DT_MIPS_RLD_MAP: 23900b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS: 23910b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASS_NO: 23920b57cec5SDimitry Andric case DT_MIPS_DELTA_INSTANCE: 23930b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC: 23940b57cec5SDimitry Andric case DT_MIPS_DELTA_RELOC_NO: 23950b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM: 23960b57cec5SDimitry Andric case DT_MIPS_DELTA_SYM_NO: 23970b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM: 23980b57cec5SDimitry Andric case DT_MIPS_DELTA_CLASSSYM_NO: 23990b57cec5SDimitry Andric case DT_MIPS_CXX_FLAGS: 24000b57cec5SDimitry Andric case DT_MIPS_PIXIE_INIT: 24010b57cec5SDimitry Andric case DT_MIPS_SYMBOL_LIB: 24020b57cec5SDimitry Andric case DT_MIPS_LOCALPAGE_GOTIDX: 24030b57cec5SDimitry Andric case DT_MIPS_LOCAL_GOTIDX: 24040b57cec5SDimitry Andric case DT_MIPS_HIDDEN_GOTIDX: 24050b57cec5SDimitry Andric case DT_MIPS_PROTECTED_GOTIDX: 24060b57cec5SDimitry Andric case DT_MIPS_OPTIONS: 24070b57cec5SDimitry Andric case DT_MIPS_INTERFACE: 24080b57cec5SDimitry Andric case DT_MIPS_DYNSTR_ALIGN: 24090b57cec5SDimitry Andric case DT_MIPS_INTERFACE_SIZE: 24100b57cec5SDimitry Andric case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: 24110b57cec5SDimitry Andric case DT_MIPS_PERF_SUFFIX: 24120b57cec5SDimitry Andric case DT_MIPS_COMPACT_SIZE: 24130b57cec5SDimitry Andric case DT_MIPS_GP_VALUE: 24140b57cec5SDimitry Andric case DT_MIPS_AUX_DYNAMIC: 24150b57cec5SDimitry Andric case DT_MIPS_PLTGOT: 24160b57cec5SDimitry Andric case DT_MIPS_RWPLT: 24170b57cec5SDimitry Andric case DT_MIPS_RLD_MAP_REL: 2418d781ede6SDimitry Andric case DT_MIPS_XHASH: 24195ffd83dbSDimitry Andric return FormatHexValue(Value); 24200b57cec5SDimitry Andric case DT_MIPS_FLAGS: 2421bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags)); 24220b57cec5SDimitry Andric default: 24230b57cec5SDimitry Andric break; 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric break; 24260b57cec5SDimitry Andric default: 24270b57cec5SDimitry Andric break; 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric 24300b57cec5SDimitry Andric switch (Type) { 24310b57cec5SDimitry Andric case DT_PLTREL: 24325ffd83dbSDimitry Andric if (Value == DT_REL) 24335ffd83dbSDimitry Andric return "REL"; 24345ffd83dbSDimitry Andric if (Value == DT_RELA) 24355ffd83dbSDimitry Andric return "RELA"; 2436*0fca6ea1SDimitry Andric if (Value == DT_CREL) 2437*0fca6ea1SDimitry Andric return "CREL"; 2438bdd1243dSDimitry Andric [[fallthrough]]; 24390b57cec5SDimitry Andric case DT_PLTGOT: 24400b57cec5SDimitry Andric case DT_HASH: 24410b57cec5SDimitry Andric case DT_STRTAB: 24420b57cec5SDimitry Andric case DT_SYMTAB: 24430b57cec5SDimitry Andric case DT_RELA: 24440b57cec5SDimitry Andric case DT_INIT: 24450b57cec5SDimitry Andric case DT_FINI: 24460b57cec5SDimitry Andric case DT_REL: 24470b57cec5SDimitry Andric case DT_JMPREL: 24480b57cec5SDimitry Andric case DT_INIT_ARRAY: 24490b57cec5SDimitry Andric case DT_FINI_ARRAY: 24500b57cec5SDimitry Andric case DT_PREINIT_ARRAY: 24510b57cec5SDimitry Andric case DT_DEBUG: 2452*0fca6ea1SDimitry Andric case DT_CREL: 24530b57cec5SDimitry Andric case DT_VERDEF: 24540b57cec5SDimitry Andric case DT_VERNEED: 24550b57cec5SDimitry Andric case DT_VERSYM: 24560b57cec5SDimitry Andric case DT_GNU_HASH: 24570b57cec5SDimitry Andric case DT_NULL: 24585ffd83dbSDimitry Andric return FormatHexValue(Value); 24590b57cec5SDimitry Andric case DT_RELACOUNT: 24600b57cec5SDimitry Andric case DT_RELCOUNT: 24610b57cec5SDimitry Andric case DT_VERDEFNUM: 24620b57cec5SDimitry Andric case DT_VERNEEDNUM: 24635ffd83dbSDimitry Andric return std::to_string(Value); 24640b57cec5SDimitry Andric case DT_PLTRELSZ: 24650b57cec5SDimitry Andric case DT_RELASZ: 24660b57cec5SDimitry Andric case DT_RELAENT: 24670b57cec5SDimitry Andric case DT_STRSZ: 24680b57cec5SDimitry Andric case DT_SYMENT: 24690b57cec5SDimitry Andric case DT_RELSZ: 24700b57cec5SDimitry Andric case DT_RELENT: 24710b57cec5SDimitry Andric case DT_INIT_ARRAYSZ: 24720b57cec5SDimitry Andric case DT_FINI_ARRAYSZ: 24730b57cec5SDimitry Andric case DT_PREINIT_ARRAYSZ: 2474349cc55cSDimitry Andric case DT_RELRSZ: 2475349cc55cSDimitry Andric case DT_RELRENT: 24765f757f3fSDimitry Andric case DT_AARCH64_AUTH_RELRSZ: 24775f757f3fSDimitry Andric case DT_AARCH64_AUTH_RELRENT: 24780b57cec5SDimitry Andric case DT_ANDROID_RELSZ: 24790b57cec5SDimitry Andric case DT_ANDROID_RELASZ: 24805ffd83dbSDimitry Andric return std::to_string(Value) + " (bytes)"; 24810b57cec5SDimitry Andric case DT_NEEDED: 24820b57cec5SDimitry Andric case DT_SONAME: 24830b57cec5SDimitry Andric case DT_AUXILIARY: 24840b57cec5SDimitry Andric case DT_USED: 24850b57cec5SDimitry Andric case DT_FILTER: 24860b57cec5SDimitry Andric case DT_RPATH: 24870b57cec5SDimitry Andric case DT_RUNPATH: { 24880b57cec5SDimitry Andric const std::map<uint64_t, const char *> TagNames = { 24895ffd83dbSDimitry Andric {DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"}, 24905ffd83dbSDimitry Andric {DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"}, 24915ffd83dbSDimitry Andric {DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"}, 24920b57cec5SDimitry Andric {DT_RUNPATH, "Library runpath"}, 24930b57cec5SDimitry Andric }; 24945ffd83dbSDimitry Andric 24955ffd83dbSDimitry Andric return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]") 24965ffd83dbSDimitry Andric .str(); 24970b57cec5SDimitry Andric } 24980b57cec5SDimitry Andric case DT_FLAGS: 2499bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags)); 25000b57cec5SDimitry Andric case DT_FLAGS_1: 2501bdd1243dSDimitry Andric return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1)); 25020b57cec5SDimitry Andric default: 25035ffd83dbSDimitry Andric return FormatHexValue(Value); 25040b57cec5SDimitry Andric } 25050b57cec5SDimitry Andric } 25060b57cec5SDimitry Andric 25078bcb0991SDimitry Andric template <class ELFT> 25085ffd83dbSDimitry Andric StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { 25095ffd83dbSDimitry Andric if (DynamicStringTable.empty() && !DynamicStringTable.data()) { 2510e8d8bef9SDimitry Andric reportUniqueWarning("string table was not found"); 25115ffd83dbSDimitry Andric return "<?>"; 25125ffd83dbSDimitry Andric } 25135ffd83dbSDimitry Andric 25145ffd83dbSDimitry Andric auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) { 2515e8d8bef9SDimitry Andric reportUniqueWarning("string table at offset 0x" + Twine::utohexstr(Offset) + 2516e8d8bef9SDimitry Andric Msg); 25175ffd83dbSDimitry Andric return "<?>"; 25185ffd83dbSDimitry Andric }; 25195ffd83dbSDimitry Andric 2520e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 25215ffd83dbSDimitry Andric const uint64_t Offset = 2522e8d8bef9SDimitry Andric (const uint8_t *)DynamicStringTable.data() - Obj.base(); 25235ffd83dbSDimitry Andric if (DynamicStringTable.size() > FileSize - Offset) 25245ffd83dbSDimitry Andric return WarnAndReturn(" with size 0x" + 25255ffd83dbSDimitry Andric Twine::utohexstr(DynamicStringTable.size()) + 25265ffd83dbSDimitry Andric " goes past the end of the file (0x" + 25275ffd83dbSDimitry Andric Twine::utohexstr(FileSize) + ")", 25285ffd83dbSDimitry Andric Offset); 25295ffd83dbSDimitry Andric 25305ffd83dbSDimitry Andric if (Value >= DynamicStringTable.size()) 25315ffd83dbSDimitry Andric return WarnAndReturn( 25325ffd83dbSDimitry Andric ": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) + 25335ffd83dbSDimitry Andric ": it goes past the end of the table (0x" + 25345ffd83dbSDimitry Andric Twine::utohexstr(Offset + DynamicStringTable.size()) + ")", 25355ffd83dbSDimitry Andric Offset); 25365ffd83dbSDimitry Andric 25375ffd83dbSDimitry Andric if (DynamicStringTable.back() != '\0') 25385ffd83dbSDimitry Andric return WarnAndReturn(": unable to read the string at 0x" + 25395ffd83dbSDimitry Andric Twine::utohexstr(Offset + Value) + 25405ffd83dbSDimitry Andric ": the string table is not null-terminated", 25415ffd83dbSDimitry Andric Offset); 25425ffd83dbSDimitry Andric 25438bcb0991SDimitry Andric return DynamicStringTable.data() + Value; 25448bcb0991SDimitry Andric } 25458bcb0991SDimitry Andric 25460b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() { 25470b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF); 25480b57cec5SDimitry Andric Ctx.printUnwindInformation(); 25490b57cec5SDimitry Andric } 25500b57cec5SDimitry Andric 2551e8d8bef9SDimitry Andric // The namespace is needed to fix the compilation with GCC older than 7.0+. 25520b57cec5SDimitry Andric namespace { 25530b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printUnwindInfo() { 2554e8d8bef9SDimitry Andric if (Obj.getHeader().e_machine == EM_ARM) { 2555e8d8bef9SDimitry Andric ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF.getFileName(), 25568bcb0991SDimitry Andric DotSymtabSec); 25570b57cec5SDimitry Andric Ctx.PrintUnwindInformation(); 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF); 25600b57cec5SDimitry Andric Ctx.printUnwindInformation(); 25610b57cec5SDimitry Andric } 2562e8d8bef9SDimitry Andric } // namespace 25630b57cec5SDimitry Andric 25640b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() { 25650b57cec5SDimitry Andric ListScope D(W, "NeededLibraries"); 25660b57cec5SDimitry Andric 25675ffd83dbSDimitry Andric std::vector<StringRef> Libs; 25680b57cec5SDimitry Andric for (const auto &Entry : dynamic_table()) 25698bcb0991SDimitry Andric if (Entry.d_tag == ELF::DT_NEEDED) 25708bcb0991SDimitry Andric Libs.push_back(getDynamicString(Entry.d_un.d_val)); 25710b57cec5SDimitry Andric 25725ffd83dbSDimitry Andric llvm::sort(Libs); 25730b57cec5SDimitry Andric 25745ffd83dbSDimitry Andric for (StringRef L : Libs) 25755f757f3fSDimitry Andric W.printString(L); 25760b57cec5SDimitry Andric } 25770b57cec5SDimitry Andric 25785ffd83dbSDimitry Andric template <class ELFT> 2579e8d8bef9SDimitry Andric static Error checkHashTable(const ELFDumper<ELFT> &Dumper, 25805ffd83dbSDimitry Andric const typename ELFT::Hash *H, 25815ffd83dbSDimitry Andric bool *IsHeaderValid = nullptr) { 2582e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 2583e8d8bef9SDimitry Andric const uint64_t SecOffset = (const uint8_t *)H - Obj.base(); 2584e8d8bef9SDimitry Andric if (Dumper.getHashTableEntSize() == 8) { 2585e8d8bef9SDimitry Andric auto It = llvm::find_if(ElfMachineType, [&](const EnumEntry<unsigned> &E) { 2586e8d8bef9SDimitry Andric return E.Value == Obj.getHeader().e_machine; 2587e8d8bef9SDimitry Andric }); 2588e8d8bef9SDimitry Andric if (IsHeaderValid) 2589e8d8bef9SDimitry Andric *IsHeaderValid = false; 2590e8d8bef9SDimitry Andric return createError("the hash table at 0x" + Twine::utohexstr(SecOffset) + 2591e8d8bef9SDimitry Andric " is not supported: it contains non-standard 8 " 2592e8d8bef9SDimitry Andric "byte entries on " + 2593e8d8bef9SDimitry Andric It->AltName + " platform"); 2594e8d8bef9SDimitry Andric } 2595e8d8bef9SDimitry Andric 2596e8d8bef9SDimitry Andric auto MakeError = [&](const Twine &Msg = "") { 2597e8d8bef9SDimitry Andric return createError("the hash table at offset 0x" + 2598e8d8bef9SDimitry Andric Twine::utohexstr(SecOffset) + 25995ffd83dbSDimitry Andric " goes past the end of the file (0x" + 2600e8d8bef9SDimitry Andric Twine::utohexstr(Obj.getBufSize()) + ")" + Msg); 26015ffd83dbSDimitry Andric }; 26025ffd83dbSDimitry Andric 26035ffd83dbSDimitry Andric // Each SHT_HASH section starts from two 32-bit fields: nbucket and nchain. 26045ffd83dbSDimitry Andric const unsigned HeaderSize = 2 * sizeof(typename ELFT::Word); 26055ffd83dbSDimitry Andric 26065ffd83dbSDimitry Andric if (IsHeaderValid) 2607e8d8bef9SDimitry Andric *IsHeaderValid = Obj.getBufSize() - SecOffset >= HeaderSize; 26085ffd83dbSDimitry Andric 2609e8d8bef9SDimitry Andric if (Obj.getBufSize() - SecOffset < HeaderSize) 2610e8d8bef9SDimitry Andric return MakeError(); 26115ffd83dbSDimitry Andric 2612e8d8bef9SDimitry Andric if (Obj.getBufSize() - SecOffset - HeaderSize < 26135ffd83dbSDimitry Andric ((uint64_t)H->nbucket + H->nchain) * sizeof(typename ELFT::Word)) 2614e8d8bef9SDimitry Andric return MakeError(", nbucket = " + Twine(H->nbucket) + 26155ffd83dbSDimitry Andric ", nchain = " + Twine(H->nchain)); 26165ffd83dbSDimitry Andric return Error::success(); 26175ffd83dbSDimitry Andric } 26185ffd83dbSDimitry Andric 26195ffd83dbSDimitry Andric template <class ELFT> 2620e8d8bef9SDimitry Andric static Error checkGNUHashTable(const ELFFile<ELFT> &Obj, 26215ffd83dbSDimitry Andric const typename ELFT::GnuHash *GnuHashTable, 26225ffd83dbSDimitry Andric bool *IsHeaderValid = nullptr) { 26235ffd83dbSDimitry Andric const uint8_t *TableData = reinterpret_cast<const uint8_t *>(GnuHashTable); 2624e8d8bef9SDimitry Andric assert(TableData >= Obj.base() && TableData < Obj.base() + Obj.getBufSize() && 26255ffd83dbSDimitry Andric "GnuHashTable must always point to a location inside the file"); 26265ffd83dbSDimitry Andric 2627e8d8bef9SDimitry Andric uint64_t TableOffset = TableData - Obj.base(); 26285ffd83dbSDimitry Andric if (IsHeaderValid) 2629e8d8bef9SDimitry Andric *IsHeaderValid = TableOffset + /*Header size:*/ 16 < Obj.getBufSize(); 26305ffd83dbSDimitry Andric if (TableOffset + 16 + (uint64_t)GnuHashTable->nbuckets * 4 + 26315ffd83dbSDimitry Andric (uint64_t)GnuHashTable->maskwords * sizeof(typename ELFT::Off) >= 2632e8d8bef9SDimitry Andric Obj.getBufSize()) 26335ffd83dbSDimitry Andric return createError("unable to dump the SHT_GNU_HASH " 26345ffd83dbSDimitry Andric "section at 0x" + 26355ffd83dbSDimitry Andric Twine::utohexstr(TableOffset) + 26365ffd83dbSDimitry Andric ": it goes past the end of the file"); 26375ffd83dbSDimitry Andric return Error::success(); 26385ffd83dbSDimitry Andric } 26395ffd83dbSDimitry Andric 26400b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashTable() { 26410b57cec5SDimitry Andric DictScope D(W, "HashTable"); 26420b57cec5SDimitry Andric if (!HashTable) 26430b57cec5SDimitry Andric return; 26445ffd83dbSDimitry Andric 26455ffd83dbSDimitry Andric bool IsHeaderValid; 2646e8d8bef9SDimitry Andric Error Err = checkHashTable(*this, HashTable, &IsHeaderValid); 26475ffd83dbSDimitry Andric if (IsHeaderValid) { 26480b57cec5SDimitry Andric W.printNumber("Num Buckets", HashTable->nbucket); 26490b57cec5SDimitry Andric W.printNumber("Num Chains", HashTable->nchain); 26505ffd83dbSDimitry Andric } 26515ffd83dbSDimitry Andric 26525ffd83dbSDimitry Andric if (Err) { 26535ffd83dbSDimitry Andric reportUniqueWarning(std::move(Err)); 26545ffd83dbSDimitry Andric return; 26555ffd83dbSDimitry Andric } 26565ffd83dbSDimitry Andric 26570b57cec5SDimitry Andric W.printList("Buckets", HashTable->buckets()); 26580b57cec5SDimitry Andric W.printList("Chains", HashTable->chains()); 26590b57cec5SDimitry Andric } 26600b57cec5SDimitry Andric 26615ffd83dbSDimitry Andric template <class ELFT> 26625ffd83dbSDimitry Andric static Expected<ArrayRef<typename ELFT::Word>> 2663bdd1243dSDimitry Andric getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion, 26645ffd83dbSDimitry Andric const typename ELFT::GnuHash *GnuHashTable) { 26655ffd83dbSDimitry Andric if (!DynSymRegion) 26665ffd83dbSDimitry Andric return createError("no dynamic symbol table found"); 26675ffd83dbSDimitry Andric 26685ffd83dbSDimitry Andric ArrayRef<typename ELFT::Sym> DynSymTable = 2669e8d8bef9SDimitry Andric DynSymRegion->template getAsArrayRef<typename ELFT::Sym>(); 26705ffd83dbSDimitry Andric size_t NumSyms = DynSymTable.size(); 26715ffd83dbSDimitry Andric if (!NumSyms) 26725ffd83dbSDimitry Andric return createError("the dynamic symbol table is empty"); 26735ffd83dbSDimitry Andric 26745ffd83dbSDimitry Andric if (GnuHashTable->symndx < NumSyms) 26755ffd83dbSDimitry Andric return GnuHashTable->values(NumSyms); 26765ffd83dbSDimitry Andric 26775ffd83dbSDimitry Andric // A normal empty GNU hash table section produced by linker might have 26785ffd83dbSDimitry Andric // symndx set to the number of dynamic symbols + 1 (for the zero symbol) 26795ffd83dbSDimitry Andric // and have dummy null values in the Bloom filter and in the buckets 26805ffd83dbSDimitry Andric // vector (or no values at all). It happens because the value of symndx is not 26815ffd83dbSDimitry Andric // important for dynamic loaders when the GNU hash table is empty. They just 26825ffd83dbSDimitry Andric // skip the whole object during symbol lookup. In such cases, the symndx value 26835ffd83dbSDimitry Andric // is irrelevant and we should not report a warning. 26845ffd83dbSDimitry Andric ArrayRef<typename ELFT::Word> Buckets = GnuHashTable->buckets(); 26855ffd83dbSDimitry Andric if (!llvm::all_of(Buckets, [](typename ELFT::Word V) { return V == 0; })) 2686e8d8bef9SDimitry Andric return createError( 2687e8d8bef9SDimitry Andric "the first hashed symbol index (" + Twine(GnuHashTable->symndx) + 2688e8d8bef9SDimitry Andric ") is greater than or equal to the number of dynamic symbols (" + 26895ffd83dbSDimitry Andric Twine(NumSyms) + ")"); 26905ffd83dbSDimitry Andric // There is no way to represent an array of (dynamic symbols count - symndx) 26915ffd83dbSDimitry Andric // length. 26925ffd83dbSDimitry Andric return ArrayRef<typename ELFT::Word>(); 26935ffd83dbSDimitry Andric } 26945ffd83dbSDimitry Andric 26955ffd83dbSDimitry Andric template <typename ELFT> 2696e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printGnuHashTable() { 26970b57cec5SDimitry Andric DictScope D(W, "GnuHashTable"); 26980b57cec5SDimitry Andric if (!GnuHashTable) 26990b57cec5SDimitry Andric return; 27005ffd83dbSDimitry Andric 27015ffd83dbSDimitry Andric bool IsHeaderValid; 2702e8d8bef9SDimitry Andric Error Err = checkGNUHashTable<ELFT>(Obj, GnuHashTable, &IsHeaderValid); 27035ffd83dbSDimitry Andric if (IsHeaderValid) { 27040b57cec5SDimitry Andric W.printNumber("Num Buckets", GnuHashTable->nbuckets); 27050b57cec5SDimitry Andric W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); 27060b57cec5SDimitry Andric W.printNumber("Num Mask Words", GnuHashTable->maskwords); 27070b57cec5SDimitry Andric W.printNumber("Shift Count", GnuHashTable->shift2); 27085ffd83dbSDimitry Andric } 27095ffd83dbSDimitry Andric 27105ffd83dbSDimitry Andric if (Err) { 27115ffd83dbSDimitry Andric reportUniqueWarning(std::move(Err)); 27125ffd83dbSDimitry Andric return; 27135ffd83dbSDimitry Andric } 27145ffd83dbSDimitry Andric 27155ffd83dbSDimitry Andric ArrayRef<typename ELFT::Off> BloomFilter = GnuHashTable->filter(); 27165ffd83dbSDimitry Andric W.printHexList("Bloom Filter", BloomFilter); 27175ffd83dbSDimitry Andric 27185ffd83dbSDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets(); 27195ffd83dbSDimitry Andric W.printList("Buckets", Buckets); 27205ffd83dbSDimitry Andric 27215ffd83dbSDimitry Andric Expected<ArrayRef<Elf_Word>> Chains = 27225ffd83dbSDimitry Andric getGnuHashTableChains<ELFT>(DynSymRegion, GnuHashTable); 27235ffd83dbSDimitry Andric if (!Chains) { 2724e8d8bef9SDimitry Andric reportUniqueWarning("unable to dump 'Values' for the SHT_GNU_HASH " 27255ffd83dbSDimitry Andric "section: " + 2726e8d8bef9SDimitry Andric toString(Chains.takeError())); 27275ffd83dbSDimitry Andric return; 27285ffd83dbSDimitry Andric } 27295ffd83dbSDimitry Andric 27305ffd83dbSDimitry Andric W.printHexList("Values", *Chains); 27310b57cec5SDimitry Andric } 27320b57cec5SDimitry Andric 273306c3fb27SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() { 273406c3fb27SDimitry Andric // Print histogram for the .hash section. 273506c3fb27SDimitry Andric if (this->HashTable) { 273606c3fb27SDimitry Andric if (Error E = checkHashTable<ELFT>(*this, this->HashTable)) 273706c3fb27SDimitry Andric this->reportUniqueWarning(std::move(E)); 273806c3fb27SDimitry Andric else 273906c3fb27SDimitry Andric printHashHistogram(*this->HashTable); 274006c3fb27SDimitry Andric } 274106c3fb27SDimitry Andric 274206c3fb27SDimitry Andric // Print histogram for the .gnu.hash section. 274306c3fb27SDimitry Andric if (this->GnuHashTable) { 274406c3fb27SDimitry Andric if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable)) 274506c3fb27SDimitry Andric this->reportUniqueWarning(std::move(E)); 274606c3fb27SDimitry Andric else 274706c3fb27SDimitry Andric printGnuHashHistogram(*this->GnuHashTable); 274806c3fb27SDimitry Andric } 274906c3fb27SDimitry Andric } 275006c3fb27SDimitry Andric 275106c3fb27SDimitry Andric template <typename ELFT> 275206c3fb27SDimitry Andric void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const { 275306c3fb27SDimitry Andric size_t NBucket = HashTable.nbucket; 275406c3fb27SDimitry Andric size_t NChain = HashTable.nchain; 275506c3fb27SDimitry Andric ArrayRef<Elf_Word> Buckets = HashTable.buckets(); 275606c3fb27SDimitry Andric ArrayRef<Elf_Word> Chains = HashTable.chains(); 275706c3fb27SDimitry Andric size_t TotalSyms = 0; 275806c3fb27SDimitry Andric // If hash table is correct, we have at least chains with 0 length. 275906c3fb27SDimitry Andric size_t MaxChain = 1; 276006c3fb27SDimitry Andric 276106c3fb27SDimitry Andric if (NChain == 0 || NBucket == 0) 276206c3fb27SDimitry Andric return; 276306c3fb27SDimitry Andric 276406c3fb27SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 27655f757f3fSDimitry Andric // Go over all buckets and note chain lengths of each bucket (total 276606c3fb27SDimitry Andric // unique chain lengths). 276706c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) { 276806c3fb27SDimitry Andric BitVector Visited(NChain); 276906c3fb27SDimitry Andric for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) { 277006c3fb27SDimitry Andric if (C == ELF::STN_UNDEF) 277106c3fb27SDimitry Andric break; 277206c3fb27SDimitry Andric if (Visited[C]) { 277306c3fb27SDimitry Andric this->reportUniqueWarning( 277406c3fb27SDimitry Andric ".hash section is invalid: bucket " + Twine(C) + 277506c3fb27SDimitry Andric ": a cycle was detected in the linked chain"); 277606c3fb27SDimitry Andric break; 277706c3fb27SDimitry Andric } 277806c3fb27SDimitry Andric Visited[C] = true; 277906c3fb27SDimitry Andric if (MaxChain <= ++ChainLen[B]) 278006c3fb27SDimitry Andric ++MaxChain; 278106c3fb27SDimitry Andric } 278206c3fb27SDimitry Andric TotalSyms += ChainLen[B]; 278306c3fb27SDimitry Andric } 278406c3fb27SDimitry Andric 278506c3fb27SDimitry Andric if (!TotalSyms) 278606c3fb27SDimitry Andric return; 278706c3fb27SDimitry Andric 278806c3fb27SDimitry Andric std::vector<size_t> Count(MaxChain, 0); 278906c3fb27SDimitry Andric // Count how long is the chain for each bucket. 279006c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; B++) 279106c3fb27SDimitry Andric ++Count[ChainLen[B]]; 279206c3fb27SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 279306c3fb27SDimitry Andric // coverage of the symbols. 279406c3fb27SDimitry Andric printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false); 279506c3fb27SDimitry Andric } 279606c3fb27SDimitry Andric 279706c3fb27SDimitry Andric template <class ELFT> 279806c3fb27SDimitry Andric void ELFDumper<ELFT>::printGnuHashHistogram( 279906c3fb27SDimitry Andric const Elf_GnuHash &GnuHashTable) const { 280006c3fb27SDimitry Andric Expected<ArrayRef<Elf_Word>> ChainsOrErr = 280106c3fb27SDimitry Andric getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable); 280206c3fb27SDimitry Andric if (!ChainsOrErr) { 280306c3fb27SDimitry Andric this->reportUniqueWarning("unable to print the GNU hash table histogram: " + 280406c3fb27SDimitry Andric toString(ChainsOrErr.takeError())); 280506c3fb27SDimitry Andric return; 280606c3fb27SDimitry Andric } 280706c3fb27SDimitry Andric 280806c3fb27SDimitry Andric ArrayRef<Elf_Word> Chains = *ChainsOrErr; 280906c3fb27SDimitry Andric size_t Symndx = GnuHashTable.symndx; 281006c3fb27SDimitry Andric size_t TotalSyms = 0; 281106c3fb27SDimitry Andric size_t MaxChain = 1; 281206c3fb27SDimitry Andric 281306c3fb27SDimitry Andric size_t NBucket = GnuHashTable.nbuckets; 281406c3fb27SDimitry Andric if (Chains.empty() || NBucket == 0) 281506c3fb27SDimitry Andric return; 281606c3fb27SDimitry Andric 281706c3fb27SDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets(); 281806c3fb27SDimitry Andric std::vector<size_t> ChainLen(NBucket, 0); 281906c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) { 282006c3fb27SDimitry Andric if (!Buckets[B]) 282106c3fb27SDimitry Andric continue; 282206c3fb27SDimitry Andric size_t Len = 1; 282306c3fb27SDimitry Andric for (size_t C = Buckets[B] - Symndx; 282406c3fb27SDimitry Andric C < Chains.size() && (Chains[C] & 1) == 0; ++C) 282506c3fb27SDimitry Andric if (MaxChain < ++Len) 282606c3fb27SDimitry Andric ++MaxChain; 282706c3fb27SDimitry Andric ChainLen[B] = Len; 282806c3fb27SDimitry Andric TotalSyms += Len; 282906c3fb27SDimitry Andric } 283006c3fb27SDimitry Andric ++MaxChain; 283106c3fb27SDimitry Andric 283206c3fb27SDimitry Andric if (!TotalSyms) 283306c3fb27SDimitry Andric return; 283406c3fb27SDimitry Andric 283506c3fb27SDimitry Andric std::vector<size_t> Count(MaxChain, 0); 283606c3fb27SDimitry Andric for (size_t B = 0; B < NBucket; ++B) 283706c3fb27SDimitry Andric ++Count[ChainLen[B]]; 283806c3fb27SDimitry Andric // Print Number of buckets with each chain lengths and their cumulative 283906c3fb27SDimitry Andric // coverage of the symbols. 284006c3fb27SDimitry Andric printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true); 284106c3fb27SDimitry Andric } 284206c3fb27SDimitry Andric 28430b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { 2844e8d8bef9SDimitry Andric StringRef SOName = "<Not found>"; 2845e8d8bef9SDimitry Andric if (SONameOffset) 2846e8d8bef9SDimitry Andric SOName = getDynamicString(*SONameOffset); 28470b57cec5SDimitry Andric W.printString("LoadName", SOName); 28480b57cec5SDimitry Andric } 28490b57cec5SDimitry Andric 28508bcb0991SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() { 2851e8d8bef9SDimitry Andric switch (Obj.getHeader().e_machine) { 2852*0fca6ea1SDimitry Andric case EM_HEXAGON: 2853*0fca6ea1SDimitry Andric printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES, 2854*0fca6ea1SDimitry Andric std::make_unique<HexagonAttributeParser>(&W), 28555f757f3fSDimitry Andric llvm::endianness::little); 2856*0fca6ea1SDimitry Andric break; 2857*0fca6ea1SDimitry Andric case EM_ARM: 2858*0fca6ea1SDimitry Andric printAttributes( 2859*0fca6ea1SDimitry Andric ELF::SHT_ARM_ATTRIBUTES, std::make_unique<ARMAttributeParser>(&W), 2860*0fca6ea1SDimitry Andric Obj.isLE() ? llvm::endianness::little : llvm::endianness::big); 2861349cc55cSDimitry Andric break; 28625ffd83dbSDimitry Andric case EM_RISCV: 2863349cc55cSDimitry Andric if (Obj.isLE()) 2864349cc55cSDimitry Andric printAttributes(ELF::SHT_RISCV_ATTRIBUTES, 2865349cc55cSDimitry Andric std::make_unique<RISCVAttributeParser>(&W), 28665f757f3fSDimitry Andric llvm::endianness::little); 2867349cc55cSDimitry Andric else 2868349cc55cSDimitry Andric reportUniqueWarning("attribute printing not implemented for big-endian " 2869349cc55cSDimitry Andric "RISC-V objects"); 2870349cc55cSDimitry Andric break; 2871349cc55cSDimitry Andric case EM_MSP430: 2872349cc55cSDimitry Andric printAttributes(ELF::SHT_MSP430_ATTRIBUTES, 2873349cc55cSDimitry Andric std::make_unique<MSP430AttributeParser>(&W), 28745f757f3fSDimitry Andric llvm::endianness::little); 28758bcb0991SDimitry Andric break; 28768bcb0991SDimitry Andric case EM_MIPS: { 2877e8d8bef9SDimitry Andric printMipsABIFlags(); 28788bcb0991SDimitry Andric printMipsOptions(); 28798bcb0991SDimitry Andric printMipsReginfo(); 2880e8d8bef9SDimitry Andric MipsGOTParser<ELFT> Parser(*this); 28815ffd83dbSDimitry Andric if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols())) 2882e8d8bef9SDimitry Andric reportUniqueWarning(std::move(E)); 28835ffd83dbSDimitry Andric else if (!Parser.isGotEmpty()) 2884e8d8bef9SDimitry Andric printMipsGOT(Parser); 28855ffd83dbSDimitry Andric 28865ffd83dbSDimitry Andric if (Error E = Parser.findPLT(dynamic_table())) 2887e8d8bef9SDimitry Andric reportUniqueWarning(std::move(E)); 28885ffd83dbSDimitry Andric else if (!Parser.isPltEmpty()) 2889e8d8bef9SDimitry Andric printMipsPLT(Parser); 28908bcb0991SDimitry Andric break; 28918bcb0991SDimitry Andric } 28928bcb0991SDimitry Andric default: 28938bcb0991SDimitry Andric break; 28948bcb0991SDimitry Andric } 28958bcb0991SDimitry Andric } 28968bcb0991SDimitry Andric 2897349cc55cSDimitry Andric template <class ELFT> 2898349cc55cSDimitry Andric void ELFDumper<ELFT>::printAttributes( 2899349cc55cSDimitry Andric unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser, 29005f757f3fSDimitry Andric llvm::endianness Endianness) { 2901349cc55cSDimitry Andric assert((AttrShType != ELF::SHT_NULL) && AttrParser && 2902349cc55cSDimitry Andric "Incomplete ELF attribute implementation"); 29030b57cec5SDimitry Andric DictScope BA(W, "BuildAttributes"); 2904e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 2905349cc55cSDimitry Andric if (Sec.sh_type != AttrShType) 29060b57cec5SDimitry Andric continue; 29070b57cec5SDimitry Andric 2908e8d8bef9SDimitry Andric ArrayRef<uint8_t> Contents; 2909e8d8bef9SDimitry Andric if (Expected<ArrayRef<uint8_t>> ContentOrErr = 2910e8d8bef9SDimitry Andric Obj.getSectionContents(Sec)) { 2911e8d8bef9SDimitry Andric Contents = *ContentOrErr; 2912e8d8bef9SDimitry Andric if (Contents.empty()) { 2913e8d8bef9SDimitry Andric reportUniqueWarning("the " + describe(Sec) + " is empty"); 29140b57cec5SDimitry Andric continue; 29150b57cec5SDimitry Andric } 2916e8d8bef9SDimitry Andric } else { 2917e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the content of the " + describe(Sec) + 2918e8d8bef9SDimitry Andric ": " + toString(ContentOrErr.takeError())); 29190b57cec5SDimitry Andric continue; 2920e8d8bef9SDimitry Andric } 29210b57cec5SDimitry Andric 2922e8d8bef9SDimitry Andric W.printHex("FormatVersion", Contents[0]); 2923e8d8bef9SDimitry Andric 2924349cc55cSDimitry Andric if (Error E = AttrParser->parse(Contents, Endianness)) 2925e8d8bef9SDimitry Andric reportUniqueWarning("unable to dump attributes from the " + 2926e8d8bef9SDimitry Andric describe(Sec) + ": " + toString(std::move(E))); 29275ffd83dbSDimitry Andric } 29280b57cec5SDimitry Andric } 2929e8d8bef9SDimitry Andric 2930e8d8bef9SDimitry Andric namespace { 29310b57cec5SDimitry Andric 29320b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser { 29330b57cec5SDimitry Andric public: 2934e8d8bef9SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 2935e8d8bef9SDimitry Andric using Entry = typename ELFT::Addr; 29360b57cec5SDimitry Andric using Entries = ArrayRef<Entry>; 29370b57cec5SDimitry Andric 29380b57cec5SDimitry Andric const bool IsStatic; 2939e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj; 2940e8d8bef9SDimitry Andric const ELFDumper<ELFT> &Dumper; 29410b57cec5SDimitry Andric 2942e8d8bef9SDimitry Andric MipsGOTParser(const ELFDumper<ELFT> &D); 29435ffd83dbSDimitry Andric Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); 29445ffd83dbSDimitry Andric Error findPLT(Elf_Dyn_Range DynTable); 29450b57cec5SDimitry Andric 29465ffd83dbSDimitry Andric bool isGotEmpty() const { return GotEntries.empty(); } 29475ffd83dbSDimitry Andric bool isPltEmpty() const { return PltEntries.empty(); } 29480b57cec5SDimitry Andric 29490b57cec5SDimitry Andric uint64_t getGp() const; 29500b57cec5SDimitry Andric 29510b57cec5SDimitry Andric const Entry *getGotLazyResolver() const; 29520b57cec5SDimitry Andric const Entry *getGotModulePointer() const; 29530b57cec5SDimitry Andric const Entry *getPltLazyResolver() const; 29540b57cec5SDimitry Andric const Entry *getPltModulePointer() const; 29550b57cec5SDimitry Andric 29560b57cec5SDimitry Andric Entries getLocalEntries() const; 29570b57cec5SDimitry Andric Entries getGlobalEntries() const; 29580b57cec5SDimitry Andric Entries getOtherEntries() const; 29590b57cec5SDimitry Andric Entries getPltEntries() const; 29600b57cec5SDimitry Andric 29610b57cec5SDimitry Andric uint64_t getGotAddress(const Entry * E) const; 29620b57cec5SDimitry Andric int64_t getGotOffset(const Entry * E) const; 29630b57cec5SDimitry Andric const Elf_Sym *getGotSym(const Entry *E) const; 29640b57cec5SDimitry Andric 29650b57cec5SDimitry Andric uint64_t getPltAddress(const Entry * E) const; 29660b57cec5SDimitry Andric const Elf_Sym *getPltSym(const Entry *E) const; 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric StringRef getPltStrTable() const { return PltStrTable; } 2969e8d8bef9SDimitry Andric const Elf_Shdr *getPltSymTable() const { return PltSymTable; } 29700b57cec5SDimitry Andric 29710b57cec5SDimitry Andric private: 29720b57cec5SDimitry Andric const Elf_Shdr *GotSec; 29730b57cec5SDimitry Andric size_t LocalNum; 29740b57cec5SDimitry Andric size_t GlobalNum; 29750b57cec5SDimitry Andric 29760b57cec5SDimitry Andric const Elf_Shdr *PltSec; 29770b57cec5SDimitry Andric const Elf_Shdr *PltRelSec; 29780b57cec5SDimitry Andric const Elf_Shdr *PltSymTable; 29798bcb0991SDimitry Andric StringRef FileName; 29808bcb0991SDimitry Andric 29810b57cec5SDimitry Andric Elf_Sym_Range GotDynSyms; 29820b57cec5SDimitry Andric StringRef PltStrTable; 29830b57cec5SDimitry Andric 29840b57cec5SDimitry Andric Entries GotEntries; 29850b57cec5SDimitry Andric Entries PltEntries; 29860b57cec5SDimitry Andric }; 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric } // end anonymous namespace 29890b57cec5SDimitry Andric 29900b57cec5SDimitry Andric template <class ELFT> 2991e8d8bef9SDimitry Andric MipsGOTParser<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &D) 2992e8d8bef9SDimitry Andric : IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject().getELFFile()), 2993e8d8bef9SDimitry Andric Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr), 2994e8d8bef9SDimitry Andric PltRelSec(nullptr), PltSymTable(nullptr), 2995e8d8bef9SDimitry Andric FileName(D.getElfObject().getFileName()) {} 29965ffd83dbSDimitry Andric 29975ffd83dbSDimitry Andric template <class ELFT> 29985ffd83dbSDimitry Andric Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable, 29995ffd83dbSDimitry Andric Elf_Sym_Range DynSyms) { 30000b57cec5SDimitry Andric // See "Global Offset Table" in Chapter 5 in the following document 30010b57cec5SDimitry Andric // for detailed GOT description. 30020b57cec5SDimitry Andric // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf 30030b57cec5SDimitry Andric 30040b57cec5SDimitry Andric // Find static GOT secton. 30050b57cec5SDimitry Andric if (IsStatic) { 3006e8d8bef9SDimitry Andric GotSec = Dumper.findSectionByName(".got"); 30070b57cec5SDimitry Andric if (!GotSec) 30085ffd83dbSDimitry Andric return Error::success(); 30090b57cec5SDimitry Andric 30108bcb0991SDimitry Andric ArrayRef<uint8_t> Content = 3011e8d8bef9SDimitry Andric unwrapOrError(FileName, Obj.getSectionContents(*GotSec)); 30120b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 30130b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 30140b57cec5SDimitry Andric LocalNum = GotEntries.size(); 30155ffd83dbSDimitry Andric return Error::success(); 30160b57cec5SDimitry Andric } 30170b57cec5SDimitry Andric 30185ffd83dbSDimitry Andric // Lookup dynamic table tags which define the GOT layout. 3019bdd1243dSDimitry Andric std::optional<uint64_t> DtPltGot; 3020bdd1243dSDimitry Andric std::optional<uint64_t> DtLocalGotNum; 3021bdd1243dSDimitry Andric std::optional<uint64_t> DtGotSym; 30220b57cec5SDimitry Andric for (const auto &Entry : DynTable) { 30230b57cec5SDimitry Andric switch (Entry.getTag()) { 30240b57cec5SDimitry Andric case ELF::DT_PLTGOT: 30250b57cec5SDimitry Andric DtPltGot = Entry.getVal(); 30260b57cec5SDimitry Andric break; 30270b57cec5SDimitry Andric case ELF::DT_MIPS_LOCAL_GOTNO: 30280b57cec5SDimitry Andric DtLocalGotNum = Entry.getVal(); 30290b57cec5SDimitry Andric break; 30300b57cec5SDimitry Andric case ELF::DT_MIPS_GOTSYM: 30310b57cec5SDimitry Andric DtGotSym = Entry.getVal(); 30320b57cec5SDimitry Andric break; 30330b57cec5SDimitry Andric } 30340b57cec5SDimitry Andric } 30350b57cec5SDimitry Andric 30365ffd83dbSDimitry Andric if (!DtPltGot && !DtLocalGotNum && !DtGotSym) 30375ffd83dbSDimitry Andric return Error::success(); 30385ffd83dbSDimitry Andric 30390b57cec5SDimitry Andric if (!DtPltGot) 30405ffd83dbSDimitry Andric return createError("cannot find PLTGOT dynamic tag"); 30410b57cec5SDimitry Andric if (!DtLocalGotNum) 30425ffd83dbSDimitry Andric return createError("cannot find MIPS_LOCAL_GOTNO dynamic tag"); 30430b57cec5SDimitry Andric if (!DtGotSym) 30445ffd83dbSDimitry Andric return createError("cannot find MIPS_GOTSYM dynamic tag"); 30450b57cec5SDimitry Andric 30460b57cec5SDimitry Andric size_t DynSymTotal = DynSyms.size(); 30470b57cec5SDimitry Andric if (*DtGotSym > DynSymTotal) 30485ffd83dbSDimitry Andric return createError("DT_MIPS_GOTSYM value (" + Twine(*DtGotSym) + 30495ffd83dbSDimitry Andric ") exceeds the number of dynamic symbols (" + 30505ffd83dbSDimitry Andric Twine(DynSymTotal) + ")"); 30510b57cec5SDimitry Andric 30528bcb0991SDimitry Andric GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot); 30530b57cec5SDimitry Andric if (!GotSec) 30545ffd83dbSDimitry Andric return createError("there is no non-empty GOT section at 0x" + 30555ffd83dbSDimitry Andric Twine::utohexstr(*DtPltGot)); 30560b57cec5SDimitry Andric 30570b57cec5SDimitry Andric LocalNum = *DtLocalGotNum; 30580b57cec5SDimitry Andric GlobalNum = DynSymTotal - *DtGotSym; 30590b57cec5SDimitry Andric 30608bcb0991SDimitry Andric ArrayRef<uint8_t> Content = 3061e8d8bef9SDimitry Andric unwrapOrError(FileName, Obj.getSectionContents(*GotSec)); 30620b57cec5SDimitry Andric GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), 30630b57cec5SDimitry Andric Content.size() / sizeof(Entry)); 30640b57cec5SDimitry Andric GotDynSyms = DynSyms.drop_front(*DtGotSym); 30655ffd83dbSDimitry Andric 30665ffd83dbSDimitry Andric return Error::success(); 30670b57cec5SDimitry Andric } 30680b57cec5SDimitry Andric 30695ffd83dbSDimitry Andric template <class ELFT> 30705ffd83dbSDimitry Andric Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) { 30715ffd83dbSDimitry Andric // Lookup dynamic table tags which define the PLT layout. 3072bdd1243dSDimitry Andric std::optional<uint64_t> DtMipsPltGot; 3073bdd1243dSDimitry Andric std::optional<uint64_t> DtJmpRel; 30745ffd83dbSDimitry Andric for (const auto &Entry : DynTable) { 30755ffd83dbSDimitry Andric switch (Entry.getTag()) { 30765ffd83dbSDimitry Andric case ELF::DT_MIPS_PLTGOT: 30775ffd83dbSDimitry Andric DtMipsPltGot = Entry.getVal(); 30785ffd83dbSDimitry Andric break; 30795ffd83dbSDimitry Andric case ELF::DT_JMPREL: 30805ffd83dbSDimitry Andric DtJmpRel = Entry.getVal(); 30815ffd83dbSDimitry Andric break; 30825ffd83dbSDimitry Andric } 30835ffd83dbSDimitry Andric } 30845ffd83dbSDimitry Andric 30855ffd83dbSDimitry Andric if (!DtMipsPltGot && !DtJmpRel) 30865ffd83dbSDimitry Andric return Error::success(); 30875ffd83dbSDimitry Andric 30880b57cec5SDimitry Andric // Find PLT section. 30890b57cec5SDimitry Andric if (!DtMipsPltGot) 30905ffd83dbSDimitry Andric return createError("cannot find MIPS_PLTGOT dynamic tag"); 30910b57cec5SDimitry Andric if (!DtJmpRel) 30925ffd83dbSDimitry Andric return createError("cannot find JMPREL dynamic tag"); 30930b57cec5SDimitry Andric 30948bcb0991SDimitry Andric PltSec = findNotEmptySectionByAddress(Obj, FileName, *DtMipsPltGot); 30950b57cec5SDimitry Andric if (!PltSec) 30965ffd83dbSDimitry Andric return createError("there is no non-empty PLTGOT section at 0x" + 30970b57cec5SDimitry Andric Twine::utohexstr(*DtMipsPltGot)); 30980b57cec5SDimitry Andric 30998bcb0991SDimitry Andric PltRelSec = findNotEmptySectionByAddress(Obj, FileName, *DtJmpRel); 31000b57cec5SDimitry Andric if (!PltRelSec) 31015ffd83dbSDimitry Andric return createError("there is no non-empty RELPLT section at 0x" + 31020b57cec5SDimitry Andric Twine::utohexstr(*DtJmpRel)); 31030b57cec5SDimitry Andric 31045ffd83dbSDimitry Andric if (Expected<ArrayRef<uint8_t>> PltContentOrErr = 3105e8d8bef9SDimitry Andric Obj.getSectionContents(*PltSec)) 31065ffd83dbSDimitry Andric PltEntries = 31075ffd83dbSDimitry Andric Entries(reinterpret_cast<const Entry *>(PltContentOrErr->data()), 31085ffd83dbSDimitry Andric PltContentOrErr->size() / sizeof(Entry)); 31095ffd83dbSDimitry Andric else 31105ffd83dbSDimitry Andric return createError("unable to read PLTGOT section content: " + 31115ffd83dbSDimitry Andric toString(PltContentOrErr.takeError())); 31120b57cec5SDimitry Andric 31135ffd83dbSDimitry Andric if (Expected<const Elf_Shdr *> PltSymTableOrErr = 3114e8d8bef9SDimitry Andric Obj.getSection(PltRelSec->sh_link)) 31155ffd83dbSDimitry Andric PltSymTable = *PltSymTableOrErr; 3116e8d8bef9SDimitry Andric else 3117e8d8bef9SDimitry Andric return createError("unable to get a symbol table linked to the " + 3118e8d8bef9SDimitry Andric describe(Obj, *PltRelSec) + ": " + 31195ffd83dbSDimitry Andric toString(PltSymTableOrErr.takeError())); 31205ffd83dbSDimitry Andric 31215ffd83dbSDimitry Andric if (Expected<StringRef> StrTabOrErr = 3122e8d8bef9SDimitry Andric Obj.getStringTableForSymtab(*PltSymTable)) 31235ffd83dbSDimitry Andric PltStrTable = *StrTabOrErr; 3124e8d8bef9SDimitry Andric else 3125e8d8bef9SDimitry Andric return createError("unable to get a string table for the " + 3126e8d8bef9SDimitry Andric describe(Obj, *PltSymTable) + ": " + 3127e8d8bef9SDimitry Andric toString(StrTabOrErr.takeError())); 31285ffd83dbSDimitry Andric 31295ffd83dbSDimitry Andric return Error::success(); 31300b57cec5SDimitry Andric } 31310b57cec5SDimitry Andric 31320b57cec5SDimitry Andric template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { 31330b57cec5SDimitry Andric return GotSec->sh_addr + 0x7ff0; 31340b57cec5SDimitry Andric } 31350b57cec5SDimitry Andric 31360b57cec5SDimitry Andric template <class ELFT> 31370b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31380b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotLazyResolver() const { 31390b57cec5SDimitry Andric return LocalNum > 0 ? &GotEntries[0] : nullptr; 31400b57cec5SDimitry Andric } 31410b57cec5SDimitry Andric 31420b57cec5SDimitry Andric template <class ELFT> 31430b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 31440b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotModulePointer() const { 31450b57cec5SDimitry Andric if (LocalNum < 2) 31460b57cec5SDimitry Andric return nullptr; 31470b57cec5SDimitry Andric const Entry &E = GotEntries[1]; 31480b57cec5SDimitry Andric if ((E >> (sizeof(Entry) * 8 - 1)) == 0) 31490b57cec5SDimitry Andric return nullptr; 31500b57cec5SDimitry Andric return &E; 31510b57cec5SDimitry Andric } 31520b57cec5SDimitry Andric 31530b57cec5SDimitry Andric template <class ELFT> 31540b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31550b57cec5SDimitry Andric MipsGOTParser<ELFT>::getLocalEntries() const { 31560b57cec5SDimitry Andric size_t Skip = getGotModulePointer() ? 2 : 1; 31570b57cec5SDimitry Andric if (LocalNum - Skip <= 0) 31580b57cec5SDimitry Andric return Entries(); 31590b57cec5SDimitry Andric return GotEntries.slice(Skip, LocalNum - Skip); 31600b57cec5SDimitry Andric } 31610b57cec5SDimitry Andric 31620b57cec5SDimitry Andric template <class ELFT> 31630b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31640b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGlobalEntries() const { 31650b57cec5SDimitry Andric if (GlobalNum == 0) 31660b57cec5SDimitry Andric return Entries(); 31670b57cec5SDimitry Andric return GotEntries.slice(LocalNum, GlobalNum); 31680b57cec5SDimitry Andric } 31690b57cec5SDimitry Andric 31700b57cec5SDimitry Andric template <class ELFT> 31710b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 31720b57cec5SDimitry Andric MipsGOTParser<ELFT>::getOtherEntries() const { 31730b57cec5SDimitry Andric size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; 31740b57cec5SDimitry Andric if (OtherNum == 0) 31750b57cec5SDimitry Andric return Entries(); 31760b57cec5SDimitry Andric return GotEntries.slice(LocalNum + GlobalNum, OtherNum); 31770b57cec5SDimitry Andric } 31780b57cec5SDimitry Andric 31790b57cec5SDimitry Andric template <class ELFT> 31800b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { 31810b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 31820b57cec5SDimitry Andric return GotSec->sh_addr + Offset; 31830b57cec5SDimitry Andric } 31840b57cec5SDimitry Andric 31850b57cec5SDimitry Andric template <class ELFT> 31860b57cec5SDimitry Andric int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { 31870b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); 31880b57cec5SDimitry Andric return Offset - 0x7ff0; 31890b57cec5SDimitry Andric } 31900b57cec5SDimitry Andric 31910b57cec5SDimitry Andric template <class ELFT> 31920b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 31930b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { 31940b57cec5SDimitry Andric int64_t Offset = std::distance(GotEntries.data(), E); 31950b57cec5SDimitry Andric return &GotDynSyms[Offset - LocalNum]; 31960b57cec5SDimitry Andric } 31970b57cec5SDimitry Andric 31980b57cec5SDimitry Andric template <class ELFT> 31990b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 32000b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltLazyResolver() const { 32010b57cec5SDimitry Andric return PltEntries.empty() ? nullptr : &PltEntries[0]; 32020b57cec5SDimitry Andric } 32030b57cec5SDimitry Andric 32040b57cec5SDimitry Andric template <class ELFT> 32050b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry * 32060b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltModulePointer() const { 32070b57cec5SDimitry Andric return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; 32080b57cec5SDimitry Andric } 32090b57cec5SDimitry Andric 32100b57cec5SDimitry Andric template <class ELFT> 32110b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries 32120b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltEntries() const { 32130b57cec5SDimitry Andric if (PltEntries.size() <= 2) 32140b57cec5SDimitry Andric return Entries(); 32150b57cec5SDimitry Andric return PltEntries.slice(2, PltEntries.size() - 2); 32160b57cec5SDimitry Andric } 32170b57cec5SDimitry Andric 32180b57cec5SDimitry Andric template <class ELFT> 32190b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { 32200b57cec5SDimitry Andric int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); 32210b57cec5SDimitry Andric return PltSec->sh_addr + Offset; 32220b57cec5SDimitry Andric } 32230b57cec5SDimitry Andric 32240b57cec5SDimitry Andric template <class ELFT> 32250b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym * 32260b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { 32270b57cec5SDimitry Andric int64_t Offset = std::distance(getPltEntries().data(), E); 32280b57cec5SDimitry Andric if (PltRelSec->sh_type == ELF::SHT_REL) { 3229e8d8bef9SDimitry Andric Elf_Rel_Range Rels = unwrapOrError(FileName, Obj.rels(*PltRelSec)); 32308bcb0991SDimitry Andric return unwrapOrError(FileName, 3231e8d8bef9SDimitry Andric Obj.getRelocationSymbol(Rels[Offset], PltSymTable)); 32320b57cec5SDimitry Andric } else { 3233e8d8bef9SDimitry Andric Elf_Rela_Range Rels = unwrapOrError(FileName, Obj.relas(*PltRelSec)); 32348bcb0991SDimitry Andric return unwrapOrError(FileName, 3235e8d8bef9SDimitry Andric Obj.getRelocationSymbol(Rels[Offset], PltSymTable)); 32360b57cec5SDimitry Andric } 32370b57cec5SDimitry Andric } 32380b57cec5SDimitry Andric 3239349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsISAExtType[] = { 32400b57cec5SDimitry Andric {"None", Mips::AFL_EXT_NONE}, 32410b57cec5SDimitry Andric {"Broadcom SB-1", Mips::AFL_EXT_SB1}, 32420b57cec5SDimitry Andric {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON}, 32430b57cec5SDimitry Andric {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, 32440b57cec5SDimitry Andric {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, 32450b57cec5SDimitry Andric {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, 32460b57cec5SDimitry Andric {"LSI R4010", Mips::AFL_EXT_4010}, 32470b57cec5SDimitry Andric {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E}, 32480b57cec5SDimitry Andric {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F}, 32490b57cec5SDimitry Andric {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A}, 32500b57cec5SDimitry Andric {"MIPS R4650", Mips::AFL_EXT_4650}, 32510b57cec5SDimitry Andric {"MIPS R5900", Mips::AFL_EXT_5900}, 32520b57cec5SDimitry Andric {"MIPS R10000", Mips::AFL_EXT_10000}, 32530b57cec5SDimitry Andric {"NEC VR4100", Mips::AFL_EXT_4100}, 32540b57cec5SDimitry Andric {"NEC VR4111/VR4181", Mips::AFL_EXT_4111}, 32550b57cec5SDimitry Andric {"NEC VR4120", Mips::AFL_EXT_4120}, 32560b57cec5SDimitry Andric {"NEC VR5400", Mips::AFL_EXT_5400}, 32570b57cec5SDimitry Andric {"NEC VR5500", Mips::AFL_EXT_5500}, 32580b57cec5SDimitry Andric {"RMI Xlr", Mips::AFL_EXT_XLR}, 32590b57cec5SDimitry Andric {"Toshiba R3900", Mips::AFL_EXT_3900} 32600b57cec5SDimitry Andric }; 32610b57cec5SDimitry Andric 3262349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsASEFlags[] = { 32630b57cec5SDimitry Andric {"DSP", Mips::AFL_ASE_DSP}, 32640b57cec5SDimitry Andric {"DSPR2", Mips::AFL_ASE_DSPR2}, 32650b57cec5SDimitry Andric {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, 32660b57cec5SDimitry Andric {"MCU", Mips::AFL_ASE_MCU}, 32670b57cec5SDimitry Andric {"MDMX", Mips::AFL_ASE_MDMX}, 32680b57cec5SDimitry Andric {"MIPS-3D", Mips::AFL_ASE_MIPS3D}, 32690b57cec5SDimitry Andric {"MT", Mips::AFL_ASE_MT}, 32700b57cec5SDimitry Andric {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS}, 32710b57cec5SDimitry Andric {"VZ", Mips::AFL_ASE_VIRT}, 32720b57cec5SDimitry Andric {"MSA", Mips::AFL_ASE_MSA}, 32730b57cec5SDimitry Andric {"MIPS16", Mips::AFL_ASE_MIPS16}, 32740b57cec5SDimitry Andric {"microMIPS", Mips::AFL_ASE_MICROMIPS}, 32750b57cec5SDimitry Andric {"XPA", Mips::AFL_ASE_XPA}, 32760b57cec5SDimitry Andric {"CRC", Mips::AFL_ASE_CRC}, 32770b57cec5SDimitry Andric {"GINV", Mips::AFL_ASE_GINV}, 32780b57cec5SDimitry Andric }; 32790b57cec5SDimitry Andric 3280349cc55cSDimitry Andric const EnumEntry<unsigned> ElfMipsFpABIType[] = { 32810b57cec5SDimitry Andric {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY}, 32820b57cec5SDimitry Andric {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, 32830b57cec5SDimitry Andric {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, 32840b57cec5SDimitry Andric {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT}, 32850b57cec5SDimitry Andric {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", 32860b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, 32870b57cec5SDimitry Andric {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX}, 32880b57cec5SDimitry Andric {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, 32890b57cec5SDimitry Andric {"Hard float compat (32-bit CPU, 64-bit FPU)", 32900b57cec5SDimitry Andric Mips::Val_GNU_MIPS_ABI_FP_64A} 32910b57cec5SDimitry Andric }; 32920b57cec5SDimitry Andric 32930b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFlags1[] { 32940b57cec5SDimitry Andric {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, 32950b57cec5SDimitry Andric }; 32960b57cec5SDimitry Andric 32970b57cec5SDimitry Andric static int getMipsRegisterSize(uint8_t Flag) { 32980b57cec5SDimitry Andric switch (Flag) { 32990b57cec5SDimitry Andric case Mips::AFL_REG_NONE: 33000b57cec5SDimitry Andric return 0; 33010b57cec5SDimitry Andric case Mips::AFL_REG_32: 33020b57cec5SDimitry Andric return 32; 33030b57cec5SDimitry Andric case Mips::AFL_REG_64: 33040b57cec5SDimitry Andric return 64; 33050b57cec5SDimitry Andric case Mips::AFL_REG_128: 33060b57cec5SDimitry Andric return 128; 33070b57cec5SDimitry Andric default: 33080b57cec5SDimitry Andric return -1; 33090b57cec5SDimitry Andric } 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric template <class ELFT> 33130b57cec5SDimitry Andric static void printMipsReginfoData(ScopedPrinter &W, 33140b57cec5SDimitry Andric const Elf_Mips_RegInfo<ELFT> &Reginfo) { 33150b57cec5SDimitry Andric W.printHex("GP", Reginfo.ri_gp_value); 33160b57cec5SDimitry Andric W.printHex("General Mask", Reginfo.ri_gprmask); 33170b57cec5SDimitry Andric W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]); 33180b57cec5SDimitry Andric W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]); 33190b57cec5SDimitry Andric W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]); 33200b57cec5SDimitry Andric W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]); 33210b57cec5SDimitry Andric } 33220b57cec5SDimitry Andric 33230b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { 3324e8d8bef9SDimitry Andric const Elf_Shdr *RegInfoSec = findSectionByName(".reginfo"); 3325e8d8bef9SDimitry Andric if (!RegInfoSec) { 33260b57cec5SDimitry Andric W.startLine() << "There is no .reginfo section in the file.\n"; 33270b57cec5SDimitry Andric return; 33280b57cec5SDimitry Andric } 3329e8d8bef9SDimitry Andric 3330e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = 3331e8d8bef9SDimitry Andric Obj.getSectionContents(*RegInfoSec); 3332e8d8bef9SDimitry Andric if (!ContentsOrErr) { 3333e8d8bef9SDimitry Andric this->reportUniqueWarning( 3334e8d8bef9SDimitry Andric "unable to read the content of the .reginfo section (" + 3335e8d8bef9SDimitry Andric describe(*RegInfoSec) + "): " + toString(ContentsOrErr.takeError())); 3336e8d8bef9SDimitry Andric return; 3337e8d8bef9SDimitry Andric } 3338e8d8bef9SDimitry Andric 3339e8d8bef9SDimitry Andric if (ContentsOrErr->size() < sizeof(Elf_Mips_RegInfo<ELFT>)) { 3340e8d8bef9SDimitry Andric this->reportUniqueWarning("the .reginfo section has an invalid size (0x" + 3341e8d8bef9SDimitry Andric Twine::utohexstr(ContentsOrErr->size()) + ")"); 33420b57cec5SDimitry Andric return; 33430b57cec5SDimitry Andric } 33440b57cec5SDimitry Andric 33450b57cec5SDimitry Andric DictScope GS(W, "MIPS RegInfo"); 3346e8d8bef9SDimitry Andric printMipsReginfoData(W, *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>( 3347e8d8bef9SDimitry Andric ContentsOrErr->data())); 3348e8d8bef9SDimitry Andric } 3349e8d8bef9SDimitry Andric 3350e8d8bef9SDimitry Andric template <class ELFT> 3351e8d8bef9SDimitry Andric static Expected<const Elf_Mips_Options<ELFT> *> 3352e8d8bef9SDimitry Andric readMipsOptions(const uint8_t *SecBegin, ArrayRef<uint8_t> &SecData, 3353e8d8bef9SDimitry Andric bool &IsSupported) { 3354e8d8bef9SDimitry Andric if (SecData.size() < sizeof(Elf_Mips_Options<ELFT>)) 3355e8d8bef9SDimitry Andric return createError("the .MIPS.options section has an invalid size (0x" + 3356e8d8bef9SDimitry Andric Twine::utohexstr(SecData.size()) + ")"); 3357e8d8bef9SDimitry Andric 3358e8d8bef9SDimitry Andric const Elf_Mips_Options<ELFT> *O = 3359e8d8bef9SDimitry Andric reinterpret_cast<const Elf_Mips_Options<ELFT> *>(SecData.data()); 3360e8d8bef9SDimitry Andric const uint8_t Size = O->size; 3361e8d8bef9SDimitry Andric if (Size > SecData.size()) { 3362e8d8bef9SDimitry Andric const uint64_t Offset = SecData.data() - SecBegin; 3363e8d8bef9SDimitry Andric const uint64_t SecSize = Offset + SecData.size(); 3364e8d8bef9SDimitry Andric return createError("a descriptor of size 0x" + Twine::utohexstr(Size) + 3365e8d8bef9SDimitry Andric " at offset 0x" + Twine::utohexstr(Offset) + 3366e8d8bef9SDimitry Andric " goes past the end of the .MIPS.options " 3367e8d8bef9SDimitry Andric "section of size 0x" + 3368e8d8bef9SDimitry Andric Twine::utohexstr(SecSize)); 3369e8d8bef9SDimitry Andric } 3370e8d8bef9SDimitry Andric 3371e8d8bef9SDimitry Andric IsSupported = O->kind == ODK_REGINFO; 3372e8d8bef9SDimitry Andric const size_t ExpectedSize = 3373e8d8bef9SDimitry Andric sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>); 3374e8d8bef9SDimitry Andric 3375e8d8bef9SDimitry Andric if (IsSupported) 3376e8d8bef9SDimitry Andric if (Size < ExpectedSize) 3377e8d8bef9SDimitry Andric return createError( 3378e8d8bef9SDimitry Andric "a .MIPS.options entry of kind " + 3379e8d8bef9SDimitry Andric Twine(getElfMipsOptionsOdkType(O->kind)) + 3380e8d8bef9SDimitry Andric " has an invalid size (0x" + Twine::utohexstr(Size) + 3381e8d8bef9SDimitry Andric "), the expected size is 0x" + Twine::utohexstr(ExpectedSize)); 3382e8d8bef9SDimitry Andric 3383e8d8bef9SDimitry Andric SecData = SecData.drop_front(Size); 3384e8d8bef9SDimitry Andric return O; 33850b57cec5SDimitry Andric } 33860b57cec5SDimitry Andric 33870b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { 3388e8d8bef9SDimitry Andric const Elf_Shdr *MipsOpts = findSectionByName(".MIPS.options"); 3389e8d8bef9SDimitry Andric if (!MipsOpts) { 33900b57cec5SDimitry Andric W.startLine() << "There is no .MIPS.options section in the file.\n"; 33910b57cec5SDimitry Andric return; 33920b57cec5SDimitry Andric } 33930b57cec5SDimitry Andric 33940b57cec5SDimitry Andric DictScope GS(W, "MIPS Options"); 33950b57cec5SDimitry Andric 3396e8d8bef9SDimitry Andric ArrayRef<uint8_t> Data = 3397e8d8bef9SDimitry Andric unwrapOrError(ObjF.getFileName(), Obj.getSectionContents(*MipsOpts)); 3398e8d8bef9SDimitry Andric const uint8_t *const SecBegin = Data.begin(); 3399e8d8bef9SDimitry Andric while (!Data.empty()) { 3400e8d8bef9SDimitry Andric bool IsSupported; 3401e8d8bef9SDimitry Andric Expected<const Elf_Mips_Options<ELFT> *> OptsOrErr = 3402e8d8bef9SDimitry Andric readMipsOptions<ELFT>(SecBegin, Data, IsSupported); 3403e8d8bef9SDimitry Andric if (!OptsOrErr) { 3404e8d8bef9SDimitry Andric reportUniqueWarning(OptsOrErr.takeError()); 34050b57cec5SDimitry Andric break; 34060b57cec5SDimitry Andric } 3407e8d8bef9SDimitry Andric 3408e8d8bef9SDimitry Andric unsigned Kind = (*OptsOrErr)->kind; 3409e8d8bef9SDimitry Andric const char *Type = getElfMipsOptionsOdkType(Kind); 3410e8d8bef9SDimitry Andric if (!IsSupported) { 3411e8d8bef9SDimitry Andric W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind 3412e8d8bef9SDimitry Andric << ")\n"; 3413e8d8bef9SDimitry Andric continue; 3414e8d8bef9SDimitry Andric } 3415e8d8bef9SDimitry Andric 3416e8d8bef9SDimitry Andric DictScope GS(W, Type); 3417e8d8bef9SDimitry Andric if (Kind == ODK_REGINFO) 3418e8d8bef9SDimitry Andric printMipsReginfoData(W, (*OptsOrErr)->getRegInfo()); 3419e8d8bef9SDimitry Andric else 3420e8d8bef9SDimitry Andric llvm_unreachable("unexpected .MIPS.options section descriptor kind"); 34210b57cec5SDimitry Andric } 34220b57cec5SDimitry Andric } 34230b57cec5SDimitry Andric 34240b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { 3425e8d8bef9SDimitry Andric const Elf_Shdr *StackMapSection = findSectionByName(".llvm_stackmaps"); 34260b57cec5SDimitry Andric if (!StackMapSection) 34270b57cec5SDimitry Andric return; 34280b57cec5SDimitry Andric 3429e8d8bef9SDimitry Andric auto Warn = [&](Error &&E) { 3430e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to read the stack map from " + 3431e8d8bef9SDimitry Andric describe(*StackMapSection) + ": " + 3432e8d8bef9SDimitry Andric toString(std::move(E))); 3433e8d8bef9SDimitry Andric }; 34340b57cec5SDimitry Andric 3435e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentOrErr = 3436e8d8bef9SDimitry Andric Obj.getSectionContents(*StackMapSection); 3437e8d8bef9SDimitry Andric if (!ContentOrErr) { 3438e8d8bef9SDimitry Andric Warn(ContentOrErr.takeError()); 3439e8d8bef9SDimitry Andric return; 34400b57cec5SDimitry Andric } 34410b57cec5SDimitry Andric 3442*0fca6ea1SDimitry Andric if (Error E = 3443*0fca6ea1SDimitry Andric StackMapParser<ELFT::Endianness>::validateHeader(*ContentOrErr)) { 3444e8d8bef9SDimitry Andric Warn(std::move(E)); 3445e8d8bef9SDimitry Andric return; 34460b57cec5SDimitry Andric } 34470b57cec5SDimitry Andric 3448*0fca6ea1SDimitry Andric prettyPrintStackMap(W, StackMapParser<ELFT::Endianness>(*ContentOrErr)); 3449e8d8bef9SDimitry Andric } 3450e8d8bef9SDimitry Andric 3451e8d8bef9SDimitry Andric template <class ELFT> 3452e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex, 3453e8d8bef9SDimitry Andric const Elf_Shdr &Sec, const Elf_Shdr *SymTab) { 3454e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> Target = getRelocationTarget(R, SymTab); 3455e8d8bef9SDimitry Andric if (!Target) 3456e8d8bef9SDimitry Andric reportUniqueWarning("unable to print relocation " + Twine(RelIndex) + 3457e8d8bef9SDimitry Andric " in " + describe(Sec) + ": " + 3458e8d8bef9SDimitry Andric toString(Target.takeError())); 3459e8d8bef9SDimitry Andric else 3460e8d8bef9SDimitry Andric printRelRelaReloc(R, *Target); 34610b57cec5SDimitry Andric } 34620b57cec5SDimitry Andric 346306c3fb27SDimitry Andric template <class ELFT> 346406c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> 346506c3fb27SDimitry Andric ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header, 346606c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 346706c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags), 346806c3fb27SDimitry Andric std::end(ElfSymOtherFlags)); 346906c3fb27SDimitry Andric if (Header.e_machine == EM_MIPS) { 347006c3fb27SDimitry Andric // Someone in their infinite wisdom decided to make STO_MIPS_MIPS16 347106c3fb27SDimitry Andric // flag overlap with other ST_MIPS_xxx flags. So consider both 347206c3fb27SDimitry Andric // cases separately. 347306c3fb27SDimitry Andric if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) 347406c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 347506c3fb27SDimitry Andric std::begin(ElfMips16SymOtherFlags), 347606c3fb27SDimitry Andric std::end(ElfMips16SymOtherFlags)); 347706c3fb27SDimitry Andric else 347806c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 347906c3fb27SDimitry Andric std::begin(ElfMipsSymOtherFlags), 348006c3fb27SDimitry Andric std::end(ElfMipsSymOtherFlags)); 348106c3fb27SDimitry Andric } else if (Header.e_machine == EM_AARCH64) { 348206c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), 348306c3fb27SDimitry Andric std::begin(ElfAArch64SymOtherFlags), 348406c3fb27SDimitry Andric std::end(ElfAArch64SymOtherFlags)); 348506c3fb27SDimitry Andric } else if (Header.e_machine == EM_RISCV) { 348606c3fb27SDimitry Andric SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags), 348706c3fb27SDimitry Andric std::end(ElfRISCVSymOtherFlags)); 348806c3fb27SDimitry Andric } 348906c3fb27SDimitry Andric return SymOtherFlags; 349006c3fb27SDimitry Andric } 349106c3fb27SDimitry Andric 34920b57cec5SDimitry Andric static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, 34930b57cec5SDimitry Andric StringRef Str2) { 34940b57cec5SDimitry Andric OS.PadToColumn(2u); 34950b57cec5SDimitry Andric OS << Str1; 34960b57cec5SDimitry Andric OS.PadToColumn(37u); 34970b57cec5SDimitry Andric OS << Str2 << "\n"; 34980b57cec5SDimitry Andric OS.flush(); 34990b57cec5SDimitry Andric } 35000b57cec5SDimitry Andric 35010b57cec5SDimitry Andric template <class ELFT> 3502e8d8bef9SDimitry Andric static std::string getSectionHeadersNumString(const ELFFile<ELFT> &Obj, 35038bcb0991SDimitry Andric StringRef FileName) { 3504e8d8bef9SDimitry Andric const typename ELFT::Ehdr &ElfHeader = Obj.getHeader(); 3505e8d8bef9SDimitry Andric if (ElfHeader.e_shnum != 0) 3506e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shnum); 35070b57cec5SDimitry Andric 3508e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections(); 3509e8d8bef9SDimitry Andric if (!ArrOrErr) { 3510e8d8bef9SDimitry Andric // In this case we can ignore an error, because we have already reported a 3511e8d8bef9SDimitry Andric // warning about the broken section header table earlier. 3512e8d8bef9SDimitry Andric consumeError(ArrOrErr.takeError()); 3513e8d8bef9SDimitry Andric return "<?>"; 3514e8d8bef9SDimitry Andric } 3515e8d8bef9SDimitry Andric 3516e8d8bef9SDimitry Andric if (ArrOrErr->empty()) 35170b57cec5SDimitry Andric return "0"; 3518e8d8bef9SDimitry Andric return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")"; 35190b57cec5SDimitry Andric } 35200b57cec5SDimitry Andric 35210b57cec5SDimitry Andric template <class ELFT> 3522e8d8bef9SDimitry Andric static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> &Obj, 35238bcb0991SDimitry Andric StringRef FileName) { 3524e8d8bef9SDimitry Andric const typename ELFT::Ehdr &ElfHeader = Obj.getHeader(); 3525e8d8bef9SDimitry Andric if (ElfHeader.e_shstrndx != SHN_XINDEX) 3526e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shstrndx); 35270b57cec5SDimitry Andric 3528e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections(); 3529e8d8bef9SDimitry Andric if (!ArrOrErr) { 3530e8d8bef9SDimitry Andric // In this case we can ignore an error, because we have already reported a 3531e8d8bef9SDimitry Andric // warning about the broken section header table earlier. 3532e8d8bef9SDimitry Andric consumeError(ArrOrErr.takeError()); 3533e8d8bef9SDimitry Andric return "<?>"; 35340b57cec5SDimitry Andric } 35350b57cec5SDimitry Andric 3536e8d8bef9SDimitry Andric if (ArrOrErr->empty()) 3537e8d8bef9SDimitry Andric return "65535 (corrupt: out of range)"; 3538e8d8bef9SDimitry Andric return to_string(ElfHeader.e_shstrndx) + " (" + 3539e8d8bef9SDimitry Andric to_string((*ArrOrErr)[0].sh_link) + ")"; 3540e8d8bef9SDimitry Andric } 3541e8d8bef9SDimitry Andric 3542e8d8bef9SDimitry Andric static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) { 3543e8d8bef9SDimitry Andric auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) { 3544e8d8bef9SDimitry Andric return E.Value == Type; 3545e8d8bef9SDimitry Andric }); 3546bdd1243dSDimitry Andric if (It != ArrayRef(ElfObjectFileType).end()) 3547e8d8bef9SDimitry Andric return It; 3548e8d8bef9SDimitry Andric return nullptr; 3549e8d8bef9SDimitry Andric } 3550e8d8bef9SDimitry Andric 35510eae32dcSDimitry Andric template <class ELFT> 35520eae32dcSDimitry Andric void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj, 35530eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 35540eae32dcSDimitry Andric const Archive *A) { 35550eae32dcSDimitry Andric if (InputFilenames.size() > 1 || A) { 35560eae32dcSDimitry Andric this->W.startLine() << "\n"; 35570eae32dcSDimitry Andric this->W.printString("File", FileStr); 35580eae32dcSDimitry Andric } 35590eae32dcSDimitry Andric } 35600eae32dcSDimitry Andric 3561e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() { 3562e8d8bef9SDimitry Andric const Elf_Ehdr &e = this->Obj.getHeader(); 35630b57cec5SDimitry Andric OS << "ELF Header:\n"; 35640b57cec5SDimitry Andric OS << " Magic: "; 35650b57cec5SDimitry Andric std::string Str; 35660b57cec5SDimitry Andric for (int i = 0; i < ELF::EI_NIDENT; i++) 3567e8d8bef9SDimitry Andric OS << format(" %02x", static_cast<int>(e.e_ident[i])); 35680b57cec5SDimitry Andric OS << "\n"; 3569bdd1243dSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass)); 35700b57cec5SDimitry Andric printFields(OS, "Class:", Str); 3571bdd1243dSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding)); 35720b57cec5SDimitry Andric printFields(OS, "Data:", Str); 35730b57cec5SDimitry Andric OS.PadToColumn(2u); 35740b57cec5SDimitry Andric OS << "Version:"; 35750b57cec5SDimitry Andric OS.PadToColumn(37u); 357681ad6265SDimitry Andric OS << utohexstr(e.e_ident[ELF::EI_VERSION]); 3577e8d8bef9SDimitry Andric if (e.e_version == ELF::EV_CURRENT) 35780b57cec5SDimitry Andric OS << " (current)"; 35790b57cec5SDimitry Andric OS << "\n"; 3580cb14a3feSDimitry Andric auto OSABI = ArrayRef(ElfOSABI); 3581cb14a3feSDimitry Andric if (e.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && 3582cb14a3feSDimitry Andric e.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { 3583cb14a3feSDimitry Andric switch (e.e_machine) { 3584*0fca6ea1SDimitry Andric case ELF::EM_ARM: 3585*0fca6ea1SDimitry Andric OSABI = ArrayRef(ARMElfOSABI); 3586*0fca6ea1SDimitry Andric break; 3587cb14a3feSDimitry Andric case ELF::EM_AMDGPU: 3588cb14a3feSDimitry Andric OSABI = ArrayRef(AMDGPUElfOSABI); 3589cb14a3feSDimitry Andric break; 3590cb14a3feSDimitry Andric default: 3591cb14a3feSDimitry Andric break; 3592cb14a3feSDimitry Andric } 3593cb14a3feSDimitry Andric } 3594cb14a3feSDimitry Andric Str = enumToString(e.e_ident[ELF::EI_OSABI], OSABI); 35950b57cec5SDimitry Andric printFields(OS, "OS/ABI:", Str); 3596480093f4SDimitry Andric printFields(OS, 3597e8d8bef9SDimitry Andric "ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION])); 3598e8d8bef9SDimitry Andric 3599e8d8bef9SDimitry Andric if (const EnumEntry<unsigned> *E = getObjectFileEnumEntry(e.e_type)) { 3600e8d8bef9SDimitry Andric Str = E->AltName.str(); 3601e8d8bef9SDimitry Andric } else { 3602e8d8bef9SDimitry Andric if (e.e_type >= ET_LOPROC) 360381ad6265SDimitry Andric Str = "Processor Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")"; 3604e8d8bef9SDimitry Andric else if (e.e_type >= ET_LOOS) 360581ad6265SDimitry Andric Str = "OS Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")"; 3606e8d8bef9SDimitry Andric else 360781ad6265SDimitry Andric Str = "<unknown>: " + utohexstr(e.e_type, /*LowerCase=*/true); 3608e8d8bef9SDimitry Andric } 36090b57cec5SDimitry Andric printFields(OS, "Type:", Str); 3610e8d8bef9SDimitry Andric 3611bdd1243dSDimitry Andric Str = enumToString(e.e_machine, ArrayRef(ElfMachineType)); 36120b57cec5SDimitry Andric printFields(OS, "Machine:", Str); 361381ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_version); 36140b57cec5SDimitry Andric printFields(OS, "Version:", Str); 361581ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_entry); 36160b57cec5SDimitry Andric printFields(OS, "Entry point address:", Str); 3617e8d8bef9SDimitry Andric Str = to_string(e.e_phoff) + " (bytes into file)"; 36180b57cec5SDimitry Andric printFields(OS, "Start of program headers:", Str); 3619e8d8bef9SDimitry Andric Str = to_string(e.e_shoff) + " (bytes into file)"; 36200b57cec5SDimitry Andric printFields(OS, "Start of section headers:", Str); 36210b57cec5SDimitry Andric std::string ElfFlags; 3622e8d8bef9SDimitry Andric if (e.e_machine == EM_MIPS) 3623bdd1243dSDimitry Andric ElfFlags = printFlags( 3624bdd1243dSDimitry Andric e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH), 3625bdd1243dSDimitry Andric unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH)); 3626e8d8bef9SDimitry Andric else if (e.e_machine == EM_RISCV) 3627bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags)); 3628fe6060f1SDimitry Andric else if (e.e_machine == EM_AVR) 3629bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags), 3630fe6060f1SDimitry Andric unsigned(ELF::EF_AVR_ARCH_MASK)); 3631972a253aSDimitry Andric else if (e.e_machine == EM_LOONGARCH) 3632bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags), 3633bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK), 3634bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_OBJABI_MASK)); 3635bdd1243dSDimitry Andric else if (e.e_machine == EM_XTENSA) 3636bdd1243dSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags), 3637bdd1243dSDimitry Andric unsigned(ELF::EF_XTENSA_MACH)); 36385f757f3fSDimitry Andric else if (e.e_machine == EM_CUDA) 36395f757f3fSDimitry Andric ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags), 36405f757f3fSDimitry Andric unsigned(ELF::EF_CUDA_SM)); 3641cb14a3feSDimitry Andric else if (e.e_machine == EM_AMDGPU) { 3642cb14a3feSDimitry Andric switch (e.e_ident[ELF::EI_ABIVERSION]) { 3643cb14a3feSDimitry Andric default: 3644cb14a3feSDimitry Andric break; 3645cb14a3feSDimitry Andric case 0: 3646cb14a3feSDimitry Andric // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags. 3647cb14a3feSDimitry Andric [[fallthrough]]; 3648cb14a3feSDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V3: 3649cb14a3feSDimitry Andric ElfFlags = 3650cb14a3feSDimitry Andric printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3), 3651cb14a3feSDimitry Andric unsigned(ELF::EF_AMDGPU_MACH)); 3652cb14a3feSDimitry Andric break; 3653cb14a3feSDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V4: 3654cb14a3feSDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V5: 3655cb14a3feSDimitry Andric ElfFlags = 3656cb14a3feSDimitry Andric printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4), 3657cb14a3feSDimitry Andric unsigned(ELF::EF_AMDGPU_MACH), 3658cb14a3feSDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4), 3659cb14a3feSDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4)); 3660cb14a3feSDimitry Andric break; 3661*0fca6ea1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V6: { 3662*0fca6ea1SDimitry Andric ElfFlags = 3663*0fca6ea1SDimitry Andric printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4), 3664*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH), 3665*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4), 3666*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4)); 3667*0fca6ea1SDimitry Andric if (auto GenericV = e.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) { 3668*0fca6ea1SDimitry Andric ElfFlags += 3669*0fca6ea1SDimitry Andric ", generic_v" + 3670*0fca6ea1SDimitry Andric to_string(GenericV >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET); 3671*0fca6ea1SDimitry Andric } 3672*0fca6ea1SDimitry Andric } break; 3673cb14a3feSDimitry Andric } 3674cb14a3feSDimitry Andric } 367581ad6265SDimitry Andric Str = "0x" + utohexstr(e.e_flags); 36760b57cec5SDimitry Andric if (!ElfFlags.empty()) 36770b57cec5SDimitry Andric Str = Str + ", " + ElfFlags; 36780b57cec5SDimitry Andric printFields(OS, "Flags:", Str); 3679e8d8bef9SDimitry Andric Str = to_string(e.e_ehsize) + " (bytes)"; 36800b57cec5SDimitry Andric printFields(OS, "Size of this header:", Str); 3681e8d8bef9SDimitry Andric Str = to_string(e.e_phentsize) + " (bytes)"; 36820b57cec5SDimitry Andric printFields(OS, "Size of program headers:", Str); 3683e8d8bef9SDimitry Andric Str = to_string(e.e_phnum); 36840b57cec5SDimitry Andric printFields(OS, "Number of program headers:", Str); 3685e8d8bef9SDimitry Andric Str = to_string(e.e_shentsize) + " (bytes)"; 36860b57cec5SDimitry Andric printFields(OS, "Size of section headers:", Str); 3687e8d8bef9SDimitry Andric Str = getSectionHeadersNumString(this->Obj, this->FileName); 36880b57cec5SDimitry Andric printFields(OS, "Number of section headers:", Str); 3689e8d8bef9SDimitry Andric Str = getSectionHeaderTableIndexString(this->Obj, this->FileName); 36900b57cec5SDimitry Andric printFields(OS, "Section header string table index:", Str); 36910b57cec5SDimitry Andric } 36920b57cec5SDimitry Andric 3693e8d8bef9SDimitry Andric template <class ELFT> std::vector<GroupSection> ELFDumper<ELFT>::getGroups() { 3694e8d8bef9SDimitry Andric auto GetSignature = [&](const Elf_Sym &Sym, unsigned SymNdx, 3695e8d8bef9SDimitry Andric const Elf_Shdr &Symtab) -> StringRef { 3696e8d8bef9SDimitry Andric Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab); 3697e8d8bef9SDimitry Andric if (!StrTableOrErr) { 3698e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the string table for " + 3699e8d8bef9SDimitry Andric describe(Symtab) + ": " + 3700e8d8bef9SDimitry Andric toString(StrTableOrErr.takeError())); 3701e8d8bef9SDimitry Andric return "<?>"; 3702e8d8bef9SDimitry Andric } 37030b57cec5SDimitry Andric 3704e8d8bef9SDimitry Andric StringRef Strings = *StrTableOrErr; 3705e8d8bef9SDimitry Andric if (Sym.st_name >= Strings.size()) { 3706e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the name of the symbol with index " + 3707e8d8bef9SDimitry Andric Twine(SymNdx) + ": st_name (0x" + 3708e8d8bef9SDimitry Andric Twine::utohexstr(Sym.st_name) + 3709e8d8bef9SDimitry Andric ") is past the end of the string table of size 0x" + 3710e8d8bef9SDimitry Andric Twine::utohexstr(Strings.size())); 3711e8d8bef9SDimitry Andric return "<?>"; 3712e8d8bef9SDimitry Andric } 37130b57cec5SDimitry Andric 3714e8d8bef9SDimitry Andric return StrTableOrErr->data() + Sym.st_name; 3715e8d8bef9SDimitry Andric }; 37160b57cec5SDimitry Andric 37170b57cec5SDimitry Andric std::vector<GroupSection> Ret; 37180b57cec5SDimitry Andric uint64_t I = 0; 3719e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 37200b57cec5SDimitry Andric ++I; 37210b57cec5SDimitry Andric if (Sec.sh_type != ELF::SHT_GROUP) 37220b57cec5SDimitry Andric continue; 37230b57cec5SDimitry Andric 3724e8d8bef9SDimitry Andric StringRef Signature = "<?>"; 3725e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Sec.sh_link)) { 3726e8d8bef9SDimitry Andric if (Expected<const Elf_Sym *> SymOrErr = 3727e8d8bef9SDimitry Andric Obj.template getEntry<Elf_Sym>(**SymtabOrErr, Sec.sh_info)) 3728e8d8bef9SDimitry Andric Signature = GetSignature(**SymOrErr, Sec.sh_info, **SymtabOrErr); 3729e8d8bef9SDimitry Andric else 3730e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the signature symbol for " + 3731e8d8bef9SDimitry Andric describe(Sec) + ": " + 3732e8d8bef9SDimitry Andric toString(SymOrErr.takeError())); 3733e8d8bef9SDimitry Andric } else { 3734e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the symbol table for " + 3735e8d8bef9SDimitry Andric describe(Sec) + ": " + 3736e8d8bef9SDimitry Andric toString(SymtabOrErr.takeError())); 3737e8d8bef9SDimitry Andric } 37380b57cec5SDimitry Andric 3739e8d8bef9SDimitry Andric ArrayRef<Elf_Word> Data; 3740e8d8bef9SDimitry Andric if (Expected<ArrayRef<Elf_Word>> ContentsOrErr = 3741e8d8bef9SDimitry Andric Obj.template getSectionContentsAsArray<Elf_Word>(Sec)) { 3742e8d8bef9SDimitry Andric if (ContentsOrErr->empty()) 3743e8d8bef9SDimitry Andric reportUniqueWarning("unable to read the section group flag from the " + 3744e8d8bef9SDimitry Andric describe(Sec) + ": the section is empty"); 3745e8d8bef9SDimitry Andric else 3746e8d8bef9SDimitry Andric Data = *ContentsOrErr; 3747e8d8bef9SDimitry Andric } else { 3748e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the content of the " + describe(Sec) + 3749e8d8bef9SDimitry Andric ": " + toString(ContentsOrErr.takeError())); 3750e8d8bef9SDimitry Andric } 3751e8d8bef9SDimitry Andric 3752e8d8bef9SDimitry Andric Ret.push_back({getPrintableSectionName(Sec), 37530b57cec5SDimitry Andric maybeDemangle(Signature), 37540b57cec5SDimitry Andric Sec.sh_name, 37550b57cec5SDimitry Andric I - 1, 37560b57cec5SDimitry Andric Sec.sh_link, 37570b57cec5SDimitry Andric Sec.sh_info, 3758e8d8bef9SDimitry Andric Data.empty() ? Elf_Word(0) : Data[0], 37590b57cec5SDimitry Andric {}}); 37600b57cec5SDimitry Andric 3761e8d8bef9SDimitry Andric if (Data.empty()) 3762e8d8bef9SDimitry Andric continue; 3763e8d8bef9SDimitry Andric 37640b57cec5SDimitry Andric std::vector<GroupMember> &GM = Ret.back().Members; 37650b57cec5SDimitry Andric for (uint32_t Ndx : Data.slice(1)) { 3766e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(Ndx)) { 3767e8d8bef9SDimitry Andric GM.push_back({getPrintableSectionName(**SecOrErr), Ndx}); 3768e8d8bef9SDimitry Andric } else { 3769e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the section with index " + 3770e8d8bef9SDimitry Andric Twine(Ndx) + " when dumping the " + describe(Sec) + 3771e8d8bef9SDimitry Andric ": " + toString(SecOrErr.takeError())); 3772e8d8bef9SDimitry Andric GM.push_back({"<?>", Ndx}); 3773e8d8bef9SDimitry Andric } 37740b57cec5SDimitry Andric } 37750b57cec5SDimitry Andric } 37760b57cec5SDimitry Andric return Ret; 37770b57cec5SDimitry Andric } 37780b57cec5SDimitry Andric 3779e8d8bef9SDimitry Andric static DenseMap<uint64_t, const GroupSection *> 37800b57cec5SDimitry Andric mapSectionsToGroups(ArrayRef<GroupSection> Groups) { 37810b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Ret; 37820b57cec5SDimitry Andric for (const GroupSection &G : Groups) 37830b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) 37840b57cec5SDimitry Andric Ret.insert({GM.Index, &G}); 37850b57cec5SDimitry Andric return Ret; 37860b57cec5SDimitry Andric } 37870b57cec5SDimitry Andric 3788e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printGroupSections() { 3789e8d8bef9SDimitry Andric std::vector<GroupSection> V = this->getGroups(); 37900b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 37910b57cec5SDimitry Andric for (const GroupSection &G : V) { 37920b57cec5SDimitry Andric OS << "\n" 37930b57cec5SDimitry Andric << getGroupType(G.Type) << " group section [" 37940b57cec5SDimitry Andric << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature 37950b57cec5SDimitry Andric << "] contains " << G.Members.size() << " sections:\n" 37960b57cec5SDimitry Andric << " [Index] Name\n"; 37970b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 37980b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 3799e8d8bef9SDimitry Andric if (MainGroup != &G) 3800e8d8bef9SDimitry Andric this->reportUniqueWarning( 3801e8d8bef9SDimitry Andric "section with index " + Twine(GM.Index) + 3802e8d8bef9SDimitry Andric ", included in the group section with index " + 3803e8d8bef9SDimitry Andric Twine(MainGroup->Index) + 3804e8d8bef9SDimitry Andric ", was also found in the group section with index " + 3805e8d8bef9SDimitry Andric Twine(G.Index)); 38060b57cec5SDimitry Andric OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n"; 38070b57cec5SDimitry Andric } 38080b57cec5SDimitry Andric } 38090b57cec5SDimitry Andric 38100b57cec5SDimitry Andric if (V.empty()) 38110b57cec5SDimitry Andric OS << "There are no section groups in this file.\n"; 38120b57cec5SDimitry Andric } 38130b57cec5SDimitry Andric 38140b57cec5SDimitry Andric template <class ELFT> 3815e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R, 3816e8d8bef9SDimitry Andric const RelSymbol<ELFT> &RelSym) { 38170b57cec5SDimitry Andric // First two fields are bit width dependent. The rest of them are fixed width. 38180b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 38190b57cec5SDimitry Andric Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; 38200b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 16 : 8; 38210b57cec5SDimitry Andric 3822e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_hex_no_prefix(R.Offset, Width)); 3823e8d8bef9SDimitry Andric Fields[1].Str = to_string(format_hex_no_prefix(R.Info, Width)); 38240b57cec5SDimitry Andric 38250b57cec5SDimitry Andric SmallString<32> RelocName; 3826e8d8bef9SDimitry Andric this->Obj.getRelocationTypeName(R.Type, RelocName); 38270b57cec5SDimitry Andric Fields[2].Str = RelocName.c_str(); 38280b57cec5SDimitry Andric 3829e8d8bef9SDimitry Andric if (RelSym.Sym) 3830e8d8bef9SDimitry Andric Fields[3].Str = 3831e8d8bef9SDimitry Andric to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width)); 383206c3fb27SDimitry Andric if (RelSym.Sym && RelSym.Name.empty()) 383306c3fb27SDimitry Andric Fields[4].Str = "<null>"; 383406c3fb27SDimitry Andric else 3835e8d8bef9SDimitry Andric Fields[4].Str = std::string(RelSym.Name); 383606c3fb27SDimitry Andric 38370b57cec5SDimitry Andric for (const Field &F : Fields) 38380b57cec5SDimitry Andric printField(F); 38390b57cec5SDimitry Andric 38400b57cec5SDimitry Andric std::string Addend; 3841bdd1243dSDimitry Andric if (std::optional<int64_t> A = R.Addend) { 3842e8d8bef9SDimitry Andric int64_t RelAddend = *A; 384306c3fb27SDimitry Andric if (!Fields[4].Str.empty()) { 3844e8d8bef9SDimitry Andric if (RelAddend < 0) { 38450b57cec5SDimitry Andric Addend = " - "; 38468a4dda33SDimitry Andric RelAddend = -static_cast<uint64_t>(RelAddend); 3847e8d8bef9SDimitry Andric } else { 38480b57cec5SDimitry Andric Addend = " + "; 38490b57cec5SDimitry Andric } 3850e8d8bef9SDimitry Andric } 385181ad6265SDimitry Andric Addend += utohexstr(RelAddend, /*LowerCase=*/true); 38520b57cec5SDimitry Andric } 38530b57cec5SDimitry Andric OS << Addend << "\n"; 38540b57cec5SDimitry Andric } 38550b57cec5SDimitry Andric 3856e8d8bef9SDimitry Andric template <class ELFT> 38575f757f3fSDimitry Andric static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType, 3858*0fca6ea1SDimitry Andric const typename ELFT::Ehdr &EHeader, 3859*0fca6ea1SDimitry Andric uint64_t CrelHdr = 0) { 38600b57cec5SDimitry Andric bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; 38610b57cec5SDimitry Andric if (ELFT::Is64Bits) 3862*0fca6ea1SDimitry Andric OS << " Offset Info Type Symbol's " 3863*0fca6ea1SDimitry Andric "Value Symbol's Name"; 38640b57cec5SDimitry Andric else 3865*0fca6ea1SDimitry Andric OS << " Offset Info Type Sym. Value Symbol's Name"; 3866*0fca6ea1SDimitry Andric if (IsRela || (SType == ELF::SHT_CREL && (CrelHdr & CREL_HDR_ADDEND))) 38670b57cec5SDimitry Andric OS << " + Addend"; 38680b57cec5SDimitry Andric OS << "\n"; 38690b57cec5SDimitry Andric } 38700b57cec5SDimitry Andric 3871e8d8bef9SDimitry Andric template <class ELFT> 3872e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name, 3873e8d8bef9SDimitry Andric const DynRegionInfo &Reg) { 3874e8d8bef9SDimitry Andric uint64_t Offset = Reg.Addr - this->Obj.base(); 3875e8d8bef9SDimitry Andric OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x" 3876*0fca6ea1SDimitry Andric << utohexstr(Offset, /*LowerCase=*/true); 3877*0fca6ea1SDimitry Andric if (Type != ELF::SHT_CREL) 3878*0fca6ea1SDimitry Andric OS << " contains " << Reg.Size << " bytes"; 3879*0fca6ea1SDimitry Andric OS << ":\n"; 38805f757f3fSDimitry Andric printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader()); 3881e8d8bef9SDimitry Andric } 3882e8d8bef9SDimitry Andric 3883e8d8bef9SDimitry Andric template <class ELFT> 38845f757f3fSDimitry Andric static bool isRelocationSec(const typename ELFT::Shdr &Sec, 38855f757f3fSDimitry Andric const typename ELFT::Ehdr &EHeader) { 3886e8d8bef9SDimitry Andric return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA || 3887*0fca6ea1SDimitry Andric Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_CREL || 3888*0fca6ea1SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_REL || 3889e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELA || 38905f757f3fSDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELR || 38915f757f3fSDimitry Andric (EHeader.e_machine == EM_AARCH64 && 38925f757f3fSDimitry Andric Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR); 3893e8d8bef9SDimitry Andric } 3894e8d8bef9SDimitry Andric 3895e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() { 3896*0fca6ea1SDimitry Andric auto PrintAsRelr = [&](const Elf_Shdr &Sec) { 3897*0fca6ea1SDimitry Andric return Sec.sh_type == ELF::SHT_RELR || 3898*0fca6ea1SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELR || 3899*0fca6ea1SDimitry Andric (this->Obj.getHeader().e_machine == EM_AARCH64 && 3900*0fca6ea1SDimitry Andric Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR); 3901*0fca6ea1SDimitry Andric }; 3902e8d8bef9SDimitry Andric auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> { 39030b57cec5SDimitry Andric // Android's packed relocation section needs to be unpacked first 39040b57cec5SDimitry Andric // to get the actual number of entries. 3905e8d8bef9SDimitry Andric if (Sec.sh_type == ELF::SHT_ANDROID_REL || 3906e8d8bef9SDimitry Andric Sec.sh_type == ELF::SHT_ANDROID_RELA) { 3907e8d8bef9SDimitry Andric Expected<std::vector<typename ELFT::Rela>> RelasOrErr = 3908e8d8bef9SDimitry Andric this->Obj.android_relas(Sec); 3909e8d8bef9SDimitry Andric if (!RelasOrErr) 3910e8d8bef9SDimitry Andric return RelasOrErr.takeError(); 3911e8d8bef9SDimitry Andric return RelasOrErr->size(); 39120b57cec5SDimitry Andric } 3913e8d8bef9SDimitry Andric 3914*0fca6ea1SDimitry Andric if (Sec.sh_type == ELF::SHT_CREL) { 3915*0fca6ea1SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = 3916*0fca6ea1SDimitry Andric this->Obj.getSectionContents(Sec); 3917*0fca6ea1SDimitry Andric if (!ContentsOrErr) 3918*0fca6ea1SDimitry Andric return ContentsOrErr.takeError(); 3919*0fca6ea1SDimitry Andric auto NumOrErr = this->Obj.getCrelHeader(*ContentsOrErr); 3920*0fca6ea1SDimitry Andric if (!NumOrErr) 3921*0fca6ea1SDimitry Andric return NumOrErr.takeError(); 3922*0fca6ea1SDimitry Andric return *NumOrErr / 8; 3923*0fca6ea1SDimitry Andric } 3924*0fca6ea1SDimitry Andric 3925*0fca6ea1SDimitry Andric if (PrintAsRelr(Sec)) { 3926e8d8bef9SDimitry Andric Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec); 3927e8d8bef9SDimitry Andric if (!RelrsOrErr) 3928e8d8bef9SDimitry Andric return RelrsOrErr.takeError(); 3929e8d8bef9SDimitry Andric return this->Obj.decode_relrs(*RelrsOrErr).size(); 39300b57cec5SDimitry Andric } 39315ffd83dbSDimitry Andric 3932e8d8bef9SDimitry Andric return Sec.getEntityCount(); 3933e8d8bef9SDimitry Andric }; 3934e8d8bef9SDimitry Andric 3935e8d8bef9SDimitry Andric bool HasRelocSections = false; 3936e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 39375f757f3fSDimitry Andric if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader())) 3938e8d8bef9SDimitry Andric continue; 3939e8d8bef9SDimitry Andric HasRelocSections = true; 3940e8d8bef9SDimitry Andric 3941e8d8bef9SDimitry Andric std::string EntriesNum = "<?>"; 3942e8d8bef9SDimitry Andric if (Expected<size_t> NumOrErr = GetEntriesNum(Sec)) 3943e8d8bef9SDimitry Andric EntriesNum = std::to_string(*NumOrErr); 39440b57cec5SDimitry Andric else 3945e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get the number of relocations in " + 3946e8d8bef9SDimitry Andric this->describe(Sec) + ": " + 3947e8d8bef9SDimitry Andric toString(NumOrErr.takeError())); 3948e8d8bef9SDimitry Andric 3949e8d8bef9SDimitry Andric uintX_t Offset = Sec.sh_offset; 3950e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(Sec); 3951e8d8bef9SDimitry Andric OS << "\nRelocation section '" << Name << "' at offset 0x" 395281ad6265SDimitry Andric << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum 3953e8d8bef9SDimitry Andric << " entries:\n"; 3954*0fca6ea1SDimitry Andric 3955*0fca6ea1SDimitry Andric if (PrintAsRelr(Sec)) { 3956*0fca6ea1SDimitry Andric printRelr(Sec); 3957*0fca6ea1SDimitry Andric } else { 3958*0fca6ea1SDimitry Andric uint64_t CrelHdr = 0; 3959*0fca6ea1SDimitry Andric // For CREL, read the header and call printRelocationsHelper only if 3960*0fca6ea1SDimitry Andric // GetEntriesNum(Sec) succeeded. 3961*0fca6ea1SDimitry Andric if (Sec.sh_type == ELF::SHT_CREL && EntriesNum != "<?>") { 3962*0fca6ea1SDimitry Andric CrelHdr = cantFail(this->Obj.getCrelHeader( 3963*0fca6ea1SDimitry Andric cantFail(this->Obj.getSectionContents(Sec)))); 3964*0fca6ea1SDimitry Andric } 3965*0fca6ea1SDimitry Andric printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader(), 3966*0fca6ea1SDimitry Andric CrelHdr); 3967*0fca6ea1SDimitry Andric if (Sec.sh_type != ELF::SHT_CREL || EntriesNum != "<?>") 3968e8d8bef9SDimitry Andric this->printRelocationsHelper(Sec); 39690b57cec5SDimitry Andric } 3970*0fca6ea1SDimitry Andric } 39710b57cec5SDimitry Andric if (!HasRelocSections) 39720b57cec5SDimitry Andric OS << "\nThere are no relocations in this file.\n"; 39730b57cec5SDimitry Andric } 39740b57cec5SDimitry Andric 3975*0fca6ea1SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printRelr(const Elf_Shdr &Sec) { 3976*0fca6ea1SDimitry Andric Expected<Elf_Relr_Range> RangeOrErr = this->Obj.relrs(Sec); 3977*0fca6ea1SDimitry Andric if (!RangeOrErr) { 3978*0fca6ea1SDimitry Andric this->reportUniqueWarning("unable to read relocations from " + 3979*0fca6ea1SDimitry Andric this->describe(Sec) + ": " + 3980*0fca6ea1SDimitry Andric toString(RangeOrErr.takeError())); 3981*0fca6ea1SDimitry Andric return; 3982*0fca6ea1SDimitry Andric } 3983*0fca6ea1SDimitry Andric if (ELFT::Is64Bits) 3984*0fca6ea1SDimitry Andric OS << "Index: Entry Address Symbolic Address\n"; 3985*0fca6ea1SDimitry Andric else 3986*0fca6ea1SDimitry Andric OS << "Index: Entry Address Symbolic Address\n"; 3987*0fca6ea1SDimitry Andric 3988*0fca6ea1SDimitry Andric // If .symtab is available, collect its defined symbols and sort them by 3989*0fca6ea1SDimitry Andric // st_value. 3990*0fca6ea1SDimitry Andric SmallVector<std::pair<uint64_t, std::string>, 0> Syms; 3991*0fca6ea1SDimitry Andric if (this->DotSymtabSec) { 3992*0fca6ea1SDimitry Andric Elf_Sym_Range Symtab; 3993*0fca6ea1SDimitry Andric std::optional<StringRef> Strtab; 3994*0fca6ea1SDimitry Andric std::tie(Symtab, Strtab) = this->getSymtabAndStrtab(); 3995*0fca6ea1SDimitry Andric if (Symtab.size() && Strtab) { 3996*0fca6ea1SDimitry Andric for (auto [I, Sym] : enumerate(Symtab)) { 3997*0fca6ea1SDimitry Andric if (!Sym.st_shndx) 3998*0fca6ea1SDimitry Andric continue; 3999*0fca6ea1SDimitry Andric Syms.emplace_back(Sym.st_value, 4000*0fca6ea1SDimitry Andric this->getFullSymbolName(Sym, I, ArrayRef<Elf_Word>(), 4001*0fca6ea1SDimitry Andric *Strtab, false)); 4002*0fca6ea1SDimitry Andric } 4003*0fca6ea1SDimitry Andric } 4004*0fca6ea1SDimitry Andric } 4005*0fca6ea1SDimitry Andric llvm::stable_sort(Syms); 4006*0fca6ea1SDimitry Andric 4007*0fca6ea1SDimitry Andric typename ELFT::uint Base = 0; 4008*0fca6ea1SDimitry Andric size_t I = 0; 4009*0fca6ea1SDimitry Andric auto Print = [&](uint64_t Where) { 4010*0fca6ea1SDimitry Andric OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8); 4011*0fca6ea1SDimitry Andric for (; I < Syms.size() && Syms[I].first <= Where; ++I) 4012*0fca6ea1SDimitry Andric ; 4013*0fca6ea1SDimitry Andric // Try symbolizing the address. Find the nearest symbol before or at the 4014*0fca6ea1SDimitry Andric // address and print the symbol and the address difference. 4015*0fca6ea1SDimitry Andric if (I) { 4016*0fca6ea1SDimitry Andric OS << " " << Syms[I - 1].second; 4017*0fca6ea1SDimitry Andric if (Syms[I - 1].first < Where) 4018*0fca6ea1SDimitry Andric OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first); 4019*0fca6ea1SDimitry Andric } 4020*0fca6ea1SDimitry Andric OS << '\n'; 4021*0fca6ea1SDimitry Andric }; 4022*0fca6ea1SDimitry Andric for (auto [Index, R] : enumerate(*RangeOrErr)) { 4023*0fca6ea1SDimitry Andric typename ELFT::uint Entry = R; 4024*0fca6ea1SDimitry Andric OS << formatv("{0:4}: ", Index) 4025*0fca6ea1SDimitry Andric << format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' '; 4026*0fca6ea1SDimitry Andric if ((Entry & 1) == 0) { 4027*0fca6ea1SDimitry Andric Print(Entry); 4028*0fca6ea1SDimitry Andric Base = Entry + sizeof(typename ELFT::uint); 4029*0fca6ea1SDimitry Andric } else { 4030*0fca6ea1SDimitry Andric bool First = true; 4031*0fca6ea1SDimitry Andric for (auto Where = Base; Entry >>= 1; 4032*0fca6ea1SDimitry Andric Where += sizeof(typename ELFT::uint)) { 4033*0fca6ea1SDimitry Andric if (Entry & 1) { 4034*0fca6ea1SDimitry Andric if (First) 4035*0fca6ea1SDimitry Andric First = false; 4036*0fca6ea1SDimitry Andric else 4037*0fca6ea1SDimitry Andric OS.indent(ELFT::Is64Bits ? 24 : 16); 4038*0fca6ea1SDimitry Andric Print(Where); 4039*0fca6ea1SDimitry Andric } 4040*0fca6ea1SDimitry Andric } 4041*0fca6ea1SDimitry Andric Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint); 4042*0fca6ea1SDimitry Andric } 4043*0fca6ea1SDimitry Andric } 4044*0fca6ea1SDimitry Andric } 4045*0fca6ea1SDimitry Andric 40460b57cec5SDimitry Andric // Print the offset of a particular section from anyone of the ranges: 40470b57cec5SDimitry Andric // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER]. 40480b57cec5SDimitry Andric // If 'Type' does not fall within any of those ranges, then a string is 40490b57cec5SDimitry Andric // returned as '<unknown>' followed by the type value. 40500b57cec5SDimitry Andric static std::string getSectionTypeOffsetString(unsigned Type) { 40510b57cec5SDimitry Andric if (Type >= SHT_LOOS && Type <= SHT_HIOS) 405281ad6265SDimitry Andric return "LOOS+0x" + utohexstr(Type - SHT_LOOS); 40530b57cec5SDimitry Andric else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC) 405481ad6265SDimitry Andric return "LOPROC+0x" + utohexstr(Type - SHT_LOPROC); 40550b57cec5SDimitry Andric else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER) 405681ad6265SDimitry Andric return "LOUSER+0x" + utohexstr(Type - SHT_LOUSER); 405781ad6265SDimitry Andric return "0x" + utohexstr(Type) + ": <unknown>"; 40580b57cec5SDimitry Andric } 40590b57cec5SDimitry Andric 4060e8d8bef9SDimitry Andric static std::string getSectionTypeString(unsigned Machine, unsigned Type) { 4061e8d8bef9SDimitry Andric StringRef Name = getELFSectionTypeName(Machine, Type); 40620b57cec5SDimitry Andric 4063e8d8bef9SDimitry Andric // Handle SHT_GNU_* type names. 406481ad6265SDimitry Andric if (Name.consume_front("SHT_GNU_")) { 406581ad6265SDimitry Andric if (Name == "HASH") 40660b57cec5SDimitry Andric return "GNU_HASH"; 4067e8d8bef9SDimitry Andric // E.g. SHT_GNU_verneed -> VERNEED. 406881ad6265SDimitry Andric return Name.upper(); 40690b57cec5SDimitry Andric } 4070e8d8bef9SDimitry Andric 4071e8d8bef9SDimitry Andric if (Name == "SHT_SYMTAB_SHNDX") 4072e8d8bef9SDimitry Andric return "SYMTAB SECTION INDICES"; 4073e8d8bef9SDimitry Andric 407481ad6265SDimitry Andric if (Name.consume_front("SHT_")) 407581ad6265SDimitry Andric return Name.str(); 4076e8d8bef9SDimitry Andric return getSectionTypeOffsetString(Type); 40770b57cec5SDimitry Andric } 40780b57cec5SDimitry Andric 4079480093f4SDimitry Andric static void printSectionDescription(formatted_raw_ostream &OS, 4080480093f4SDimitry Andric unsigned EMachine) { 4081480093f4SDimitry Andric OS << "Key to Flags:\n"; 4082480093f4SDimitry Andric OS << " W (write), A (alloc), X (execute), M (merge), S (strings), I " 4083480093f4SDimitry Andric "(info),\n"; 4084480093f4SDimitry Andric OS << " L (link order), O (extra OS processing required), G (group), T " 4085480093f4SDimitry Andric "(TLS),\n"; 4086480093f4SDimitry Andric OS << " C (compressed), x (unknown), o (OS specific), E (exclude),\n"; 4087fe6060f1SDimitry Andric OS << " R (retain)"; 4088480093f4SDimitry Andric 4089480093f4SDimitry Andric if (EMachine == EM_X86_64) 4090fe6060f1SDimitry Andric OS << ", l (large)"; 4091480093f4SDimitry Andric else if (EMachine == EM_ARM) 4092fe6060f1SDimitry Andric OS << ", y (purecode)"; 4093480093f4SDimitry Andric 4094fe6060f1SDimitry Andric OS << ", p (processor specific)\n"; 4095480093f4SDimitry Andric } 4096480093f4SDimitry Andric 4097e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() { 4098e8d8bef9SDimitry Andric ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections()); 4099bdd1243dSDimitry Andric if (Sections.empty()) { 4100bdd1243dSDimitry Andric OS << "\nThere are no sections in this file.\n"; 4101bdd1243dSDimitry Andric Expected<StringRef> SecStrTableOrErr = 4102bdd1243dSDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler); 4103bdd1243dSDimitry Andric if (!SecStrTableOrErr) 4104bdd1243dSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 4105bdd1243dSDimitry Andric return; 4106bdd1243dSDimitry Andric } 4107bdd1243dSDimitry Andric unsigned Bias = ELFT::Is64Bits ? 0 : 8; 41080b57cec5SDimitry Andric OS << "There are " << to_string(Sections.size()) 41090b57cec5SDimitry Andric << " section headers, starting at offset " 411081ad6265SDimitry Andric << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n"; 41110b57cec5SDimitry Andric OS << "Section Headers:\n"; 41120b57cec5SDimitry Andric Field Fields[11] = { 41130b57cec5SDimitry Andric {"[Nr]", 2}, {"Name", 7}, {"Type", 25}, 41140b57cec5SDimitry Andric {"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias}, 41150b57cec5SDimitry Andric {"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias}, 41160b57cec5SDimitry Andric {"Inf", 82 - Bias}, {"Al", 86 - Bias}}; 4117e8d8bef9SDimitry Andric for (const Field &F : Fields) 41180b57cec5SDimitry Andric printField(F); 41190b57cec5SDimitry Andric OS << "\n"; 41200b57cec5SDimitry Andric 41215ffd83dbSDimitry Andric StringRef SecStrTable; 41225ffd83dbSDimitry Andric if (Expected<StringRef> SecStrTableOrErr = 4123e8d8bef9SDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler)) 41245ffd83dbSDimitry Andric SecStrTable = *SecStrTableOrErr; 41255ffd83dbSDimitry Andric else 41265ffd83dbSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 41275ffd83dbSDimitry Andric 41280b57cec5SDimitry Andric size_t SectionIndex = 0; 41290b57cec5SDimitry Andric for (const Elf_Shdr &Sec : Sections) { 41300b57cec5SDimitry Andric Fields[0].Str = to_string(SectionIndex); 41315ffd83dbSDimitry Andric if (SecStrTable.empty()) 41325ffd83dbSDimitry Andric Fields[1].Str = "<no-strings>"; 41335ffd83dbSDimitry Andric else 41345ffd83dbSDimitry Andric Fields[1].Str = std::string(unwrapOrError<StringRef>( 4135e8d8bef9SDimitry Andric this->FileName, this->Obj.getSectionName(Sec, SecStrTable))); 41360b57cec5SDimitry Andric Fields[2].Str = 4137e8d8bef9SDimitry Andric getSectionTypeString(this->Obj.getHeader().e_machine, Sec.sh_type); 41380b57cec5SDimitry Andric Fields[3].Str = 41390b57cec5SDimitry Andric to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8)); 41400b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); 41410b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6)); 41420b57cec5SDimitry Andric Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); 414381ad6265SDimitry Andric Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI], 414481ad6265SDimitry Andric this->Obj.getHeader().e_machine, Sec.sh_flags); 41450b57cec5SDimitry Andric Fields[8].Str = to_string(Sec.sh_link); 41460b57cec5SDimitry Andric Fields[9].Str = to_string(Sec.sh_info); 41470b57cec5SDimitry Andric Fields[10].Str = to_string(Sec.sh_addralign); 41480b57cec5SDimitry Andric 41490b57cec5SDimitry Andric OS.PadToColumn(Fields[0].Column); 41500b57cec5SDimitry Andric OS << "[" << right_justify(Fields[0].Str, 2) << "]"; 41510b57cec5SDimitry Andric for (int i = 1; i < 7; i++) 41520b57cec5SDimitry Andric printField(Fields[i]); 41530b57cec5SDimitry Andric OS.PadToColumn(Fields[7].Column); 41540b57cec5SDimitry Andric OS << right_justify(Fields[7].Str, 3); 41550b57cec5SDimitry Andric OS.PadToColumn(Fields[8].Column); 41560b57cec5SDimitry Andric OS << right_justify(Fields[8].Str, 2); 41570b57cec5SDimitry Andric OS.PadToColumn(Fields[9].Column); 41580b57cec5SDimitry Andric OS << right_justify(Fields[9].Str, 3); 41590b57cec5SDimitry Andric OS.PadToColumn(Fields[10].Column); 41600b57cec5SDimitry Andric OS << right_justify(Fields[10].Str, 2); 41610b57cec5SDimitry Andric OS << "\n"; 41620b57cec5SDimitry Andric ++SectionIndex; 41630b57cec5SDimitry Andric } 4164e8d8bef9SDimitry Andric printSectionDescription(OS, this->Obj.getHeader().e_machine); 41650b57cec5SDimitry Andric } 41660b57cec5SDimitry Andric 41670b57cec5SDimitry Andric template <class ELFT> 4168e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab, 41698bcb0991SDimitry Andric size_t Entries, 41705f757f3fSDimitry Andric bool NonVisibilityBitsUsed, 41715f757f3fSDimitry Andric bool ExtraSymInfo) const { 4172e8d8bef9SDimitry Andric StringRef Name; 4173e8d8bef9SDimitry Andric if (Symtab) 4174e8d8bef9SDimitry Andric Name = this->getPrintableSectionName(*Symtab); 41750b57cec5SDimitry Andric if (!Name.empty()) 41765ffd83dbSDimitry Andric OS << "\nSymbol table '" << Name << "'"; 41770b57cec5SDimitry Andric else 41785ffd83dbSDimitry Andric OS << "\nSymbol table for image"; 41795ffd83dbSDimitry Andric OS << " contains " << Entries << " entries:\n"; 41800b57cec5SDimitry Andric 41815f757f3fSDimitry Andric if (ELFT::Is64Bits) { 41828bcb0991SDimitry Andric OS << " Num: Value Size Type Bind Vis"; 41835f757f3fSDimitry Andric if (ExtraSymInfo) 41845f757f3fSDimitry Andric OS << "+Other"; 41855f757f3fSDimitry Andric } else { 41868bcb0991SDimitry Andric OS << " Num: Value Size Type Bind Vis"; 41875f757f3fSDimitry Andric if (ExtraSymInfo) 41885f757f3fSDimitry Andric OS << "+Other"; 41895f757f3fSDimitry Andric } 41908bcb0991SDimitry Andric 41915f757f3fSDimitry Andric OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0)); 41925f757f3fSDimitry Andric if (ExtraSymInfo) 41935f757f3fSDimitry Andric OS << "Ndx(SecName) Name [+ Version Info]\n"; 41945f757f3fSDimitry Andric else 41958bcb0991SDimitry Andric OS << "Ndx Name\n"; 41960b57cec5SDimitry Andric } 41970b57cec5SDimitry Andric 41980b57cec5SDimitry Andric template <class ELFT> 41995f757f3fSDimitry Andric std::string GNUELFDumper<ELFT>::getSymbolSectionNdx( 42005f757f3fSDimitry Andric const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable, 42015f757f3fSDimitry Andric bool ExtraSymInfo) const { 4202e8d8bef9SDimitry Andric unsigned SectionIndex = Symbol.st_shndx; 42030b57cec5SDimitry Andric switch (SectionIndex) { 42040b57cec5SDimitry Andric case ELF::SHN_UNDEF: 42050b57cec5SDimitry Andric return "UND"; 42060b57cec5SDimitry Andric case ELF::SHN_ABS: 42070b57cec5SDimitry Andric return "ABS"; 42080b57cec5SDimitry Andric case ELF::SHN_COMMON: 42090b57cec5SDimitry Andric return "COM"; 4210480093f4SDimitry Andric case ELF::SHN_XINDEX: { 4211e8d8bef9SDimitry Andric Expected<uint32_t> IndexOrErr = 4212e8d8bef9SDimitry Andric object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable); 4213480093f4SDimitry Andric if (!IndexOrErr) { 4214e8d8bef9SDimitry Andric assert(Symbol.st_shndx == SHN_XINDEX && 4215e8d8bef9SDimitry Andric "getExtendedSymbolTableIndex should only fail due to an invalid " 4216480093f4SDimitry Andric "SHT_SYMTAB_SHNDX table/reference"); 4217480093f4SDimitry Andric this->reportUniqueWarning(IndexOrErr.takeError()); 4218480093f4SDimitry Andric return "RSV[0xffff]"; 4219480093f4SDimitry Andric } 42205f757f3fSDimitry Andric SectionIndex = *IndexOrErr; 42215f757f3fSDimitry Andric break; 4222480093f4SDimitry Andric } 42230b57cec5SDimitry Andric default: 42240b57cec5SDimitry Andric // Find if: 42250b57cec5SDimitry Andric // Processor specific 42260b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC) 42270b57cec5SDimitry Andric return std::string("PRC[0x") + 42280b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 42290b57cec5SDimitry Andric // OS specific 42300b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS) 42310b57cec5SDimitry Andric return std::string("OS[0x") + 42320b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 42330b57cec5SDimitry Andric // Architecture reserved: 42340b57cec5SDimitry Andric if (SectionIndex >= ELF::SHN_LORESERVE && 42350b57cec5SDimitry Andric SectionIndex <= ELF::SHN_HIRESERVE) 42360b57cec5SDimitry Andric return std::string("RSV[0x") + 42370b57cec5SDimitry Andric to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; 42385f757f3fSDimitry Andric break; 42390b57cec5SDimitry Andric } 42405f757f3fSDimitry Andric 42415f757f3fSDimitry Andric std::string Extra; 42425f757f3fSDimitry Andric if (ExtraSymInfo) { 42435f757f3fSDimitry Andric auto Sec = this->Obj.getSection(SectionIndex); 42445f757f3fSDimitry Andric if (!Sec) { 42455f757f3fSDimitry Andric this->reportUniqueWarning(Sec.takeError()); 42465f757f3fSDimitry Andric } else { 42475f757f3fSDimitry Andric auto SecName = this->Obj.getSectionName(**Sec); 42485f757f3fSDimitry Andric if (!SecName) 42495f757f3fSDimitry Andric this->reportUniqueWarning(SecName.takeError()); 42505f757f3fSDimitry Andric else 42515f757f3fSDimitry Andric Extra = Twine(" (" + *SecName + ")").str(); 42525f757f3fSDimitry Andric } 42535f757f3fSDimitry Andric } 42545f757f3fSDimitry Andric return to_string(format_decimal(SectionIndex, 3)) + Extra; 42550b57cec5SDimitry Andric } 42560b57cec5SDimitry Andric 42570b57cec5SDimitry Andric template <class ELFT> 4258e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 4259e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 4260bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 42615f757f3fSDimitry Andric bool IsDynamic, bool NonVisibilityBitsUsed, 42625f757f3fSDimitry Andric bool ExtraSymInfo) const { 42630b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 42640b57cec5SDimitry Andric Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias, 42658bcb0991SDimitry Andric 31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias}; 4266e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(SymIndex, 6)) + ":"; 4267e8d8bef9SDimitry Andric Fields[1].Str = 4268e8d8bef9SDimitry Andric to_string(format_hex_no_prefix(Symbol.st_value, ELFT::Is64Bits ? 16 : 8)); 4269e8d8bef9SDimitry Andric Fields[2].Str = to_string(format_decimal(Symbol.st_size, 5)); 42700b57cec5SDimitry Andric 4271e8d8bef9SDimitry Andric unsigned char SymbolType = Symbol.getType(); 4272e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 42730b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 4274bdd1243dSDimitry Andric Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes)); 42750b57cec5SDimitry Andric else 4276bdd1243dSDimitry Andric Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes)); 42770b57cec5SDimitry Andric 42780b57cec5SDimitry Andric Fields[4].Str = 4279bdd1243dSDimitry Andric enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings)); 42800b57cec5SDimitry Andric Fields[5].Str = 4281bdd1243dSDimitry Andric enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities)); 4282e8d8bef9SDimitry Andric 4283e8d8bef9SDimitry Andric if (Symbol.st_other & ~0x3) { 4284e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) { 4285e8d8bef9SDimitry Andric uint8_t Other = Symbol.st_other & ~0x3; 4286e8d8bef9SDimitry Andric if (Other & STO_AARCH64_VARIANT_PCS) { 4287e8d8bef9SDimitry Andric Other &= ~STO_AARCH64_VARIANT_PCS; 4288e8d8bef9SDimitry Andric Fields[5].Str += " [VARIANT_PCS"; 4289e8d8bef9SDimitry Andric if (Other != 0) 429081ad6265SDimitry Andric Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true)); 4291e8d8bef9SDimitry Andric Fields[5].Str.append("]"); 4292e8d8bef9SDimitry Andric } 4293349cc55cSDimitry Andric } else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) { 4294349cc55cSDimitry Andric uint8_t Other = Symbol.st_other & ~0x3; 4295349cc55cSDimitry Andric if (Other & STO_RISCV_VARIANT_CC) { 4296349cc55cSDimitry Andric Other &= ~STO_RISCV_VARIANT_CC; 4297349cc55cSDimitry Andric Fields[5].Str += " [VARIANT_CC"; 4298349cc55cSDimitry Andric if (Other != 0) 429981ad6265SDimitry Andric Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true)); 4300349cc55cSDimitry Andric Fields[5].Str.append("]"); 4301349cc55cSDimitry Andric } 4302e8d8bef9SDimitry Andric } else { 43038bcb0991SDimitry Andric Fields[5].Str += 4304e8d8bef9SDimitry Andric " [<other: " + to_string(format_hex(Symbol.st_other, 2)) + ">]"; 4305e8d8bef9SDimitry Andric } 4306e8d8bef9SDimitry Andric } 43078bcb0991SDimitry Andric 43088bcb0991SDimitry Andric Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0; 43095f757f3fSDimitry Andric Fields[6].Str = 43105f757f3fSDimitry Andric getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo); 43118bcb0991SDimitry Andric 43125f757f3fSDimitry Andric Fields[7].Column += ExtraSymInfo ? 10 : 0; 4313e8d8bef9SDimitry Andric Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable, 4314e8d8bef9SDimitry Andric StrTable, IsDynamic); 4315e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 43160b57cec5SDimitry Andric printField(Entry); 43170b57cec5SDimitry Andric OS << "\n"; 43180b57cec5SDimitry Andric } 43190b57cec5SDimitry Andric 43200b57cec5SDimitry Andric template <class ELFT> 4321e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol, 4322e8d8bef9SDimitry Andric unsigned SymIndex, 4323e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 4324e8d8bef9SDimitry Andric StringRef StrTable, 43250b57cec5SDimitry Andric uint32_t Bucket) { 43260b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 43270b57cec5SDimitry Andric Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias, 43280b57cec5SDimitry Andric 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; 4329e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(SymIndex, 5)); 43300b57cec5SDimitry Andric Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":"; 43310b57cec5SDimitry Andric 43320b57cec5SDimitry Andric Fields[2].Str = to_string( 43338bcb0991SDimitry Andric format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8)); 43340b57cec5SDimitry Andric Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5)); 43350b57cec5SDimitry Andric 43360b57cec5SDimitry Andric unsigned char SymbolType = Symbol->getType(); 4337e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 43380b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 4339bdd1243dSDimitry Andric Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes)); 43400b57cec5SDimitry Andric else 4341bdd1243dSDimitry Andric Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes)); 43420b57cec5SDimitry Andric 43430b57cec5SDimitry Andric Fields[5].Str = 4344bdd1243dSDimitry Andric enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings)); 4345bdd1243dSDimitry Andric Fields[6].Str = 4346bdd1243dSDimitry Andric enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities)); 4347e8d8bef9SDimitry Andric Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable); 4348e8d8bef9SDimitry Andric Fields[8].Str = 4349e8d8bef9SDimitry Andric this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true); 43500b57cec5SDimitry Andric 4351e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 43520b57cec5SDimitry Andric printField(Entry); 43530b57cec5SDimitry Andric OS << "\n"; 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric 43560b57cec5SDimitry Andric template <class ELFT> 4357e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols, 43585f757f3fSDimitry Andric bool PrintDynamicSymbols, 43595f757f3fSDimitry Andric bool ExtraSymInfo) { 43600b57cec5SDimitry Andric if (!PrintSymbols && !PrintDynamicSymbols) 43610b57cec5SDimitry Andric return; 43620b57cec5SDimitry Andric // GNU readelf prints both the .dynsym and .symtab with --symbols. 43635f757f3fSDimitry Andric this->printSymbolsHelper(true, ExtraSymInfo); 43640b57cec5SDimitry Andric if (PrintSymbols) 43655f757f3fSDimitry Andric this->printSymbolsHelper(false, ExtraSymInfo); 43660b57cec5SDimitry Andric } 43670b57cec5SDimitry Andric 43685ffd83dbSDimitry Andric template <class ELFT> 4369e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) { 4370e8d8bef9SDimitry Andric if (this->DynamicStringTable.empty()) 43710b57cec5SDimitry Andric return; 43720b57cec5SDimitry Andric 43730b57cec5SDimitry Andric if (ELFT::Is64Bits) 43740b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 43750b57cec5SDimitry Andric else 43760b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 43770b57cec5SDimitry Andric OS << "\n"; 43780b57cec5SDimitry Andric 4379e8d8bef9SDimitry Andric Elf_Sym_Range DynSyms = this->dynamic_symbols(); 43805ffd83dbSDimitry Andric const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0]; 43815ffd83dbSDimitry Andric if (!FirstSym) { 43825ffd83dbSDimitry Andric this->reportUniqueWarning( 4383e8d8bef9SDimitry Andric Twine("unable to print symbols for the .hash table: the " 43845ffd83dbSDimitry Andric "dynamic symbol table ") + 4385e8d8bef9SDimitry Andric (this->DynSymRegion ? "is empty" : "was not found")); 43865ffd83dbSDimitry Andric return; 43875ffd83dbSDimitry Andric } 43885ffd83dbSDimitry Andric 4389e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 4390e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 43915ffd83dbSDimitry Andric auto Buckets = SysVHash.buckets(); 43925ffd83dbSDimitry Andric auto Chains = SysVHash.chains(); 43935ffd83dbSDimitry Andric for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) { 43940b57cec5SDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 43950b57cec5SDimitry Andric continue; 439604eeddc0SDimitry Andric BitVector Visited(SysVHash.nchain); 43975ffd83dbSDimitry Andric for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) { 43980b57cec5SDimitry Andric if (Ch == ELF::STN_UNDEF) 43990b57cec5SDimitry Andric break; 44008bcb0991SDimitry Andric 44018bcb0991SDimitry Andric if (Visited[Ch]) { 4402e8d8bef9SDimitry Andric this->reportUniqueWarning(".hash section is invalid: bucket " + 44035ffd83dbSDimitry Andric Twine(Ch) + 4404e8d8bef9SDimitry Andric ": a cycle was detected in the linked chain"); 44058bcb0991SDimitry Andric break; 44068bcb0991SDimitry Andric } 44078bcb0991SDimitry Andric 4408e8d8bef9SDimitry Andric printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable, 4409e8d8bef9SDimitry Andric Buc); 44108bcb0991SDimitry Andric Visited[Ch] = true; 44110b57cec5SDimitry Andric } 44120b57cec5SDimitry Andric } 44130b57cec5SDimitry Andric } 44140b57cec5SDimitry Andric 44155ffd83dbSDimitry Andric template <class ELFT> 4416e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) { 4417e8d8bef9SDimitry Andric if (this->DynamicStringTable.empty()) 44185ffd83dbSDimitry Andric return; 44195ffd83dbSDimitry Andric 4420e8d8bef9SDimitry Andric Elf_Sym_Range DynSyms = this->dynamic_symbols(); 44215ffd83dbSDimitry Andric const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0]; 44225ffd83dbSDimitry Andric if (!FirstSym) { 4423e8d8bef9SDimitry Andric this->reportUniqueWarning( 44245ffd83dbSDimitry Andric Twine("unable to print symbols for the .gnu.hash table: the " 44255ffd83dbSDimitry Andric "dynamic symbol table ") + 4426e8d8bef9SDimitry Andric (this->DynSymRegion ? "is empty" : "was not found")); 44275ffd83dbSDimitry Andric return; 44285ffd83dbSDimitry Andric } 44295ffd83dbSDimitry Andric 4430e8d8bef9SDimitry Andric auto GetSymbol = [&](uint64_t SymIndex, 4431e8d8bef9SDimitry Andric uint64_t SymsTotal) -> const Elf_Sym * { 4432e8d8bef9SDimitry Andric if (SymIndex >= SymsTotal) { 4433e8d8bef9SDimitry Andric this->reportUniqueWarning( 4434e8d8bef9SDimitry Andric "unable to print hashed symbol with index " + Twine(SymIndex) + 4435e8d8bef9SDimitry Andric ", which is greater than or equal to the number of dynamic symbols " 4436e8d8bef9SDimitry Andric "(" + 4437e8d8bef9SDimitry Andric Twine::utohexstr(SymsTotal) + ")"); 4438e8d8bef9SDimitry Andric return nullptr; 4439e8d8bef9SDimitry Andric } 4440e8d8bef9SDimitry Andric return FirstSym + SymIndex; 4441e8d8bef9SDimitry Andric }; 4442e8d8bef9SDimitry Andric 4443e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Word>> ValuesOrErr = 4444e8d8bef9SDimitry Andric getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHash); 4445e8d8bef9SDimitry Andric ArrayRef<Elf_Word> Values; 4446e8d8bef9SDimitry Andric if (!ValuesOrErr) 4447e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get hash values for the SHT_GNU_HASH " 4448e8d8bef9SDimitry Andric "section: " + 4449e8d8bef9SDimitry Andric toString(ValuesOrErr.takeError())); 4450e8d8bef9SDimitry Andric else 4451e8d8bef9SDimitry Andric Values = *ValuesOrErr; 4452e8d8bef9SDimitry Andric 4453e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 4454e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 44555ffd83dbSDimitry Andric ArrayRef<Elf_Word> Buckets = GnuHash.buckets(); 44565ffd83dbSDimitry Andric for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) { 44575ffd83dbSDimitry Andric if (Buckets[Buc] == ELF::STN_UNDEF) 44585ffd83dbSDimitry Andric continue; 44595ffd83dbSDimitry Andric uint32_t Index = Buckets[Buc]; 4460e8d8bef9SDimitry Andric // Print whole chain. 44615ffd83dbSDimitry Andric while (true) { 4462e8d8bef9SDimitry Andric uint32_t SymIndex = Index++; 4463e8d8bef9SDimitry Andric if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size())) 4464e8d8bef9SDimitry Andric printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable, 4465e8d8bef9SDimitry Andric Buc); 4466e8d8bef9SDimitry Andric else 4467e8d8bef9SDimitry Andric break; 4468e8d8bef9SDimitry Andric 4469e8d8bef9SDimitry Andric if (SymIndex < GnuHash.symndx) { 4470e8d8bef9SDimitry Andric this->reportUniqueWarning( 4471e8d8bef9SDimitry Andric "unable to read the hash value for symbol with index " + 4472e8d8bef9SDimitry Andric Twine(SymIndex) + 4473e8d8bef9SDimitry Andric ", which is less than the index of the first hashed symbol (" + 4474e8d8bef9SDimitry Andric Twine(GnuHash.symndx) + ")"); 4475e8d8bef9SDimitry Andric break; 4476e8d8bef9SDimitry Andric } 4477e8d8bef9SDimitry Andric 4478e8d8bef9SDimitry Andric // Chain ends at symbol with stopper bit. 4479e8d8bef9SDimitry Andric if ((Values[SymIndex - GnuHash.symndx] & 1) == 1) 44805ffd83dbSDimitry Andric break; 44815ffd83dbSDimitry Andric } 44825ffd83dbSDimitry Andric } 44835ffd83dbSDimitry Andric } 44845ffd83dbSDimitry Andric 4485e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printHashSymbols() { 4486e8d8bef9SDimitry Andric if (this->HashTable) { 44875ffd83dbSDimitry Andric OS << "\n Symbol table of .hash for image:\n"; 4488e8d8bef9SDimitry Andric if (Error E = checkHashTable<ELFT>(*this, this->HashTable)) 44895ffd83dbSDimitry Andric this->reportUniqueWarning(std::move(E)); 44905ffd83dbSDimitry Andric else 4491e8d8bef9SDimitry Andric printHashTableSymbols(*this->HashTable); 44925ffd83dbSDimitry Andric } 44935ffd83dbSDimitry Andric 44945ffd83dbSDimitry Andric // Try printing the .gnu.hash table. 4495e8d8bef9SDimitry Andric if (this->GnuHashTable) { 44960b57cec5SDimitry Andric OS << "\n Symbol table of .gnu.hash for image:\n"; 44970b57cec5SDimitry Andric if (ELFT::Is64Bits) 44980b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 44990b57cec5SDimitry Andric else 45000b57cec5SDimitry Andric OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; 45010b57cec5SDimitry Andric OS << "\n"; 45025ffd83dbSDimitry Andric 4503e8d8bef9SDimitry Andric if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable)) 45045ffd83dbSDimitry Andric this->reportUniqueWarning(std::move(E)); 45055ffd83dbSDimitry Andric else 4506e8d8bef9SDimitry Andric printGnuHashTableSymbols(*this->GnuHashTable); 4507e8d8bef9SDimitry Andric } 4508e8d8bef9SDimitry Andric } 4509e8d8bef9SDimitry Andric 4510e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() { 4511e8d8bef9SDimitry Andric ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections()); 4512bdd1243dSDimitry Andric if (Sections.empty()) { 4513bdd1243dSDimitry Andric OS << "\nThere are no sections in this file.\n"; 4514bdd1243dSDimitry Andric Expected<StringRef> SecStrTableOrErr = 4515bdd1243dSDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler); 4516bdd1243dSDimitry Andric if (!SecStrTableOrErr) 4517bdd1243dSDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 4518bdd1243dSDimitry Andric return; 4519bdd1243dSDimitry Andric } 4520e8d8bef9SDimitry Andric OS << "There are " << to_string(Sections.size()) 4521e8d8bef9SDimitry Andric << " section headers, starting at offset " 452281ad6265SDimitry Andric << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n"; 4523e8d8bef9SDimitry Andric 4524e8d8bef9SDimitry Andric OS << "Section Headers:\n"; 4525e8d8bef9SDimitry Andric 4526e8d8bef9SDimitry Andric auto PrintFields = [&](ArrayRef<Field> V) { 4527e8d8bef9SDimitry Andric for (const Field &F : V) 4528e8d8bef9SDimitry Andric printField(F); 4529e8d8bef9SDimitry Andric OS << "\n"; 4530e8d8bef9SDimitry Andric }; 4531e8d8bef9SDimitry Andric 4532e8d8bef9SDimitry Andric PrintFields({{"[Nr]", 2}, {"Name", 7}}); 4533e8d8bef9SDimitry Andric 4534e8d8bef9SDimitry Andric constexpr bool Is64 = ELFT::Is64Bits; 4535e8d8bef9SDimitry Andric PrintFields({{"Type", 7}, 4536e8d8bef9SDimitry Andric {Is64 ? "Address" : "Addr", 23}, 4537e8d8bef9SDimitry Andric {"Off", Is64 ? 40 : 32}, 4538e8d8bef9SDimitry Andric {"Size", Is64 ? 47 : 39}, 4539e8d8bef9SDimitry Andric {"ES", Is64 ? 54 : 46}, 4540e8d8bef9SDimitry Andric {"Lk", Is64 ? 59 : 51}, 4541e8d8bef9SDimitry Andric {"Inf", Is64 ? 62 : 54}, 4542e8d8bef9SDimitry Andric {"Al", Is64 ? 66 : 57}}); 4543e8d8bef9SDimitry Andric PrintFields({{"Flags", 7}}); 4544e8d8bef9SDimitry Andric 4545e8d8bef9SDimitry Andric StringRef SecStrTable; 4546e8d8bef9SDimitry Andric if (Expected<StringRef> SecStrTableOrErr = 4547e8d8bef9SDimitry Andric this->Obj.getSectionStringTable(Sections, this->WarningHandler)) 4548e8d8bef9SDimitry Andric SecStrTable = *SecStrTableOrErr; 4549e8d8bef9SDimitry Andric else 4550e8d8bef9SDimitry Andric this->reportUniqueWarning(SecStrTableOrErr.takeError()); 4551e8d8bef9SDimitry Andric 4552e8d8bef9SDimitry Andric size_t SectionIndex = 0; 4553e8d8bef9SDimitry Andric const unsigned AddrSize = Is64 ? 16 : 8; 4554e8d8bef9SDimitry Andric for (const Elf_Shdr &S : Sections) { 4555e8d8bef9SDimitry Andric StringRef Name = "<?>"; 4556e8d8bef9SDimitry Andric if (Expected<StringRef> NameOrErr = 4557e8d8bef9SDimitry Andric this->Obj.getSectionName(S, SecStrTable)) 4558e8d8bef9SDimitry Andric Name = *NameOrErr; 4559e8d8bef9SDimitry Andric else 4560e8d8bef9SDimitry Andric this->reportUniqueWarning(NameOrErr.takeError()); 4561e8d8bef9SDimitry Andric 4562e8d8bef9SDimitry Andric OS.PadToColumn(2); 4563e8d8bef9SDimitry Andric OS << "[" << right_justify(to_string(SectionIndex), 2) << "]"; 4564e8d8bef9SDimitry Andric PrintFields({{Name, 7}}); 4565e8d8bef9SDimitry Andric PrintFields( 4566e8d8bef9SDimitry Andric {{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7}, 4567e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23}, 4568e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32}, 4569e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39}, 4570e8d8bef9SDimitry Andric {to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46}, 4571e8d8bef9SDimitry Andric {to_string(S.sh_link), Is64 ? 59 : 51}, 4572e8d8bef9SDimitry Andric {to_string(S.sh_info), Is64 ? 63 : 55}, 4573e8d8bef9SDimitry Andric {to_string(S.sh_addralign), Is64 ? 66 : 58}}); 4574e8d8bef9SDimitry Andric 4575e8d8bef9SDimitry Andric OS.PadToColumn(7); 4576e8d8bef9SDimitry Andric OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: "; 4577e8d8bef9SDimitry Andric 4578e8d8bef9SDimitry Andric DenseMap<unsigned, StringRef> FlagToName = { 4579e8d8bef9SDimitry Andric {SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"}, 4580e8d8bef9SDimitry Andric {SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"}, 4581e8d8bef9SDimitry Andric {SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"}, 4582e8d8bef9SDimitry Andric {SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"}, 4583e8d8bef9SDimitry Andric {SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"}, 4584e8d8bef9SDimitry Andric {SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}}; 4585e8d8bef9SDimitry Andric 4586e8d8bef9SDimitry Andric uint64_t Flags = S.sh_flags; 4587e8d8bef9SDimitry Andric uint64_t UnknownFlags = 0; 4588fe6060f1SDimitry Andric ListSeparator LS; 4589e8d8bef9SDimitry Andric while (Flags) { 4590e8d8bef9SDimitry Andric // Take the least significant bit as a flag. 4591e8d8bef9SDimitry Andric uint64_t Flag = Flags & -Flags; 4592e8d8bef9SDimitry Andric Flags -= Flag; 4593e8d8bef9SDimitry Andric 4594e8d8bef9SDimitry Andric auto It = FlagToName.find(Flag); 4595fe6060f1SDimitry Andric if (It != FlagToName.end()) 4596fe6060f1SDimitry Andric OS << LS << It->second; 4597fe6060f1SDimitry Andric else 4598e8d8bef9SDimitry Andric UnknownFlags |= Flag; 4599e8d8bef9SDimitry Andric } 4600e8d8bef9SDimitry Andric 4601e8d8bef9SDimitry Andric auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) { 4602e8d8bef9SDimitry Andric uint64_t FlagsToPrint = UnknownFlags & Mask; 4603e8d8bef9SDimitry Andric if (!FlagsToPrint) 4604e8d8bef9SDimitry Andric return; 4605e8d8bef9SDimitry Andric 4606fe6060f1SDimitry Andric OS << LS << Name << " (" 4607e8d8bef9SDimitry Andric << to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")"; 4608e8d8bef9SDimitry Andric UnknownFlags &= ~Mask; 4609e8d8bef9SDimitry Andric }; 4610e8d8bef9SDimitry Andric 4611e8d8bef9SDimitry Andric PrintUnknownFlags(SHF_MASKOS, "OS"); 4612e8d8bef9SDimitry Andric PrintUnknownFlags(SHF_MASKPROC, "PROC"); 4613e8d8bef9SDimitry Andric PrintUnknownFlags(uint64_t(-1), "UNKNOWN"); 4614e8d8bef9SDimitry Andric 4615e8d8bef9SDimitry Andric OS << "\n"; 4616e8d8bef9SDimitry Andric ++SectionIndex; 4617bdd1243dSDimitry Andric 4618bdd1243dSDimitry Andric if (!(S.sh_flags & SHF_COMPRESSED)) 4619bdd1243dSDimitry Andric continue; 4620bdd1243dSDimitry Andric Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S); 4621bdd1243dSDimitry Andric if (!Data || Data->size() < sizeof(Elf_Chdr)) { 4622bdd1243dSDimitry Andric consumeError(Data.takeError()); 4623bdd1243dSDimitry Andric reportWarning(createError("SHF_COMPRESSED section '" + Name + 4624bdd1243dSDimitry Andric "' does not have an Elf_Chdr header"), 4625bdd1243dSDimitry Andric this->FileName); 4626bdd1243dSDimitry Andric OS.indent(7); 4627bdd1243dSDimitry Andric OS << "[<corrupt>]"; 4628bdd1243dSDimitry Andric } else { 4629bdd1243dSDimitry Andric OS.indent(7); 4630bdd1243dSDimitry Andric auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data()); 4631bdd1243dSDimitry Andric if (Chdr->ch_type == ELFCOMPRESS_ZLIB) 4632bdd1243dSDimitry Andric OS << "ZLIB"; 4633bdd1243dSDimitry Andric else if (Chdr->ch_type == ELFCOMPRESS_ZSTD) 4634bdd1243dSDimitry Andric OS << "ZSTD"; 4635bdd1243dSDimitry Andric else 4636bdd1243dSDimitry Andric OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type)); 4637bdd1243dSDimitry Andric OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8) 4638bdd1243dSDimitry Andric << ", " << Chdr->ch_addralign; 4639bdd1243dSDimitry Andric } 4640bdd1243dSDimitry Andric OS << '\n'; 46410b57cec5SDimitry Andric } 46420b57cec5SDimitry Andric } 46430b57cec5SDimitry Andric 46440b57cec5SDimitry Andric static inline std::string printPhdrFlags(unsigned Flag) { 46450b57cec5SDimitry Andric std::string Str; 46460b57cec5SDimitry Andric Str = (Flag & PF_R) ? "R" : " "; 46470b57cec5SDimitry Andric Str += (Flag & PF_W) ? "W" : " "; 46480b57cec5SDimitry Andric Str += (Flag & PF_X) ? "E" : " "; 46490b57cec5SDimitry Andric return Str; 46500b57cec5SDimitry Andric } 46510b57cec5SDimitry Andric 46520b57cec5SDimitry Andric template <class ELFT> 46535ffd83dbSDimitry Andric static bool checkTLSSections(const typename ELFT::Phdr &Phdr, 46545ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 46555ffd83dbSDimitry Andric if (Sec.sh_flags & ELF::SHF_TLS) { 46565ffd83dbSDimitry Andric // .tbss must only be shown in the PT_TLS segment. 46575ffd83dbSDimitry Andric if (Sec.sh_type == ELF::SHT_NOBITS) 46585ffd83dbSDimitry Andric return Phdr.p_type == ELF::PT_TLS; 46595ffd83dbSDimitry Andric 46605ffd83dbSDimitry Andric // SHF_TLS sections are only shown in PT_TLS, PT_LOAD or PT_GNU_RELRO 46615ffd83dbSDimitry Andric // segments. 46625ffd83dbSDimitry Andric return (Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) || 46635ffd83dbSDimitry Andric (Phdr.p_type == ELF::PT_GNU_RELRO); 46640b57cec5SDimitry Andric } 46650b57cec5SDimitry Andric 46665ffd83dbSDimitry Andric // PT_TLS must only have SHF_TLS sections. 46675ffd83dbSDimitry Andric return Phdr.p_type != ELF::PT_TLS; 46685ffd83dbSDimitry Andric } 46695ffd83dbSDimitry Andric 46700b57cec5SDimitry Andric template <class ELFT> 46715ffd83dbSDimitry Andric static bool checkPTDynamic(const typename ELFT::Phdr &Phdr, 46725ffd83dbSDimitry Andric const typename ELFT::Shdr &Sec) { 46735ffd83dbSDimitry Andric if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0) 46740b57cec5SDimitry Andric return true; 46755ffd83dbSDimitry Andric 46765ffd83dbSDimitry Andric // We get here when we have an empty section. Only non-empty sections can be 46775ffd83dbSDimitry Andric // at the start or at the end of PT_DYNAMIC. 46780b57cec5SDimitry Andric // Is section within the phdr both based on offset and VMA? 46795ffd83dbSDimitry Andric bool CheckOffset = (Sec.sh_type == ELF::SHT_NOBITS) || 46800b57cec5SDimitry Andric (Sec.sh_offset > Phdr.p_offset && 46815ffd83dbSDimitry Andric Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz); 46825ffd83dbSDimitry Andric bool CheckVA = !(Sec.sh_flags & ELF::SHF_ALLOC) || 46835ffd83dbSDimitry Andric (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz); 46845ffd83dbSDimitry Andric return CheckOffset && CheckVA; 46850b57cec5SDimitry Andric } 46860b57cec5SDimitry Andric 46870b57cec5SDimitry Andric template <class ELFT> 4688e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printProgramHeaders( 4689e8d8bef9SDimitry Andric bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) { 4690bdd1243dSDimitry Andric const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE); 4691bdd1243dSDimitry Andric // Exit early if no program header or section mapping details were requested. 4692bdd1243dSDimitry Andric if (!PrintProgramHeaders && !ShouldPrintSectionMapping) 4693bdd1243dSDimitry Andric return; 46940b57cec5SDimitry Andric 4695bdd1243dSDimitry Andric if (PrintProgramHeaders) { 4696bdd1243dSDimitry Andric const Elf_Ehdr &Header = this->Obj.getHeader(); 4697bdd1243dSDimitry Andric if (Header.e_phnum == 0) { 4698bdd1243dSDimitry Andric OS << "\nThere are no program headers in this file.\n"; 4699bdd1243dSDimitry Andric } else { 4700bdd1243dSDimitry Andric printProgramHeaders(); 4701bdd1243dSDimitry Andric } 4702bdd1243dSDimitry Andric } 4703bdd1243dSDimitry Andric 4704bdd1243dSDimitry Andric if (ShouldPrintSectionMapping) 4705e8d8bef9SDimitry Andric printSectionMapping(); 47060b57cec5SDimitry Andric } 47070b57cec5SDimitry Andric 4708e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printProgramHeaders() { 47090b57cec5SDimitry Andric unsigned Bias = ELFT::Is64Bits ? 8 : 0; 4710e8d8bef9SDimitry Andric const Elf_Ehdr &Header = this->Obj.getHeader(); 47110b57cec5SDimitry Andric Field Fields[8] = {2, 17, 26, 37 + Bias, 47120b57cec5SDimitry Andric 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias}; 47130b57cec5SDimitry Andric OS << "\nElf file type is " 4714bdd1243dSDimitry Andric << enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n" 4715e8d8bef9SDimitry Andric << "Entry point " << format_hex(Header.e_entry, 3) << "\n" 4716e8d8bef9SDimitry Andric << "There are " << Header.e_phnum << " program headers," 4717e8d8bef9SDimitry Andric << " starting at offset " << Header.e_phoff << "\n\n" 47180b57cec5SDimitry Andric << "Program Headers:\n"; 47190b57cec5SDimitry Andric if (ELFT::Is64Bits) 47200b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr " 47210b57cec5SDimitry Andric << " FileSiz MemSiz Flg Align\n"; 47220b57cec5SDimitry Andric else 47230b57cec5SDimitry Andric OS << " Type Offset VirtAddr PhysAddr FileSiz " 47240b57cec5SDimitry Andric << "MemSiz Flg Align\n"; 47250b57cec5SDimitry Andric 47260b57cec5SDimitry Andric unsigned Width = ELFT::Is64Bits ? 18 : 10; 47270b57cec5SDimitry Andric unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7; 47285ffd83dbSDimitry Andric 4729e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 47305ffd83dbSDimitry Andric if (!PhdrsOrErr) { 4731e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to dump program headers: " + 4732e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 47335ffd83dbSDimitry Andric return; 47345ffd83dbSDimitry Andric } 47355ffd83dbSDimitry Andric 47365ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 4737e8d8bef9SDimitry Andric Fields[0].Str = getGNUPtType(Header.e_machine, Phdr.p_type); 47380b57cec5SDimitry Andric Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8)); 47390b57cec5SDimitry Andric Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width)); 47400b57cec5SDimitry Andric Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width)); 47410b57cec5SDimitry Andric Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth)); 47420b57cec5SDimitry Andric Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth)); 47430b57cec5SDimitry Andric Fields[6].Str = printPhdrFlags(Phdr.p_flags); 47440b57cec5SDimitry Andric Fields[7].Str = to_string(format_hex(Phdr.p_align, 1)); 4745e8d8bef9SDimitry Andric for (const Field &F : Fields) 4746e8d8bef9SDimitry Andric printField(F); 47470b57cec5SDimitry Andric if (Phdr.p_type == ELF::PT_INTERP) { 47485ffd83dbSDimitry Andric OS << "\n"; 47495ffd83dbSDimitry Andric auto ReportBadInterp = [&](const Twine &Msg) { 4750e8d8bef9SDimitry Andric this->reportUniqueWarning( 4751e8d8bef9SDimitry Andric "unable to read program interpreter name at offset 0x" + 4752e8d8bef9SDimitry Andric Twine::utohexstr(Phdr.p_offset) + ": " + Msg); 47535ffd83dbSDimitry Andric }; 47545ffd83dbSDimitry Andric 4755e8d8bef9SDimitry Andric if (Phdr.p_offset >= this->Obj.getBufSize()) { 47565ffd83dbSDimitry Andric ReportBadInterp("it goes past the end of the file (0x" + 4757e8d8bef9SDimitry Andric Twine::utohexstr(this->Obj.getBufSize()) + ")"); 47585ffd83dbSDimitry Andric continue; 47595ffd83dbSDimitry Andric } 47605ffd83dbSDimitry Andric 47615ffd83dbSDimitry Andric const char *Data = 4762e8d8bef9SDimitry Andric reinterpret_cast<const char *>(this->Obj.base()) + Phdr.p_offset; 4763e8d8bef9SDimitry Andric size_t MaxSize = this->Obj.getBufSize() - Phdr.p_offset; 47645ffd83dbSDimitry Andric size_t Len = strnlen(Data, MaxSize); 47655ffd83dbSDimitry Andric if (Len == MaxSize) { 47665ffd83dbSDimitry Andric ReportBadInterp("it is not null-terminated"); 47675ffd83dbSDimitry Andric continue; 47685ffd83dbSDimitry Andric } 47695ffd83dbSDimitry Andric 47705ffd83dbSDimitry Andric OS << " [Requesting program interpreter: "; 47715ffd83dbSDimitry Andric OS << StringRef(Data, Len) << "]"; 47720b57cec5SDimitry Andric } 47730b57cec5SDimitry Andric OS << "\n"; 47740b57cec5SDimitry Andric } 47750b57cec5SDimitry Andric } 47760b57cec5SDimitry Andric 4777e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printSectionMapping() { 47780b57cec5SDimitry Andric OS << "\n Section to Segment mapping:\n Segment Sections...\n"; 47790b57cec5SDimitry Andric DenseSet<const Elf_Shdr *> BelongsToSegment; 47800b57cec5SDimitry Andric int Phnum = 0; 47815ffd83dbSDimitry Andric 4782e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 47835ffd83dbSDimitry Andric if (!PhdrsOrErr) { 4784e8d8bef9SDimitry Andric this->reportUniqueWarning( 47855ffd83dbSDimitry Andric "can't read program headers to build section to segment mapping: " + 4786e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 47875ffd83dbSDimitry Andric return; 47885ffd83dbSDimitry Andric } 47895ffd83dbSDimitry Andric 47905ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 47910b57cec5SDimitry Andric std::string Sections; 47920b57cec5SDimitry Andric OS << format(" %2.2d ", Phnum++); 47930b57cec5SDimitry Andric // Check if each section is in a segment and then print mapping. 4794e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 47955ffd83dbSDimitry Andric if (Sec.sh_type == ELF::SHT_NULL) 47965ffd83dbSDimitry Andric continue; 47975ffd83dbSDimitry Andric 47980b57cec5SDimitry Andric // readelf additionally makes sure it does not print zero sized sections 47990b57cec5SDimitry Andric // at end of segments and for PT_DYNAMIC both start and end of section 48000b57cec5SDimitry Andric // .tbss must only be shown in PT_TLS section. 48015f757f3fSDimitry Andric if (isSectionInSegment<ELFT>(Phdr, Sec) && 48025f757f3fSDimitry Andric checkTLSSections<ELFT>(Phdr, Sec) && 48035f757f3fSDimitry Andric checkPTDynamic<ELFT>(Phdr, Sec)) { 48048bcb0991SDimitry Andric Sections += 4805e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() + 48068bcb0991SDimitry Andric " "; 48070b57cec5SDimitry Andric BelongsToSegment.insert(&Sec); 48080b57cec5SDimitry Andric } 48090b57cec5SDimitry Andric } 48100b57cec5SDimitry Andric OS << Sections << "\n"; 48110b57cec5SDimitry Andric OS.flush(); 48120b57cec5SDimitry Andric } 48130b57cec5SDimitry Andric 48140b57cec5SDimitry Andric // Display sections that do not belong to a segment. 48150b57cec5SDimitry Andric std::string Sections; 4816e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 48170b57cec5SDimitry Andric if (BelongsToSegment.find(&Sec) == BelongsToSegment.end()) 48188bcb0991SDimitry Andric Sections += 4819e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() + 4820e8d8bef9SDimitry Andric ' '; 48210b57cec5SDimitry Andric } 48220b57cec5SDimitry Andric if (!Sections.empty()) { 48230b57cec5SDimitry Andric OS << " None " << Sections << '\n'; 48240b57cec5SDimitry Andric OS.flush(); 48250b57cec5SDimitry Andric } 48260b57cec5SDimitry Andric } 48270b57cec5SDimitry Andric 48288bcb0991SDimitry Andric namespace { 48298bcb0991SDimitry Andric 48308bcb0991SDimitry Andric template <class ELFT> 4831e8d8bef9SDimitry Andric RelSymbol<ELFT> getSymbolForReloc(const ELFDumper<ELFT> &Dumper, 4832e8d8bef9SDimitry Andric const Relocation<ELFT> &Reloc) { 4833e8d8bef9SDimitry Andric using Elf_Sym = typename ELFT::Sym; 4834e8d8bef9SDimitry Andric auto WarnAndReturn = [&](const Elf_Sym *Sym, 48355ffd83dbSDimitry Andric const Twine &Reason) -> RelSymbol<ELFT> { 4836e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 4837e8d8bef9SDimitry Andric "unable to get name of the dynamic symbol with index " + 4838e8d8bef9SDimitry Andric Twine(Reloc.Symbol) + ": " + Reason); 48395ffd83dbSDimitry Andric return {Sym, "<corrupt>"}; 48405ffd83dbSDimitry Andric }; 48418bcb0991SDimitry Andric 4842e8d8bef9SDimitry Andric ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols(); 4843e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = Symbols.begin(); 48445ffd83dbSDimitry Andric if (!FirstSym) 48455ffd83dbSDimitry Andric return WarnAndReturn(nullptr, "no dynamic symbol table found"); 48465ffd83dbSDimitry Andric 48475ffd83dbSDimitry Andric // We might have an object without a section header. In this case the size of 48485ffd83dbSDimitry Andric // Symbols is zero, because there is no way to know the size of the dynamic 48495ffd83dbSDimitry Andric // table. We should allow this case and not print a warning. 4850e8d8bef9SDimitry Andric if (!Symbols.empty() && Reloc.Symbol >= Symbols.size()) 48515ffd83dbSDimitry Andric return WarnAndReturn( 48525ffd83dbSDimitry Andric nullptr, 48535ffd83dbSDimitry Andric "index is greater than or equal to the number of dynamic symbols (" + 48545ffd83dbSDimitry Andric Twine(Symbols.size()) + ")"); 48555ffd83dbSDimitry Andric 4856e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 4857e8d8bef9SDimitry Andric const uint64_t FileSize = Obj.getBufSize(); 4858e8d8bef9SDimitry Andric const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) + 4859e8d8bef9SDimitry Andric (uint64_t)Reloc.Symbol * sizeof(Elf_Sym); 4860e8d8bef9SDimitry Andric if (SymOffset + sizeof(Elf_Sym) > FileSize) 4861e8d8bef9SDimitry Andric return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) + 4862e8d8bef9SDimitry Andric " goes past the end of the file (0x" + 4863e8d8bef9SDimitry Andric Twine::utohexstr(FileSize) + ")"); 4864e8d8bef9SDimitry Andric 4865e8d8bef9SDimitry Andric const Elf_Sym *Sym = FirstSym + Reloc.Symbol; 4866e8d8bef9SDimitry Andric Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable()); 48675ffd83dbSDimitry Andric if (!ErrOrName) 48685ffd83dbSDimitry Andric return WarnAndReturn(Sym, toString(ErrOrName.takeError())); 48695ffd83dbSDimitry Andric 48705ffd83dbSDimitry Andric return {Sym == FirstSym ? nullptr : Sym, maybeDemangle(*ErrOrName)}; 48718bcb0991SDimitry Andric } 48728bcb0991SDimitry Andric } // namespace 48738bcb0991SDimitry Andric 48740b57cec5SDimitry Andric template <class ELFT> 4875e8d8bef9SDimitry Andric static size_t getMaxDynamicTagSize(const ELFFile<ELFT> &Obj, 48765ffd83dbSDimitry Andric typename ELFT::DynRange Tags) { 48775ffd83dbSDimitry Andric size_t Max = 0; 48785ffd83dbSDimitry Andric for (const typename ELFT::Dyn &Dyn : Tags) 4879e8d8bef9SDimitry Andric Max = std::max(Max, Obj.getDynamicTagAsString(Dyn.d_tag).size()); 48805ffd83dbSDimitry Andric return Max; 48815ffd83dbSDimitry Andric } 48825ffd83dbSDimitry Andric 4883e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDynamicTable() { 4884e8d8bef9SDimitry Andric Elf_Dyn_Range Table = this->dynamic_table(); 48850b57cec5SDimitry Andric if (Table.empty()) 48860b57cec5SDimitry Andric return; 48870b57cec5SDimitry Andric 48880b57cec5SDimitry Andric OS << "Dynamic section at offset " 4889e8d8bef9SDimitry Andric << format_hex(reinterpret_cast<const uint8_t *>(this->DynamicTable.Addr) - 4890e8d8bef9SDimitry Andric this->Obj.base(), 48910b57cec5SDimitry Andric 1) 48920b57cec5SDimitry Andric << " contains " << Table.size() << " entries:\n"; 48930b57cec5SDimitry Andric 48945ffd83dbSDimitry Andric // The type name is surrounded with round brackets, hence add 2. 4895e8d8bef9SDimitry Andric size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table) + 2; 48965ffd83dbSDimitry Andric // The "Name/Value" column should be indented from the "Type" column by N 48975ffd83dbSDimitry Andric // spaces, where N = MaxTagSize - length of "Type" (4) + trailing 48985ffd83dbSDimitry Andric // space (1) = 3. 48995ffd83dbSDimitry Andric OS << " Tag" + std::string(ELFT::Is64Bits ? 16 : 8, ' ') + "Type" 49005ffd83dbSDimitry Andric << std::string(MaxTagSize - 3, ' ') << "Name/Value\n"; 49015ffd83dbSDimitry Andric 49025ffd83dbSDimitry Andric std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s "; 49030b57cec5SDimitry Andric for (auto Entry : Table) { 49040b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 49055ffd83dbSDimitry Andric std::string Type = 4906349cc55cSDimitry Andric std::string("(") + this->Obj.getDynamicTagAsString(Tag) + ")"; 4907e8d8bef9SDimitry Andric std::string Value = this->getDynamicEntry(Tag, Entry.getVal()); 49085ffd83dbSDimitry Andric OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10) 49095ffd83dbSDimitry Andric << format(ValueFmt.c_str(), Type.c_str()) << Value << "\n"; 49100b57cec5SDimitry Andric } 49110b57cec5SDimitry Andric } 49120b57cec5SDimitry Andric 4913e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDynamicRelocations() { 4914e8d8bef9SDimitry Andric this->printDynamicRelocationsHelper(); 49150b57cec5SDimitry Andric } 49165ffd83dbSDimitry Andric 4917e8d8bef9SDimitry Andric template <class ELFT> 4918e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printDynamicReloc(const Relocation<ELFT> &R) { 4919e8d8bef9SDimitry Andric printRelRelaReloc(R, getSymbolForReloc(*this, R)); 4920e8d8bef9SDimitry Andric } 4921e8d8bef9SDimitry Andric 4922e8d8bef9SDimitry Andric template <class ELFT> 4923e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) { 4924e8d8bef9SDimitry Andric this->forEachRelocationDo( 4925*0fca6ea1SDimitry Andric Sec, [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec, 4926*0fca6ea1SDimitry Andric const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); }); 4927e8d8bef9SDimitry Andric } 4928e8d8bef9SDimitry Andric 4929e8d8bef9SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() { 4930e8d8bef9SDimitry Andric const bool IsMips64EL = this->Obj.isMips64EL(); 4931*0fca6ea1SDimitry Andric auto DumpCrelRegion = [&](DynRegionInfo &Region) { 4932*0fca6ea1SDimitry Andric // While the size is unknown, a valid CREL has at least one byte. We can 4933*0fca6ea1SDimitry Andric // check whether Addr is in bounds, and then decode CREL until the file 4934*0fca6ea1SDimitry Andric // end. 4935*0fca6ea1SDimitry Andric Region.Size = Region.EntSize = 1; 4936*0fca6ea1SDimitry Andric if (!Region.template getAsArrayRef<uint8_t>().empty()) { 4937*0fca6ea1SDimitry Andric const uint64_t Offset = 4938*0fca6ea1SDimitry Andric Region.Addr - reinterpret_cast<const uint8_t *>( 4939*0fca6ea1SDimitry Andric ObjF.getMemoryBufferRef().getBufferStart()); 4940*0fca6ea1SDimitry Andric const uint64_t ObjSize = ObjF.getMemoryBufferRef().getBufferSize(); 4941*0fca6ea1SDimitry Andric auto RelsOrRelas = 4942*0fca6ea1SDimitry Andric Obj.decodeCrel(ArrayRef<uint8_t>(Region.Addr, ObjSize - Offset)); 4943*0fca6ea1SDimitry Andric if (!RelsOrRelas) { 4944*0fca6ea1SDimitry Andric reportUniqueWarning(toString(RelsOrRelas.takeError())); 4945*0fca6ea1SDimitry Andric } else { 4946*0fca6ea1SDimitry Andric for (const Elf_Rel &R : RelsOrRelas->first) 4947*0fca6ea1SDimitry Andric printDynamicReloc(Relocation<ELFT>(R, false)); 4948*0fca6ea1SDimitry Andric for (const Elf_Rela &R : RelsOrRelas->second) 4949*0fca6ea1SDimitry Andric printDynamicReloc(Relocation<ELFT>(R, false)); 4950*0fca6ea1SDimitry Andric } 4951*0fca6ea1SDimitry Andric } 4952*0fca6ea1SDimitry Andric }; 4953*0fca6ea1SDimitry Andric 4954*0fca6ea1SDimitry Andric if (this->DynCrelRegion.Addr) { 4955*0fca6ea1SDimitry Andric printDynamicRelocHeader(ELF::SHT_CREL, "CREL", this->DynCrelRegion); 4956*0fca6ea1SDimitry Andric DumpCrelRegion(this->DynCrelRegion); 4957*0fca6ea1SDimitry Andric } 4958*0fca6ea1SDimitry Andric 4959e8d8bef9SDimitry Andric if (this->DynRelaRegion.Size > 0) { 4960e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion); 4961e8d8bef9SDimitry Andric for (const Elf_Rela &Rela : 4962e8d8bef9SDimitry Andric this->DynRelaRegion.template getAsArrayRef<Elf_Rela>()) 4963e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL)); 4964e8d8bef9SDimitry Andric } 4965e8d8bef9SDimitry Andric 4966e8d8bef9SDimitry Andric if (this->DynRelRegion.Size > 0) { 4967e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "REL", this->DynRelRegion); 4968e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : 4969e8d8bef9SDimitry Andric this->DynRelRegion.template getAsArrayRef<Elf_Rel>()) 4970e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 4971e8d8bef9SDimitry Andric } 4972e8d8bef9SDimitry Andric 4973e8d8bef9SDimitry Andric if (this->DynRelrRegion.Size > 0) { 4974e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "RELR", this->DynRelrRegion); 4975e8d8bef9SDimitry Andric Elf_Relr_Range Relrs = 4976e8d8bef9SDimitry Andric this->DynRelrRegion.template getAsArrayRef<Elf_Relr>(); 4977e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : Obj.decode_relrs(Relrs)) 4978e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 4979e8d8bef9SDimitry Andric } 4980e8d8bef9SDimitry Andric 4981e8d8bef9SDimitry Andric if (this->DynPLTRelRegion.Size) { 4982e8d8bef9SDimitry Andric if (this->DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { 4983e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_RELA, "PLT", this->DynPLTRelRegion); 4984e8d8bef9SDimitry Andric for (const Elf_Rela &Rela : 4985e8d8bef9SDimitry Andric this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>()) 4986e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL)); 4987*0fca6ea1SDimitry Andric } else if (this->DynPLTRelRegion.EntSize == 1) { 4988*0fca6ea1SDimitry Andric DumpCrelRegion(this->DynPLTRelRegion); 49890b57cec5SDimitry Andric } else { 4990e8d8bef9SDimitry Andric printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion); 4991e8d8bef9SDimitry Andric for (const Elf_Rel &Rel : 4992e8d8bef9SDimitry Andric this->DynPLTRelRegion.template getAsArrayRef<Elf_Rel>()) 4993e8d8bef9SDimitry Andric printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL)); 49940b57cec5SDimitry Andric } 49950b57cec5SDimitry Andric } 49965ffd83dbSDimitry Andric } 49970b57cec5SDimitry Andric 49980b57cec5SDimitry Andric template <class ELFT> 4999e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printGNUVersionSectionProlog( 5000e8d8bef9SDimitry Andric const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) { 5001e8d8bef9SDimitry Andric // Don't inline the SecName, because it might report a warning to stderr and 5002e8d8bef9SDimitry Andric // corrupt the output. 5003e8d8bef9SDimitry Andric StringRef SecName = this->getPrintableSectionName(Sec); 5004480093f4SDimitry Andric OS << Label << " section '" << SecName << "' " 50050b57cec5SDimitry Andric << "contains " << EntriesNum << " entries:\n"; 50060b57cec5SDimitry Andric 5007e8d8bef9SDimitry Andric StringRef LinkedSecName = "<corrupt>"; 5008e8d8bef9SDimitry Andric if (Expected<const typename ELFT::Shdr *> LinkedSecOrErr = 5009e8d8bef9SDimitry Andric this->Obj.getSection(Sec.sh_link)) 5010e8d8bef9SDimitry Andric LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr); 5011480093f4SDimitry Andric else 5012e8d8bef9SDimitry Andric this->reportUniqueWarning("invalid section linked to " + 5013e8d8bef9SDimitry Andric this->describe(Sec) + ": " + 5014e8d8bef9SDimitry Andric toString(LinkedSecOrErr.takeError())); 5015480093f4SDimitry Andric 5016e8d8bef9SDimitry Andric OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16) 5017e8d8bef9SDimitry Andric << " Offset: " << format_hex(Sec.sh_offset, 8) 5018e8d8bef9SDimitry Andric << " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n"; 50190b57cec5SDimitry Andric } 50200b57cec5SDimitry Andric 50210b57cec5SDimitry Andric template <class ELFT> 5022e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) { 50230b57cec5SDimitry Andric if (!Sec) 50240b57cec5SDimitry Andric return; 50250b57cec5SDimitry Andric 5026e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version symbols", 5027480093f4SDimitry Andric Sec->sh_size / sizeof(Elf_Versym)); 5028480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VerTableOrErr = 5029e8d8bef9SDimitry Andric this->getVersionTable(*Sec, /*SymTab=*/nullptr, 5030e8d8bef9SDimitry Andric /*StrTab=*/nullptr, /*SymTabSec=*/nullptr); 5031480093f4SDimitry Andric if (!VerTableOrErr) { 5032480093f4SDimitry Andric this->reportUniqueWarning(VerTableOrErr.takeError()); 5033480093f4SDimitry Andric return; 5034480093f4SDimitry Andric } 50350b57cec5SDimitry Andric 5036bdd1243dSDimitry Andric SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr; 5037bdd1243dSDimitry Andric if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr = 5038e8d8bef9SDimitry Andric this->getVersionMap()) 5039e8d8bef9SDimitry Andric VersionMap = *MapOrErr; 5040e8d8bef9SDimitry Andric else 5041e8d8bef9SDimitry Andric this->reportUniqueWarning(MapOrErr.takeError()); 5042e8d8bef9SDimitry Andric 5043480093f4SDimitry Andric ArrayRef<Elf_Versym> VerTable = *VerTableOrErr; 5044480093f4SDimitry Andric std::vector<StringRef> Versions; 5045480093f4SDimitry Andric for (size_t I = 0, E = VerTable.size(); I < E; ++I) { 5046480093f4SDimitry Andric unsigned Ndx = VerTable[I].vs_index; 5047480093f4SDimitry Andric if (Ndx == VER_NDX_LOCAL || Ndx == VER_NDX_GLOBAL) { 5048480093f4SDimitry Andric Versions.emplace_back(Ndx == VER_NDX_LOCAL ? "*local*" : "*global*"); 5049480093f4SDimitry Andric continue; 5050480093f4SDimitry Andric } 5051480093f4SDimitry Andric 5052e8d8bef9SDimitry Andric if (!VersionMap) { 5053e8d8bef9SDimitry Andric Versions.emplace_back("<corrupt>"); 5054e8d8bef9SDimitry Andric continue; 5055480093f4SDimitry Andric } 5056e8d8bef9SDimitry Andric 5057e8d8bef9SDimitry Andric bool IsDefault; 5058e8d8bef9SDimitry Andric Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex( 5059bdd1243dSDimitry Andric Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt); 5060e8d8bef9SDimitry Andric if (!NameOrErr) { 5061e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get a version for entry " + 5062e8d8bef9SDimitry Andric Twine(I) + " of " + this->describe(*Sec) + 5063e8d8bef9SDimitry Andric ": " + toString(NameOrErr.takeError())); 5064480093f4SDimitry Andric Versions.emplace_back("<corrupt>"); 5065480093f4SDimitry Andric continue; 5066480093f4SDimitry Andric } 5067480093f4SDimitry Andric Versions.emplace_back(*NameOrErr); 5068480093f4SDimitry Andric } 50690b57cec5SDimitry Andric 50700b57cec5SDimitry Andric // readelf prints 4 entries per line. 5071480093f4SDimitry Andric uint64_t Entries = VerTable.size(); 50720b57cec5SDimitry Andric for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) { 50730b57cec5SDimitry Andric OS << " " << format_hex_no_prefix(VersymRow, 3) << ":"; 5074480093f4SDimitry Andric for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) { 5075480093f4SDimitry Andric unsigned Ndx = VerTable[VersymRow + I].vs_index; 5076480093f4SDimitry Andric OS << format("%4x%c", Ndx & VERSYM_VERSION, 5077480093f4SDimitry Andric Ndx & VERSYM_HIDDEN ? 'h' : ' '); 5078480093f4SDimitry Andric OS << left_justify("(" + std::string(Versions[VersymRow + I]) + ")", 13); 50790b57cec5SDimitry Andric } 50800b57cec5SDimitry Andric OS << '\n'; 50810b57cec5SDimitry Andric } 50820b57cec5SDimitry Andric OS << '\n'; 50830b57cec5SDimitry Andric } 50840b57cec5SDimitry Andric 50850b57cec5SDimitry Andric static std::string versionFlagToString(unsigned Flags) { 50860b57cec5SDimitry Andric if (Flags == 0) 50870b57cec5SDimitry Andric return "none"; 50880b57cec5SDimitry Andric 50890b57cec5SDimitry Andric std::string Ret; 50900b57cec5SDimitry Andric auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) { 50910b57cec5SDimitry Andric if (!(Flags & Flag)) 50920b57cec5SDimitry Andric return; 50930b57cec5SDimitry Andric if (!Ret.empty()) 50940b57cec5SDimitry Andric Ret += " | "; 50950b57cec5SDimitry Andric Ret += Name; 50960b57cec5SDimitry Andric Flags &= ~Flag; 50970b57cec5SDimitry Andric }; 50980b57cec5SDimitry Andric 50990b57cec5SDimitry Andric AddFlag(VER_FLG_BASE, "BASE"); 51000b57cec5SDimitry Andric AddFlag(VER_FLG_WEAK, "WEAK"); 51010b57cec5SDimitry Andric AddFlag(VER_FLG_INFO, "INFO"); 51020b57cec5SDimitry Andric AddFlag(~0, "<unknown>"); 51030b57cec5SDimitry Andric return Ret; 51040b57cec5SDimitry Andric } 51050b57cec5SDimitry Andric 51060b57cec5SDimitry Andric template <class ELFT> 5107e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) { 51080b57cec5SDimitry Andric if (!Sec) 51090b57cec5SDimitry Andric return; 51100b57cec5SDimitry Andric 5111e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info); 51120b57cec5SDimitry Andric 5113e8d8bef9SDimitry Andric Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec); 5114480093f4SDimitry Andric if (!V) { 5115480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 5116480093f4SDimitry Andric return; 51170b57cec5SDimitry Andric } 51180b57cec5SDimitry Andric 5119480093f4SDimitry Andric for (const VerDef &Def : *V) { 5120480093f4SDimitry Andric OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u Name: %s\n", 5121480093f4SDimitry Andric Def.Offset, Def.Version, 5122480093f4SDimitry Andric versionFlagToString(Def.Flags).c_str(), Def.Ndx, Def.Cnt, 5123480093f4SDimitry Andric Def.Name.data()); 5124480093f4SDimitry Andric unsigned I = 0; 5125480093f4SDimitry Andric for (const VerdAux &Aux : Def.AuxV) 5126480093f4SDimitry Andric OS << format(" 0x%04x: Parent %u: %s\n", Aux.Offset, ++I, 5127480093f4SDimitry Andric Aux.Name.data()); 51280b57cec5SDimitry Andric } 5129480093f4SDimitry Andric 51300b57cec5SDimitry Andric OS << '\n'; 51310b57cec5SDimitry Andric } 51320b57cec5SDimitry Andric 51330b57cec5SDimitry Andric template <class ELFT> 5134e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) { 51350b57cec5SDimitry Andric if (!Sec) 51360b57cec5SDimitry Andric return; 51370b57cec5SDimitry Andric 51380b57cec5SDimitry Andric unsigned VerneedNum = Sec->sh_info; 5139e8d8bef9SDimitry Andric printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum); 51400b57cec5SDimitry Andric 5141480093f4SDimitry Andric Expected<std::vector<VerNeed>> V = 5142e8d8bef9SDimitry Andric this->Obj.getVersionDependencies(*Sec, this->WarningHandler); 5143480093f4SDimitry Andric if (!V) { 5144480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 5145480093f4SDimitry Andric return; 51460b57cec5SDimitry Andric } 5147480093f4SDimitry Andric 5148480093f4SDimitry Andric for (const VerNeed &VN : *V) { 5149480093f4SDimitry Andric OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset, 5150480093f4SDimitry Andric VN.Version, VN.File.data(), VN.Cnt); 5151480093f4SDimitry Andric for (const VernAux &Aux : VN.AuxV) 5152480093f4SDimitry Andric OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset, 5153480093f4SDimitry Andric Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(), 5154480093f4SDimitry Andric Aux.Other); 51550b57cec5SDimitry Andric } 51560b57cec5SDimitry Andric OS << '\n'; 51570b57cec5SDimitry Andric } 51580b57cec5SDimitry Andric 51590b57cec5SDimitry Andric template <class ELFT> 516006c3fb27SDimitry Andric void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket, 516106c3fb27SDimitry Andric size_t MaxChain, 516206c3fb27SDimitry Andric size_t TotalSyms, 516306c3fb27SDimitry Andric ArrayRef<size_t> Count, 516406c3fb27SDimitry Andric bool IsGnu) const { 51650b57cec5SDimitry Andric size_t CumulativeNonZero = 0; 516606c3fb27SDimitry Andric OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "") 516706c3fb27SDimitry Andric << " bucket list length (total of " << NBucket << " buckets)\n" 51680b57cec5SDimitry Andric << " Length Number % of total Coverage\n"; 516906c3fb27SDimitry Andric for (size_t I = 0; I < MaxChain; ++I) { 51700b57cec5SDimitry Andric CumulativeNonZero += Count[I] * I; 51710b57cec5SDimitry Andric OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I], 51720b57cec5SDimitry Andric (Count[I] * 100.0) / NBucket, 51730b57cec5SDimitry Andric (CumulativeNonZero * 100.0) / TotalSyms); 51740b57cec5SDimitry Andric } 51750b57cec5SDimitry Andric } 51760b57cec5SDimitry Andric 5177e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() { 51780b57cec5SDimitry Andric OS << "GNUStyle::printCGProfile not implemented\n"; 51790b57cec5SDimitry Andric } 51800b57cec5SDimitry Andric 5181*0fca6ea1SDimitry Andric template <class ELFT> 5182*0fca6ea1SDimitry Andric void GNUELFDumper<ELFT>::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) { 5183fe6060f1SDimitry Andric OS << "GNUStyle::printBBAddrMaps not implemented\n"; 5184fe6060f1SDimitry Andric } 5185fe6060f1SDimitry Andric 5186e8d8bef9SDimitry Andric static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) { 5187e8d8bef9SDimitry Andric std::vector<uint64_t> Ret; 5188e8d8bef9SDimitry Andric const uint8_t *Cur = Data.begin(); 5189e8d8bef9SDimitry Andric const uint8_t *End = Data.end(); 5190e8d8bef9SDimitry Andric while (Cur != End) { 5191e8d8bef9SDimitry Andric unsigned Size; 51925f757f3fSDimitry Andric const char *Err = nullptr; 5193e8d8bef9SDimitry Andric Ret.push_back(decodeULEB128(Cur, &Size, End, &Err)); 5194e8d8bef9SDimitry Andric if (Err) 5195e8d8bef9SDimitry Andric return createError(Err); 5196e8d8bef9SDimitry Andric Cur += Size; 5197e8d8bef9SDimitry Andric } 5198e8d8bef9SDimitry Andric return Ret; 5199e8d8bef9SDimitry Andric } 5200e8d8bef9SDimitry Andric 52010b57cec5SDimitry Andric template <class ELFT> 5202e8d8bef9SDimitry Andric static Expected<std::vector<uint64_t>> 5203e8d8bef9SDimitry Andric decodeAddrsigSection(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) { 5204e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Sec); 5205e8d8bef9SDimitry Andric if (!ContentsOrErr) 5206e8d8bef9SDimitry Andric return ContentsOrErr.takeError(); 5207e8d8bef9SDimitry Andric 5208e8d8bef9SDimitry Andric if (Expected<std::vector<uint64_t>> SymsOrErr = 5209e8d8bef9SDimitry Andric toULEB128Array(*ContentsOrErr)) 5210e8d8bef9SDimitry Andric return *SymsOrErr; 5211e8d8bef9SDimitry Andric else 5212e8d8bef9SDimitry Andric return createError("unable to decode " + describe(Obj, Sec) + ": " + 5213e8d8bef9SDimitry Andric toString(SymsOrErr.takeError())); 52140b57cec5SDimitry Andric } 52150b57cec5SDimitry Andric 5216e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() { 5217e8d8bef9SDimitry Andric if (!this->DotAddrsigSec) 5218e8d8bef9SDimitry Andric return; 52190b57cec5SDimitry Andric 5220e8d8bef9SDimitry Andric Expected<std::vector<uint64_t>> SymsOrErr = 5221e8d8bef9SDimitry Andric decodeAddrsigSection(this->Obj, *this->DotAddrsigSec); 5222e8d8bef9SDimitry Andric if (!SymsOrErr) { 5223e8d8bef9SDimitry Andric this->reportUniqueWarning(SymsOrErr.takeError()); 5224e8d8bef9SDimitry Andric return; 52250b57cec5SDimitry Andric } 52260b57cec5SDimitry Andric 5227e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(*this->DotAddrsigSec); 5228e8d8bef9SDimitry Andric OS << "\nAddress-significant symbols section '" << Name << "'" 5229e8d8bef9SDimitry Andric << " contains " << SymsOrErr->size() << " entries:\n"; 5230e8d8bef9SDimitry Andric OS << " Num: Name\n"; 52318bcb0991SDimitry Andric 5232e8d8bef9SDimitry Andric Field Fields[2] = {0, 8}; 5233e8d8bef9SDimitry Andric size_t SymIndex = 0; 5234e8d8bef9SDimitry Andric for (uint64_t Sym : *SymsOrErr) { 5235e8d8bef9SDimitry Andric Fields[0].Str = to_string(format_decimal(++SymIndex, 6)) + ":"; 5236e8d8bef9SDimitry Andric Fields[1].Str = this->getStaticSymbolName(Sym); 5237e8d8bef9SDimitry Andric for (const Field &Entry : Fields) 5238e8d8bef9SDimitry Andric printField(Entry); 5239e8d8bef9SDimitry Andric OS << "\n"; 52408bcb0991SDimitry Andric } 52410b57cec5SDimitry Andric } 52420b57cec5SDimitry Andric 5243*0fca6ea1SDimitry Andric template <class ELFT> 5244*0fca6ea1SDimitry Andric static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize, 5245*0fca6ea1SDimitry Andric ArrayRef<uint8_t> Desc) { 5246*0fca6ea1SDimitry Andric OS << " AArch64 PAuth ABI core info: "; 5247*0fca6ea1SDimitry Andric // DataSize - size without padding, Desc.size() - size with padding 5248*0fca6ea1SDimitry Andric if (DataSize != 16) { 5249*0fca6ea1SDimitry Andric OS << format("<corrupted size: expected 16, got %d>", DataSize); 5250*0fca6ea1SDimitry Andric return false; 5251*0fca6ea1SDimitry Andric } 5252*0fca6ea1SDimitry Andric 5253*0fca6ea1SDimitry Andric uint64_t Platform = 5254*0fca6ea1SDimitry Andric support::endian::read64<ELFT::Endianness>(Desc.data() + 0); 5255*0fca6ea1SDimitry Andric uint64_t Version = support::endian::read64<ELFT::Endianness>(Desc.data() + 8); 5256*0fca6ea1SDimitry Andric 5257*0fca6ea1SDimitry Andric const char *PlatformDesc = [Platform]() { 5258*0fca6ea1SDimitry Andric switch (Platform) { 5259*0fca6ea1SDimitry Andric case AARCH64_PAUTH_PLATFORM_INVALID: 5260*0fca6ea1SDimitry Andric return "invalid"; 5261*0fca6ea1SDimitry Andric case AARCH64_PAUTH_PLATFORM_BAREMETAL: 5262*0fca6ea1SDimitry Andric return "baremetal"; 5263*0fca6ea1SDimitry Andric case AARCH64_PAUTH_PLATFORM_LLVM_LINUX: 5264*0fca6ea1SDimitry Andric return "llvm_linux"; 5265*0fca6ea1SDimitry Andric default: 5266*0fca6ea1SDimitry Andric return "unknown"; 5267*0fca6ea1SDimitry Andric } 5268*0fca6ea1SDimitry Andric }(); 5269*0fca6ea1SDimitry Andric 5270*0fca6ea1SDimitry Andric std::string VersionDesc = [Platform, Version]() -> std::string { 5271*0fca6ea1SDimitry Andric if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX) 5272*0fca6ea1SDimitry Andric return ""; 5273*0fca6ea1SDimitry Andric if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1))) 5274*0fca6ea1SDimitry Andric return "unknown"; 5275*0fca6ea1SDimitry Andric 5276*0fca6ea1SDimitry Andric std::array<StringRef, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1> 5277*0fca6ea1SDimitry Andric Flags; 5278*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS] = "Intrinsics"; 5279*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS] = "Calls"; 5280*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS] = "Returns"; 5281*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS] = "AuthTraps"; 5282*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR] = 5283*0fca6ea1SDimitry Andric "VTPtrAddressDiscrimination"; 5284*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] = 5285*0fca6ea1SDimitry Andric "VTPtrTypeDiscrimination"; 5286*0fca6ea1SDimitry Andric Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini"; 5287*0fca6ea1SDimitry Andric 5288*0fca6ea1SDimitry Andric static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI == 5289*0fca6ea1SDimitry Andric AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, 5290*0fca6ea1SDimitry Andric "Update when new enum items are defined"); 5291*0fca6ea1SDimitry Andric 5292*0fca6ea1SDimitry Andric std::string Desc; 5293*0fca6ea1SDimitry Andric for (uint32_t I = 0, End = Flags.size(); I < End; ++I) { 5294*0fca6ea1SDimitry Andric if (!(Version & (1ULL << I))) 5295*0fca6ea1SDimitry Andric Desc += '!'; 5296*0fca6ea1SDimitry Andric Desc += 5297*0fca6ea1SDimitry Andric Twine("PointerAuth" + Flags[I] + (I == End - 1 ? "" : ", ")).str(); 5298*0fca6ea1SDimitry Andric } 5299*0fca6ea1SDimitry Andric return Desc; 5300*0fca6ea1SDimitry Andric }(); 5301*0fca6ea1SDimitry Andric 5302*0fca6ea1SDimitry Andric OS << format("platform 0x%" PRIx64 " (%s), version 0x%" PRIx64, Platform, 5303*0fca6ea1SDimitry Andric PlatformDesc, Version); 5304*0fca6ea1SDimitry Andric if (!VersionDesc.empty()) 5305*0fca6ea1SDimitry Andric OS << format(" (%s)", VersionDesc.c_str()); 5306*0fca6ea1SDimitry Andric 5307*0fca6ea1SDimitry Andric return true; 5308*0fca6ea1SDimitry Andric } 5309*0fca6ea1SDimitry Andric 53100b57cec5SDimitry Andric template <typename ELFT> 53110b57cec5SDimitry Andric static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, 53120b57cec5SDimitry Andric ArrayRef<uint8_t> Data) { 53130b57cec5SDimitry Andric std::string str; 53140b57cec5SDimitry Andric raw_string_ostream OS(str); 53150b57cec5SDimitry Andric uint32_t PrData; 53160b57cec5SDimitry Andric auto DumpBit = [&](uint32_t Flag, StringRef Name) { 53170b57cec5SDimitry Andric if (PrData & Flag) { 53180b57cec5SDimitry Andric PrData &= ~Flag; 53190b57cec5SDimitry Andric OS << Name; 53200b57cec5SDimitry Andric if (PrData) 53210b57cec5SDimitry Andric OS << ", "; 53220b57cec5SDimitry Andric } 53230b57cec5SDimitry Andric }; 53240b57cec5SDimitry Andric 53250b57cec5SDimitry Andric switch (Type) { 53260b57cec5SDimitry Andric default: 53270b57cec5SDimitry Andric OS << format("<application-specific type 0x%x>", Type); 53280b57cec5SDimitry Andric return OS.str(); 53290b57cec5SDimitry Andric case GNU_PROPERTY_STACK_SIZE: { 53300b57cec5SDimitry Andric OS << "stack size: "; 53310b57cec5SDimitry Andric if (DataSize == sizeof(typename ELFT::uint)) 53320b57cec5SDimitry Andric OS << formatv("{0:x}", 53330b57cec5SDimitry Andric (uint64_t)(*(const typename ELFT::Addr *)Data.data())); 53340b57cec5SDimitry Andric else 53350b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 53360b57cec5SDimitry Andric return OS.str(); 53370b57cec5SDimitry Andric } 53380b57cec5SDimitry Andric case GNU_PROPERTY_NO_COPY_ON_PROTECTED: 53390b57cec5SDimitry Andric OS << "no copy on protected"; 53400b57cec5SDimitry Andric if (DataSize) 53410b57cec5SDimitry Andric OS << format(" <corrupt length: 0x%x>", DataSize); 53420b57cec5SDimitry Andric return OS.str(); 53430b57cec5SDimitry Andric case GNU_PROPERTY_AARCH64_FEATURE_1_AND: 53440b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_1_AND: 53450b57cec5SDimitry Andric OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: " 53460b57cec5SDimitry Andric : "x86 feature: "); 53470b57cec5SDimitry Andric if (DataSize != 4) { 53480b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 53490b57cec5SDimitry Andric return OS.str(); 53500b57cec5SDimitry Andric } 5351*0fca6ea1SDimitry Andric PrData = endian::read32<ELFT::Endianness>(Data.data()); 53520b57cec5SDimitry Andric if (PrData == 0) { 53530b57cec5SDimitry Andric OS << "<None>"; 53540b57cec5SDimitry Andric return OS.str(); 53550b57cec5SDimitry Andric } 53560b57cec5SDimitry Andric if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { 53570b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI"); 53580b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC"); 53595f757f3fSDimitry Andric DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS"); 53600b57cec5SDimitry Andric } else { 53610b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT"); 53620b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK"); 53630b57cec5SDimitry Andric } 53640b57cec5SDimitry Andric if (PrData) 53650b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 53660b57cec5SDimitry Andric return OS.str(); 5367*0fca6ea1SDimitry Andric case GNU_PROPERTY_AARCH64_FEATURE_PAUTH: 5368*0fca6ea1SDimitry Andric printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data); 5369*0fca6ea1SDimitry Andric return OS.str(); 53700b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_NEEDED: 53710b57cec5SDimitry Andric case GNU_PROPERTY_X86_FEATURE_2_USED: 53720b57cec5SDimitry Andric OS << "x86 feature " 53730b57cec5SDimitry Andric << (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: "); 53740b57cec5SDimitry Andric if (DataSize != 4) { 53750b57cec5SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 53760b57cec5SDimitry Andric return OS.str(); 53770b57cec5SDimitry Andric } 5378*0fca6ea1SDimitry Andric PrData = endian::read32<ELFT::Endianness>(Data.data()); 53790b57cec5SDimitry Andric if (PrData == 0) { 53800b57cec5SDimitry Andric OS << "<None>"; 53810b57cec5SDimitry Andric return OS.str(); 53820b57cec5SDimitry Andric } 53830b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86"); 53840b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87"); 53850b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX"); 53860b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM"); 53870b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM"); 53880b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM"); 53890b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR"); 53900b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE"); 53910b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT"); 53920b57cec5SDimitry Andric DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC"); 53930b57cec5SDimitry Andric if (PrData) 53940b57cec5SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 53950b57cec5SDimitry Andric return OS.str(); 5396fe6060f1SDimitry Andric case GNU_PROPERTY_X86_ISA_1_NEEDED: 5397fe6060f1SDimitry Andric case GNU_PROPERTY_X86_ISA_1_USED: 5398fe6060f1SDimitry Andric OS << "x86 ISA " 5399fe6060f1SDimitry Andric << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: "); 5400fe6060f1SDimitry Andric if (DataSize != 4) { 5401fe6060f1SDimitry Andric OS << format("<corrupt length: 0x%x>", DataSize); 5402fe6060f1SDimitry Andric return OS.str(); 5403fe6060f1SDimitry Andric } 5404*0fca6ea1SDimitry Andric PrData = endian::read32<ELFT::Endianness>(Data.data()); 5405fe6060f1SDimitry Andric if (PrData == 0) { 5406fe6060f1SDimitry Andric OS << "<None>"; 5407fe6060f1SDimitry Andric return OS.str(); 5408fe6060f1SDimitry Andric } 5409fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline"); 5410fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2"); 5411fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3"); 5412fe6060f1SDimitry Andric DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4"); 5413fe6060f1SDimitry Andric if (PrData) 5414fe6060f1SDimitry Andric OS << format("<unknown flags: 0x%x>", PrData); 5415fe6060f1SDimitry Andric return OS.str(); 54160b57cec5SDimitry Andric } 54170b57cec5SDimitry Andric } 54180b57cec5SDimitry Andric 54190b57cec5SDimitry Andric template <typename ELFT> 54200b57cec5SDimitry Andric static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) { 54210b57cec5SDimitry Andric using Elf_Word = typename ELFT::Word; 54220b57cec5SDimitry Andric 54230b57cec5SDimitry Andric SmallVector<std::string, 4> Properties; 54240b57cec5SDimitry Andric while (Arr.size() >= 8) { 54250b57cec5SDimitry Andric uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); 54260b57cec5SDimitry Andric uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); 54270b57cec5SDimitry Andric Arr = Arr.drop_front(8); 54280b57cec5SDimitry Andric 54290b57cec5SDimitry Andric // Take padding size into account if present. 54300b57cec5SDimitry Andric uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); 54310b57cec5SDimitry Andric std::string str; 54320b57cec5SDimitry Andric raw_string_ostream OS(str); 54330b57cec5SDimitry Andric if (Arr.size() < PaddedSize) { 54340b57cec5SDimitry Andric OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize); 54350b57cec5SDimitry Andric Properties.push_back(OS.str()); 54360b57cec5SDimitry Andric break; 54370b57cec5SDimitry Andric } 54380b57cec5SDimitry Andric Properties.push_back( 54390b57cec5SDimitry Andric getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize))); 54400b57cec5SDimitry Andric Arr = Arr.drop_front(PaddedSize); 54410b57cec5SDimitry Andric } 54420b57cec5SDimitry Andric 54430b57cec5SDimitry Andric if (!Arr.empty()) 54440b57cec5SDimitry Andric Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>"); 54450b57cec5SDimitry Andric 54460b57cec5SDimitry Andric return Properties; 54470b57cec5SDimitry Andric } 54480b57cec5SDimitry Andric 54490b57cec5SDimitry Andric struct GNUAbiTag { 54500b57cec5SDimitry Andric std::string OSName; 54510b57cec5SDimitry Andric std::string ABI; 54520b57cec5SDimitry Andric bool IsValid; 54530b57cec5SDimitry Andric }; 54540b57cec5SDimitry Andric 54550b57cec5SDimitry Andric template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) { 54560b57cec5SDimitry Andric typedef typename ELFT::Word Elf_Word; 54570b57cec5SDimitry Andric 54580b57cec5SDimitry Andric ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()), 54590b57cec5SDimitry Andric reinterpret_cast<const Elf_Word *>(Desc.end())); 54600b57cec5SDimitry Andric 54610b57cec5SDimitry Andric if (Words.size() < 4) 54620b57cec5SDimitry Andric return {"", "", /*IsValid=*/false}; 54630b57cec5SDimitry Andric 54640b57cec5SDimitry Andric static const char *OSNames[] = { 54650b57cec5SDimitry Andric "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", 54660b57cec5SDimitry Andric }; 54670b57cec5SDimitry Andric StringRef OSName = "Unknown"; 5468bdd1243dSDimitry Andric if (Words[0] < std::size(OSNames)) 54690b57cec5SDimitry Andric OSName = OSNames[Words[0]]; 54700b57cec5SDimitry Andric uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; 54710b57cec5SDimitry Andric std::string str; 54720b57cec5SDimitry Andric raw_string_ostream ABI(str); 54730b57cec5SDimitry Andric ABI << Major << "." << Minor << "." << Patch; 54745ffd83dbSDimitry Andric return {std::string(OSName), ABI.str(), /*IsValid=*/true}; 54750b57cec5SDimitry Andric } 54760b57cec5SDimitry Andric 54770b57cec5SDimitry Andric static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) { 54780b57cec5SDimitry Andric std::string str; 54790b57cec5SDimitry Andric raw_string_ostream OS(str); 5480e8d8bef9SDimitry Andric for (uint8_t B : Desc) 54810b57cec5SDimitry Andric OS << format_hex_no_prefix(B, 2); 54820b57cec5SDimitry Andric return OS.str(); 54830b57cec5SDimitry Andric } 54840b57cec5SDimitry Andric 5485349cc55cSDimitry Andric static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) { 54860b57cec5SDimitry Andric return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 54870b57cec5SDimitry Andric } 54880b57cec5SDimitry Andric 54890b57cec5SDimitry Andric template <typename ELFT> 5490fe6060f1SDimitry Andric static bool printGNUNote(raw_ostream &OS, uint32_t NoteType, 54910b57cec5SDimitry Andric ArrayRef<uint8_t> Desc) { 5492fe6060f1SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 54930b57cec5SDimitry Andric switch (NoteType) { 54940b57cec5SDimitry Andric default: 5495fe6060f1SDimitry Andric return false; 54960b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 54970b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 54980b57cec5SDimitry Andric if (!AbiTag.IsValid) 54990b57cec5SDimitry Andric OS << " <corrupt GNU_ABI_TAG>"; 55000b57cec5SDimitry Andric else 55010b57cec5SDimitry Andric OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI; 55020b57cec5SDimitry Andric break; 55030b57cec5SDimitry Andric } 55040b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 55050b57cec5SDimitry Andric OS << " Build ID: " << getGNUBuildId(Desc); 55060b57cec5SDimitry Andric break; 55070b57cec5SDimitry Andric } 55080b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 5509349cc55cSDimitry Andric OS << " Version: " << getDescAsStringRef(Desc); 55100b57cec5SDimitry Andric break; 55110b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 55120b57cec5SDimitry Andric OS << " Properties:"; 5513e8d8bef9SDimitry Andric for (const std::string &Property : getGNUPropertyList<ELFT>(Desc)) 55140b57cec5SDimitry Andric OS << " " << Property << "\n"; 55150b57cec5SDimitry Andric break; 55160b57cec5SDimitry Andric } 55170b57cec5SDimitry Andric OS << '\n'; 5518fe6060f1SDimitry Andric return true; 5519fe6060f1SDimitry Andric } 5520fe6060f1SDimitry Andric 552181ad6265SDimitry Andric using AndroidNoteProperties = std::vector<std::pair<StringRef, std::string>>; 552281ad6265SDimitry Andric static AndroidNoteProperties getAndroidNoteProperties(uint32_t NoteType, 552381ad6265SDimitry Andric ArrayRef<uint8_t> Desc) { 552481ad6265SDimitry Andric AndroidNoteProperties Props; 552581ad6265SDimitry Andric switch (NoteType) { 552681ad6265SDimitry Andric case ELF::NT_ANDROID_TYPE_MEMTAG: 552781ad6265SDimitry Andric if (Desc.empty()) { 552881ad6265SDimitry Andric Props.emplace_back("Invalid .note.android.memtag", ""); 552981ad6265SDimitry Andric return Props; 553081ad6265SDimitry Andric } 553181ad6265SDimitry Andric 553281ad6265SDimitry Andric switch (Desc[0] & NT_MEMTAG_LEVEL_MASK) { 553381ad6265SDimitry Andric case NT_MEMTAG_LEVEL_NONE: 553481ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "NONE"); 553581ad6265SDimitry Andric break; 553681ad6265SDimitry Andric case NT_MEMTAG_LEVEL_ASYNC: 553781ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "ASYNC"); 553881ad6265SDimitry Andric break; 553981ad6265SDimitry Andric case NT_MEMTAG_LEVEL_SYNC: 554081ad6265SDimitry Andric Props.emplace_back("Tagging Mode", "SYNC"); 554181ad6265SDimitry Andric break; 554281ad6265SDimitry Andric default: 554381ad6265SDimitry Andric Props.emplace_back( 554481ad6265SDimitry Andric "Tagging Mode", 554581ad6265SDimitry Andric ("Unknown (" + Twine::utohexstr(Desc[0] & NT_MEMTAG_LEVEL_MASK) + ")") 554681ad6265SDimitry Andric .str()); 554781ad6265SDimitry Andric break; 554881ad6265SDimitry Andric } 554981ad6265SDimitry Andric Props.emplace_back("Heap", 555081ad6265SDimitry Andric (Desc[0] & NT_MEMTAG_HEAP) ? "Enabled" : "Disabled"); 555181ad6265SDimitry Andric Props.emplace_back("Stack", 555281ad6265SDimitry Andric (Desc[0] & NT_MEMTAG_STACK) ? "Enabled" : "Disabled"); 555381ad6265SDimitry Andric break; 555481ad6265SDimitry Andric default: 555581ad6265SDimitry Andric return Props; 555681ad6265SDimitry Andric } 555781ad6265SDimitry Andric return Props; 555881ad6265SDimitry Andric } 555981ad6265SDimitry Andric 556081ad6265SDimitry Andric static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType, 556181ad6265SDimitry Andric ArrayRef<uint8_t> Desc) { 556281ad6265SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 556381ad6265SDimitry Andric AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc); 556481ad6265SDimitry Andric if (Props.empty()) 556581ad6265SDimitry Andric return false; 556681ad6265SDimitry Andric for (const auto &KV : Props) 556781ad6265SDimitry Andric OS << " " << KV.first << ": " << KV.second << '\n'; 556881ad6265SDimitry Andric return true; 556981ad6265SDimitry Andric } 557081ad6265SDimitry Andric 557106c3fb27SDimitry Andric template <class ELFT> 557206c3fb27SDimitry Andric void GNUELFDumper<ELFT>::printMemtag( 557306c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 557406c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 557506c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) { 557606c3fb27SDimitry Andric OS << "Memtag Dynamic Entries:\n"; 557706c3fb27SDimitry Andric if (DynamicEntries.empty()) 557806c3fb27SDimitry Andric OS << " < none found >\n"; 557906c3fb27SDimitry Andric for (const auto &DynamicEntryKV : DynamicEntries) 558006c3fb27SDimitry Andric OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second 558106c3fb27SDimitry Andric << "\n"; 558206c3fb27SDimitry Andric 558306c3fb27SDimitry Andric if (!AndroidNoteDesc.empty()) { 558406c3fb27SDimitry Andric OS << "Memtag Android Note:\n"; 558506c3fb27SDimitry Andric printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc); 558606c3fb27SDimitry Andric } 558706c3fb27SDimitry Andric 558806c3fb27SDimitry Andric if (Descriptors.empty()) 558906c3fb27SDimitry Andric return; 559006c3fb27SDimitry Andric 559106c3fb27SDimitry Andric OS << "Memtag Global Descriptors:\n"; 559206c3fb27SDimitry Andric for (const auto &[Addr, BytesToTag] : Descriptors) { 559306c3fb27SDimitry Andric OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x" 559406c3fb27SDimitry Andric << utohexstr(BytesToTag, /*LowerCase=*/true) << "\n"; 559506c3fb27SDimitry Andric } 559606c3fb27SDimitry Andric } 559706c3fb27SDimitry Andric 5598349cc55cSDimitry Andric template <typename ELFT> 5599349cc55cSDimitry Andric static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType, 5600349cc55cSDimitry Andric ArrayRef<uint8_t> Desc) { 5601349cc55cSDimitry Andric switch (NoteType) { 5602349cc55cSDimitry Andric default: 5603349cc55cSDimitry Andric return false; 5604349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION: 5605349cc55cSDimitry Andric OS << " Version: " << getDescAsStringRef(Desc); 5606349cc55cSDimitry Andric break; 5607349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER: 5608349cc55cSDimitry Andric OS << " Producer: " << getDescAsStringRef(Desc); 5609349cc55cSDimitry Andric break; 5610349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION: 5611349cc55cSDimitry Andric OS << " Producer version: " << getDescAsStringRef(Desc); 5612349cc55cSDimitry Andric break; 5613349cc55cSDimitry Andric } 5614349cc55cSDimitry Andric OS << '\n'; 5615349cc55cSDimitry Andric return true; 5616349cc55cSDimitry Andric } 5617349cc55cSDimitry Andric 5618349cc55cSDimitry Andric const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = { 5619fe6060f1SDimitry Andric {"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE}, 5620fe6060f1SDimitry Andric {"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE}, 5621fe6060f1SDimitry Andric {"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE}, 5622fe6060f1SDimitry Andric {"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED}, 5623fe6060f1SDimitry Andric {"LA48", NT_FREEBSD_FCTL_LA48}, 5624fe6060f1SDimitry Andric {"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE}, 5625fe6060f1SDimitry Andric }; 5626fe6060f1SDimitry Andric 5627fe6060f1SDimitry Andric struct FreeBSDNote { 5628fe6060f1SDimitry Andric std::string Type; 5629fe6060f1SDimitry Andric std::string Value; 5630fe6060f1SDimitry Andric }; 5631fe6060f1SDimitry Andric 5632fe6060f1SDimitry Andric template <typename ELFT> 5633bdd1243dSDimitry Andric static std::optional<FreeBSDNote> 5634fe6060f1SDimitry Andric getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) { 5635fe6060f1SDimitry Andric if (IsCore) 5636bdd1243dSDimitry Andric return std::nullopt; // No pretty-printing yet. 5637fe6060f1SDimitry Andric switch (NoteType) { 5638fe6060f1SDimitry Andric case ELF::NT_FREEBSD_ABI_TAG: 5639fe6060f1SDimitry Andric if (Desc.size() != 4) 5640bdd1243dSDimitry Andric return std::nullopt; 5641*0fca6ea1SDimitry Andric return FreeBSDNote{"ABI tag", 5642*0fca6ea1SDimitry Andric utostr(endian::read32<ELFT::Endianness>(Desc.data()))}; 5643fe6060f1SDimitry Andric case ELF::NT_FREEBSD_ARCH_TAG: 5644fe6060f1SDimitry Andric return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; 5645fe6060f1SDimitry Andric case ELF::NT_FREEBSD_FEATURE_CTL: { 5646fe6060f1SDimitry Andric if (Desc.size() != 4) 5647bdd1243dSDimitry Andric return std::nullopt; 5648*0fca6ea1SDimitry Andric unsigned Value = endian::read32<ELFT::Endianness>(Desc.data()); 5649fe6060f1SDimitry Andric std::string FlagsStr; 5650fe6060f1SDimitry Andric raw_string_ostream OS(FlagsStr); 5651bdd1243dSDimitry Andric printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS); 5652fe6060f1SDimitry Andric if (OS.str().empty()) 5653fe6060f1SDimitry Andric OS << "0x" << utohexstr(Value); 5654fe6060f1SDimitry Andric else 5655fe6060f1SDimitry Andric OS << "(0x" << utohexstr(Value) << ")"; 5656fe6060f1SDimitry Andric return FreeBSDNote{"Feature flags", OS.str()}; 5657fe6060f1SDimitry Andric } 5658fe6060f1SDimitry Andric default: 5659bdd1243dSDimitry Andric return std::nullopt; 5660fe6060f1SDimitry Andric } 56610b57cec5SDimitry Andric } 56620b57cec5SDimitry Andric 56630b57cec5SDimitry Andric struct AMDNote { 56640b57cec5SDimitry Andric std::string Type; 56650b57cec5SDimitry Andric std::string Value; 56660b57cec5SDimitry Andric }; 56670b57cec5SDimitry Andric 56680b57cec5SDimitry Andric template <typename ELFT> 56690b57cec5SDimitry Andric static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 56700b57cec5SDimitry Andric switch (NoteType) { 56710b57cec5SDimitry Andric default: 56720b57cec5SDimitry Andric return {"", ""}; 5673fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: { 5674fe6060f1SDimitry Andric struct CodeObjectVersion { 56755f757f3fSDimitry Andric support::aligned_ulittle32_t MajorVersion; 56765f757f3fSDimitry Andric support::aligned_ulittle32_t MinorVersion; 5677fe6060f1SDimitry Andric }; 5678fe6060f1SDimitry Andric if (Desc.size() != sizeof(CodeObjectVersion)) 5679fe6060f1SDimitry Andric return {"AMD HSA Code Object Version", 5680fe6060f1SDimitry Andric "Invalid AMD HSA Code Object Version"}; 5681fe6060f1SDimitry Andric std::string VersionString; 5682fe6060f1SDimitry Andric raw_string_ostream StrOS(VersionString); 5683fe6060f1SDimitry Andric auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data()); 5684fe6060f1SDimitry Andric StrOS << "[Major: " << Version->MajorVersion 5685fe6060f1SDimitry Andric << ", Minor: " << Version->MinorVersion << "]"; 5686fe6060f1SDimitry Andric return {"AMD HSA Code Object Version", VersionString}; 5687fe6060f1SDimitry Andric } 5688fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_HSAIL: { 5689fe6060f1SDimitry Andric struct HSAILProperties { 56905f757f3fSDimitry Andric support::aligned_ulittle32_t HSAILMajorVersion; 56915f757f3fSDimitry Andric support::aligned_ulittle32_t HSAILMinorVersion; 5692fe6060f1SDimitry Andric uint8_t Profile; 5693fe6060f1SDimitry Andric uint8_t MachineModel; 5694fe6060f1SDimitry Andric uint8_t DefaultFloatRound; 5695fe6060f1SDimitry Andric }; 5696fe6060f1SDimitry Andric if (Desc.size() != sizeof(HSAILProperties)) 5697fe6060f1SDimitry Andric return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"}; 5698fe6060f1SDimitry Andric auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data()); 5699fe6060f1SDimitry Andric std::string HSAILPropetiesString; 5700fe6060f1SDimitry Andric raw_string_ostream StrOS(HSAILPropetiesString); 5701fe6060f1SDimitry Andric StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion 5702fe6060f1SDimitry Andric << ", HSAIL Minor: " << Properties->HSAILMinorVersion 5703fe6060f1SDimitry Andric << ", Profile: " << uint32_t(Properties->Profile) 5704fe6060f1SDimitry Andric << ", Machine Model: " << uint32_t(Properties->MachineModel) 5705fe6060f1SDimitry Andric << ", Default Float Round: " 5706fe6060f1SDimitry Andric << uint32_t(Properties->DefaultFloatRound) << "]"; 5707fe6060f1SDimitry Andric return {"AMD HSA HSAIL Properties", HSAILPropetiesString}; 5708fe6060f1SDimitry Andric } 5709fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_ISA_VERSION: { 5710fe6060f1SDimitry Andric struct IsaVersion { 57115f757f3fSDimitry Andric support::aligned_ulittle16_t VendorNameSize; 57125f757f3fSDimitry Andric support::aligned_ulittle16_t ArchitectureNameSize; 57135f757f3fSDimitry Andric support::aligned_ulittle32_t Major; 57145f757f3fSDimitry Andric support::aligned_ulittle32_t Minor; 57155f757f3fSDimitry Andric support::aligned_ulittle32_t Stepping; 5716fe6060f1SDimitry Andric }; 5717fe6060f1SDimitry Andric if (Desc.size() < sizeof(IsaVersion)) 5718fe6060f1SDimitry Andric return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"}; 5719fe6060f1SDimitry Andric auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data()); 5720fe6060f1SDimitry Andric if (Desc.size() < sizeof(IsaVersion) + 5721fe6060f1SDimitry Andric Isa->VendorNameSize + Isa->ArchitectureNameSize || 5722fe6060f1SDimitry Andric Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0) 5723fe6060f1SDimitry Andric return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"}; 5724fe6060f1SDimitry Andric std::string IsaString; 5725fe6060f1SDimitry Andric raw_string_ostream StrOS(IsaString); 5726fe6060f1SDimitry Andric StrOS << "[Vendor: " 5727fe6060f1SDimitry Andric << StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1) 5728fe6060f1SDimitry Andric << ", Architecture: " 5729fe6060f1SDimitry Andric << StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize, 5730fe6060f1SDimitry Andric Isa->ArchitectureNameSize - 1) 5731fe6060f1SDimitry Andric << ", Major: " << Isa->Major << ", Minor: " << Isa->Minor 5732fe6060f1SDimitry Andric << ", Stepping: " << Isa->Stepping << "]"; 5733fe6060f1SDimitry Andric return {"AMD HSA ISA Version", IsaString}; 5734fe6060f1SDimitry Andric } 5735fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_METADATA: { 5736fe6060f1SDimitry Andric if (Desc.size() == 0) 5737fe6060f1SDimitry Andric return {"AMD HSA Metadata", ""}; 57380b57cec5SDimitry Andric return { 5739fe6060f1SDimitry Andric "AMD HSA Metadata", 5740fe6060f1SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)}; 5741fe6060f1SDimitry Andric } 5742fe6060f1SDimitry Andric case ELF::NT_AMD_HSA_ISA_NAME: { 5743fe6060f1SDimitry Andric if (Desc.size() == 0) 5744fe6060f1SDimitry Andric return {"AMD HSA ISA Name", ""}; 57450b57cec5SDimitry Andric return { 5746fe6060f1SDimitry Andric "AMD HSA ISA Name", 57470b57cec5SDimitry Andric std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())}; 57480b57cec5SDimitry Andric } 5749fe6060f1SDimitry Andric case ELF::NT_AMD_PAL_METADATA: { 5750fe6060f1SDimitry Andric struct PALMetadata { 57515f757f3fSDimitry Andric support::aligned_ulittle32_t Key; 57525f757f3fSDimitry Andric support::aligned_ulittle32_t Value; 5753fe6060f1SDimitry Andric }; 5754fe6060f1SDimitry Andric if (Desc.size() % sizeof(PALMetadata) != 0) 5755fe6060f1SDimitry Andric return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"}; 5756fe6060f1SDimitry Andric auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data()); 5757fe6060f1SDimitry Andric std::string MetadataString; 5758fe6060f1SDimitry Andric raw_string_ostream StrOS(MetadataString); 5759fe6060f1SDimitry Andric for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) { 5760fe6060f1SDimitry Andric StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]"; 5761fe6060f1SDimitry Andric } 5762fe6060f1SDimitry Andric return {"AMD PAL Metadata", MetadataString}; 5763fe6060f1SDimitry Andric } 5764fe6060f1SDimitry Andric } 57650b57cec5SDimitry Andric } 57660b57cec5SDimitry Andric 57670b57cec5SDimitry Andric struct AMDGPUNote { 57680b57cec5SDimitry Andric std::string Type; 57690b57cec5SDimitry Andric std::string Value; 57700b57cec5SDimitry Andric }; 57710b57cec5SDimitry Andric 57720b57cec5SDimitry Andric template <typename ELFT> 57730b57cec5SDimitry Andric static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) { 57740b57cec5SDimitry Andric switch (NoteType) { 57750b57cec5SDimitry Andric default: 57760b57cec5SDimitry Andric return {"", ""}; 57770b57cec5SDimitry Andric case ELF::NT_AMDGPU_METADATA: { 5778e8d8bef9SDimitry Andric StringRef MsgPackString = 57790b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size()); 57800b57cec5SDimitry Andric msgpack::Document MsgPackDoc; 57810b57cec5SDimitry Andric if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false)) 5782fe6060f1SDimitry Andric return {"", ""}; 57830b57cec5SDimitry Andric 5784fe6060f1SDimitry Andric std::string MetadataString; 578506c3fb27SDimitry Andric 578606c3fb27SDimitry Andric // FIXME: Metadata Verifier only works with AMDHSA. 578706c3fb27SDimitry Andric // This is an ugly workaround to avoid the verifier for other MD 578806c3fb27SDimitry Andric // formats (e.g. amdpal) 57895f757f3fSDimitry Andric if (MsgPackString.contains("amdhsa.")) { 579006c3fb27SDimitry Andric AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true); 5791e8d8bef9SDimitry Andric if (!Verifier.verify(MsgPackDoc.getRoot())) 5792fe6060f1SDimitry Andric MetadataString = "Invalid AMDGPU Metadata\n"; 579306c3fb27SDimitry Andric } 5794e8d8bef9SDimitry Andric 5795fe6060f1SDimitry Andric raw_string_ostream StrOS(MetadataString); 5796fe6060f1SDimitry Andric if (MsgPackDoc.getRoot().isScalar()) { 5797fe6060f1SDimitry Andric // TODO: passing a scalar root to toYAML() asserts: 5798fe6060f1SDimitry Andric // (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && 5799fe6060f1SDimitry Andric // "plain scalar documents are not supported") 5800fe6060f1SDimitry Andric // To avoid this crash we print the raw data instead. 5801fe6060f1SDimitry Andric return {"", ""}; 5802fe6060f1SDimitry Andric } 58030b57cec5SDimitry Andric MsgPackDoc.toYAML(StrOS); 58040b57cec5SDimitry Andric return {"AMDGPU Metadata", StrOS.str()}; 58050b57cec5SDimitry Andric } 58060b57cec5SDimitry Andric } 58070b57cec5SDimitry Andric } 58080b57cec5SDimitry Andric 58098bcb0991SDimitry Andric struct CoreFileMapping { 58108bcb0991SDimitry Andric uint64_t Start, End, Offset; 58118bcb0991SDimitry Andric StringRef Filename; 58128bcb0991SDimitry Andric }; 58138bcb0991SDimitry Andric 58148bcb0991SDimitry Andric struct CoreNote { 58158bcb0991SDimitry Andric uint64_t PageSize; 58168bcb0991SDimitry Andric std::vector<CoreFileMapping> Mappings; 58178bcb0991SDimitry Andric }; 58188bcb0991SDimitry Andric 58198bcb0991SDimitry Andric static Expected<CoreNote> readCoreNote(DataExtractor Desc) { 58208bcb0991SDimitry Andric // Expected format of the NT_FILE note description: 58218bcb0991SDimitry Andric // 1. # of file mappings (call it N) 58228bcb0991SDimitry Andric // 2. Page size 58238bcb0991SDimitry Andric // 3. N (start, end, offset) triples 58248bcb0991SDimitry Andric // 4. N packed filenames (null delimited) 58258bcb0991SDimitry Andric // Each field is an Elf_Addr, except for filenames which are char* strings. 58268bcb0991SDimitry Andric 58278bcb0991SDimitry Andric CoreNote Ret; 58288bcb0991SDimitry Andric const int Bytes = Desc.getAddressSize(); 58298bcb0991SDimitry Andric 58308bcb0991SDimitry Andric if (!Desc.isValidOffsetForAddress(2)) 5831e8d8bef9SDimitry Andric return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) + 5832e8d8bef9SDimitry Andric " is too short, expected at least 0x" + 5833e8d8bef9SDimitry Andric Twine::utohexstr(Bytes * 2)); 58348bcb0991SDimitry Andric if (Desc.getData().back() != 0) 5835e8d8bef9SDimitry Andric return createError("the note is not NUL terminated"); 58368bcb0991SDimitry Andric 58378bcb0991SDimitry Andric uint64_t DescOffset = 0; 58388bcb0991SDimitry Andric uint64_t FileCount = Desc.getAddress(&DescOffset); 58398bcb0991SDimitry Andric Ret.PageSize = Desc.getAddress(&DescOffset); 58408bcb0991SDimitry Andric 58418bcb0991SDimitry Andric if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes)) 5842e8d8bef9SDimitry Andric return createError("unable to read file mappings (found " + 5843e8d8bef9SDimitry Andric Twine(FileCount) + "): the note of size 0x" + 5844e8d8bef9SDimitry Andric Twine::utohexstr(Desc.size()) + " is too short"); 58458bcb0991SDimitry Andric 58468bcb0991SDimitry Andric uint64_t FilenamesOffset = 0; 58478bcb0991SDimitry Andric DataExtractor Filenames( 58488bcb0991SDimitry Andric Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes), 58498bcb0991SDimitry Andric Desc.isLittleEndian(), Desc.getAddressSize()); 58508bcb0991SDimitry Andric 58518bcb0991SDimitry Andric Ret.Mappings.resize(FileCount); 5852e8d8bef9SDimitry Andric size_t I = 0; 58538bcb0991SDimitry Andric for (CoreFileMapping &Mapping : Ret.Mappings) { 5854e8d8bef9SDimitry Andric ++I; 58558bcb0991SDimitry Andric if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1)) 5856e8d8bef9SDimitry Andric return createError( 5857e8d8bef9SDimitry Andric "unable to read the file name for the mapping with index " + 5858e8d8bef9SDimitry Andric Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) + 5859e8d8bef9SDimitry Andric " is truncated"); 58608bcb0991SDimitry Andric Mapping.Start = Desc.getAddress(&DescOffset); 58618bcb0991SDimitry Andric Mapping.End = Desc.getAddress(&DescOffset); 58628bcb0991SDimitry Andric Mapping.Offset = Desc.getAddress(&DescOffset); 58638bcb0991SDimitry Andric Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset); 58648bcb0991SDimitry Andric } 58658bcb0991SDimitry Andric 58668bcb0991SDimitry Andric return Ret; 58678bcb0991SDimitry Andric } 58688bcb0991SDimitry Andric 58698bcb0991SDimitry Andric template <typename ELFT> 58708bcb0991SDimitry Andric static void printCoreNote(raw_ostream &OS, const CoreNote &Note) { 58718bcb0991SDimitry Andric // Length of "0x<address>" string. 58728bcb0991SDimitry Andric const int FieldWidth = ELFT::Is64Bits ? 18 : 10; 58738bcb0991SDimitry Andric 58748bcb0991SDimitry Andric OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n'; 58758bcb0991SDimitry Andric OS << " " << right_justify("Start", FieldWidth) << " " 58768bcb0991SDimitry Andric << right_justify("End", FieldWidth) << " " 58778bcb0991SDimitry Andric << right_justify("Page Offset", FieldWidth) << '\n'; 58788bcb0991SDimitry Andric for (const CoreFileMapping &Mapping : Note.Mappings) { 58798bcb0991SDimitry Andric OS << " " << format_hex(Mapping.Start, FieldWidth) << " " 58808bcb0991SDimitry Andric << format_hex(Mapping.End, FieldWidth) << " " 58818bcb0991SDimitry Andric << format_hex(Mapping.Offset, FieldWidth) << "\n " 58828bcb0991SDimitry Andric << Mapping.Filename << '\n'; 58838bcb0991SDimitry Andric } 58848bcb0991SDimitry Andric } 58858bcb0991SDimitry Andric 5886349cc55cSDimitry Andric const NoteType GenericNoteTypes[] = { 5887e8d8bef9SDimitry Andric {ELF::NT_VERSION, "NT_VERSION (version)"}, 5888e8d8bef9SDimitry Andric {ELF::NT_ARCH, "NT_ARCH (architecture)"}, 5889e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"}, 5890e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"}, 5891e8d8bef9SDimitry Andric }; 5892e8d8bef9SDimitry Andric 5893349cc55cSDimitry Andric const NoteType GNUNoteTypes[] = { 5894e8d8bef9SDimitry Andric {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, 5895e8d8bef9SDimitry Andric {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, 5896e8d8bef9SDimitry Andric {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, 5897e8d8bef9SDimitry Andric {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, 5898e8d8bef9SDimitry Andric {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, 5899e8d8bef9SDimitry Andric }; 5900e8d8bef9SDimitry Andric 5901349cc55cSDimitry Andric const NoteType FreeBSDCoreNoteTypes[] = { 5902e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, 5903e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, 5904e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, 5905e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, 5906e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, 5907e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, 5908e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, 5909e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, 5910e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, 5911e8d8bef9SDimitry Andric "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, 5912e8d8bef9SDimitry Andric {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, 5913e8d8bef9SDimitry Andric }; 5914e8d8bef9SDimitry Andric 5915349cc55cSDimitry Andric const NoteType FreeBSDNoteTypes[] = { 5916fe6060f1SDimitry Andric {ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"}, 5917fe6060f1SDimitry Andric {ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"}, 5918fe6060f1SDimitry Andric {ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"}, 5919fe6060f1SDimitry Andric {ELF::NT_FREEBSD_FEATURE_CTL, 5920fe6060f1SDimitry Andric "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"}, 5921fe6060f1SDimitry Andric }; 5922fe6060f1SDimitry Andric 59234824e7fdSDimitry Andric const NoteType NetBSDCoreNoteTypes[] = { 59244824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_PROCINFO, 59254824e7fdSDimitry Andric "NT_NETBSDCORE_PROCINFO (procinfo structure)"}, 59264824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"}, 59274824e7fdSDimitry Andric {ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"}, 59284824e7fdSDimitry Andric }; 59294824e7fdSDimitry Andric 5930349cc55cSDimitry Andric const NoteType OpenBSDCoreNoteTypes[] = { 5931349cc55cSDimitry Andric {ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"}, 5932349cc55cSDimitry Andric {ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"}, 5933349cc55cSDimitry Andric {ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"}, 5934349cc55cSDimitry Andric {ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"}, 5935349cc55cSDimitry Andric {ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"}, 5936349cc55cSDimitry Andric }; 5937349cc55cSDimitry Andric 5938349cc55cSDimitry Andric const NoteType AMDNoteTypes[] = { 5939fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_CODE_OBJECT_VERSION, 5940fe6060f1SDimitry Andric "NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"}, 5941fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"}, 5942fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"}, 5943fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"}, 5944fe6060f1SDimitry Andric {ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"}, 5945fe6060f1SDimitry Andric {ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"}, 5946e8d8bef9SDimitry Andric }; 5947e8d8bef9SDimitry Andric 5948349cc55cSDimitry Andric const NoteType AMDGPUNoteTypes[] = { 5949e8d8bef9SDimitry Andric {ELF::NT_AMDGPU_METADATA, "NT_AMDGPU_METADATA (AMDGPU Metadata)"}, 5950e8d8bef9SDimitry Andric }; 5951e8d8bef9SDimitry Andric 5952349cc55cSDimitry Andric const NoteType LLVMOMPOFFLOADNoteTypes[] = { 5953349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION, 5954349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_VERSION (image format version)"}, 5955349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER, 5956349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_PRODUCER (producing toolchain)"}, 5957349cc55cSDimitry Andric {ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION, 5958349cc55cSDimitry Andric "NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION (producing toolchain version)"}, 5959349cc55cSDimitry Andric }; 5960349cc55cSDimitry Andric 596181ad6265SDimitry Andric const NoteType AndroidNoteTypes[] = { 596281ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_IDENT, "NT_ANDROID_TYPE_IDENT"}, 596381ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_KUSER, "NT_ANDROID_TYPE_KUSER"}, 596481ad6265SDimitry Andric {ELF::NT_ANDROID_TYPE_MEMTAG, 596581ad6265SDimitry Andric "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"}, 596681ad6265SDimitry Andric }; 596781ad6265SDimitry Andric 5968349cc55cSDimitry Andric const NoteType CoreNoteTypes[] = { 5969e8d8bef9SDimitry Andric {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"}, 5970e8d8bef9SDimitry Andric {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"}, 5971e8d8bef9SDimitry Andric {ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"}, 5972e8d8bef9SDimitry Andric {ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"}, 5973e8d8bef9SDimitry Andric {ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"}, 5974e8d8bef9SDimitry Andric {ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"}, 5975e8d8bef9SDimitry Andric {ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"}, 5976e8d8bef9SDimitry Andric {ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"}, 5977e8d8bef9SDimitry Andric {ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"}, 5978e8d8bef9SDimitry Andric {ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"}, 5979e8d8bef9SDimitry Andric {ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"}, 5980e8d8bef9SDimitry Andric 5981e8d8bef9SDimitry Andric {ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"}, 5982e8d8bef9SDimitry Andric {ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"}, 5983e8d8bef9SDimitry Andric {ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"}, 5984e8d8bef9SDimitry Andric {ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"}, 5985e8d8bef9SDimitry Andric {ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"}, 5986e8d8bef9SDimitry Andric {ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"}, 5987e8d8bef9SDimitry Andric {ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"}, 5988e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"}, 5989e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CFPR, 5990e8d8bef9SDimitry Andric "NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"}, 5991e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CVMX, 5992e8d8bef9SDimitry Andric "NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"}, 5993e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"}, 5994e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"}, 5995e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"}, 5996e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"}, 5997e8d8bef9SDimitry Andric {ELF::NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"}, 5998e8d8bef9SDimitry Andric 5999e8d8bef9SDimitry Andric {ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"}, 6000e8d8bef9SDimitry Andric {ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"}, 6001e8d8bef9SDimitry Andric {ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"}, 6002e8d8bef9SDimitry Andric 6003e8d8bef9SDimitry Andric {ELF::NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS (s390 upper register halves)"}, 6004e8d8bef9SDimitry Andric {ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"}, 6005e8d8bef9SDimitry Andric {ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"}, 6006e8d8bef9SDimitry Andric {ELF::NT_S390_TODPREG, "NT_S390_TODPREG (s390 TOD programmable register)"}, 6007e8d8bef9SDimitry Andric {ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"}, 6008e8d8bef9SDimitry Andric {ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"}, 6009e8d8bef9SDimitry Andric {ELF::NT_S390_LAST_BREAK, 6010e8d8bef9SDimitry Andric "NT_S390_LAST_BREAK (s390 last breaking event address)"}, 6011e8d8bef9SDimitry Andric {ELF::NT_S390_SYSTEM_CALL, 6012e8d8bef9SDimitry Andric "NT_S390_SYSTEM_CALL (s390 system call restart data)"}, 6013e8d8bef9SDimitry Andric {ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"}, 6014e8d8bef9SDimitry Andric {ELF::NT_S390_VXRS_LOW, 6015e8d8bef9SDimitry Andric "NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"}, 6016e8d8bef9SDimitry Andric {ELF::NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"}, 6017e8d8bef9SDimitry Andric {ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"}, 6018e8d8bef9SDimitry Andric {ELF::NT_S390_GS_BC, 6019e8d8bef9SDimitry Andric "NT_S390_GS_BC (s390 guarded-storage broadcast control)"}, 6020e8d8bef9SDimitry Andric 6021e8d8bef9SDimitry Andric {ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"}, 6022e8d8bef9SDimitry Andric {ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"}, 6023e8d8bef9SDimitry Andric {ELF::NT_ARM_HW_BREAK, 6024e8d8bef9SDimitry Andric "NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"}, 6025e8d8bef9SDimitry Andric {ELF::NT_ARM_HW_WATCH, 6026e8d8bef9SDimitry Andric "NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"}, 602706c3fb27SDimitry Andric {ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"}, 602806c3fb27SDimitry Andric {ELF::NT_ARM_PAC_MASK, 602906c3fb27SDimitry Andric "NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"}, 60305f757f3fSDimitry Andric {ELF::NT_ARM_TAGGED_ADDR_CTRL, 60315f757f3fSDimitry Andric "NT_ARM_TAGGED_ADDR_CTRL (AArch64 Tagged Address Control)"}, 603206c3fb27SDimitry Andric {ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"}, 603306c3fb27SDimitry Andric {ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"}, 603406c3fb27SDimitry Andric {ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"}, 6035e8d8bef9SDimitry Andric 6036e8d8bef9SDimitry Andric {ELF::NT_FILE, "NT_FILE (mapped files)"}, 6037e8d8bef9SDimitry Andric {ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"}, 6038e8d8bef9SDimitry Andric {ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"}, 6039e8d8bef9SDimitry Andric }; 6040e8d8bef9SDimitry Andric 60410b57cec5SDimitry Andric template <class ELFT> 6042fe6060f1SDimitry Andric StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) { 6043e8d8bef9SDimitry Andric uint32_t Type = Note.getType(); 6044e8d8bef9SDimitry Andric auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef { 6045e8d8bef9SDimitry Andric for (const NoteType &N : V) 6046e8d8bef9SDimitry Andric if (N.ID == Type) 6047e8d8bef9SDimitry Andric return N.Name; 6048e8d8bef9SDimitry Andric return ""; 6049e8d8bef9SDimitry Andric }; 6050e8d8bef9SDimitry Andric 6051e8d8bef9SDimitry Andric StringRef Name = Note.getName(); 6052e8d8bef9SDimitry Andric if (Name == "GNU") 6053e8d8bef9SDimitry Andric return FindNote(GNUNoteTypes); 6054fe6060f1SDimitry Andric if (Name == "FreeBSD") { 6055fe6060f1SDimitry Andric if (ELFType == ELF::ET_CORE) { 6056fe6060f1SDimitry Andric // FreeBSD also places the generic core notes in the FreeBSD namespace. 6057fe6060f1SDimitry Andric StringRef Result = FindNote(FreeBSDCoreNoteTypes); 6058fe6060f1SDimitry Andric if (!Result.empty()) 6059fe6060f1SDimitry Andric return Result; 6060fe6060f1SDimitry Andric return FindNote(CoreNoteTypes); 6061fe6060f1SDimitry Andric } else { 6062e8d8bef9SDimitry Andric return FindNote(FreeBSDNoteTypes); 6063fe6060f1SDimitry Andric } 6064fe6060f1SDimitry Andric } 60655f757f3fSDimitry Andric if (ELFType == ELF::ET_CORE && Name.starts_with("NetBSD-CORE")) { 60664824e7fdSDimitry Andric StringRef Result = FindNote(NetBSDCoreNoteTypes); 60674824e7fdSDimitry Andric if (!Result.empty()) 60684824e7fdSDimitry Andric return Result; 60694824e7fdSDimitry Andric return FindNote(CoreNoteTypes); 60704824e7fdSDimitry Andric } 60715f757f3fSDimitry Andric if (ELFType == ELF::ET_CORE && Name.starts_with("OpenBSD")) { 6072349cc55cSDimitry Andric // OpenBSD also places the generic core notes in the OpenBSD namespace. 6073349cc55cSDimitry Andric StringRef Result = FindNote(OpenBSDCoreNoteTypes); 6074349cc55cSDimitry Andric if (!Result.empty()) 6075349cc55cSDimitry Andric return Result; 6076349cc55cSDimitry Andric return FindNote(CoreNoteTypes); 6077349cc55cSDimitry Andric } 6078e8d8bef9SDimitry Andric if (Name == "AMD") 6079e8d8bef9SDimitry Andric return FindNote(AMDNoteTypes); 6080e8d8bef9SDimitry Andric if (Name == "AMDGPU") 6081e8d8bef9SDimitry Andric return FindNote(AMDGPUNoteTypes); 6082349cc55cSDimitry Andric if (Name == "LLVMOMPOFFLOAD") 6083349cc55cSDimitry Andric return FindNote(LLVMOMPOFFLOADNoteTypes); 608481ad6265SDimitry Andric if (Name == "Android") 608581ad6265SDimitry Andric return FindNote(AndroidNoteTypes); 6086e8d8bef9SDimitry Andric 6087e8d8bef9SDimitry Andric if (ELFType == ELF::ET_CORE) 6088e8d8bef9SDimitry Andric return FindNote(CoreNoteTypes); 6089e8d8bef9SDimitry Andric return FindNote(GenericNoteTypes); 6090e8d8bef9SDimitry Andric } 6091e8d8bef9SDimitry Andric 6092e8d8bef9SDimitry Andric template <class ELFT> 609306c3fb27SDimitry Andric static void processNotesHelper( 6094e8d8bef9SDimitry Andric const ELFDumper<ELFT> &Dumper, 6095bdd1243dSDimitry Andric llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off, 609606c3fb27SDimitry Andric typename ELFT::Addr, size_t)> 6097e8d8bef9SDimitry Andric StartNotesFn, 6098fe6060f1SDimitry Andric llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn, 6099e8d8bef9SDimitry Andric llvm::function_ref<void()> FinishNotesFn) { 6100e8d8bef9SDimitry Andric const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile(); 6101fe6060f1SDimitry Andric bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE; 6102e8d8bef9SDimitry Andric 6103e8d8bef9SDimitry Andric ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections()); 6104fe6060f1SDimitry Andric if (!IsCoreFile && !Sections.empty()) { 6105e8d8bef9SDimitry Andric for (const typename ELFT::Shdr &S : Sections) { 6106e8d8bef9SDimitry Andric if (S.sh_type != SHT_NOTE) 6107e8d8bef9SDimitry Andric continue; 6108bdd1243dSDimitry Andric StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset, 610906c3fb27SDimitry Andric S.sh_size, S.sh_addralign); 6110e8d8bef9SDimitry Andric Error Err = Error::success(); 6111e8d8bef9SDimitry Andric size_t I = 0; 6112e8d8bef9SDimitry Andric for (const typename ELFT::Note Note : Obj.notes(S, Err)) { 6113fe6060f1SDimitry Andric if (Error E = ProcessNoteFn(Note, IsCoreFile)) 6114e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 6115e8d8bef9SDimitry Andric "unable to read note with index " + Twine(I) + " from the " + 6116e8d8bef9SDimitry Andric describe(Obj, S) + ": " + toString(std::move(E))); 6117e8d8bef9SDimitry Andric ++I; 6118e8d8bef9SDimitry Andric } 6119e8d8bef9SDimitry Andric if (Err) 6120e8d8bef9SDimitry Andric Dumper.reportUniqueWarning("unable to read notes from the " + 6121e8d8bef9SDimitry Andric describe(Obj, S) + ": " + 6122e8d8bef9SDimitry Andric toString(std::move(Err))); 6123e8d8bef9SDimitry Andric FinishNotesFn(); 6124e8d8bef9SDimitry Andric } 6125e8d8bef9SDimitry Andric return; 6126e8d8bef9SDimitry Andric } 6127e8d8bef9SDimitry Andric 6128e8d8bef9SDimitry Andric Expected<ArrayRef<typename ELFT::Phdr>> PhdrsOrErr = Obj.program_headers(); 6129e8d8bef9SDimitry Andric if (!PhdrsOrErr) { 6130e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 6131e8d8bef9SDimitry Andric "unable to read program headers to locate the PT_NOTE segment: " + 6132e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 6133e8d8bef9SDimitry Andric return; 6134e8d8bef9SDimitry Andric } 6135e8d8bef9SDimitry Andric 6136e8d8bef9SDimitry Andric for (size_t I = 0, E = (*PhdrsOrErr).size(); I != E; ++I) { 6137e8d8bef9SDimitry Andric const typename ELFT::Phdr &P = (*PhdrsOrErr)[I]; 6138e8d8bef9SDimitry Andric if (P.p_type != PT_NOTE) 6139e8d8bef9SDimitry Andric continue; 614006c3fb27SDimitry Andric StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align); 6141e8d8bef9SDimitry Andric Error Err = Error::success(); 6142e8d8bef9SDimitry Andric size_t Index = 0; 6143e8d8bef9SDimitry Andric for (const typename ELFT::Note Note : Obj.notes(P, Err)) { 6144fe6060f1SDimitry Andric if (Error E = ProcessNoteFn(Note, IsCoreFile)) 6145e8d8bef9SDimitry Andric Dumper.reportUniqueWarning("unable to read note with index " + 6146e8d8bef9SDimitry Andric Twine(Index) + 6147e8d8bef9SDimitry Andric " from the PT_NOTE segment with index " + 6148e8d8bef9SDimitry Andric Twine(I) + ": " + toString(std::move(E))); 6149e8d8bef9SDimitry Andric ++Index; 6150e8d8bef9SDimitry Andric } 6151e8d8bef9SDimitry Andric if (Err) 6152e8d8bef9SDimitry Andric Dumper.reportUniqueWarning( 6153e8d8bef9SDimitry Andric "unable to read notes from the PT_NOTE segment with index " + 6154e8d8bef9SDimitry Andric Twine(I) + ": " + toString(std::move(Err))); 6155e8d8bef9SDimitry Andric FinishNotesFn(); 6156e8d8bef9SDimitry Andric } 6157e8d8bef9SDimitry Andric } 6158e8d8bef9SDimitry Andric 6159e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printNotes() { 616006c3fb27SDimitry Andric size_t Align = 0; 6161fe6060f1SDimitry Andric bool IsFirstHeader = true; 6162bdd1243dSDimitry Andric auto PrintHeader = [&](std::optional<StringRef> SecName, 61635ffd83dbSDimitry Andric const typename ELFT::Off Offset, 616406c3fb27SDimitry Andric const typename ELFT::Addr Size, size_t Al) { 616506c3fb27SDimitry Andric Align = std::max<size_t>(Al, 4); 6166fe6060f1SDimitry Andric // Print a newline between notes sections to match GNU readelf. 6167fe6060f1SDimitry Andric if (!IsFirstHeader) { 6168fe6060f1SDimitry Andric OS << '\n'; 6169fe6060f1SDimitry Andric } else { 6170fe6060f1SDimitry Andric IsFirstHeader = false; 6171fe6060f1SDimitry Andric } 6172fe6060f1SDimitry Andric 61735ffd83dbSDimitry Andric OS << "Displaying notes found "; 61745ffd83dbSDimitry Andric 61755ffd83dbSDimitry Andric if (SecName) 61765ffd83dbSDimitry Andric OS << "in: " << *SecName << "\n"; 61775ffd83dbSDimitry Andric else 61785ffd83dbSDimitry Andric OS << "at file offset " << format_hex(Offset, 10) << " with length " 61795ffd83dbSDimitry Andric << format_hex(Size, 10) << ":\n"; 61805ffd83dbSDimitry Andric 61815ffd83dbSDimitry Andric OS << " Owner Data size \tDescription\n"; 61820b57cec5SDimitry Andric }; 61830b57cec5SDimitry Andric 6184fe6060f1SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 61850b57cec5SDimitry Andric StringRef Name = Note.getName(); 618606c3fb27SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(Align); 61870b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 61880b57cec5SDimitry Andric 61898bcb0991SDimitry Andric // Print the note owner/type. 61908bcb0991SDimitry Andric OS << " " << left_justify(Name, 20) << ' ' 61910b57cec5SDimitry Andric << format_hex(Descriptor.size(), 10) << '\t'; 6192e8d8bef9SDimitry Andric 6193e8d8bef9SDimitry Andric StringRef NoteType = 6194e8d8bef9SDimitry Andric getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type); 61958bcb0991SDimitry Andric if (!NoteType.empty()) 61968bcb0991SDimitry Andric OS << NoteType << '\n'; 61978bcb0991SDimitry Andric else 61988bcb0991SDimitry Andric OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n"; 61998bcb0991SDimitry Andric 62008bcb0991SDimitry Andric // Print the description, or fallback to printing raw bytes for unknown 6201fe6060f1SDimitry Andric // owners/if we fail to pretty-print the contents. 62028bcb0991SDimitry Andric if (Name == "GNU") { 6203fe6060f1SDimitry Andric if (printGNUNote<ELFT>(OS, Type, Descriptor)) 6204fe6060f1SDimitry Andric return Error::success(); 6205fe6060f1SDimitry Andric } else if (Name == "FreeBSD") { 6206bdd1243dSDimitry Andric if (std::optional<FreeBSDNote> N = 6207fe6060f1SDimitry Andric getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) { 6208fe6060f1SDimitry Andric OS << " " << N->Type << ": " << N->Value << '\n'; 6209fe6060f1SDimitry Andric return Error::success(); 6210fe6060f1SDimitry Andric } 62118bcb0991SDimitry Andric } else if (Name == "AMD") { 62120b57cec5SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 6213fe6060f1SDimitry Andric if (!N.Type.empty()) { 62140b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 6215fe6060f1SDimitry Andric return Error::success(); 6216fe6060f1SDimitry Andric } 62170b57cec5SDimitry Andric } else if (Name == "AMDGPU") { 62180b57cec5SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 6219fe6060f1SDimitry Andric if (!N.Type.empty()) { 62200b57cec5SDimitry Andric OS << " " << N.Type << ":\n " << N.Value << '\n'; 6221fe6060f1SDimitry Andric return Error::success(); 6222fe6060f1SDimitry Andric } 6223349cc55cSDimitry Andric } else if (Name == "LLVMOMPOFFLOAD") { 6224349cc55cSDimitry Andric if (printLLVMOMPOFFLOADNote<ELFT>(OS, Type, Descriptor)) 6225349cc55cSDimitry Andric return Error::success(); 62268bcb0991SDimitry Andric } else if (Name == "CORE") { 62278bcb0991SDimitry Andric if (Type == ELF::NT_FILE) { 62285f757f3fSDimitry Andric DataExtractor DescExtractor( 6229*0fca6ea1SDimitry Andric Descriptor, ELFT::Endianness == llvm::endianness::little, 62308bcb0991SDimitry Andric sizeof(Elf_Addr)); 6231fe6060f1SDimitry Andric if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) { 6232e8d8bef9SDimitry Andric printCoreNote<ELFT>(OS, *NoteOrErr); 6233fe6060f1SDimitry Andric return Error::success(); 6234fe6060f1SDimitry Andric } else { 6235e8d8bef9SDimitry Andric return NoteOrErr.takeError(); 62360b57cec5SDimitry Andric } 6237fe6060f1SDimitry Andric } 623881ad6265SDimitry Andric } else if (Name == "Android") { 623981ad6265SDimitry Andric if (printAndroidNote(OS, Type, Descriptor)) 624081ad6265SDimitry Andric return Error::success(); 6241fe6060f1SDimitry Andric } 6242fe6060f1SDimitry Andric if (!Descriptor.empty()) { 62438bcb0991SDimitry Andric OS << " description data:"; 62448bcb0991SDimitry Andric for (uint8_t B : Descriptor) 62458bcb0991SDimitry Andric OS << " " << format("%02x", B); 62460b57cec5SDimitry Andric OS << '\n'; 62478bcb0991SDimitry Andric } 6248e8d8bef9SDimitry Andric return Error::success(); 62490b57cec5SDimitry Andric }; 62500b57cec5SDimitry Andric 625106c3fb27SDimitry Andric processNotesHelper(*this, /*StartNotesFn=*/PrintHeader, 625206c3fb27SDimitry Andric /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {}); 625306c3fb27SDimitry Andric } 625406c3fb27SDimitry Andric 625506c3fb27SDimitry Andric template <class ELFT> 625606c3fb27SDimitry Andric ArrayRef<uint8_t> 625706c3fb27SDimitry Andric ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) { 625806c3fb27SDimitry Andric for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) { 625906c3fb27SDimitry Andric if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC) 626006c3fb27SDimitry Andric continue; 626106c3fb27SDimitry Andric if (Sec.sh_addr != ExpectedAddr) { 626206c3fb27SDimitry Andric reportUniqueWarning( 626306c3fb27SDimitry Andric "SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" + 626406c3fb27SDimitry Andric Twine::utohexstr(Sec.sh_addr) + 626506c3fb27SDimitry Andric ", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" + 626606c3fb27SDimitry Andric Twine::utohexstr(ExpectedAddr)); 626706c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 626806c3fb27SDimitry Andric } 626906c3fb27SDimitry Andric Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec); 627006c3fb27SDimitry Andric if (auto E = Contents.takeError()) { 627106c3fb27SDimitry Andric reportUniqueWarning( 627206c3fb27SDimitry Andric "couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " + 627306c3fb27SDimitry Andric toString(std::move(E))); 627406c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 627506c3fb27SDimitry Andric } 627606c3fb27SDimitry Andric return Contents.get(); 627706c3fb27SDimitry Andric } 627806c3fb27SDimitry Andric return ArrayRef<uint8_t>(); 627906c3fb27SDimitry Andric } 628006c3fb27SDimitry Andric 628106c3fb27SDimitry Andric // Reserve the lower three bits of the first byte of the step distance when 628206c3fb27SDimitry Andric // encoding the memtag descriptors. Found to be the best overall size tradeoff 628306c3fb27SDimitry Andric // when compiling Android T with full MTE globals enabled. 628406c3fb27SDimitry Andric constexpr uint64_t MemtagStepVarintReservedBits = 3; 628506c3fb27SDimitry Andric constexpr uint64_t MemtagGranuleSize = 16; 628606c3fb27SDimitry Andric 628706c3fb27SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printMemtag() { 628806c3fb27SDimitry Andric if (Obj.getHeader().e_machine != EM_AARCH64) return; 628906c3fb27SDimitry Andric std::vector<std::pair<std::string, std::string>> DynamicEntries; 629006c3fb27SDimitry Andric uint64_t MemtagGlobalsSz = 0; 629106c3fb27SDimitry Andric uint64_t MemtagGlobals = 0; 629206c3fb27SDimitry Andric for (const typename ELFT::Dyn &Entry : dynamic_table()) { 629306c3fb27SDimitry Andric uintX_t Tag = Entry.getTag(); 629406c3fb27SDimitry Andric switch (Tag) { 629506c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALSSZ: 629606c3fb27SDimitry Andric MemtagGlobalsSz = Entry.getVal(); 629706c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 629806c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 629906c3fb27SDimitry Andric break; 630006c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_GLOBALS: 630106c3fb27SDimitry Andric MemtagGlobals = Entry.getVal(); 630206c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 630306c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 630406c3fb27SDimitry Andric break; 630506c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_MODE: 630606c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_HEAP: 630706c3fb27SDimitry Andric case DT_AARCH64_MEMTAG_STACK: 630806c3fb27SDimitry Andric DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag), 630906c3fb27SDimitry Andric getDynamicEntry(Tag, Entry.getVal())); 631006c3fb27SDimitry Andric break; 631106c3fb27SDimitry Andric } 631206c3fb27SDimitry Andric } 631306c3fb27SDimitry Andric 631406c3fb27SDimitry Andric ArrayRef<uint8_t> AndroidNoteDesc; 631506c3fb27SDimitry Andric auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 631606c3fb27SDimitry Andric if (Note.getName() == "Android" && 631706c3fb27SDimitry Andric Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG) 631806c3fb27SDimitry Andric AndroidNoteDesc = Note.getDesc(4); 631906c3fb27SDimitry Andric return Error::success(); 632006c3fb27SDimitry Andric }; 632106c3fb27SDimitry Andric 632206c3fb27SDimitry Andric processNotesHelper( 632306c3fb27SDimitry Andric *this, 632406c3fb27SDimitry Andric /*StartNotesFn=*/ 632506c3fb27SDimitry Andric [](std::optional<StringRef>, const typename ELFT::Off, 632606c3fb27SDimitry Andric const typename ELFT::Addr, size_t) {}, 632706c3fb27SDimitry Andric /*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {}); 632806c3fb27SDimitry Andric 632906c3fb27SDimitry Andric ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals); 633006c3fb27SDimitry Andric if (Contents.size() != MemtagGlobalsSz) { 633106c3fb27SDimitry Andric reportUniqueWarning( 633206c3fb27SDimitry Andric "mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" + 633306c3fb27SDimitry Andric Twine::utohexstr(MemtagGlobalsSz) + 633406c3fb27SDimitry Andric ") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" + 633506c3fb27SDimitry Andric Twine::utohexstr(Contents.size()) + ")"); 633606c3fb27SDimitry Andric Contents = ArrayRef<uint8_t>(); 633706c3fb27SDimitry Andric } 633806c3fb27SDimitry Andric 633906c3fb27SDimitry Andric std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors; 634006c3fb27SDimitry Andric uint64_t Address = 0; 634106c3fb27SDimitry Andric // See the AArch64 MemtagABI document for a description of encoding scheme: 634206c3fb27SDimitry Andric // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic 634306c3fb27SDimitry Andric for (size_t I = 0; I < Contents.size();) { 634406c3fb27SDimitry Andric const char *Error = nullptr; 634506c3fb27SDimitry Andric unsigned DecodedBytes = 0; 634606c3fb27SDimitry Andric uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes, 634706c3fb27SDimitry Andric Contents.end(), &Error); 634806c3fb27SDimitry Andric I += DecodedBytes; 634906c3fb27SDimitry Andric if (Error) { 635006c3fb27SDimitry Andric reportUniqueWarning( 635106c3fb27SDimitry Andric "error decoding distance uleb, " + Twine(DecodedBytes) + 635206c3fb27SDimitry Andric " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error)); 635306c3fb27SDimitry Andric GlobalDescriptors.clear(); 635406c3fb27SDimitry Andric break; 635506c3fb27SDimitry Andric } 635606c3fb27SDimitry Andric uint64_t Distance = Value >> MemtagStepVarintReservedBits; 635706c3fb27SDimitry Andric uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1); 635806c3fb27SDimitry Andric if (GranulesToTag == 0) { 635906c3fb27SDimitry Andric GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes, 636006c3fb27SDimitry Andric Contents.end(), &Error) + 636106c3fb27SDimitry Andric 1; 636206c3fb27SDimitry Andric I += DecodedBytes; 636306c3fb27SDimitry Andric if (Error) { 636406c3fb27SDimitry Andric reportUniqueWarning( 636506c3fb27SDimitry Andric "error decoding size-only uleb, " + Twine(DecodedBytes) + 636606c3fb27SDimitry Andric " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error)); 636706c3fb27SDimitry Andric GlobalDescriptors.clear(); 636806c3fb27SDimitry Andric break; 636906c3fb27SDimitry Andric } 637006c3fb27SDimitry Andric } 637106c3fb27SDimitry Andric Address += Distance * MemtagGranuleSize; 637206c3fb27SDimitry Andric GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize); 637306c3fb27SDimitry Andric Address += GranulesToTag * MemtagGranuleSize; 637406c3fb27SDimitry Andric } 637506c3fb27SDimitry Andric 637606c3fb27SDimitry Andric printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors); 63775ffd83dbSDimitry Andric } 63785ffd83dbSDimitry Andric 6379e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() { 63800b57cec5SDimitry Andric OS << "printELFLinkerOptions not implemented!\n"; 63810b57cec5SDimitry Andric } 63820b57cec5SDimitry Andric 6383480093f4SDimitry Andric template <class ELFT> 6384e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printDependentLibsHelper( 63855ffd83dbSDimitry Andric function_ref<void(const Elf_Shdr &)> OnSectionStart, 63865ffd83dbSDimitry Andric function_ref<void(StringRef, uint64_t)> OnLibEntry) { 63875ffd83dbSDimitry Andric auto Warn = [this](unsigned SecNdx, StringRef Msg) { 6388e8d8bef9SDimitry Andric this->reportUniqueWarning("SHT_LLVM_DEPENDENT_LIBRARIES section at index " + 6389e8d8bef9SDimitry Andric Twine(SecNdx) + " is broken: " + Msg); 63905ffd83dbSDimitry Andric }; 63915ffd83dbSDimitry Andric 63925ffd83dbSDimitry Andric unsigned I = -1; 6393e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) { 63945ffd83dbSDimitry Andric ++I; 63955ffd83dbSDimitry Andric if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES) 63965ffd83dbSDimitry Andric continue; 63975ffd83dbSDimitry Andric 63985ffd83dbSDimitry Andric OnSectionStart(Shdr); 63995ffd83dbSDimitry Andric 6400e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Shdr); 64015ffd83dbSDimitry Andric if (!ContentsOrErr) { 64025ffd83dbSDimitry Andric Warn(I, toString(ContentsOrErr.takeError())); 64035ffd83dbSDimitry Andric continue; 64045ffd83dbSDimitry Andric } 64055ffd83dbSDimitry Andric 64065ffd83dbSDimitry Andric ArrayRef<uint8_t> Contents = *ContentsOrErr; 64075ffd83dbSDimitry Andric if (!Contents.empty() && Contents.back() != 0) { 64085ffd83dbSDimitry Andric Warn(I, "the content is not null-terminated"); 64095ffd83dbSDimitry Andric continue; 64105ffd83dbSDimitry Andric } 64115ffd83dbSDimitry Andric 64125ffd83dbSDimitry Andric for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) { 64135ffd83dbSDimitry Andric StringRef Lib((const char *)I); 64145ffd83dbSDimitry Andric OnLibEntry(Lib, I - Contents.begin()); 64155ffd83dbSDimitry Andric I += Lib.size() + 1; 64165ffd83dbSDimitry Andric } 64175ffd83dbSDimitry Andric } 64185ffd83dbSDimitry Andric } 64195ffd83dbSDimitry Andric 64205ffd83dbSDimitry Andric template <class ELFT> 6421e8d8bef9SDimitry Andric void ELFDumper<ELFT>::forEachRelocationDo( 6422*0fca6ea1SDimitry Andric const Elf_Shdr &Sec, 6423e8d8bef9SDimitry Andric llvm::function_ref<void(const Relocation<ELFT> &, unsigned, 6424e8d8bef9SDimitry Andric const Elf_Shdr &, const Elf_Shdr *)> 6425*0fca6ea1SDimitry Andric RelRelaFn) { 6426e8d8bef9SDimitry Andric auto Warn = [&](Error &&E, 6427e8d8bef9SDimitry Andric const Twine &Prefix = "unable to read relocations from") { 6428e8d8bef9SDimitry Andric this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " + 6429e8d8bef9SDimitry Andric toString(std::move(E))); 6430e8d8bef9SDimitry Andric }; 6431e8d8bef9SDimitry Andric 64325f757f3fSDimitry Andric // SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an 64335f757f3fSDimitry Andric // associated symbol table. For them we should not treat the value of the 64345f757f3fSDimitry Andric // sh_link field as an index of a symbol table. 6435e8d8bef9SDimitry Andric const Elf_Shdr *SymTab; 64365f757f3fSDimitry Andric if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR && 64375f757f3fSDimitry Andric !(Obj.getHeader().e_machine == EM_AARCH64 && 64385f757f3fSDimitry Andric Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) { 6439e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link); 6440e8d8bef9SDimitry Andric if (!SymTabOrErr) { 6441e8d8bef9SDimitry Andric Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for"); 6442e8d8bef9SDimitry Andric return; 6443e8d8bef9SDimitry Andric } 6444e8d8bef9SDimitry Andric SymTab = *SymTabOrErr; 6445e8d8bef9SDimitry Andric } 6446e8d8bef9SDimitry Andric 6447e8d8bef9SDimitry Andric unsigned RelNdx = 0; 6448e8d8bef9SDimitry Andric const bool IsMips64EL = this->Obj.isMips64EL(); 6449e8d8bef9SDimitry Andric switch (Sec.sh_type) { 6450e8d8bef9SDimitry Andric case ELF::SHT_REL: 6451e8d8bef9SDimitry Andric if (Expected<Elf_Rel_Range> RangeOrErr = Obj.rels(Sec)) { 6452e8d8bef9SDimitry Andric for (const Elf_Rel &R : *RangeOrErr) 6453e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6454e8d8bef9SDimitry Andric } else { 6455e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6456e8d8bef9SDimitry Andric } 6457e8d8bef9SDimitry Andric break; 6458e8d8bef9SDimitry Andric case ELF::SHT_RELA: 6459e8d8bef9SDimitry Andric if (Expected<Elf_Rela_Range> RangeOrErr = Obj.relas(Sec)) { 6460e8d8bef9SDimitry Andric for (const Elf_Rela &R : *RangeOrErr) 6461e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6462e8d8bef9SDimitry Andric } else { 6463e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6464e8d8bef9SDimitry Andric } 6465e8d8bef9SDimitry Andric break; 64665f757f3fSDimitry Andric case ELF::SHT_AARCH64_AUTH_RELR: 64675f757f3fSDimitry Andric if (Obj.getHeader().e_machine != EM_AARCH64) 64685f757f3fSDimitry Andric break; 64695f757f3fSDimitry Andric [[fallthrough]]; 6470e8d8bef9SDimitry Andric case ELF::SHT_RELR: 6471e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_RELR: { 6472e8d8bef9SDimitry Andric Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec); 6473e8d8bef9SDimitry Andric if (!RangeOrErr) { 6474e8d8bef9SDimitry Andric Warn(RangeOrErr.takeError()); 6475e8d8bef9SDimitry Andric break; 6476e8d8bef9SDimitry Andric } 6477e8d8bef9SDimitry Andric 6478e8d8bef9SDimitry Andric for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr)) 6479e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, 6480e8d8bef9SDimitry Andric /*SymTab=*/nullptr); 6481e8d8bef9SDimitry Andric break; 6482e8d8bef9SDimitry Andric } 6483*0fca6ea1SDimitry Andric case ELF::SHT_CREL: { 6484*0fca6ea1SDimitry Andric if (auto RelsOrRelas = Obj.crels(Sec)) { 6485*0fca6ea1SDimitry Andric for (const Elf_Rel &R : RelsOrRelas->first) 6486*0fca6ea1SDimitry Andric RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab); 6487*0fca6ea1SDimitry Andric for (const Elf_Rela &R : RelsOrRelas->second) 6488*0fca6ea1SDimitry Andric RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab); 6489*0fca6ea1SDimitry Andric } else { 6490*0fca6ea1SDimitry Andric Warn(RelsOrRelas.takeError()); 6491*0fca6ea1SDimitry Andric } 6492*0fca6ea1SDimitry Andric break; 6493*0fca6ea1SDimitry Andric } 6494e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_REL: 6495e8d8bef9SDimitry Andric case ELF::SHT_ANDROID_RELA: 6496e8d8bef9SDimitry Andric if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) { 6497e8d8bef9SDimitry Andric for (const Elf_Rela &R : *RelasOrErr) 6498e8d8bef9SDimitry Andric RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab); 6499e8d8bef9SDimitry Andric } else { 6500e8d8bef9SDimitry Andric Warn(RelasOrErr.takeError()); 6501e8d8bef9SDimitry Andric } 6502e8d8bef9SDimitry Andric break; 6503e8d8bef9SDimitry Andric } 6504e8d8bef9SDimitry Andric } 6505e8d8bef9SDimitry Andric 6506e8d8bef9SDimitry Andric template <class ELFT> 6507e8d8bef9SDimitry Andric StringRef ELFDumper<ELFT>::getPrintableSectionName(const Elf_Shdr &Sec) const { 6508e8d8bef9SDimitry Andric StringRef Name = "<?>"; 6509e8d8bef9SDimitry Andric if (Expected<StringRef> SecNameOrErr = 6510e8d8bef9SDimitry Andric Obj.getSectionName(Sec, this->WarningHandler)) 6511e8d8bef9SDimitry Andric Name = *SecNameOrErr; 6512e8d8bef9SDimitry Andric else 6513e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to get the name of " + describe(Sec) + 6514e8d8bef9SDimitry Andric ": " + toString(SecNameOrErr.takeError())); 6515e8d8bef9SDimitry Andric return Name; 6516e8d8bef9SDimitry Andric } 6517e8d8bef9SDimitry Andric 6518e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printDependentLibs() { 65195ffd83dbSDimitry Andric bool SectionStarted = false; 65205ffd83dbSDimitry Andric struct NameOffset { 65215ffd83dbSDimitry Andric StringRef Name; 65225ffd83dbSDimitry Andric uint64_t Offset; 65235ffd83dbSDimitry Andric }; 65245ffd83dbSDimitry Andric std::vector<NameOffset> SecEntries; 65255ffd83dbSDimitry Andric NameOffset Current; 65265ffd83dbSDimitry Andric auto PrintSection = [&]() { 65275ffd83dbSDimitry Andric OS << "Dependent libraries section " << Current.Name << " at offset " 65285ffd83dbSDimitry Andric << format_hex(Current.Offset, 1) << " contains " << SecEntries.size() 65295ffd83dbSDimitry Andric << " entries:\n"; 65305ffd83dbSDimitry Andric for (NameOffset Entry : SecEntries) 6531e8d8bef9SDimitry Andric OS << " [" << format("%6" PRIx64, Entry.Offset) << "] " << Entry.Name 65325ffd83dbSDimitry Andric << "\n"; 65335ffd83dbSDimitry Andric OS << "\n"; 65345ffd83dbSDimitry Andric SecEntries.clear(); 65355ffd83dbSDimitry Andric }; 65365ffd83dbSDimitry Andric 65375ffd83dbSDimitry Andric auto OnSectionStart = [&](const Elf_Shdr &Shdr) { 65385ffd83dbSDimitry Andric if (SectionStarted) 65395ffd83dbSDimitry Andric PrintSection(); 65405ffd83dbSDimitry Andric SectionStarted = true; 65415ffd83dbSDimitry Andric Current.Offset = Shdr.sh_offset; 6542e8d8bef9SDimitry Andric Current.Name = this->getPrintableSectionName(Shdr); 65435ffd83dbSDimitry Andric }; 65445ffd83dbSDimitry Andric auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) { 65455ffd83dbSDimitry Andric SecEntries.push_back(NameOffset{Lib, Offset}); 65465ffd83dbSDimitry Andric }; 65475ffd83dbSDimitry Andric 6548e8d8bef9SDimitry Andric this->printDependentLibsHelper(OnSectionStart, OnLibEntry); 65495ffd83dbSDimitry Andric if (SectionStarted) 65505ffd83dbSDimitry Andric PrintSection(); 6551480093f4SDimitry Andric } 6552480093f4SDimitry Andric 65538bcb0991SDimitry Andric template <class ELFT> 6554fe6060f1SDimitry Andric SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress( 6555bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) { 6556fe6060f1SDimitry Andric SmallVector<uint32_t> SymbolIndexes; 655781ad6265SDimitry Andric if (!this->AddressToIndexMap) { 6558fe6060f1SDimitry Andric // Populate the address to index map upon the first invocation of this 6559fe6060f1SDimitry Andric // function. 6560fe6060f1SDimitry Andric this->AddressToIndexMap.emplace(); 6561e8d8bef9SDimitry Andric if (this->DotSymtabSec) { 6562fe6060f1SDimitry Andric if (Expected<Elf_Sym_Range> SymsOrError = 6563fe6060f1SDimitry Andric Obj.symbols(this->DotSymtabSec)) { 6564e8d8bef9SDimitry Andric uint32_t Index = (uint32_t)-1; 6565e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : *SymsOrError) { 6566e8d8bef9SDimitry Andric ++Index; 6567e8d8bef9SDimitry Andric 6568e8d8bef9SDimitry Andric if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC) 65698bcb0991SDimitry Andric continue; 6570e8d8bef9SDimitry Andric 6571fe6060f1SDimitry Andric Expected<uint64_t> SymAddrOrErr = 6572fe6060f1SDimitry Andric ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress(); 6573fe6060f1SDimitry Andric if (!SymAddrOrErr) { 6574e8d8bef9SDimitry Andric std::string Name = this->getStaticSymbolName(Index); 6575e8d8bef9SDimitry Andric reportUniqueWarning("unable to get address of symbol '" + Name + 6576e8d8bef9SDimitry Andric "': " + toString(SymAddrOrErr.takeError())); 6577fe6060f1SDimitry Andric return SymbolIndexes; 65788bcb0991SDimitry Andric } 6579e8d8bef9SDimitry Andric 6580fe6060f1SDimitry Andric (*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index); 6581fe6060f1SDimitry Andric } 6582fe6060f1SDimitry Andric } else { 6583fe6060f1SDimitry Andric reportUniqueWarning("unable to read the symbol table: " + 6584fe6060f1SDimitry Andric toString(SymsOrError.takeError())); 6585fe6060f1SDimitry Andric } 6586fe6060f1SDimitry Andric } 6587fe6060f1SDimitry Andric } 6588fe6060f1SDimitry Andric 6589fe6060f1SDimitry Andric auto Symbols = this->AddressToIndexMap->find(SymValue); 6590fe6060f1SDimitry Andric if (Symbols == this->AddressToIndexMap->end()) 6591fe6060f1SDimitry Andric return SymbolIndexes; 6592fe6060f1SDimitry Andric 6593fe6060f1SDimitry Andric for (uint32_t Index : Symbols->second) { 6594e8d8bef9SDimitry Andric // Check if the symbol is in the right section. FunctionSec == None 6595e8d8bef9SDimitry Andric // means "any section". 6596e8d8bef9SDimitry Andric if (FunctionSec) { 6597fe6060f1SDimitry Andric const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index)); 6598e8d8bef9SDimitry Andric if (Expected<const Elf_Shdr *> SecOrErr = 6599e8d8bef9SDimitry Andric Obj.getSection(Sym, this->DotSymtabSec, 6600e8d8bef9SDimitry Andric this->getShndxTable(this->DotSymtabSec))) { 6601e8d8bef9SDimitry Andric if (*FunctionSec != *SecOrErr) 6602e8d8bef9SDimitry Andric continue; 6603e8d8bef9SDimitry Andric } else { 6604e8d8bef9SDimitry Andric std::string Name = this->getStaticSymbolName(Index); 6605e8d8bef9SDimitry Andric // Note: it is impossible to trigger this error currently, it is 6606e8d8bef9SDimitry Andric // untested. 6607e8d8bef9SDimitry Andric reportUniqueWarning("unable to get section of symbol '" + Name + 6608e8d8bef9SDimitry Andric "': " + toString(SecOrErr.takeError())); 6609fe6060f1SDimitry Andric return SymbolIndexes; 6610e8d8bef9SDimitry Andric } 6611e8d8bef9SDimitry Andric } 6612e8d8bef9SDimitry Andric 6613fe6060f1SDimitry Andric SymbolIndexes.push_back(Index); 66148bcb0991SDimitry Andric } 66158bcb0991SDimitry Andric 6616fe6060f1SDimitry Andric return SymbolIndexes; 6617fe6060f1SDimitry Andric } 6618fe6060f1SDimitry Andric 6619fe6060f1SDimitry Andric template <class ELFT> 6620fe6060f1SDimitry Andric bool ELFDumper<ELFT>::printFunctionStackSize( 6621bdd1243dSDimitry Andric uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec, 6622fe6060f1SDimitry Andric const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) { 6623fe6060f1SDimitry Andric SmallVector<uint32_t> FuncSymIndexes = 6624fe6060f1SDimitry Andric this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec); 6625fe6060f1SDimitry Andric if (FuncSymIndexes.empty()) 6626e8d8bef9SDimitry Andric reportUniqueWarning( 6627e8d8bef9SDimitry Andric "could not identify function symbol for stack size entry in " + 6628e8d8bef9SDimitry Andric describe(StackSizeSec)); 66298bcb0991SDimitry Andric 66308bcb0991SDimitry Andric // Extract the size. The expectation is that Offset is pointing to the right 66318bcb0991SDimitry Andric // place, i.e. past the function address. 6632e8d8bef9SDimitry Andric Error Err = Error::success(); 6633e8d8bef9SDimitry Andric uint64_t StackSize = Data.getULEB128(Offset, &Err); 6634e8d8bef9SDimitry Andric if (Err) { 6635e8d8bef9SDimitry Andric reportUniqueWarning("could not extract a valid stack size from " + 6636e8d8bef9SDimitry Andric describe(StackSizeSec) + ": " + 6637e8d8bef9SDimitry Andric toString(std::move(Err))); 6638e8d8bef9SDimitry Andric return false; 6639e8d8bef9SDimitry Andric } 6640fe6060f1SDimitry Andric 6641fe6060f1SDimitry Andric if (FuncSymIndexes.empty()) { 6642fe6060f1SDimitry Andric printStackSizeEntry(StackSize, {"?"}); 6643fe6060f1SDimitry Andric } else { 6644fe6060f1SDimitry Andric SmallVector<std::string> FuncSymNames; 6645fe6060f1SDimitry Andric for (uint32_t Index : FuncSymIndexes) 6646fe6060f1SDimitry Andric FuncSymNames.push_back(this->getStaticSymbolName(Index)); 6647fe6060f1SDimitry Andric printStackSizeEntry(StackSize, FuncSymNames); 6648fe6060f1SDimitry Andric } 6649fe6060f1SDimitry Andric 6650e8d8bef9SDimitry Andric return true; 66518bcb0991SDimitry Andric } 66528bcb0991SDimitry Andric 66538bcb0991SDimitry Andric template <class ELFT> 6654e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size, 6655fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) { 66568bcb0991SDimitry Andric OS.PadToColumn(2); 66578bcb0991SDimitry Andric OS << format_decimal(Size, 11); 66588bcb0991SDimitry Andric OS.PadToColumn(18); 6659fe6060f1SDimitry Andric 6660fe6060f1SDimitry Andric OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n"; 66618bcb0991SDimitry Andric } 66628bcb0991SDimitry Andric 66638bcb0991SDimitry Andric template <class ELFT> 6664e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R, 6665e8d8bef9SDimitry Andric const Elf_Shdr &RelocSec, unsigned Ndx, 6666e8d8bef9SDimitry Andric const Elf_Shdr *SymTab, 6667e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec, 6668e8d8bef9SDimitry Andric const Elf_Shdr &StackSizeSec, 66698bcb0991SDimitry Andric const RelocationResolver &Resolver, 66708bcb0991SDimitry Andric DataExtractor Data) { 66718bcb0991SDimitry Andric // This function ignores potentially erroneous input, unless it is directly 66728bcb0991SDimitry Andric // related to stack size reporting. 6673e8d8bef9SDimitry Andric const Elf_Sym *Sym = nullptr; 6674e8d8bef9SDimitry Andric Expected<RelSymbol<ELFT>> TargetOrErr = this->getRelocationTarget(R, SymTab); 6675e8d8bef9SDimitry Andric if (!TargetOrErr) 6676e8d8bef9SDimitry Andric reportUniqueWarning("unable to get the target of relocation with index " + 6677e8d8bef9SDimitry Andric Twine(Ndx) + " in " + describe(RelocSec) + ": " + 6678e8d8bef9SDimitry Andric toString(TargetOrErr.takeError())); 6679e8d8bef9SDimitry Andric else 6680e8d8bef9SDimitry Andric Sym = TargetOrErr->Sym; 6681e8d8bef9SDimitry Andric 66828bcb0991SDimitry Andric uint64_t RelocSymValue = 0; 6683e8d8bef9SDimitry Andric if (Sym) { 6684e8d8bef9SDimitry Andric Expected<const Elf_Shdr *> SectionOrErr = 6685e8d8bef9SDimitry Andric this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab)); 66868bcb0991SDimitry Andric if (!SectionOrErr) { 6687e8d8bef9SDimitry Andric reportUniqueWarning( 6688e8d8bef9SDimitry Andric "cannot identify the section for relocation symbol '" + 6689e8d8bef9SDimitry Andric (*TargetOrErr).Name + "': " + toString(SectionOrErr.takeError())); 66908bcb0991SDimitry Andric } else if (*SectionOrErr != FunctionSec) { 6691e8d8bef9SDimitry Andric reportUniqueWarning("relocation symbol '" + (*TargetOrErr).Name + 6692e8d8bef9SDimitry Andric "' is not in the expected section"); 66938bcb0991SDimitry Andric // Pretend that the symbol is in the correct section and report its 66948bcb0991SDimitry Andric // stack size anyway. 6695e8d8bef9SDimitry Andric FunctionSec = *SectionOrErr; 66968bcb0991SDimitry Andric } 66978bcb0991SDimitry Andric 6698e8d8bef9SDimitry Andric RelocSymValue = Sym->st_value; 66998bcb0991SDimitry Andric } 67008bcb0991SDimitry Andric 6701e8d8bef9SDimitry Andric uint64_t Offset = R.Offset; 6702e8d8bef9SDimitry Andric if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) { 6703e8d8bef9SDimitry Andric reportUniqueWarning("found invalid relocation offset (0x" + 6704e8d8bef9SDimitry Andric Twine::utohexstr(Offset) + ") into " + 6705e8d8bef9SDimitry Andric describe(StackSizeSec) + 6706e8d8bef9SDimitry Andric " while trying to extract a stack size entry"); 6707e8d8bef9SDimitry Andric return; 6708e8d8bef9SDimitry Andric } 67098bcb0991SDimitry Andric 671081ad6265SDimitry Andric uint64_t SymValue = Resolver(R.Type, Offset, RelocSymValue, 671181ad6265SDimitry Andric Data.getAddress(&Offset), R.Addend.value_or(0)); 6712e8d8bef9SDimitry Andric this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data, 6713e8d8bef9SDimitry Andric &Offset); 67148bcb0991SDimitry Andric } 67158bcb0991SDimitry Andric 67168bcb0991SDimitry Andric template <class ELFT> 6717e8d8bef9SDimitry Andric void ELFDumper<ELFT>::printNonRelocatableStackSizes( 6718e8d8bef9SDimitry Andric std::function<void()> PrintHeader) { 67198bcb0991SDimitry Andric // This function ignores potentially erroneous input, unless it is directly 67208bcb0991SDimitry Andric // related to stack size reporting. 6721e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(Obj.sections())) { 6722e8d8bef9SDimitry Andric if (this->getPrintableSectionName(Sec) != ".stack_sizes") 67238bcb0991SDimitry Andric continue; 67248bcb0991SDimitry Andric PrintHeader(); 67258bcb0991SDimitry Andric ArrayRef<uint8_t> Contents = 6726e8d8bef9SDimitry Andric unwrapOrError(this->FileName, Obj.getSectionContents(Sec)); 6727e8d8bef9SDimitry Andric DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr)); 67288bcb0991SDimitry Andric uint64_t Offset = 0; 67298bcb0991SDimitry Andric while (Offset < Contents.size()) { 67308bcb0991SDimitry Andric // The function address is followed by a ULEB representing the stack 67318bcb0991SDimitry Andric // size. Check for an extra byte before we try to process the entry. 67328bcb0991SDimitry Andric if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) { 6733e8d8bef9SDimitry Andric reportUniqueWarning( 6734e8d8bef9SDimitry Andric describe(Sec) + 6735e8d8bef9SDimitry Andric " ended while trying to extract a stack size entry"); 6736e8d8bef9SDimitry Andric break; 67378bcb0991SDimitry Andric } 67388bcb0991SDimitry Andric uint64_t SymValue = Data.getAddress(&Offset); 6739bdd1243dSDimitry Andric if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec, 6740bdd1243dSDimitry Andric Data, &Offset)) 6741e8d8bef9SDimitry Andric break; 67428bcb0991SDimitry Andric } 67438bcb0991SDimitry Andric } 67448bcb0991SDimitry Andric } 67458bcb0991SDimitry Andric 67468bcb0991SDimitry Andric template <class ELFT> 6747fe6060f1SDimitry Andric void ELFDumper<ELFT>::printRelocatableStackSizes( 6748fe6060f1SDimitry Andric std::function<void()> PrintHeader) { 6749fe6060f1SDimitry Andric // Build a map between stack size sections and their corresponding relocation 6750fe6060f1SDimitry Andric // sections. 6751fe6060f1SDimitry Andric auto IsMatch = [&](const Elf_Shdr &Sec) -> bool { 6752fe6060f1SDimitry Andric StringRef SectionName; 6753fe6060f1SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec)) 6754fe6060f1SDimitry Andric SectionName = *NameOrErr; 6755fe6060f1SDimitry Andric else 6756fe6060f1SDimitry Andric consumeError(NameOrErr.takeError()); 6757fe6060f1SDimitry Andric 6758fe6060f1SDimitry Andric return SectionName == ".stack_sizes"; 6759fe6060f1SDimitry Andric }; 67608bcb0991SDimitry Andric 676106c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> 676206c3fb27SDimitry Andric StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch); 676306c3fb27SDimitry Andric if (!StackSizeRelocMapOrErr) { 676406c3fb27SDimitry Andric reportUniqueWarning("unable to get stack size map section(s): " + 676506c3fb27SDimitry Andric toString(StackSizeRelocMapOrErr.takeError())); 676606c3fb27SDimitry Andric return; 676706c3fb27SDimitry Andric } 676806c3fb27SDimitry Andric 676906c3fb27SDimitry Andric for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) { 67708bcb0991SDimitry Andric PrintHeader(); 6771e8d8bef9SDimitry Andric const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first; 6772e8d8bef9SDimitry Andric const Elf_Shdr *RelocSec = StackSizeMapEntry.second; 67738bcb0991SDimitry Andric 67748bcb0991SDimitry Andric // Warn about stack size sections without a relocation section. 6775e8d8bef9SDimitry Andric if (!RelocSec) { 6776e8d8bef9SDimitry Andric reportWarning(createError(".stack_sizes (" + describe(*StackSizesELFSec) + 6777e8d8bef9SDimitry Andric ") does not have a corresponding " 67788bcb0991SDimitry Andric "relocation section"), 6779e8d8bef9SDimitry Andric FileName); 67808bcb0991SDimitry Andric continue; 67818bcb0991SDimitry Andric } 67828bcb0991SDimitry Andric 67838bcb0991SDimitry Andric // A .stack_sizes section header's sh_link field is supposed to point 67848bcb0991SDimitry Andric // to the section that contains the functions whose stack sizes are 67858bcb0991SDimitry Andric // described in it. 6786e8d8bef9SDimitry Andric const Elf_Shdr *FunctionSec = unwrapOrError( 6787e8d8bef9SDimitry Andric this->FileName, Obj.getSection(StackSizesELFSec->sh_link)); 67888bcb0991SDimitry Andric 6789e8d8bef9SDimitry Andric SupportsRelocation IsSupportedFn; 67908bcb0991SDimitry Andric RelocationResolver Resolver; 6791e8d8bef9SDimitry Andric std::tie(IsSupportedFn, Resolver) = getRelocationResolver(this->ObjF); 6792e8d8bef9SDimitry Andric ArrayRef<uint8_t> Contents = 6793e8d8bef9SDimitry Andric unwrapOrError(this->FileName, Obj.getSectionContents(*StackSizesELFSec)); 6794e8d8bef9SDimitry Andric DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr)); 6795e8d8bef9SDimitry Andric 6796e8d8bef9SDimitry Andric forEachRelocationDo( 6797*0fca6ea1SDimitry Andric *RelocSec, [&](const Relocation<ELFT> &R, unsigned Ndx, 6798*0fca6ea1SDimitry Andric const Elf_Shdr &Sec, const Elf_Shdr *SymTab) { 6799e8d8bef9SDimitry Andric if (!IsSupportedFn || !IsSupportedFn(R.Type)) { 6800e8d8bef9SDimitry Andric reportUniqueWarning( 6801e8d8bef9SDimitry Andric describe(*RelocSec) + 6802e8d8bef9SDimitry Andric " contains an unsupported relocation with index " + Twine(Ndx) + 6803e8d8bef9SDimitry Andric ": " + Obj.getRelocationTypeName(R.Type)); 6804e8d8bef9SDimitry Andric return; 68058bcb0991SDimitry Andric } 6806e8d8bef9SDimitry Andric 6807e8d8bef9SDimitry Andric this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec, 6808e8d8bef9SDimitry Andric *StackSizesELFSec, Resolver, Data); 6809e8d8bef9SDimitry Andric }); 68108bcb0991SDimitry Andric } 68118bcb0991SDimitry Andric } 68128bcb0991SDimitry Andric 68138bcb0991SDimitry Andric template <class ELFT> 6814e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printStackSizes() { 68158bcb0991SDimitry Andric bool HeaderHasBeenPrinted = false; 68168bcb0991SDimitry Andric auto PrintHeader = [&]() { 68178bcb0991SDimitry Andric if (HeaderHasBeenPrinted) 68188bcb0991SDimitry Andric return; 68198bcb0991SDimitry Andric OS << "\nStack Sizes:\n"; 68208bcb0991SDimitry Andric OS.PadToColumn(9); 68218bcb0991SDimitry Andric OS << "Size"; 68228bcb0991SDimitry Andric OS.PadToColumn(18); 6823fe6060f1SDimitry Andric OS << "Functions\n"; 68248bcb0991SDimitry Andric HeaderHasBeenPrinted = true; 68258bcb0991SDimitry Andric }; 68268bcb0991SDimitry Andric 68278bcb0991SDimitry Andric // For non-relocatable objects, look directly for sections whose name starts 68288bcb0991SDimitry Andric // with .stack_sizes and process the contents. 6829e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_type == ELF::ET_REL) 6830e8d8bef9SDimitry Andric this->printRelocatableStackSizes(PrintHeader); 68318bcb0991SDimitry Andric else 6832e8d8bef9SDimitry Andric this->printNonRelocatableStackSizes(PrintHeader); 68338bcb0991SDimitry Andric } 68348bcb0991SDimitry Andric 68350b57cec5SDimitry Andric template <class ELFT> 6836e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 68370b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 68380b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 68390b57cec5SDimitry Andric OS.PadToColumn(2); 68400b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); 68410b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 68420b57cec5SDimitry Andric OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; 68430b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 68440b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 68450b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 68460b57cec5SDimitry Andric OS << Purpose << "\n"; 68470b57cec5SDimitry Andric }; 68480b57cec5SDimitry Andric 68490b57cec5SDimitry Andric OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); 68500b57cec5SDimitry Andric OS << " Canonical gp value: " 68510b57cec5SDimitry Andric << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; 68520b57cec5SDimitry Andric 68530b57cec5SDimitry Andric OS << " Reserved entries:\n"; 68540b57cec5SDimitry Andric if (ELFT::Is64Bits) 68550b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 68560b57cec5SDimitry Andric else 68570b57cec5SDimitry Andric OS << " Address Access Initial Purpose\n"; 68580b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); 68590b57cec5SDimitry Andric if (Parser.getGotModulePointer()) 68600b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); 68610b57cec5SDimitry Andric 68620b57cec5SDimitry Andric if (!Parser.getLocalEntries().empty()) { 68630b57cec5SDimitry Andric OS << "\n"; 68640b57cec5SDimitry Andric OS << " Local entries:\n"; 68650b57cec5SDimitry Andric if (ELFT::Is64Bits) 68660b57cec5SDimitry Andric OS << " Address Access Initial\n"; 68670b57cec5SDimitry Andric else 68680b57cec5SDimitry Andric OS << " Address Access Initial\n"; 68690b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) 68700b57cec5SDimitry Andric PrintEntry(&E, ""); 68710b57cec5SDimitry Andric } 68720b57cec5SDimitry Andric 68730b57cec5SDimitry Andric if (Parser.IsStatic) 68740b57cec5SDimitry Andric return; 68750b57cec5SDimitry Andric 68760b57cec5SDimitry Andric if (!Parser.getGlobalEntries().empty()) { 68770b57cec5SDimitry Andric OS << "\n"; 68780b57cec5SDimitry Andric OS << " Global entries:\n"; 68790b57cec5SDimitry Andric if (ELFT::Is64Bits) 68800b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val." 68810b57cec5SDimitry Andric << " Type Ndx Name\n"; 68820b57cec5SDimitry Andric else 68830b57cec5SDimitry Andric OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; 6884e8d8bef9SDimitry Andric 6885e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 6886e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 68870b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 6888e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getGotSym(&E); 6889e8d8bef9SDimitry Andric const Elf_Sym &FirstSym = this->dynamic_symbols()[0]; 6890e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 6891e8d8bef9SDimitry Andric Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false); 68920b57cec5SDimitry Andric 68930b57cec5SDimitry Andric OS.PadToColumn(2); 68940b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); 68950b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 68960b57cec5SDimitry Andric OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; 68970b57cec5SDimitry Andric OS.PadToColumn(22 + Bias); 68980b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 68990b57cec5SDimitry Andric OS.PadToColumn(31 + 2 * Bias); 6900e8d8bef9SDimitry Andric OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias)); 69010b57cec5SDimitry Andric OS.PadToColumn(40 + 3 * Bias); 6902bdd1243dSDimitry Andric OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes)); 69030b57cec5SDimitry Andric OS.PadToColumn(48 + 3 * Bias); 6904e8d8bef9SDimitry Andric OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(), 6905e8d8bef9SDimitry Andric ShndxTable); 69060b57cec5SDimitry Andric OS.PadToColumn(52 + 3 * Bias); 69070b57cec5SDimitry Andric OS << SymName << "\n"; 69080b57cec5SDimitry Andric } 69090b57cec5SDimitry Andric } 69100b57cec5SDimitry Andric 69110b57cec5SDimitry Andric if (!Parser.getOtherEntries().empty()) 69120b57cec5SDimitry Andric OS << "\n Number of TLS and multi-GOT entries " 69130b57cec5SDimitry Andric << Parser.getOtherEntries().size() << "\n"; 69140b57cec5SDimitry Andric } 69150b57cec5SDimitry Andric 69160b57cec5SDimitry Andric template <class ELFT> 6917e8d8bef9SDimitry Andric void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 69180b57cec5SDimitry Andric size_t Bias = ELFT::Is64Bits ? 8 : 0; 69190b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { 69200b57cec5SDimitry Andric OS.PadToColumn(2); 69210b57cec5SDimitry Andric OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias); 69220b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 69230b57cec5SDimitry Andric OS << format_hex_no_prefix(*E, 8 + Bias); 69240b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 69250b57cec5SDimitry Andric OS << Purpose << "\n"; 69260b57cec5SDimitry Andric }; 69270b57cec5SDimitry Andric 69280b57cec5SDimitry Andric OS << "PLT GOT:\n\n"; 69290b57cec5SDimitry Andric 69300b57cec5SDimitry Andric OS << " Reserved entries:\n"; 69310b57cec5SDimitry Andric OS << " Address Initial Purpose\n"; 69320b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); 69330b57cec5SDimitry Andric if (Parser.getPltModulePointer()) 69340b57cec5SDimitry Andric PrintEntry(Parser.getPltModulePointer(), "Module pointer"); 69350b57cec5SDimitry Andric 69360b57cec5SDimitry Andric if (!Parser.getPltEntries().empty()) { 69370b57cec5SDimitry Andric OS << "\n"; 69380b57cec5SDimitry Andric OS << " Entries:\n"; 69390b57cec5SDimitry Andric OS << " Address Initial Sym.Val. Type Ndx Name\n"; 6940e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 6941e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 69420b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 6943e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getPltSym(&E); 6944e8d8bef9SDimitry Andric const Elf_Sym &FirstSym = *cantFail( 6945e8d8bef9SDimitry Andric this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0)); 6946e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 6947e8d8bef9SDimitry Andric Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false); 69480b57cec5SDimitry Andric 69490b57cec5SDimitry Andric OS.PadToColumn(2); 69500b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias)); 69510b57cec5SDimitry Andric OS.PadToColumn(11 + Bias); 69520b57cec5SDimitry Andric OS << to_string(format_hex_no_prefix(E, 8 + Bias)); 69530b57cec5SDimitry Andric OS.PadToColumn(20 + 2 * Bias); 6954e8d8bef9SDimitry Andric OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias)); 69550b57cec5SDimitry Andric OS.PadToColumn(29 + 3 * Bias); 6956bdd1243dSDimitry Andric OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes)); 69570b57cec5SDimitry Andric OS.PadToColumn(37 + 3 * Bias); 6958e8d8bef9SDimitry Andric OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(), 6959e8d8bef9SDimitry Andric ShndxTable); 69600b57cec5SDimitry Andric OS.PadToColumn(41 + 3 * Bias); 69610b57cec5SDimitry Andric OS << SymName << "\n"; 69620b57cec5SDimitry Andric } 69630b57cec5SDimitry Andric } 69640b57cec5SDimitry Andric } 69650b57cec5SDimitry Andric 69668bcb0991SDimitry Andric template <class ELFT> 6967e8d8bef9SDimitry Andric Expected<const Elf_Mips_ABIFlags<ELFT> *> 6968e8d8bef9SDimitry Andric getMipsAbiFlagsSection(const ELFDumper<ELFT> &Dumper) { 6969e8d8bef9SDimitry Andric const typename ELFT::Shdr *Sec = Dumper.findSectionByName(".MIPS.abiflags"); 6970e8d8bef9SDimitry Andric if (Sec == nullptr) 6971e8d8bef9SDimitry Andric return nullptr; 6972e8d8bef9SDimitry Andric 6973e8d8bef9SDimitry Andric constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: "; 6974e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> DataOrErr = 6975e8d8bef9SDimitry Andric Dumper.getElfObject().getELFFile().getSectionContents(*Sec); 6976e8d8bef9SDimitry Andric if (!DataOrErr) 6977e8d8bef9SDimitry Andric return createError(ErrPrefix + toString(DataOrErr.takeError())); 6978e8d8bef9SDimitry Andric 6979e8d8bef9SDimitry Andric if (DataOrErr->size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) 6980e8d8bef9SDimitry Andric return createError(ErrPrefix + "it has a wrong size (" + 6981e8d8bef9SDimitry Andric Twine(DataOrErr->size()) + ")"); 6982e8d8bef9SDimitry Andric return reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(DataOrErr->data()); 6983e8d8bef9SDimitry Andric } 6984e8d8bef9SDimitry Andric 6985e8d8bef9SDimitry Andric template <class ELFT> void GNUELFDumper<ELFT>::printMipsABIFlags() { 6986e8d8bef9SDimitry Andric const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr; 6987e8d8bef9SDimitry Andric if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr = 6988e8d8bef9SDimitry Andric getMipsAbiFlagsSection(*this)) 6989e8d8bef9SDimitry Andric Flags = *SecOrErr; 6990e8d8bef9SDimitry Andric else 6991e8d8bef9SDimitry Andric this->reportUniqueWarning(SecOrErr.takeError()); 6992e8d8bef9SDimitry Andric if (!Flags) 69938bcb0991SDimitry Andric return; 69948bcb0991SDimitry Andric 69958bcb0991SDimitry Andric OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n"; 69968bcb0991SDimitry Andric OS << "ISA: MIPS" << int(Flags->isa_level); 69978bcb0991SDimitry Andric if (Flags->isa_rev > 1) 69988bcb0991SDimitry Andric OS << "r" << int(Flags->isa_rev); 69998bcb0991SDimitry Andric OS << "\n"; 70008bcb0991SDimitry Andric OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n"; 70018bcb0991SDimitry Andric OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n"; 70028bcb0991SDimitry Andric OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n"; 7003bdd1243dSDimitry Andric OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType)) 7004bdd1243dSDimitry Andric << "\n"; 70058bcb0991SDimitry Andric OS << "ISA Extension: " 7006bdd1243dSDimitry Andric << enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n"; 70078bcb0991SDimitry Andric if (Flags->ases == 0) 70088bcb0991SDimitry Andric OS << "ASEs: None\n"; 70098bcb0991SDimitry Andric else 70108bcb0991SDimitry Andric // FIXME: Print each flag on a separate line. 7011bdd1243dSDimitry Andric OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags)) 70128bcb0991SDimitry Andric << "\n"; 70138bcb0991SDimitry Andric OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n"; 70148bcb0991SDimitry Andric OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n"; 70158bcb0991SDimitry Andric OS << "\n"; 70168bcb0991SDimitry Andric } 70178bcb0991SDimitry Andric 7018e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printFileHeaders() { 7019e8d8bef9SDimitry Andric const Elf_Ehdr &E = this->Obj.getHeader(); 70200b57cec5SDimitry Andric { 70210b57cec5SDimitry Andric DictScope D(W, "ElfHeader"); 70220b57cec5SDimitry Andric { 70230b57cec5SDimitry Andric DictScope D(W, "Ident"); 7024bdd1243dSDimitry Andric W.printBinary("Magic", 7025bdd1243dSDimitry Andric ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4)); 7026bdd1243dSDimitry Andric W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass)); 7027e8d8bef9SDimitry Andric W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA], 7028bdd1243dSDimitry Andric ArrayRef(ElfDataEncoding)); 7029e8d8bef9SDimitry Andric W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]); 70300b57cec5SDimitry Andric 7031bdd1243dSDimitry Andric auto OSABI = ArrayRef(ElfOSABI); 7032e8d8bef9SDimitry Andric if (E.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && 7033e8d8bef9SDimitry Andric E.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { 7034e8d8bef9SDimitry Andric switch (E.e_machine) { 70350b57cec5SDimitry Andric case ELF::EM_AMDGPU: 7036bdd1243dSDimitry Andric OSABI = ArrayRef(AMDGPUElfOSABI); 70370b57cec5SDimitry Andric break; 70380b57cec5SDimitry Andric case ELF::EM_ARM: 7039bdd1243dSDimitry Andric OSABI = ArrayRef(ARMElfOSABI); 70400b57cec5SDimitry Andric break; 70410b57cec5SDimitry Andric case ELF::EM_TI_C6000: 7042bdd1243dSDimitry Andric OSABI = ArrayRef(C6000ElfOSABI); 70430b57cec5SDimitry Andric break; 70440b57cec5SDimitry Andric } 70450b57cec5SDimitry Andric } 7046e8d8bef9SDimitry Andric W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI); 7047e8d8bef9SDimitry Andric W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]); 7048bdd1243dSDimitry Andric W.printBinary("Unused", 7049bdd1243dSDimitry Andric ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD)); 70500b57cec5SDimitry Andric } 70510b57cec5SDimitry Andric 7052e8d8bef9SDimitry Andric std::string TypeStr; 7053e8d8bef9SDimitry Andric if (const EnumEntry<unsigned> *Ent = getObjectFileEnumEntry(E.e_type)) { 7054e8d8bef9SDimitry Andric TypeStr = Ent->Name.str(); 7055e8d8bef9SDimitry Andric } else { 7056e8d8bef9SDimitry Andric if (E.e_type >= ET_LOPROC) 7057e8d8bef9SDimitry Andric TypeStr = "Processor Specific"; 7058e8d8bef9SDimitry Andric else if (E.e_type >= ET_LOOS) 7059e8d8bef9SDimitry Andric TypeStr = "OS Specific"; 7060e8d8bef9SDimitry Andric else 7061e8d8bef9SDimitry Andric TypeStr = "Unknown"; 7062e8d8bef9SDimitry Andric } 706381ad6265SDimitry Andric W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")"); 7064e8d8bef9SDimitry Andric 7065bdd1243dSDimitry Andric W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType)); 7066e8d8bef9SDimitry Andric W.printNumber("Version", E.e_version); 7067e8d8bef9SDimitry Andric W.printHex("Entry", E.e_entry); 7068e8d8bef9SDimitry Andric W.printHex("ProgramHeaderOffset", E.e_phoff); 7069e8d8bef9SDimitry Andric W.printHex("SectionHeaderOffset", E.e_shoff); 7070e8d8bef9SDimitry Andric if (E.e_machine == EM_MIPS) 7071bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags), 70720b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), 70730b57cec5SDimitry Andric unsigned(ELF::EF_MIPS_MACH)); 7074fe6060f1SDimitry Andric else if (E.e_machine == EM_AMDGPU) { 7075fe6060f1SDimitry Andric switch (E.e_ident[ELF::EI_ABIVERSION]) { 7076fe6060f1SDimitry Andric default: 7077fe6060f1SDimitry Andric W.printHex("Flags", E.e_flags); 7078fe6060f1SDimitry Andric break; 7079fe6060f1SDimitry Andric case 0: 7080fe6060f1SDimitry Andric // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags. 7081bdd1243dSDimitry Andric [[fallthrough]]; 7082fe6060f1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V3: 7083fe6060f1SDimitry Andric W.printFlags("Flags", E.e_flags, 7084bdd1243dSDimitry Andric ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3), 70850b57cec5SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH)); 7086fe6060f1SDimitry Andric break; 7087fe6060f1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V4: 70881fd87a68SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V5: 7089fe6060f1SDimitry Andric W.printFlags("Flags", E.e_flags, 7090bdd1243dSDimitry Andric ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4), 7091fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH), 7092fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4), 7093fe6060f1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4)); 7094fe6060f1SDimitry Andric break; 7095*0fca6ea1SDimitry Andric case ELF::ELFABIVERSION_AMDGPU_HSA_V6: { 7096*0fca6ea1SDimitry Andric std::optional<FlagEntry> VerFlagEntry; 7097*0fca6ea1SDimitry Andric // The string needs to remain alive from the moment we create a 7098*0fca6ea1SDimitry Andric // FlagEntry until printFlags is done. 7099*0fca6ea1SDimitry Andric std::string FlagStr; 7100*0fca6ea1SDimitry Andric if (auto VersionFlag = E.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) { 7101*0fca6ea1SDimitry Andric unsigned Version = 7102*0fca6ea1SDimitry Andric VersionFlag >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET; 7103*0fca6ea1SDimitry Andric FlagStr = "EF_AMDGPU_GENERIC_VERSION_V" + std::to_string(Version); 7104*0fca6ea1SDimitry Andric VerFlagEntry = FlagEntry(FlagStr, VersionFlag); 7105*0fca6ea1SDimitry Andric } 7106*0fca6ea1SDimitry Andric W.printFlags( 7107*0fca6ea1SDimitry Andric "Flags", E.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4), 7108*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_MACH), 7109*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4), 7110*0fca6ea1SDimitry Andric unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4), 7111*0fca6ea1SDimitry Andric VerFlagEntry ? ArrayRef(*VerFlagEntry) : ArrayRef<FlagEntry>()); 7112*0fca6ea1SDimitry Andric break; 7113*0fca6ea1SDimitry Andric } 7114fe6060f1SDimitry Andric } 7115fe6060f1SDimitry Andric } else if (E.e_machine == EM_RISCV) 7116bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags)); 7117fe6060f1SDimitry Andric else if (E.e_machine == EM_AVR) 7118bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags), 7119fe6060f1SDimitry Andric unsigned(ELF::EF_AVR_ARCH_MASK)); 7120972a253aSDimitry Andric else if (E.e_machine == EM_LOONGARCH) 7121bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags), 7122bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK), 7123bdd1243dSDimitry Andric unsigned(ELF::EF_LOONGARCH_OBJABI_MASK)); 7124bdd1243dSDimitry Andric else if (E.e_machine == EM_XTENSA) 7125bdd1243dSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags), 7126bdd1243dSDimitry Andric unsigned(ELF::EF_XTENSA_MACH)); 71275f757f3fSDimitry Andric else if (E.e_machine == EM_CUDA) 71285f757f3fSDimitry Andric W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderNVPTXFlags), 71295f757f3fSDimitry Andric unsigned(ELF::EF_CUDA_SM)); 71300b57cec5SDimitry Andric else 7131e8d8bef9SDimitry Andric W.printFlags("Flags", E.e_flags); 7132e8d8bef9SDimitry Andric W.printNumber("HeaderSize", E.e_ehsize); 7133e8d8bef9SDimitry Andric W.printNumber("ProgramHeaderEntrySize", E.e_phentsize); 7134e8d8bef9SDimitry Andric W.printNumber("ProgramHeaderCount", E.e_phnum); 7135e8d8bef9SDimitry Andric W.printNumber("SectionHeaderEntrySize", E.e_shentsize); 71368bcb0991SDimitry Andric W.printString("SectionHeaderCount", 7137e8d8bef9SDimitry Andric getSectionHeadersNumString(this->Obj, this->FileName)); 71380b57cec5SDimitry Andric W.printString("StringTableSectionIndex", 7139e8d8bef9SDimitry Andric getSectionHeaderTableIndexString(this->Obj, this->FileName)); 71400b57cec5SDimitry Andric } 71410b57cec5SDimitry Andric } 71420b57cec5SDimitry Andric 7143e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() { 71440b57cec5SDimitry Andric DictScope Lists(W, "Groups"); 7145e8d8bef9SDimitry Andric std::vector<GroupSection> V = this->getGroups(); 71460b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); 71470b57cec5SDimitry Andric for (const GroupSection &G : V) { 71480b57cec5SDimitry Andric DictScope D(W, "Group"); 71490b57cec5SDimitry Andric W.printNumber("Name", G.Name, G.ShName); 71500b57cec5SDimitry Andric W.printNumber("Index", G.Index); 71510b57cec5SDimitry Andric W.printNumber("Link", G.Link); 71520b57cec5SDimitry Andric W.printNumber("Info", G.Info); 71530b57cec5SDimitry Andric W.printHex("Type", getGroupType(G.Type), G.Type); 715406c3fb27SDimitry Andric W.printString("Signature", G.Signature); 71550b57cec5SDimitry Andric 715606c3fb27SDimitry Andric ListScope L(W, getGroupSectionHeaderName()); 71570b57cec5SDimitry Andric for (const GroupMember &GM : G.Members) { 71580b57cec5SDimitry Andric const GroupSection *MainGroup = Map[GM.Index]; 7159e8d8bef9SDimitry Andric if (MainGroup != &G) 7160e8d8bef9SDimitry Andric this->reportUniqueWarning( 7161e8d8bef9SDimitry Andric "section with index " + Twine(GM.Index) + 7162e8d8bef9SDimitry Andric ", included in the group section with index " + 7163e8d8bef9SDimitry Andric Twine(MainGroup->Index) + 7164e8d8bef9SDimitry Andric ", was also found in the group section with index " + 7165e8d8bef9SDimitry Andric Twine(G.Index)); 716606c3fb27SDimitry Andric printSectionGroupMembers(GM.Name, GM.Index); 71670b57cec5SDimitry Andric } 71680b57cec5SDimitry Andric } 71690b57cec5SDimitry Andric 71700b57cec5SDimitry Andric if (V.empty()) 717106c3fb27SDimitry Andric printEmptyGroupMessage(); 717206c3fb27SDimitry Andric } 717306c3fb27SDimitry Andric 717406c3fb27SDimitry Andric template <class ELFT> 717506c3fb27SDimitry Andric std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const { 717606c3fb27SDimitry Andric return "Section(s) in group"; 717706c3fb27SDimitry Andric } 717806c3fb27SDimitry Andric 717906c3fb27SDimitry Andric template <class ELFT> 718006c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name, 718106c3fb27SDimitry Andric uint64_t Idx) const { 718206c3fb27SDimitry Andric W.startLine() << Name << " (" << Idx << ")\n"; 71830b57cec5SDimitry Andric } 71840b57cec5SDimitry Andric 7185e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() { 71860b57cec5SDimitry Andric ListScope D(W, "Relocations"); 71870b57cec5SDimitry Andric 7188e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 71895f757f3fSDimitry Andric if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader())) 71900b57cec5SDimitry Andric continue; 71910b57cec5SDimitry Andric 7192e8d8bef9SDimitry Andric StringRef Name = this->getPrintableSectionName(Sec); 7193e8d8bef9SDimitry Andric unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front(); 719406c3fb27SDimitry Andric printRelocationSectionInfo(Sec, Name, SecNdx); 71950b57cec5SDimitry Andric } 71960b57cec5SDimitry Andric } 71970b57cec5SDimitry Andric 71980b57cec5SDimitry Andric template <class ELFT> 719906c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R, 720006c3fb27SDimitry Andric StringRef SymbolName, 720106c3fb27SDimitry Andric StringRef RelocName) { 72020b57cec5SDimitry Andric DictScope Group(W, "Relocation"); 7203e8d8bef9SDimitry Andric W.printHex("Offset", R.Offset); 7204e8d8bef9SDimitry Andric W.printNumber("Type", RelocName, R.Type); 7205e8d8bef9SDimitry Andric W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol); 7206e8d8bef9SDimitry Andric if (R.Addend) 7207e8d8bef9SDimitry Andric W.printHex("Addend", (uintX_t)*R.Addend); 720806c3fb27SDimitry Andric } 720906c3fb27SDimitry Andric 721006c3fb27SDimitry Andric template <class ELFT> 721106c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R, 721206c3fb27SDimitry Andric StringRef SymbolName, 721306c3fb27SDimitry Andric StringRef RelocName) { 72140b57cec5SDimitry Andric raw_ostream &OS = W.startLine(); 7215e8d8bef9SDimitry Andric OS << W.hex(R.Offset) << " " << RelocName << " " 7216e8d8bef9SDimitry Andric << (!SymbolName.empty() ? SymbolName : "-"); 7217e8d8bef9SDimitry Andric if (R.Addend) 7218e8d8bef9SDimitry Andric OS << " " << W.hex((uintX_t)*R.Addend); 7219e8d8bef9SDimitry Andric OS << "\n"; 72200b57cec5SDimitry Andric } 722106c3fb27SDimitry Andric 722206c3fb27SDimitry Andric template <class ELFT> 722306c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec, 722406c3fb27SDimitry Andric StringRef Name, 722506c3fb27SDimitry Andric const unsigned SecNdx) { 722606c3fb27SDimitry Andric DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str()); 722706c3fb27SDimitry Andric this->printRelocationsHelper(Sec); 722806c3fb27SDimitry Andric } 722906c3fb27SDimitry Andric 723006c3fb27SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const { 723106c3fb27SDimitry Andric W.startLine() << "There are no group sections in the file.\n"; 723206c3fb27SDimitry Andric } 723306c3fb27SDimitry Andric 723406c3fb27SDimitry Andric template <class ELFT> 723506c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R, 723606c3fb27SDimitry Andric const RelSymbol<ELFT> &RelSym) { 723706c3fb27SDimitry Andric StringRef SymbolName = RelSym.Name; 723806c3fb27SDimitry Andric if (RelSym.Sym && RelSym.Name.empty()) 723906c3fb27SDimitry Andric SymbolName = "<null>"; 724006c3fb27SDimitry Andric SmallString<32> RelocName; 724106c3fb27SDimitry Andric this->Obj.getRelocationTypeName(R.Type, RelocName); 724206c3fb27SDimitry Andric 724306c3fb27SDimitry Andric if (opts::ExpandRelocs) { 724406c3fb27SDimitry Andric printExpandedRelRelaReloc(R, SymbolName, RelocName); 724506c3fb27SDimitry Andric } else { 724606c3fb27SDimitry Andric printDefaultRelRelaReloc(R, SymbolName, RelocName); 724706c3fb27SDimitry Andric } 72480b57cec5SDimitry Andric } 72490b57cec5SDimitry Andric 7250e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() { 72510b57cec5SDimitry Andric ListScope SectionsD(W, "Sections"); 72520b57cec5SDimitry Andric 72530b57cec5SDimitry Andric int SectionIndex = -1; 7254480093f4SDimitry Andric std::vector<EnumEntry<unsigned>> FlagsList = 725581ad6265SDimitry Andric getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI], 725681ad6265SDimitry Andric this->Obj.getHeader().e_machine); 7257e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 72580b57cec5SDimitry Andric DictScope SectionD(W, "Section"); 72590b57cec5SDimitry Andric W.printNumber("Index", ++SectionIndex); 7260e8d8bef9SDimitry Andric W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name); 7261e8d8bef9SDimitry Andric W.printHex("Type", 7262e8d8bef9SDimitry Andric object::getELFSectionTypeName(this->Obj.getHeader().e_machine, 7263e8d8bef9SDimitry Andric Sec.sh_type), 72640b57cec5SDimitry Andric Sec.sh_type); 7265bdd1243dSDimitry Andric W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList)); 72660b57cec5SDimitry Andric W.printHex("Address", Sec.sh_addr); 72670b57cec5SDimitry Andric W.printHex("Offset", Sec.sh_offset); 72680b57cec5SDimitry Andric W.printNumber("Size", Sec.sh_size); 72690b57cec5SDimitry Andric W.printNumber("Link", Sec.sh_link); 72700b57cec5SDimitry Andric W.printNumber("Info", Sec.sh_info); 72710b57cec5SDimitry Andric W.printNumber("AddressAlignment", Sec.sh_addralign); 72720b57cec5SDimitry Andric W.printNumber("EntrySize", Sec.sh_entsize); 72730b57cec5SDimitry Andric 72740b57cec5SDimitry Andric if (opts::SectionRelocations) { 72750b57cec5SDimitry Andric ListScope D(W, "Relocations"); 7276e8d8bef9SDimitry Andric this->printRelocationsHelper(Sec); 72770b57cec5SDimitry Andric } 72780b57cec5SDimitry Andric 72790b57cec5SDimitry Andric if (opts::SectionSymbols) { 72800b57cec5SDimitry Andric ListScope D(W, "Symbols"); 7281e8d8bef9SDimitry Andric if (this->DotSymtabSec) { 7282e8d8bef9SDimitry Andric StringRef StrTable = unwrapOrError( 7283e8d8bef9SDimitry Andric this->FileName, 7284e8d8bef9SDimitry Andric this->Obj.getStringTableForSymtab(*this->DotSymtabSec)); 7285e8d8bef9SDimitry Andric ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec); 72860b57cec5SDimitry Andric 7287e8d8bef9SDimitry Andric typename ELFT::SymRange Symbols = unwrapOrError( 7288e8d8bef9SDimitry Andric this->FileName, this->Obj.symbols(this->DotSymtabSec)); 7289e8d8bef9SDimitry Andric for (const Elf_Sym &Sym : Symbols) { 72900b57cec5SDimitry Andric const Elf_Shdr *SymSec = unwrapOrError( 72918bcb0991SDimitry Andric this->FileName, 7292e8d8bef9SDimitry Andric this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable)); 72930b57cec5SDimitry Andric if (SymSec == &Sec) 7294e8d8bef9SDimitry Andric printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false, 72955f757f3fSDimitry Andric /*NonVisibilityBitsUsed=*/false, 72965f757f3fSDimitry Andric /*ExtraSymInfo=*/false); 7297e8d8bef9SDimitry Andric } 72980b57cec5SDimitry Andric } 72990b57cec5SDimitry Andric } 73000b57cec5SDimitry Andric 73010b57cec5SDimitry Andric if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { 73028bcb0991SDimitry Andric ArrayRef<uint8_t> Data = 7303e8d8bef9SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec)); 73040b57cec5SDimitry Andric W.printBinaryBlock( 73050b57cec5SDimitry Andric "SectionData", 73060b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Data.data()), Data.size())); 73070b57cec5SDimitry Andric } 73080b57cec5SDimitry Andric } 73090b57cec5SDimitry Andric } 73100b57cec5SDimitry Andric 73110b57cec5SDimitry Andric template <class ELFT> 7312e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbolSection( 7313e8d8bef9SDimitry Andric const Elf_Sym &Symbol, unsigned SymIndex, 7314e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable) const { 7315bdd1243dSDimitry Andric auto GetSectionSpecialType = [&]() -> std::optional<StringRef> { 7316e8d8bef9SDimitry Andric if (Symbol.isUndefined()) 7317e8d8bef9SDimitry Andric return StringRef("Undefined"); 7318e8d8bef9SDimitry Andric if (Symbol.isProcessorSpecific()) 7319e8d8bef9SDimitry Andric return StringRef("Processor Specific"); 7320e8d8bef9SDimitry Andric if (Symbol.isOSSpecific()) 7321e8d8bef9SDimitry Andric return StringRef("Operating System Specific"); 7322e8d8bef9SDimitry Andric if (Symbol.isAbsolute()) 7323e8d8bef9SDimitry Andric return StringRef("Absolute"); 7324e8d8bef9SDimitry Andric if (Symbol.isCommon()) 7325e8d8bef9SDimitry Andric return StringRef("Common"); 7326e8d8bef9SDimitry Andric if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX) 7327e8d8bef9SDimitry Andric return StringRef("Reserved"); 7328bdd1243dSDimitry Andric return std::nullopt; 7329e8d8bef9SDimitry Andric }; 7330e8d8bef9SDimitry Andric 7331bdd1243dSDimitry Andric if (std::optional<StringRef> Type = GetSectionSpecialType()) { 7332e8d8bef9SDimitry Andric W.printHex("Section", *Type, Symbol.st_shndx); 7333e8d8bef9SDimitry Andric return; 7334e8d8bef9SDimitry Andric } 7335e8d8bef9SDimitry Andric 7336480093f4SDimitry Andric Expected<unsigned> SectionIndex = 7337e8d8bef9SDimitry Andric this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable); 7338480093f4SDimitry Andric if (!SectionIndex) { 7339e8d8bef9SDimitry Andric assert(Symbol.st_shndx == SHN_XINDEX && 7340480093f4SDimitry Andric "getSymbolSectionIndex should only fail due to an invalid " 7341480093f4SDimitry Andric "SHT_SYMTAB_SHNDX table/reference"); 7342480093f4SDimitry Andric this->reportUniqueWarning(SectionIndex.takeError()); 7343480093f4SDimitry Andric W.printHex("Section", "Reserved", SHN_XINDEX); 7344480093f4SDimitry Andric return; 7345480093f4SDimitry Andric } 7346480093f4SDimitry Andric 7347480093f4SDimitry Andric Expected<StringRef> SectionName = 7348e8d8bef9SDimitry Andric this->getSymbolSectionName(Symbol, *SectionIndex); 7349480093f4SDimitry Andric if (!SectionName) { 73505ffd83dbSDimitry Andric // Don't report an invalid section name if the section headers are missing. 73515ffd83dbSDimitry Andric // In such situations, all sections will be "invalid". 7352e8d8bef9SDimitry Andric if (!this->ObjF.sections().empty()) 7353480093f4SDimitry Andric this->reportUniqueWarning(SectionName.takeError()); 73545ffd83dbSDimitry Andric else 73555ffd83dbSDimitry Andric consumeError(SectionName.takeError()); 7356480093f4SDimitry Andric W.printHex("Section", "<?>", *SectionIndex); 7357480093f4SDimitry Andric } else { 7358480093f4SDimitry Andric W.printHex("Section", *SectionName, *SectionIndex); 7359480093f4SDimitry Andric } 7360480093f4SDimitry Andric } 7361480093f4SDimitry Andric 7362480093f4SDimitry Andric template <class ELFT> 736306c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const { 736406c3fb27SDimitry Andric std::vector<EnumEntry<unsigned>> SymOtherFlags = 736506c3fb27SDimitry Andric this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol); 736606c3fb27SDimitry Andric W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u); 736706c3fb27SDimitry Andric } 736806c3fb27SDimitry Andric 736906c3fb27SDimitry Andric template <class ELFT> 737006c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printZeroSymbolOtherField( 737106c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 737206c3fb27SDimitry Andric assert(Symbol.st_other == 0 && "non-zero Other Field"); 737306c3fb27SDimitry Andric // Usually st_other flag is zero. Do not pollute the output 737406c3fb27SDimitry Andric // by flags enumeration in that case. 737506c3fb27SDimitry Andric W.printNumber("Other", 0); 737606c3fb27SDimitry Andric } 737706c3fb27SDimitry Andric 737806c3fb27SDimitry Andric template <class ELFT> 7379e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, 7380e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable, 7381bdd1243dSDimitry Andric std::optional<StringRef> StrTable, 7382e8d8bef9SDimitry Andric bool IsDynamic, 73835f757f3fSDimitry Andric bool /*NonVisibilityBitsUsed*/, 73845f757f3fSDimitry Andric bool /*ExtraSymInfo*/) const { 7385e8d8bef9SDimitry Andric std::string FullSymbolName = this->getFullSymbolName( 7386e8d8bef9SDimitry Andric Symbol, SymIndex, ShndxTable, StrTable, IsDynamic); 7387e8d8bef9SDimitry Andric unsigned char SymbolType = Symbol.getType(); 73880b57cec5SDimitry Andric 73890b57cec5SDimitry Andric DictScope D(W, "Symbol"); 7390e8d8bef9SDimitry Andric W.printNumber("Name", FullSymbolName, Symbol.st_name); 7391e8d8bef9SDimitry Andric W.printHex("Value", Symbol.st_value); 7392e8d8bef9SDimitry Andric W.printNumber("Size", Symbol.st_size); 7393bdd1243dSDimitry Andric W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings)); 7394e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && 73950b57cec5SDimitry Andric SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) 7396bdd1243dSDimitry Andric W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes)); 73970b57cec5SDimitry Andric else 7398bdd1243dSDimitry Andric W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes)); 7399e8d8bef9SDimitry Andric if (Symbol.st_other == 0) 740006c3fb27SDimitry Andric printZeroSymbolOtherField(Symbol); 74010b57cec5SDimitry Andric else 740206c3fb27SDimitry Andric printSymbolOtherField(Symbol); 7403e8d8bef9SDimitry Andric printSymbolSection(Symbol, SymIndex, ShndxTable); 74040b57cec5SDimitry Andric } 74050b57cec5SDimitry Andric 74060b57cec5SDimitry Andric template <class ELFT> 7407e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols, 74085f757f3fSDimitry Andric bool PrintDynamicSymbols, 74095f757f3fSDimitry Andric bool ExtraSymInfo) { 7410e8d8bef9SDimitry Andric if (PrintSymbols) { 74110b57cec5SDimitry Andric ListScope Group(W, "Symbols"); 74125f757f3fSDimitry Andric this->printSymbolsHelper(false, ExtraSymInfo); 74130b57cec5SDimitry Andric } 7414e8d8bef9SDimitry Andric if (PrintDynamicSymbols) { 74150b57cec5SDimitry Andric ListScope Group(W, "DynamicSymbols"); 74165f757f3fSDimitry Andric this->printSymbolsHelper(true, ExtraSymInfo); 7417e8d8bef9SDimitry Andric } 74180b57cec5SDimitry Andric } 74190b57cec5SDimitry Andric 7420e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() { 7421e8d8bef9SDimitry Andric Elf_Dyn_Range Table = this->dynamic_table(); 74220b57cec5SDimitry Andric if (Table.empty()) 74230b57cec5SDimitry Andric return; 74240b57cec5SDimitry Andric 74250b57cec5SDimitry Andric W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n"; 74260b57cec5SDimitry Andric 7427e8d8bef9SDimitry Andric size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table); 74285ffd83dbSDimitry Andric // The "Name/Value" column should be indented from the "Type" column by N 74295ffd83dbSDimitry Andric // spaces, where N = MaxTagSize - length of "Type" (4) + trailing 74305ffd83dbSDimitry Andric // space (1) = -3. 74315ffd83dbSDimitry Andric W.startLine() << " Tag" << std::string(ELFT::Is64Bits ? 16 : 8, ' ') 74325ffd83dbSDimitry Andric << "Type" << std::string(MaxTagSize - 3, ' ') << "Name/Value\n"; 74335ffd83dbSDimitry Andric 74345ffd83dbSDimitry Andric std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s "; 74350b57cec5SDimitry Andric for (auto Entry : Table) { 74360b57cec5SDimitry Andric uintX_t Tag = Entry.getTag(); 7437e8d8bef9SDimitry Andric std::string Value = this->getDynamicEntry(Tag, Entry.getVal()); 74385ffd83dbSDimitry Andric W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true) 74395ffd83dbSDimitry Andric << " " 74405ffd83dbSDimitry Andric << format(ValueFmt.c_str(), 7441e8d8bef9SDimitry Andric this->Obj.getDynamicTagAsString(Tag).c_str()) 74425ffd83dbSDimitry Andric << Value << "\n"; 74430b57cec5SDimitry Andric } 74440b57cec5SDimitry Andric W.startLine() << "]\n"; 74450b57cec5SDimitry Andric } 74460b57cec5SDimitry Andric 7447*0fca6ea1SDimitry Andric template <class ELFT> 7448*0fca6ea1SDimitry Andric void JSONELFDumper<ELFT>::printAuxillaryDynamicTableEntryInfo( 7449*0fca6ea1SDimitry Andric const Elf_Dyn &Entry) { 7450*0fca6ea1SDimitry Andric auto FormatFlags = [this, Value = Entry.getVal()](auto Flags) { 7451*0fca6ea1SDimitry Andric ListScope L(this->W, "Flags"); 7452*0fca6ea1SDimitry Andric for (const auto &Flag : Flags) { 7453*0fca6ea1SDimitry Andric if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value) 7454*0fca6ea1SDimitry Andric this->W.printString(Flag.Name); 7455*0fca6ea1SDimitry Andric } 7456*0fca6ea1SDimitry Andric }; 7457*0fca6ea1SDimitry Andric switch (Entry.getTag()) { 7458*0fca6ea1SDimitry Andric case DT_SONAME: 7459*0fca6ea1SDimitry Andric this->W.printString("Name", this->getDynamicString(Entry.getVal())); 7460*0fca6ea1SDimitry Andric break; 7461*0fca6ea1SDimitry Andric case DT_AUXILIARY: 7462*0fca6ea1SDimitry Andric case DT_FILTER: 7463*0fca6ea1SDimitry Andric case DT_NEEDED: 7464*0fca6ea1SDimitry Andric this->W.printString("Library", this->getDynamicString(Entry.getVal())); 7465*0fca6ea1SDimitry Andric break; 7466*0fca6ea1SDimitry Andric case DT_USED: 7467*0fca6ea1SDimitry Andric this->W.printString("Object", this->getDynamicString(Entry.getVal())); 7468*0fca6ea1SDimitry Andric break; 7469*0fca6ea1SDimitry Andric case DT_RPATH: 7470*0fca6ea1SDimitry Andric case DT_RUNPATH: { 7471*0fca6ea1SDimitry Andric StringRef Value = this->getDynamicString(Entry.getVal()); 7472*0fca6ea1SDimitry Andric ListScope L(this->W, "Path"); 7473*0fca6ea1SDimitry Andric while (!Value.empty()) { 7474*0fca6ea1SDimitry Andric auto [Front, Back] = Value.split(':'); 7475*0fca6ea1SDimitry Andric this->W.printString(Front); 7476*0fca6ea1SDimitry Andric Value = Back; 7477*0fca6ea1SDimitry Andric } 7478*0fca6ea1SDimitry Andric break; 7479*0fca6ea1SDimitry Andric } 7480*0fca6ea1SDimitry Andric case DT_FLAGS: 7481*0fca6ea1SDimitry Andric FormatFlags(ArrayRef(ElfDynamicDTFlags)); 7482*0fca6ea1SDimitry Andric break; 7483*0fca6ea1SDimitry Andric case DT_FLAGS_1: 7484*0fca6ea1SDimitry Andric FormatFlags(ArrayRef(ElfDynamicDTFlags1)); 7485*0fca6ea1SDimitry Andric break; 7486*0fca6ea1SDimitry Andric default: 7487*0fca6ea1SDimitry Andric return; 7488*0fca6ea1SDimitry Andric } 7489*0fca6ea1SDimitry Andric } 7490*0fca6ea1SDimitry Andric 7491*0fca6ea1SDimitry Andric template <class ELFT> void JSONELFDumper<ELFT>::printDynamicTable() { 7492*0fca6ea1SDimitry Andric Elf_Dyn_Range Table = this->dynamic_table(); 7493*0fca6ea1SDimitry Andric ListScope L(this->W, "DynamicSection"); 7494*0fca6ea1SDimitry Andric for (const auto &Entry : Table) { 7495*0fca6ea1SDimitry Andric DictScope D(this->W); 7496*0fca6ea1SDimitry Andric uintX_t Tag = Entry.getTag(); 7497*0fca6ea1SDimitry Andric this->W.printHex("Tag", Tag); 7498*0fca6ea1SDimitry Andric this->W.printString("Type", this->Obj.getDynamicTagAsString(Tag)); 7499*0fca6ea1SDimitry Andric this->W.printHex("Value", Entry.getVal()); 7500*0fca6ea1SDimitry Andric this->printAuxillaryDynamicTableEntryInfo(Entry); 7501*0fca6ea1SDimitry Andric } 7502*0fca6ea1SDimitry Andric } 7503*0fca6ea1SDimitry Andric 7504e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() { 75050b57cec5SDimitry Andric W.startLine() << "Dynamic Relocations {\n"; 75060b57cec5SDimitry Andric W.indent(); 7507e8d8bef9SDimitry Andric this->printDynamicRelocationsHelper(); 75080b57cec5SDimitry Andric W.unindent(); 75090b57cec5SDimitry Andric W.startLine() << "}\n"; 75100b57cec5SDimitry Andric } 75110b57cec5SDimitry Andric 75120b57cec5SDimitry Andric template <class ELFT> 7513e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printProgramHeaders( 7514e8d8bef9SDimitry Andric bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) { 75150b57cec5SDimitry Andric if (PrintProgramHeaders) 7516e8d8bef9SDimitry Andric printProgramHeaders(); 75170b57cec5SDimitry Andric if (PrintSectionMapping == cl::BOU_TRUE) 7518e8d8bef9SDimitry Andric printSectionMapping(); 75190b57cec5SDimitry Andric } 75200b57cec5SDimitry Andric 7521e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printProgramHeaders() { 75220b57cec5SDimitry Andric ListScope L(W, "ProgramHeaders"); 75230b57cec5SDimitry Andric 7524e8d8bef9SDimitry Andric Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers(); 75255ffd83dbSDimitry Andric if (!PhdrsOrErr) { 7526e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to dump program headers: " + 7527e8d8bef9SDimitry Andric toString(PhdrsOrErr.takeError())); 75285ffd83dbSDimitry Andric return; 75295ffd83dbSDimitry Andric } 75305ffd83dbSDimitry Andric 75315ffd83dbSDimitry Andric for (const Elf_Phdr &Phdr : *PhdrsOrErr) { 75320b57cec5SDimitry Andric DictScope P(W, "ProgramHeader"); 7533e8d8bef9SDimitry Andric StringRef Type = 7534e8d8bef9SDimitry Andric segmentTypeToString(this->Obj.getHeader().e_machine, Phdr.p_type); 7535e8d8bef9SDimitry Andric 7536e8d8bef9SDimitry Andric W.printHex("Type", Type.empty() ? "Unknown" : Type, Phdr.p_type); 75370b57cec5SDimitry Andric W.printHex("Offset", Phdr.p_offset); 75380b57cec5SDimitry Andric W.printHex("VirtualAddress", Phdr.p_vaddr); 75390b57cec5SDimitry Andric W.printHex("PhysicalAddress", Phdr.p_paddr); 75400b57cec5SDimitry Andric W.printNumber("FileSize", Phdr.p_filesz); 75410b57cec5SDimitry Andric W.printNumber("MemSize", Phdr.p_memsz); 7542bdd1243dSDimitry Andric W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags)); 75430b57cec5SDimitry Andric W.printNumber("Alignment", Phdr.p_align); 75440b57cec5SDimitry Andric } 75450b57cec5SDimitry Andric } 75460b57cec5SDimitry Andric 75470b57cec5SDimitry Andric template <class ELFT> 7548e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) { 75498bcb0991SDimitry Andric ListScope SS(W, "VersionSymbols"); 75500b57cec5SDimitry Andric if (!Sec) 75510b57cec5SDimitry Andric return; 75520b57cec5SDimitry Andric 7553480093f4SDimitry Andric StringRef StrTable; 7554480093f4SDimitry Andric ArrayRef<Elf_Sym> Syms; 7555e8d8bef9SDimitry Andric const Elf_Shdr *SymTabSec; 7556480093f4SDimitry Andric Expected<ArrayRef<Elf_Versym>> VerTableOrErr = 7557e8d8bef9SDimitry Andric this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec); 7558480093f4SDimitry Andric if (!VerTableOrErr) { 7559480093f4SDimitry Andric this->reportUniqueWarning(VerTableOrErr.takeError()); 7560480093f4SDimitry Andric return; 7561480093f4SDimitry Andric } 75620b57cec5SDimitry Andric 7563480093f4SDimitry Andric if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size()) 7564480093f4SDimitry Andric return; 7565480093f4SDimitry Andric 7566e8d8bef9SDimitry Andric ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec); 7567480093f4SDimitry Andric for (size_t I = 0, E = Syms.size(); I < E; ++I) { 75680b57cec5SDimitry Andric DictScope S(W, "Symbol"); 7569480093f4SDimitry Andric W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION); 7570e8d8bef9SDimitry Andric W.printString("Name", 7571e8d8bef9SDimitry Andric this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable, 7572e8d8bef9SDimitry Andric /*IsDynamic=*/true)); 75730b57cec5SDimitry Andric } 75740b57cec5SDimitry Andric } 75750b57cec5SDimitry Andric 7576349cc55cSDimitry Andric const EnumEntry<unsigned> SymVersionFlags[] = { 7577e8d8bef9SDimitry Andric {"Base", "BASE", VER_FLG_BASE}, 7578e8d8bef9SDimitry Andric {"Weak", "WEAK", VER_FLG_WEAK}, 7579e8d8bef9SDimitry Andric {"Info", "INFO", VER_FLG_INFO}}; 7580e8d8bef9SDimitry Andric 75810b57cec5SDimitry Andric template <class ELFT> 7582e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) { 75838bcb0991SDimitry Andric ListScope SD(W, "VersionDefinitions"); 75840b57cec5SDimitry Andric if (!Sec) 75850b57cec5SDimitry Andric return; 75860b57cec5SDimitry Andric 7587e8d8bef9SDimitry Andric Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec); 7588480093f4SDimitry Andric if (!V) { 7589480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 7590480093f4SDimitry Andric return; 75910b57cec5SDimitry Andric } 7592480093f4SDimitry Andric 7593480093f4SDimitry Andric for (const VerDef &D : *V) { 7594480093f4SDimitry Andric DictScope Def(W, "Definition"); 7595480093f4SDimitry Andric W.printNumber("Version", D.Version); 7596bdd1243dSDimitry Andric W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags)); 7597480093f4SDimitry Andric W.printNumber("Index", D.Ndx); 7598480093f4SDimitry Andric W.printNumber("Hash", D.Hash); 7599480093f4SDimitry Andric W.printString("Name", D.Name.c_str()); 7600480093f4SDimitry Andric W.printList( 7601480093f4SDimitry Andric "Predecessors", D.AuxV, 7602480093f4SDimitry Andric [](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); }); 76030b57cec5SDimitry Andric } 76040b57cec5SDimitry Andric } 76050b57cec5SDimitry Andric 76060b57cec5SDimitry Andric template <class ELFT> 7607e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) { 76088bcb0991SDimitry Andric ListScope SD(W, "VersionRequirements"); 76090b57cec5SDimitry Andric if (!Sec) 76100b57cec5SDimitry Andric return; 76110b57cec5SDimitry Andric 7612480093f4SDimitry Andric Expected<std::vector<VerNeed>> V = 7613e8d8bef9SDimitry Andric this->Obj.getVersionDependencies(*Sec, this->WarningHandler); 7614480093f4SDimitry Andric if (!V) { 7615480093f4SDimitry Andric this->reportUniqueWarning(V.takeError()); 7616480093f4SDimitry Andric return; 76170b57cec5SDimitry Andric } 7618480093f4SDimitry Andric 7619480093f4SDimitry Andric for (const VerNeed &VN : *V) { 7620480093f4SDimitry Andric DictScope Entry(W, "Dependency"); 7621480093f4SDimitry Andric W.printNumber("Version", VN.Version); 7622480093f4SDimitry Andric W.printNumber("Count", VN.Cnt); 7623480093f4SDimitry Andric W.printString("FileName", VN.File.c_str()); 7624480093f4SDimitry Andric 7625480093f4SDimitry Andric ListScope L(W, "Entries"); 7626480093f4SDimitry Andric for (const VernAux &Aux : VN.AuxV) { 7627480093f4SDimitry Andric DictScope Entry(W, "Entry"); 7628480093f4SDimitry Andric W.printNumber("Hash", Aux.Hash); 7629bdd1243dSDimitry Andric W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags)); 7630480093f4SDimitry Andric W.printNumber("Index", Aux.Other); 7631480093f4SDimitry Andric W.printString("Name", Aux.Name.c_str()); 7632480093f4SDimitry Andric } 76330b57cec5SDimitry Andric } 76340b57cec5SDimitry Andric } 76350b57cec5SDimitry Andric 763606c3fb27SDimitry Andric template <class ELFT> 763706c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket, 763806c3fb27SDimitry Andric size_t MaxChain, 763906c3fb27SDimitry Andric size_t TotalSyms, 764006c3fb27SDimitry Andric ArrayRef<size_t> Count, 764106c3fb27SDimitry Andric bool IsGnu) const { 764206c3fb27SDimitry Andric StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram"; 764306c3fb27SDimitry Andric StringRef BucketName = IsGnu ? "Bucket" : "Chain"; 764406c3fb27SDimitry Andric StringRef ListName = IsGnu ? "Buckets" : "Chains"; 764506c3fb27SDimitry Andric DictScope Outer(W, HistName); 764606c3fb27SDimitry Andric W.printNumber("TotalBuckets", NBucket); 764706c3fb27SDimitry Andric ListScope Buckets(W, ListName); 764806c3fb27SDimitry Andric size_t CumulativeNonZero = 0; 764906c3fb27SDimitry Andric for (size_t I = 0; I < MaxChain; ++I) { 765006c3fb27SDimitry Andric CumulativeNonZero += Count[I] * I; 765106c3fb27SDimitry Andric DictScope Bucket(W, BucketName); 765206c3fb27SDimitry Andric W.printNumber("Length", I); 765306c3fb27SDimitry Andric W.printNumber("Count", Count[I]); 765406c3fb27SDimitry Andric W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket); 765506c3fb27SDimitry Andric W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms); 765606c3fb27SDimitry Andric } 76570b57cec5SDimitry Andric } 76580b57cec5SDimitry Andric 7659fe6060f1SDimitry Andric // Returns true if rel/rela section exists, and populates SymbolIndices. 7660fe6060f1SDimitry Andric // Otherwise returns false. 7661fe6060f1SDimitry Andric template <class ELFT> 7662fe6060f1SDimitry Andric static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection, 7663fe6060f1SDimitry Andric const ELFFile<ELFT> &Obj, 7664fe6060f1SDimitry Andric const LLVMELFDumper<ELFT> *Dumper, 7665fe6060f1SDimitry Andric SmallVector<uint32_t, 128> &SymbolIndices) { 7666fe6060f1SDimitry Andric if (!CGRelSection) { 7667fe6060f1SDimitry Andric Dumper->reportUniqueWarning( 7668fe6060f1SDimitry Andric "relocation section for a call graph section doesn't exist"); 7669fe6060f1SDimitry Andric return false; 7670fe6060f1SDimitry Andric } 7671fe6060f1SDimitry Andric 7672fe6060f1SDimitry Andric if (CGRelSection->sh_type == SHT_REL) { 7673fe6060f1SDimitry Andric typename ELFT::RelRange CGProfileRel; 7674fe6060f1SDimitry Andric Expected<typename ELFT::RelRange> CGProfileRelOrError = 7675fe6060f1SDimitry Andric Obj.rels(*CGRelSection); 7676fe6060f1SDimitry Andric if (!CGProfileRelOrError) { 7677fe6060f1SDimitry Andric Dumper->reportUniqueWarning("unable to load relocations for " 7678fe6060f1SDimitry Andric "SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7679fe6060f1SDimitry Andric toString(CGProfileRelOrError.takeError())); 7680fe6060f1SDimitry Andric return false; 7681fe6060f1SDimitry Andric } 7682fe6060f1SDimitry Andric 7683fe6060f1SDimitry Andric CGProfileRel = *CGProfileRelOrError; 7684fe6060f1SDimitry Andric for (const typename ELFT::Rel &Rel : CGProfileRel) 7685fe6060f1SDimitry Andric SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL())); 7686fe6060f1SDimitry Andric } else { 7687fe6060f1SDimitry Andric // MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert 7688fe6060f1SDimitry Andric // the format to SHT_RELA 7689fe6060f1SDimitry Andric // (https://sourceware.org/bugzilla/show_bug.cgi?id=28035) 7690fe6060f1SDimitry Andric typename ELFT::RelaRange CGProfileRela; 7691fe6060f1SDimitry Andric Expected<typename ELFT::RelaRange> CGProfileRelaOrError = 7692fe6060f1SDimitry Andric Obj.relas(*CGRelSection); 7693fe6060f1SDimitry Andric if (!CGProfileRelaOrError) { 7694fe6060f1SDimitry Andric Dumper->reportUniqueWarning("unable to load relocations for " 7695fe6060f1SDimitry Andric "SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7696fe6060f1SDimitry Andric toString(CGProfileRelaOrError.takeError())); 7697fe6060f1SDimitry Andric return false; 7698fe6060f1SDimitry Andric } 7699fe6060f1SDimitry Andric 7700fe6060f1SDimitry Andric CGProfileRela = *CGProfileRelaOrError; 7701fe6060f1SDimitry Andric for (const typename ELFT::Rela &Rela : CGProfileRela) 7702fe6060f1SDimitry Andric SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL())); 7703fe6060f1SDimitry Andric } 7704fe6060f1SDimitry Andric 7705fe6060f1SDimitry Andric return true; 7706fe6060f1SDimitry Andric } 7707fe6060f1SDimitry Andric 7708e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() { 7709fe6060f1SDimitry Andric auto IsMatch = [](const Elf_Shdr &Sec) -> bool { 7710fe6060f1SDimitry Andric return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE; 7711fe6060f1SDimitry Andric }; 7712fe6060f1SDimitry Andric 771306c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 771406c3fb27SDimitry Andric this->Obj.getSectionAndRelocations(IsMatch); 771506c3fb27SDimitry Andric if (!SecToRelocMapOrErr) { 771606c3fb27SDimitry Andric this->reportUniqueWarning("unable to get CG Profile section(s): " + 771706c3fb27SDimitry Andric toString(SecToRelocMapOrErr.takeError())); 771806c3fb27SDimitry Andric return; 771906c3fb27SDimitry Andric } 772006c3fb27SDimitry Andric 772106c3fb27SDimitry Andric for (const auto &CGMapEntry : *SecToRelocMapOrErr) { 7722fe6060f1SDimitry Andric const Elf_Shdr *CGSection = CGMapEntry.first; 7723fe6060f1SDimitry Andric const Elf_Shdr *CGRelSection = CGMapEntry.second; 77245ffd83dbSDimitry Andric 77255ffd83dbSDimitry Andric Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr = 7726fe6060f1SDimitry Andric this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection); 77275ffd83dbSDimitry Andric if (!CGProfileOrErr) { 77285ffd83dbSDimitry Andric this->reportUniqueWarning( 7729fe6060f1SDimitry Andric "unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " + 7730e8d8bef9SDimitry Andric toString(CGProfileOrErr.takeError())); 77315ffd83dbSDimitry Andric return; 77325ffd83dbSDimitry Andric } 77335ffd83dbSDimitry Andric 7734fe6060f1SDimitry Andric SmallVector<uint32_t, 128> SymbolIndices; 7735fe6060f1SDimitry Andric bool UseReloc = 7736fe6060f1SDimitry Andric getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices); 7737fe6060f1SDimitry Andric if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) { 7738fe6060f1SDimitry Andric this->reportUniqueWarning( 7739fe6060f1SDimitry Andric "number of from/to pairs does not match number of frequencies"); 7740fe6060f1SDimitry Andric UseReloc = false; 7741fe6060f1SDimitry Andric } 7742fe6060f1SDimitry Andric 7743fe6060f1SDimitry Andric ListScope L(W, "CGProfile"); 7744fe6060f1SDimitry Andric for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) { 7745fe6060f1SDimitry Andric const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I]; 77460b57cec5SDimitry Andric DictScope D(W, "CGProfileEntry"); 7747fe6060f1SDimitry Andric if (UseReloc) { 7748fe6060f1SDimitry Andric uint32_t From = SymbolIndices[I * 2]; 7749fe6060f1SDimitry Andric uint32_t To = SymbolIndices[I * 2 + 1]; 7750fe6060f1SDimitry Andric W.printNumber("From", this->getStaticSymbolName(From), From); 7751fe6060f1SDimitry Andric W.printNumber("To", this->getStaticSymbolName(To), To); 7752fe6060f1SDimitry Andric } 77530b57cec5SDimitry Andric W.printNumber("Weight", CGPE.cgp_weight); 77540b57cec5SDimitry Andric } 77550b57cec5SDimitry Andric } 7756fe6060f1SDimitry Andric } 7757fe6060f1SDimitry Andric 7758*0fca6ea1SDimitry Andric template <class ELFT> 7759*0fca6ea1SDimitry Andric void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) { 7760fe6060f1SDimitry Andric bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; 776106c3fb27SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 776206c3fb27SDimitry Andric auto IsMatch = [](const Elf_Shdr &Sec) -> bool { 7763*0fca6ea1SDimitry Andric return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP; 776406c3fb27SDimitry Andric }; 776506c3fb27SDimitry Andric Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr = 776606c3fb27SDimitry Andric this->Obj.getSectionAndRelocations(IsMatch); 776706c3fb27SDimitry Andric if (!SecRelocMapOrErr) { 776806c3fb27SDimitry Andric this->reportUniqueWarning( 776906c3fb27SDimitry Andric "failed to get SHT_LLVM_BB_ADDR_MAP section(s): " + 777006c3fb27SDimitry Andric toString(SecRelocMapOrErr.takeError())); 777106c3fb27SDimitry Andric return; 777281ad6265SDimitry Andric } 777306c3fb27SDimitry Andric for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) { 7774bdd1243dSDimitry Andric std::optional<const Elf_Shdr *> FunctionSec; 7775fe6060f1SDimitry Andric if (IsRelocatable) 7776fe6060f1SDimitry Andric FunctionSec = 777706c3fb27SDimitry Andric unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link)); 7778fe6060f1SDimitry Andric ListScope L(W, "BBAddrMap"); 777906c3fb27SDimitry Andric if (IsRelocatable && !RelocSec) { 778006c3fb27SDimitry Andric this->reportUniqueWarning("unable to get relocation section for " + 778106c3fb27SDimitry Andric this->describe(*Sec)); 778206c3fb27SDimitry Andric continue; 778306c3fb27SDimitry Andric } 7784*0fca6ea1SDimitry Andric std::vector<PGOAnalysisMap> PGOAnalyses; 7785349cc55cSDimitry Andric Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = 7786*0fca6ea1SDimitry Andric this->Obj.decodeBBAddrMap(*Sec, RelocSec, &PGOAnalyses); 7787fe6060f1SDimitry Andric if (!BBAddrMapOrErr) { 778806c3fb27SDimitry Andric this->reportUniqueWarning("unable to dump " + this->describe(*Sec) + 778906c3fb27SDimitry Andric ": " + toString(BBAddrMapOrErr.takeError())); 7790fe6060f1SDimitry Andric continue; 7791fe6060f1SDimitry Andric } 7792*0fca6ea1SDimitry Andric for (const auto &[AM, PAM] : zip_equal(*BBAddrMapOrErr, PGOAnalyses)) { 7793fe6060f1SDimitry Andric DictScope D(W, "Function"); 7794*0fca6ea1SDimitry Andric W.printHex("At", AM.getFunctionAddress()); 7795fe6060f1SDimitry Andric SmallVector<uint32_t> FuncSymIndex = 7796*0fca6ea1SDimitry Andric this->getSymbolIndexesForFunctionAddress(AM.getFunctionAddress(), 7797*0fca6ea1SDimitry Andric FunctionSec); 7798fe6060f1SDimitry Andric std::string FuncName = "<?>"; 7799fe6060f1SDimitry Andric if (FuncSymIndex.empty()) 7800fe6060f1SDimitry Andric this->reportUniqueWarning( 7801fe6060f1SDimitry Andric "could not identify function symbol for address (0x" + 7802*0fca6ea1SDimitry Andric Twine::utohexstr(AM.getFunctionAddress()) + ") in " + 7803*0fca6ea1SDimitry Andric this->describe(*Sec)); 7804fe6060f1SDimitry Andric else 7805fe6060f1SDimitry Andric FuncName = this->getStaticSymbolName(FuncSymIndex.front()); 7806fe6060f1SDimitry Andric W.printString("Name", FuncName); 7807*0fca6ea1SDimitry Andric { 7808*0fca6ea1SDimitry Andric ListScope BBRL(W, "BB Ranges"); 7809*0fca6ea1SDimitry Andric for (const BBAddrMap::BBRangeEntry &BBR : AM.BBRanges) { 7810*0fca6ea1SDimitry Andric DictScope BBRD(W); 7811*0fca6ea1SDimitry Andric W.printHex("Base Address", BBR.BaseAddress); 7812*0fca6ea1SDimitry Andric ListScope BBEL(W, "BB Entries"); 7813*0fca6ea1SDimitry Andric for (const BBAddrMap::BBEntry &BBE : BBR.BBEntries) { 7814*0fca6ea1SDimitry Andric DictScope BBED(W); 7815bdd1243dSDimitry Andric W.printNumber("ID", BBE.ID); 7816fe6060f1SDimitry Andric W.printHex("Offset", BBE.Offset); 7817fe6060f1SDimitry Andric W.printHex("Size", BBE.Size); 781806c3fb27SDimitry Andric W.printBoolean("HasReturn", BBE.hasReturn()); 781906c3fb27SDimitry Andric W.printBoolean("HasTailCall", BBE.hasTailCall()); 782006c3fb27SDimitry Andric W.printBoolean("IsEHPad", BBE.isEHPad()); 782106c3fb27SDimitry Andric W.printBoolean("CanFallThrough", BBE.canFallThrough()); 78225f757f3fSDimitry Andric W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch()); 7823fe6060f1SDimitry Andric } 7824fe6060f1SDimitry Andric } 7825fe6060f1SDimitry Andric } 7826*0fca6ea1SDimitry Andric 7827*0fca6ea1SDimitry Andric if (PAM.FeatEnable.hasPGOAnalysis()) { 7828*0fca6ea1SDimitry Andric DictScope PD(W, "PGO analyses"); 7829*0fca6ea1SDimitry Andric 7830*0fca6ea1SDimitry Andric if (PAM.FeatEnable.FuncEntryCount) 7831*0fca6ea1SDimitry Andric W.printNumber("FuncEntryCount", PAM.FuncEntryCount); 7832*0fca6ea1SDimitry Andric 7833*0fca6ea1SDimitry Andric if (PAM.FeatEnable.hasPGOAnalysisBBData()) { 7834*0fca6ea1SDimitry Andric ListScope L(W, "PGO BB entries"); 7835*0fca6ea1SDimitry Andric for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) { 7836*0fca6ea1SDimitry Andric DictScope L(W); 7837*0fca6ea1SDimitry Andric 7838*0fca6ea1SDimitry Andric if (PAM.FeatEnable.BBFreq) { 7839*0fca6ea1SDimitry Andric if (PrettyPGOAnalysis) { 7840*0fca6ea1SDimitry Andric std::string BlockFreqStr; 7841*0fca6ea1SDimitry Andric raw_string_ostream SS(BlockFreqStr); 7842*0fca6ea1SDimitry Andric printRelativeBlockFreq(SS, PAM.BBEntries.front().BlockFreq, 7843*0fca6ea1SDimitry Andric PBBE.BlockFreq); 7844*0fca6ea1SDimitry Andric W.printString("Frequency", BlockFreqStr); 7845*0fca6ea1SDimitry Andric } else { 7846*0fca6ea1SDimitry Andric W.printNumber("Frequency", PBBE.BlockFreq.getFrequency()); 7847*0fca6ea1SDimitry Andric } 7848*0fca6ea1SDimitry Andric } 7849*0fca6ea1SDimitry Andric 7850*0fca6ea1SDimitry Andric if (PAM.FeatEnable.BrProb) { 7851*0fca6ea1SDimitry Andric ListScope L(W, "Successors"); 7852*0fca6ea1SDimitry Andric for (const auto &Succ : PBBE.Successors) { 7853*0fca6ea1SDimitry Andric DictScope L(W); 7854*0fca6ea1SDimitry Andric W.printNumber("ID", Succ.ID); 7855*0fca6ea1SDimitry Andric if (PrettyPGOAnalysis) { 7856*0fca6ea1SDimitry Andric W.printObject("Probability", Succ.Prob); 7857*0fca6ea1SDimitry Andric } else { 7858*0fca6ea1SDimitry Andric W.printHex("Probability", Succ.Prob.getNumerator()); 7859*0fca6ea1SDimitry Andric } 7860*0fca6ea1SDimitry Andric } 7861*0fca6ea1SDimitry Andric } 7862*0fca6ea1SDimitry Andric } 7863*0fca6ea1SDimitry Andric } 7864*0fca6ea1SDimitry Andric } 7865*0fca6ea1SDimitry Andric } 7866*0fca6ea1SDimitry Andric } 7867fe6060f1SDimitry Andric } 78680b57cec5SDimitry Andric 7869e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() { 78700b57cec5SDimitry Andric ListScope L(W, "Addrsig"); 7871e8d8bef9SDimitry Andric if (!this->DotAddrsigSec) 78720b57cec5SDimitry Andric return; 7873e8d8bef9SDimitry Andric 7874e8d8bef9SDimitry Andric Expected<std::vector<uint64_t>> SymsOrErr = 7875e8d8bef9SDimitry Andric decodeAddrsigSection(this->Obj, *this->DotAddrsigSec); 7876e8d8bef9SDimitry Andric if (!SymsOrErr) { 7877e8d8bef9SDimitry Andric this->reportUniqueWarning(SymsOrErr.takeError()); 78788bcb0991SDimitry Andric return; 78798bcb0991SDimitry Andric } 78808bcb0991SDimitry Andric 7881e8d8bef9SDimitry Andric for (uint64_t Sym : *SymsOrErr) 7882e8d8bef9SDimitry Andric W.printNumber("Sym", this->getStaticSymbolName(Sym), Sym); 78830b57cec5SDimitry Andric } 78840b57cec5SDimitry Andric 78850b57cec5SDimitry Andric template <typename ELFT> 7886fe6060f1SDimitry Andric static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, 78870b57cec5SDimitry Andric ScopedPrinter &W) { 7888fe6060f1SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 78890b57cec5SDimitry Andric switch (NoteType) { 78900b57cec5SDimitry Andric default: 7891fe6060f1SDimitry Andric return false; 78920b57cec5SDimitry Andric case ELF::NT_GNU_ABI_TAG: { 78930b57cec5SDimitry Andric const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc); 78940b57cec5SDimitry Andric if (!AbiTag.IsValid) { 78950b57cec5SDimitry Andric W.printString("ABI", "<corrupt GNU_ABI_TAG>"); 7896fe6060f1SDimitry Andric return false; 78970b57cec5SDimitry Andric } else { 78980b57cec5SDimitry Andric W.printString("OS", AbiTag.OSName); 78990b57cec5SDimitry Andric W.printString("ABI", AbiTag.ABI); 79000b57cec5SDimitry Andric } 79010b57cec5SDimitry Andric break; 79020b57cec5SDimitry Andric } 79030b57cec5SDimitry Andric case ELF::NT_GNU_BUILD_ID: { 79040b57cec5SDimitry Andric W.printString("Build ID", getGNUBuildId(Desc)); 79050b57cec5SDimitry Andric break; 79060b57cec5SDimitry Andric } 79070b57cec5SDimitry Andric case ELF::NT_GNU_GOLD_VERSION: 7908349cc55cSDimitry Andric W.printString("Version", getDescAsStringRef(Desc)); 79090b57cec5SDimitry Andric break; 79100b57cec5SDimitry Andric case ELF::NT_GNU_PROPERTY_TYPE_0: 79110b57cec5SDimitry Andric ListScope D(W, "Property"); 7912e8d8bef9SDimitry Andric for (const std::string &Property : getGNUPropertyList<ELFT>(Desc)) 79130b57cec5SDimitry Andric W.printString(Property); 79140b57cec5SDimitry Andric break; 79150b57cec5SDimitry Andric } 7916fe6060f1SDimitry Andric return true; 79170b57cec5SDimitry Andric } 79180b57cec5SDimitry Andric 791981ad6265SDimitry Andric static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, 792081ad6265SDimitry Andric ScopedPrinter &W) { 792181ad6265SDimitry Andric // Return true if we were able to pretty-print the note, false otherwise. 792281ad6265SDimitry Andric AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc); 792381ad6265SDimitry Andric if (Props.empty()) 792481ad6265SDimitry Andric return false; 792581ad6265SDimitry Andric for (const auto &KV : Props) 792681ad6265SDimitry Andric W.printString(KV.first, KV.second); 792781ad6265SDimitry Andric return true; 792881ad6265SDimitry Andric } 792981ad6265SDimitry Andric 793006c3fb27SDimitry Andric template <class ELFT> 793106c3fb27SDimitry Andric void LLVMELFDumper<ELFT>::printMemtag( 793206c3fb27SDimitry Andric const ArrayRef<std::pair<std::string, std::string>> DynamicEntries, 793306c3fb27SDimitry Andric const ArrayRef<uint8_t> AndroidNoteDesc, 793406c3fb27SDimitry Andric const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) { 793506c3fb27SDimitry Andric { 793606c3fb27SDimitry Andric ListScope L(W, "Memtag Dynamic Entries:"); 793706c3fb27SDimitry Andric if (DynamicEntries.empty()) 793806c3fb27SDimitry Andric W.printString("< none found >"); 793906c3fb27SDimitry Andric for (const auto &DynamicEntryKV : DynamicEntries) 794006c3fb27SDimitry Andric W.printString(DynamicEntryKV.first, DynamicEntryKV.second); 794106c3fb27SDimitry Andric } 794206c3fb27SDimitry Andric 794306c3fb27SDimitry Andric if (!AndroidNoteDesc.empty()) { 794406c3fb27SDimitry Andric ListScope L(W, "Memtag Android Note:"); 794506c3fb27SDimitry Andric printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W); 794606c3fb27SDimitry Andric } 794706c3fb27SDimitry Andric 794806c3fb27SDimitry Andric if (Descriptors.empty()) 794906c3fb27SDimitry Andric return; 795006c3fb27SDimitry Andric 795106c3fb27SDimitry Andric { 795206c3fb27SDimitry Andric ListScope L(W, "Memtag Global Descriptors:"); 795306c3fb27SDimitry Andric for (const auto &[Addr, BytesToTag] : Descriptors) { 795406c3fb27SDimitry Andric W.printHex("0x" + utohexstr(Addr), BytesToTag); 795506c3fb27SDimitry Andric } 795606c3fb27SDimitry Andric } 795706c3fb27SDimitry Andric } 795806c3fb27SDimitry Andric 7959349cc55cSDimitry Andric template <typename ELFT> 7960349cc55cSDimitry Andric static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType, 7961349cc55cSDimitry Andric ArrayRef<uint8_t> Desc, 7962349cc55cSDimitry Andric ScopedPrinter &W) { 7963349cc55cSDimitry Andric switch (NoteType) { 7964349cc55cSDimitry Andric default: 7965349cc55cSDimitry Andric return false; 7966349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION: 7967349cc55cSDimitry Andric W.printString("Version", getDescAsStringRef(Desc)); 7968349cc55cSDimitry Andric break; 7969349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER: 7970349cc55cSDimitry Andric W.printString("Producer", getDescAsStringRef(Desc)); 7971349cc55cSDimitry Andric break; 7972349cc55cSDimitry Andric case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION: 7973349cc55cSDimitry Andric W.printString("Producer version", getDescAsStringRef(Desc)); 7974349cc55cSDimitry Andric break; 7975349cc55cSDimitry Andric } 7976349cc55cSDimitry Andric return true; 7977349cc55cSDimitry Andric } 7978349cc55cSDimitry Andric 79798bcb0991SDimitry Andric static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) { 79808bcb0991SDimitry Andric W.printNumber("Page Size", Note.PageSize); 7981*0fca6ea1SDimitry Andric ListScope D(W, "Mappings"); 79828bcb0991SDimitry Andric for (const CoreFileMapping &Mapping : Note.Mappings) { 7983*0fca6ea1SDimitry Andric DictScope D(W); 79848bcb0991SDimitry Andric W.printHex("Start", Mapping.Start); 79858bcb0991SDimitry Andric W.printHex("End", Mapping.End); 79868bcb0991SDimitry Andric W.printHex("Offset", Mapping.Offset); 79878bcb0991SDimitry Andric W.printString("Filename", Mapping.Filename); 79888bcb0991SDimitry Andric } 79898bcb0991SDimitry Andric } 79908bcb0991SDimitry Andric 7991e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() { 7992*0fca6ea1SDimitry Andric ListScope L(W, "NoteSections"); 79930b57cec5SDimitry Andric 7994*0fca6ea1SDimitry Andric std::unique_ptr<DictScope> NoteSectionScope; 7995*0fca6ea1SDimitry Andric std::unique_ptr<ListScope> NotesScope; 799606c3fb27SDimitry Andric size_t Align = 0; 7997bdd1243dSDimitry Andric auto StartNotes = [&](std::optional<StringRef> SecName, 79985ffd83dbSDimitry Andric const typename ELFT::Off Offset, 799906c3fb27SDimitry Andric const typename ELFT::Addr Size, size_t Al) { 800006c3fb27SDimitry Andric Align = std::max<size_t>(Al, 4); 8001*0fca6ea1SDimitry Andric NoteSectionScope = std::make_unique<DictScope>(W, "NoteSection"); 80025ffd83dbSDimitry Andric W.printString("Name", SecName ? *SecName : "<?>"); 80030b57cec5SDimitry Andric W.printHex("Offset", Offset); 80040b57cec5SDimitry Andric W.printHex("Size", Size); 8005*0fca6ea1SDimitry Andric NotesScope = std::make_unique<ListScope>(W, "Notes"); 80060b57cec5SDimitry Andric }; 80070b57cec5SDimitry Andric 8008*0fca6ea1SDimitry Andric auto EndNotes = [&] { 8009*0fca6ea1SDimitry Andric NotesScope.reset(); 8010*0fca6ea1SDimitry Andric NoteSectionScope.reset(); 8011*0fca6ea1SDimitry Andric }; 8012e8d8bef9SDimitry Andric 8013fe6060f1SDimitry Andric auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error { 8014*0fca6ea1SDimitry Andric DictScope D2(W); 80150b57cec5SDimitry Andric StringRef Name = Note.getName(); 801606c3fb27SDimitry Andric ArrayRef<uint8_t> Descriptor = Note.getDesc(Align); 80170b57cec5SDimitry Andric Elf_Word Type = Note.getType(); 80180b57cec5SDimitry Andric 80198bcb0991SDimitry Andric // Print the note owner/type. 80200b57cec5SDimitry Andric W.printString("Owner", Name); 80210b57cec5SDimitry Andric W.printHex("Data size", Descriptor.size()); 8022e8d8bef9SDimitry Andric 8023e8d8bef9SDimitry Andric StringRef NoteType = 8024e8d8bef9SDimitry Andric getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type); 80250b57cec5SDimitry Andric if (!NoteType.empty()) 80260b57cec5SDimitry Andric W.printString("Type", NoteType); 80270b57cec5SDimitry Andric else 80280b57cec5SDimitry Andric W.printString("Type", 80290b57cec5SDimitry Andric "Unknown (" + to_string(format_hex(Type, 10)) + ")"); 80308bcb0991SDimitry Andric 80318bcb0991SDimitry Andric // Print the description, or fallback to printing raw bytes for unknown 8032fe6060f1SDimitry Andric // owners/if we fail to pretty-print the contents. 80338bcb0991SDimitry Andric if (Name == "GNU") { 8034fe6060f1SDimitry Andric if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W)) 8035fe6060f1SDimitry Andric return Error::success(); 8036fe6060f1SDimitry Andric } else if (Name == "FreeBSD") { 8037bdd1243dSDimitry Andric if (std::optional<FreeBSDNote> N = 8038fe6060f1SDimitry Andric getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) { 8039fe6060f1SDimitry Andric W.printString(N->Type, N->Value); 8040fe6060f1SDimitry Andric return Error::success(); 8041fe6060f1SDimitry Andric } 80428bcb0991SDimitry Andric } else if (Name == "AMD") { 80438bcb0991SDimitry Andric const AMDNote N = getAMDNote<ELFT>(Type, Descriptor); 8044fe6060f1SDimitry Andric if (!N.Type.empty()) { 80458bcb0991SDimitry Andric W.printString(N.Type, N.Value); 8046fe6060f1SDimitry Andric return Error::success(); 8047fe6060f1SDimitry Andric } 80488bcb0991SDimitry Andric } else if (Name == "AMDGPU") { 80498bcb0991SDimitry Andric const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor); 8050fe6060f1SDimitry Andric if (!N.Type.empty()) { 80518bcb0991SDimitry Andric W.printString(N.Type, N.Value); 8052fe6060f1SDimitry Andric return Error::success(); 8053fe6060f1SDimitry Andric } 8054349cc55cSDimitry Andric } else if (Name == "LLVMOMPOFFLOAD") { 8055349cc55cSDimitry Andric if (printLLVMOMPOFFLOADNoteLLVMStyle<ELFT>(Type, Descriptor, W)) 8056349cc55cSDimitry Andric return Error::success(); 80578bcb0991SDimitry Andric } else if (Name == "CORE") { 80588bcb0991SDimitry Andric if (Type == ELF::NT_FILE) { 80595f757f3fSDimitry Andric DataExtractor DescExtractor( 8060*0fca6ea1SDimitry Andric Descriptor, ELFT::Endianness == llvm::endianness::little, 80618bcb0991SDimitry Andric sizeof(Elf_Addr)); 8062fe6060f1SDimitry Andric if (Expected<CoreNote> N = readCoreNote(DescExtractor)) { 8063fe6060f1SDimitry Andric printCoreNoteLLVMStyle(*N, W); 8064fe6060f1SDimitry Andric return Error::success(); 8065fe6060f1SDimitry Andric } else { 8066fe6060f1SDimitry Andric return N.takeError(); 80678bcb0991SDimitry Andric } 8068fe6060f1SDimitry Andric } 806981ad6265SDimitry Andric } else if (Name == "Android") { 807081ad6265SDimitry Andric if (printAndroidNoteLLVMStyle(Type, Descriptor, W)) 807181ad6265SDimitry Andric return Error::success(); 8072fe6060f1SDimitry Andric } 8073fe6060f1SDimitry Andric if (!Descriptor.empty()) { 80748bcb0991SDimitry Andric W.printBinaryBlock("Description data", Descriptor); 80758bcb0991SDimitry Andric } 8076e8d8bef9SDimitry Andric return Error::success(); 80770b57cec5SDimitry Andric }; 80780b57cec5SDimitry Andric 807906c3fb27SDimitry Andric processNotesHelper(*this, /*StartNotesFn=*/StartNotes, 808006c3fb27SDimitry Andric /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes); 80815ffd83dbSDimitry Andric } 80825ffd83dbSDimitry Andric 8083e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() { 80840b57cec5SDimitry Andric ListScope L(W, "LinkerOptions"); 80850b57cec5SDimitry Andric 8086480093f4SDimitry Andric unsigned I = -1; 8087e8d8bef9SDimitry Andric for (const Elf_Shdr &Shdr : cantFail(this->Obj.sections())) { 8088480093f4SDimitry Andric ++I; 80890b57cec5SDimitry Andric if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) 80900b57cec5SDimitry Andric continue; 80910b57cec5SDimitry Andric 8092e8d8bef9SDimitry Andric Expected<ArrayRef<uint8_t>> ContentsOrErr = 8093e8d8bef9SDimitry Andric this->Obj.getSectionContents(Shdr); 80945ffd83dbSDimitry Andric if (!ContentsOrErr) { 8095e8d8bef9SDimitry Andric this->reportUniqueWarning("unable to read the content of the " 80965ffd83dbSDimitry Andric "SHT_LLVM_LINKER_OPTIONS section: " + 8097e8d8bef9SDimitry Andric toString(ContentsOrErr.takeError())); 80985ffd83dbSDimitry Andric continue; 80995ffd83dbSDimitry Andric } 81005ffd83dbSDimitry Andric if (ContentsOrErr->empty()) 8101480093f4SDimitry Andric continue; 81020b57cec5SDimitry Andric 81035ffd83dbSDimitry Andric if (ContentsOrErr->back() != 0) { 8104e8d8bef9SDimitry Andric this->reportUniqueWarning("SHT_LLVM_LINKER_OPTIONS section at index " + 8105e8d8bef9SDimitry Andric Twine(I) + 8106480093f4SDimitry Andric " is broken: the " 8107e8d8bef9SDimitry Andric "content is not null-terminated"); 8108480093f4SDimitry Andric continue; 8109480093f4SDimitry Andric } 81100b57cec5SDimitry Andric 8111480093f4SDimitry Andric SmallVector<StringRef, 16> Strings; 81125ffd83dbSDimitry Andric toStringRef(ContentsOrErr->drop_back()).split(Strings, '\0'); 8113480093f4SDimitry Andric if (Strings.size() % 2 != 0) { 8114e8d8bef9SDimitry Andric this->reportUniqueWarning( 8115480093f4SDimitry Andric "SHT_LLVM_LINKER_OPTIONS section at index " + Twine(I) + 8116480093f4SDimitry Andric " is broken: an incomplete " 8117480093f4SDimitry Andric "key-value pair was found. The last possible key was: \"" + 8118e8d8bef9SDimitry Andric Strings.back() + "\""); 8119480093f4SDimitry Andric continue; 8120480093f4SDimitry Andric } 8121480093f4SDimitry Andric 8122480093f4SDimitry Andric for (size_t I = 0; I < Strings.size(); I += 2) 8123480093f4SDimitry Andric W.printString(Strings[I], Strings[I + 1]); 8124480093f4SDimitry Andric } 8125480093f4SDimitry Andric } 8126480093f4SDimitry Andric 8127e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printDependentLibs() { 8128480093f4SDimitry Andric ListScope L(W, "DependentLibs"); 81295ffd83dbSDimitry Andric this->printDependentLibsHelper( 8130e8d8bef9SDimitry Andric [](const Elf_Shdr &) {}, 81315ffd83dbSDimitry Andric [this](StringRef Lib, uint64_t) { W.printString(Lib); }); 81320b57cec5SDimitry Andric } 81330b57cec5SDimitry Andric 8134e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() { 81358bcb0991SDimitry Andric ListScope L(W, "StackSizes"); 8136e8d8bef9SDimitry Andric if (this->Obj.getHeader().e_type == ELF::ET_REL) 8137e8d8bef9SDimitry Andric this->printRelocatableStackSizes([]() {}); 81388bcb0991SDimitry Andric else 8139e8d8bef9SDimitry Andric this->printNonRelocatableStackSizes([]() {}); 81408bcb0991SDimitry Andric } 81418bcb0991SDimitry Andric 81428bcb0991SDimitry Andric template <class ELFT> 8143fe6060f1SDimitry Andric void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size, 8144fe6060f1SDimitry Andric ArrayRef<std::string> FuncNames) { 81458bcb0991SDimitry Andric DictScope D(W, "Entry"); 8146fe6060f1SDimitry Andric W.printList("Functions", FuncNames); 81478bcb0991SDimitry Andric W.printHex("Size", Size); 81488bcb0991SDimitry Andric } 81498bcb0991SDimitry Andric 81508bcb0991SDimitry Andric template <class ELFT> 8151e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { 81520b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 81530b57cec5SDimitry Andric W.printHex("Address", Parser.getGotAddress(E)); 81540b57cec5SDimitry Andric W.printNumber("Access", Parser.getGotOffset(E)); 81550b57cec5SDimitry Andric W.printHex("Initial", *E); 81560b57cec5SDimitry Andric }; 81570b57cec5SDimitry Andric 81580b57cec5SDimitry Andric DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); 81590b57cec5SDimitry Andric 81600b57cec5SDimitry Andric W.printHex("Canonical gp value", Parser.getGp()); 81610b57cec5SDimitry Andric { 81620b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 81630b57cec5SDimitry Andric { 81640b57cec5SDimitry Andric DictScope D(W, "Entry"); 81650b57cec5SDimitry Andric PrintEntry(Parser.getGotLazyResolver()); 81660b57cec5SDimitry Andric W.printString("Purpose", StringRef("Lazy resolver")); 81670b57cec5SDimitry Andric } 81680b57cec5SDimitry Andric 81690b57cec5SDimitry Andric if (Parser.getGotModulePointer()) { 81700b57cec5SDimitry Andric DictScope D(W, "Entry"); 81710b57cec5SDimitry Andric PrintEntry(Parser.getGotModulePointer()); 81720b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer (GNU extension)")); 81730b57cec5SDimitry Andric } 81740b57cec5SDimitry Andric } 81750b57cec5SDimitry Andric { 81760b57cec5SDimitry Andric ListScope LS(W, "Local entries"); 81770b57cec5SDimitry Andric for (auto &E : Parser.getLocalEntries()) { 81780b57cec5SDimitry Andric DictScope D(W, "Entry"); 81790b57cec5SDimitry Andric PrintEntry(&E); 81800b57cec5SDimitry Andric } 81810b57cec5SDimitry Andric } 81820b57cec5SDimitry Andric 81830b57cec5SDimitry Andric if (Parser.IsStatic) 81840b57cec5SDimitry Andric return; 81850b57cec5SDimitry Andric 81860b57cec5SDimitry Andric { 81870b57cec5SDimitry Andric ListScope GS(W, "Global entries"); 81880b57cec5SDimitry Andric for (auto &E : Parser.getGlobalEntries()) { 81890b57cec5SDimitry Andric DictScope D(W, "Entry"); 81900b57cec5SDimitry Andric 81910b57cec5SDimitry Andric PrintEntry(&E); 81920b57cec5SDimitry Andric 8193e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getGotSym(&E); 8194e8d8bef9SDimitry Andric W.printHex("Value", Sym.st_value); 8195bdd1243dSDimitry Andric W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes)); 81960b57cec5SDimitry Andric 8197e8d8bef9SDimitry Andric const unsigned SymIndex = &Sym - this->dynamic_symbols().begin(); 8198e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 8199e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 8200e8d8bef9SDimitry Andric printSymbolSection(Sym, SymIndex, ShndxTable); 8201e8d8bef9SDimitry Andric 8202e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 8203e8d8bef9SDimitry Andric Sym, SymIndex, ShndxTable, this->DynamicStringTable, true); 8204e8d8bef9SDimitry Andric W.printNumber("Name", SymName, Sym.st_name); 82050b57cec5SDimitry Andric } 82060b57cec5SDimitry Andric } 82070b57cec5SDimitry Andric 82080b57cec5SDimitry Andric W.printNumber("Number of TLS and multi-GOT entries", 82090b57cec5SDimitry Andric uint64_t(Parser.getOtherEntries().size())); 82100b57cec5SDimitry Andric } 82110b57cec5SDimitry Andric 82120b57cec5SDimitry Andric template <class ELFT> 8213e8d8bef9SDimitry Andric void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { 82140b57cec5SDimitry Andric auto PrintEntry = [&](const Elf_Addr *E) { 82150b57cec5SDimitry Andric W.printHex("Address", Parser.getPltAddress(E)); 82160b57cec5SDimitry Andric W.printHex("Initial", *E); 82170b57cec5SDimitry Andric }; 82180b57cec5SDimitry Andric 82190b57cec5SDimitry Andric DictScope GS(W, "PLT GOT"); 82200b57cec5SDimitry Andric 82210b57cec5SDimitry Andric { 82220b57cec5SDimitry Andric ListScope RS(W, "Reserved entries"); 82230b57cec5SDimitry Andric { 82240b57cec5SDimitry Andric DictScope D(W, "Entry"); 82250b57cec5SDimitry Andric PrintEntry(Parser.getPltLazyResolver()); 82260b57cec5SDimitry Andric W.printString("Purpose", StringRef("PLT lazy resolver")); 82270b57cec5SDimitry Andric } 82280b57cec5SDimitry Andric 82290b57cec5SDimitry Andric if (auto E = Parser.getPltModulePointer()) { 82300b57cec5SDimitry Andric DictScope D(W, "Entry"); 82310b57cec5SDimitry Andric PrintEntry(E); 82320b57cec5SDimitry Andric W.printString("Purpose", StringRef("Module pointer")); 82330b57cec5SDimitry Andric } 82340b57cec5SDimitry Andric } 82350b57cec5SDimitry Andric { 82360b57cec5SDimitry Andric ListScope LS(W, "Entries"); 8237e8d8bef9SDimitry Andric DataRegion<Elf_Word> ShndxTable( 8238e8d8bef9SDimitry Andric (const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end()); 82390b57cec5SDimitry Andric for (auto &E : Parser.getPltEntries()) { 82400b57cec5SDimitry Andric DictScope D(W, "Entry"); 82410b57cec5SDimitry Andric PrintEntry(&E); 82420b57cec5SDimitry Andric 8243e8d8bef9SDimitry Andric const Elf_Sym &Sym = *Parser.getPltSym(&E); 8244e8d8bef9SDimitry Andric W.printHex("Value", Sym.st_value); 8245bdd1243dSDimitry Andric W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes)); 8246e8d8bef9SDimitry Andric printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(), 8247e8d8bef9SDimitry Andric ShndxTable); 82480b57cec5SDimitry Andric 8249e8d8bef9SDimitry Andric const Elf_Sym *FirstSym = cantFail( 8250e8d8bef9SDimitry Andric this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0)); 8251e8d8bef9SDimitry Andric std::string SymName = this->getFullSymbolName( 8252e8d8bef9SDimitry Andric Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true); 8253e8d8bef9SDimitry Andric W.printNumber("Name", SymName, Sym.st_name); 82540b57cec5SDimitry Andric } 82550b57cec5SDimitry Andric } 82560b57cec5SDimitry Andric } 82578bcb0991SDimitry Andric 8258e8d8bef9SDimitry Andric template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() { 8259e8d8bef9SDimitry Andric const Elf_Mips_ABIFlags<ELFT> *Flags; 8260e8d8bef9SDimitry Andric if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr = 8261e8d8bef9SDimitry Andric getMipsAbiFlagsSection(*this)) { 8262e8d8bef9SDimitry Andric Flags = *SecOrErr; 8263e8d8bef9SDimitry Andric if (!Flags) { 82648bcb0991SDimitry Andric W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; 82658bcb0991SDimitry Andric return; 82668bcb0991SDimitry Andric } 8267e8d8bef9SDimitry Andric } else { 8268e8d8bef9SDimitry Andric this->reportUniqueWarning(SecOrErr.takeError()); 82698bcb0991SDimitry Andric return; 82708bcb0991SDimitry Andric } 82718bcb0991SDimitry Andric 82728bcb0991SDimitry Andric raw_ostream &OS = W.getOStream(); 82738bcb0991SDimitry Andric DictScope GS(W, "MIPS ABI Flags"); 82748bcb0991SDimitry Andric 82758bcb0991SDimitry Andric W.printNumber("Version", Flags->version); 82768bcb0991SDimitry Andric W.startLine() << "ISA: "; 82778bcb0991SDimitry Andric if (Flags->isa_rev <= 1) 82788bcb0991SDimitry Andric OS << format("MIPS%u", Flags->isa_level); 82798bcb0991SDimitry Andric else 82808bcb0991SDimitry Andric OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); 82818bcb0991SDimitry Andric OS << "\n"; 8282bdd1243dSDimitry Andric W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType)); 8283bdd1243dSDimitry Andric W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags)); 8284bdd1243dSDimitry Andric W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType)); 82858bcb0991SDimitry Andric W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); 82868bcb0991SDimitry Andric W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); 82878bcb0991SDimitry Andric W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); 8288bdd1243dSDimitry Andric W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1)); 82898bcb0991SDimitry Andric W.printHex("Flags 2", Flags->flags2); 82908bcb0991SDimitry Andric } 82910eae32dcSDimitry Andric 82920eae32dcSDimitry Andric template <class ELFT> 82930eae32dcSDimitry Andric void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj, 82940eae32dcSDimitry Andric ArrayRef<std::string> InputFilenames, 82950eae32dcSDimitry Andric const Archive *A) { 8296bdd1243dSDimitry Andric FileScope = std::make_unique<DictScope>(this->W); 82970eae32dcSDimitry Andric DictScope D(this->W, "FileSummary"); 82980eae32dcSDimitry Andric this->W.printString("File", FileStr); 82990eae32dcSDimitry Andric this->W.printString("Format", Obj.getFileFormatName()); 83000eae32dcSDimitry Andric this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch())); 83010eae32dcSDimitry Andric this->W.printString( 83020eae32dcSDimitry Andric "AddressSize", 83030eae32dcSDimitry Andric std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); 83040eae32dcSDimitry Andric this->printLoadName(); 83050eae32dcSDimitry Andric } 830606c3fb27SDimitry Andric 830706c3fb27SDimitry Andric template <class ELFT> 830806c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printZeroSymbolOtherField( 830906c3fb27SDimitry Andric const Elf_Sym &Symbol) const { 831006c3fb27SDimitry Andric // We want the JSON format to be uniform, since it is machine readable, so 831106c3fb27SDimitry Andric // always print the `Other` field the same way. 831206c3fb27SDimitry Andric this->printSymbolOtherField(Symbol); 831306c3fb27SDimitry Andric } 831406c3fb27SDimitry Andric 831506c3fb27SDimitry Andric template <class ELFT> 831606c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R, 831706c3fb27SDimitry Andric StringRef SymbolName, 831806c3fb27SDimitry Andric StringRef RelocName) { 831906c3fb27SDimitry Andric this->printExpandedRelRelaReloc(R, SymbolName, RelocName); 832006c3fb27SDimitry Andric } 832106c3fb27SDimitry Andric 832206c3fb27SDimitry Andric template <class ELFT> 832306c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec, 832406c3fb27SDimitry Andric StringRef Name, 832506c3fb27SDimitry Andric const unsigned SecNdx) { 832606c3fb27SDimitry Andric DictScope Group(this->W); 832706c3fb27SDimitry Andric this->W.printNumber("SectionIndex", SecNdx); 832806c3fb27SDimitry Andric ListScope D(this->W, "Relocs"); 832906c3fb27SDimitry Andric this->printRelocationsHelper(Sec); 833006c3fb27SDimitry Andric } 833106c3fb27SDimitry Andric 833206c3fb27SDimitry Andric template <class ELFT> 833306c3fb27SDimitry Andric std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const { 833406c3fb27SDimitry Andric return "GroupSections"; 833506c3fb27SDimitry Andric } 833606c3fb27SDimitry Andric 833706c3fb27SDimitry Andric template <class ELFT> 833806c3fb27SDimitry Andric void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name, 833906c3fb27SDimitry Andric uint64_t Idx) const { 834006c3fb27SDimitry Andric DictScope Grp(this->W); 834106c3fb27SDimitry Andric this->W.printString("Name", Name); 834206c3fb27SDimitry Andric this->W.printNumber("Index", Idx); 834306c3fb27SDimitry Andric } 834406c3fb27SDimitry Andric 834506c3fb27SDimitry Andric template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const { 834606c3fb27SDimitry Andric // JSON output does not need to print anything for empty groups 834706c3fb27SDimitry Andric } 8348