Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
35231 views
//===- ELFDumper.cpp - ELF-specific dumper --------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements the ELF-specific dumper for llvm-readobj.10///11//===----------------------------------------------------------------------===//1213#include "ARMEHABIPrinter.h"14#include "DwarfCFIEHPrinter.h"15#include "ObjDumper.h"16#include "StackMapPrinter.h"17#include "llvm-readobj.h"18#include "llvm/ADT/ArrayRef.h"19#include "llvm/ADT/BitVector.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/DenseSet.h"22#include "llvm/ADT/MapVector.h"23#include "llvm/ADT/STLExtras.h"24#include "llvm/ADT/SmallString.h"25#include "llvm/ADT/SmallVector.h"26#include "llvm/ADT/StringExtras.h"27#include "llvm/ADT/StringRef.h"28#include "llvm/ADT/Twine.h"29#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"30#include "llvm/BinaryFormat/ELF.h"31#include "llvm/BinaryFormat/MsgPackDocument.h"32#include "llvm/Demangle/Demangle.h"33#include "llvm/Object/Archive.h"34#include "llvm/Object/ELF.h"35#include "llvm/Object/ELFObjectFile.h"36#include "llvm/Object/ELFTypes.h"37#include "llvm/Object/Error.h"38#include "llvm/Object/ObjectFile.h"39#include "llvm/Object/RelocationResolver.h"40#include "llvm/Object/StackMapParser.h"41#include "llvm/Support/AMDGPUMetadata.h"42#include "llvm/Support/ARMAttributeParser.h"43#include "llvm/Support/ARMBuildAttributes.h"44#include "llvm/Support/Casting.h"45#include "llvm/Support/Compiler.h"46#include "llvm/Support/Endian.h"47#include "llvm/Support/ErrorHandling.h"48#include "llvm/Support/Format.h"49#include "llvm/Support/FormatVariadic.h"50#include "llvm/Support/FormattedStream.h"51#include "llvm/Support/HexagonAttributeParser.h"52#include "llvm/Support/LEB128.h"53#include "llvm/Support/MSP430AttributeParser.h"54#include "llvm/Support/MSP430Attributes.h"55#include "llvm/Support/MathExtras.h"56#include "llvm/Support/MipsABIFlags.h"57#include "llvm/Support/RISCVAttributeParser.h"58#include "llvm/Support/RISCVAttributes.h"59#include "llvm/Support/ScopedPrinter.h"60#include "llvm/Support/SystemZ/zOSSupport.h"61#include "llvm/Support/raw_ostream.h"62#include <algorithm>63#include <array>64#include <cinttypes>65#include <cstddef>66#include <cstdint>67#include <cstdlib>68#include <iterator>69#include <memory>70#include <optional>71#include <string>72#include <system_error>73#include <vector>7475using namespace llvm;76using namespace llvm::object;77using namespace llvm::support;78using namespace ELF;7980#define LLVM_READOBJ_ENUM_CASE(ns, enum) \81case ns::enum: \82return #enum;8384#define ENUM_ENT(enum, altName) \85{ #enum, altName, ELF::enum }8687#define ENUM_ENT_1(enum) \88{ #enum, #enum, ELF::enum }8990namespace {9192template <class ELFT> struct RelSymbol {93RelSymbol(const typename ELFT::Sym *S, StringRef N)94: Sym(S), Name(N.str()) {}95const typename ELFT::Sym *Sym;96std::string Name;97};9899/// Represents a contiguous uniform range in the file. We cannot just create a100/// range directly because when creating one of these from the .dynamic table101/// the size, entity size and virtual address are different entries in arbitrary102/// order (DT_REL, DT_RELSZ, DT_RELENT for example).103struct DynRegionInfo {104DynRegionInfo(const Binary &Owner, const ObjDumper &D)105: Obj(&Owner), Dumper(&D) {}106DynRegionInfo(const Binary &Owner, const ObjDumper &D, const uint8_t *A,107uint64_t S, uint64_t ES)108: Addr(A), Size(S), EntSize(ES), Obj(&Owner), Dumper(&D) {}109110/// Address in current address space.111const uint8_t *Addr = nullptr;112/// Size in bytes of the region.113uint64_t Size = 0;114/// Size of each entity in the region.115uint64_t EntSize = 0;116117/// Owner object. Used for error reporting.118const Binary *Obj;119/// Dumper used for error reporting.120const ObjDumper *Dumper;121/// Error prefix. Used for error reporting to provide more information.122std::string Context;123/// Region size name. Used for error reporting.124StringRef SizePrintName = "size";125/// Entry size name. Used for error reporting. If this field is empty, errors126/// will not mention the entry size.127StringRef EntSizePrintName = "entry size";128129template <typename Type> ArrayRef<Type> getAsArrayRef() const {130const Type *Start = reinterpret_cast<const Type *>(Addr);131if (!Start)132return {Start, Start};133134const uint64_t Offset =135Addr - (const uint8_t *)Obj->getMemoryBufferRef().getBufferStart();136const uint64_t ObjSize = Obj->getMemoryBufferRef().getBufferSize();137138if (Size > ObjSize - Offset) {139Dumper->reportUniqueWarning(140"unable to read data at 0x" + Twine::utohexstr(Offset) +141" of size 0x" + Twine::utohexstr(Size) + " (" + SizePrintName +142"): it goes past the end of the file of size 0x" +143Twine::utohexstr(ObjSize));144return {Start, Start};145}146147if (EntSize == sizeof(Type) && (Size % EntSize == 0))148return {Start, Start + (Size / EntSize)};149150std::string Msg;151if (!Context.empty())152Msg += Context + " has ";153154Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")")155.str();156if (!EntSizePrintName.empty())157Msg +=158(" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")")159.str();160161Dumper->reportUniqueWarning(Msg);162return {Start, Start};163}164};165166struct GroupMember {167StringRef Name;168uint64_t Index;169};170171struct GroupSection {172StringRef Name;173std::string Signature;174uint64_t ShName;175uint64_t Index;176uint32_t Link;177uint32_t Info;178uint32_t Type;179std::vector<GroupMember> Members;180};181182namespace {183184struct NoteType {185uint32_t ID;186StringRef Name;187};188189} // namespace190191template <class ELFT> class Relocation {192public:193Relocation(const typename ELFT::Rel &R, bool IsMips64EL)194: Type(R.getType(IsMips64EL)), Symbol(R.getSymbol(IsMips64EL)),195Offset(R.r_offset), Info(R.r_info) {}196197Relocation(const typename ELFT::Rela &R, bool IsMips64EL)198: Relocation((const typename ELFT::Rel &)R, IsMips64EL) {199Addend = R.r_addend;200}201202uint32_t Type;203uint32_t Symbol;204typename ELFT::uint Offset;205typename ELFT::uint Info;206std::optional<int64_t> Addend;207};208209template <class ELFT> class MipsGOTParser;210211template <typename ELFT> class ELFDumper : public ObjDumper {212LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)213214public:215ELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer);216217void printUnwindInfo() override;218void printNeededLibraries() override;219void printHashTable() override;220void printGnuHashTable() override;221void printLoadName() override;222void printVersionInfo() override;223void printArchSpecificInfo() override;224void printStackMap() const override;225void printMemtag() override;226ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr);227228// Hash histogram shows statistics of how efficient the hash was for the229// dynamic symbol table. The table shows the number of hash buckets for230// different lengths of chains as an absolute number and percentage of the231// total buckets, and the cumulative coverage of symbols for each set of232// buckets.233void printHashHistograms() override;234235const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; };236237std::string describe(const Elf_Shdr &Sec) const;238239unsigned getHashTableEntSize() const {240// EM_S390 and ELF::EM_ALPHA platforms use 8-bytes entries in SHT_HASH241// sections. This violates the ELF specification.242if (Obj.getHeader().e_machine == ELF::EM_S390 ||243Obj.getHeader().e_machine == ELF::EM_ALPHA)244return 8;245return 4;246}247248std::vector<EnumEntry<unsigned>>249getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const;250251Elf_Dyn_Range dynamic_table() const {252// A valid .dynamic section contains an array of entries terminated253// with a DT_NULL entry. However, sometimes the section content may254// continue past the DT_NULL entry, so to dump the section correctly,255// we first find the end of the entries by iterating over them.256Elf_Dyn_Range Table = DynamicTable.template getAsArrayRef<Elf_Dyn>();257258size_t Size = 0;259while (Size < Table.size())260if (Table[Size++].getTag() == DT_NULL)261break;262263return Table.slice(0, Size);264}265266Elf_Sym_Range dynamic_symbols() const {267if (!DynSymRegion)268return Elf_Sym_Range();269return DynSymRegion->template getAsArrayRef<Elf_Sym>();270}271272const Elf_Shdr *findSectionByName(StringRef Name) const;273274StringRef getDynamicStringTable() const { return DynamicStringTable; }275276protected:277virtual void printVersionSymbolSection(const Elf_Shdr *Sec) = 0;278virtual void printVersionDefinitionSection(const Elf_Shdr *Sec) = 0;279virtual void printVersionDependencySection(const Elf_Shdr *Sec) = 0;280281void282printDependentLibsHelper(function_ref<void(const Elf_Shdr &)> OnSectionStart,283function_ref<void(StringRef, uint64_t)> OnLibEntry);284285virtual void printRelRelaReloc(const Relocation<ELFT> &R,286const RelSymbol<ELFT> &RelSym) = 0;287virtual void printDynamicRelocHeader(unsigned Type, StringRef Name,288const DynRegionInfo &Reg) {}289void printReloc(const Relocation<ELFT> &R, unsigned RelIndex,290const Elf_Shdr &Sec, const Elf_Shdr *SymTab);291void printDynamicReloc(const Relocation<ELFT> &R);292void printDynamicRelocationsHelper();293void printRelocationsHelper(const Elf_Shdr &Sec);294void forEachRelocationDo(295const Elf_Shdr &Sec,296llvm::function_ref<void(const Relocation<ELFT> &, unsigned,297const Elf_Shdr &, const Elf_Shdr *)>298RelRelaFn);299300virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,301bool NonVisibilityBitsUsed,302bool ExtraSymInfo) const {};303virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,304DataRegion<Elf_Word> ShndxTable,305std::optional<StringRef> StrTable, bool IsDynamic,306bool NonVisibilityBitsUsed,307bool ExtraSymInfo) const = 0;308309virtual void printMipsABIFlags() = 0;310virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;311virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;312313virtual void printMemtag(314const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,315const ArrayRef<uint8_t> AndroidNoteDesc,316const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0;317318virtual void printHashHistogram(const Elf_Hash &HashTable) const;319virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const;320virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain,321size_t TotalSyms, ArrayRef<size_t> Count,322bool IsGnu) const = 0;323324Expected<ArrayRef<Elf_Versym>>325getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,326StringRef *StrTab, const Elf_Shdr **SymTabSec) const;327StringRef getPrintableSectionName(const Elf_Shdr &Sec) const;328329std::vector<GroupSection> getGroups();330331// Returns the function symbol index for the given address. Matches the332// symbol's section with FunctionSec when specified.333// Returns std::nullopt if no function symbol can be found for the address or334// in case it is not defined in the specified section.335SmallVector<uint32_t> getSymbolIndexesForFunctionAddress(336uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec);337bool printFunctionStackSize(uint64_t SymValue,338std::optional<const Elf_Shdr *> FunctionSec,339const Elf_Shdr &StackSizeSec, DataExtractor Data,340uint64_t *Offset);341void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec,342unsigned Ndx, const Elf_Shdr *SymTab,343const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec,344const RelocationResolver &Resolver, DataExtractor Data);345virtual void printStackSizeEntry(uint64_t Size,346ArrayRef<std::string> FuncNames) = 0;347348void printRelocatableStackSizes(std::function<void()> PrintHeader);349void printNonRelocatableStackSizes(std::function<void()> PrintHeader);350351const object::ELFObjectFile<ELFT> &ObjF;352const ELFFile<ELFT> &Obj;353StringRef FileName;354355Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size,356uint64_t EntSize) {357if (Offset + Size < Offset || Offset + Size > Obj.getBufSize())358return createError("offset (0x" + Twine::utohexstr(Offset) +359") + size (0x" + Twine::utohexstr(Size) +360") is greater than the file size (0x" +361Twine::utohexstr(Obj.getBufSize()) + ")");362return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize);363}364365void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>,366llvm::endianness);367void printMipsReginfo();368void printMipsOptions();369370std::pair<const Elf_Phdr *, const Elf_Shdr *> findDynamic();371void loadDynamicTable();372void parseDynamicTable();373374Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym,375bool &IsDefault) const;376Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const;377378DynRegionInfo DynRelRegion;379DynRegionInfo DynRelaRegion;380DynRegionInfo DynCrelRegion;381DynRegionInfo DynRelrRegion;382DynRegionInfo DynPLTRelRegion;383std::optional<DynRegionInfo> DynSymRegion;384DynRegionInfo DynSymTabShndxRegion;385DynRegionInfo DynamicTable;386StringRef DynamicStringTable;387const Elf_Hash *HashTable = nullptr;388const Elf_GnuHash *GnuHashTable = nullptr;389const Elf_Shdr *DotSymtabSec = nullptr;390const Elf_Shdr *DotDynsymSec = nullptr;391const Elf_Shdr *DotAddrsigSec = nullptr;392DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;393std::optional<uint64_t> SONameOffset;394std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;395396const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version397const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r398const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d399400std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex,401DataRegion<Elf_Word> ShndxTable,402std::optional<StringRef> StrTable,403bool IsDynamic) const;404Expected<unsigned>405getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,406DataRegion<Elf_Word> ShndxTable) const;407Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol,408unsigned SectionIndex) const;409std::string getStaticSymbolName(uint32_t Index) const;410StringRef getDynamicString(uint64_t Value) const;411412std::pair<Elf_Sym_Range, std::optional<StringRef>> getSymtabAndStrtab() const;413void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const;414std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;415416Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,417const Elf_Shdr *SymTab) const;418419ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;420421private:422mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;423};424425template <class ELFT>426std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const {427return ::describe(Obj, Sec);428}429430namespace {431432template <class ELFT> struct SymtabLink {433typename ELFT::SymRange Symbols;434StringRef StringTable;435const typename ELFT::Shdr *SymTab;436};437438// Returns the linked symbol table, symbols and associated string table for a439// given section.440template <class ELFT>441Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj,442const typename ELFT::Shdr &Sec,443unsigned ExpectedType) {444Expected<const typename ELFT::Shdr *> SymtabOrErr =445Obj.getSection(Sec.sh_link);446if (!SymtabOrErr)447return createError("invalid section linked to " + describe(Obj, Sec) +448": " + toString(SymtabOrErr.takeError()));449450if ((*SymtabOrErr)->sh_type != ExpectedType)451return createError(452"invalid section linked to " + describe(Obj, Sec) + ": expected " +453object::getELFSectionTypeName(Obj.getHeader().e_machine, ExpectedType) +454", but got " +455object::getELFSectionTypeName(Obj.getHeader().e_machine,456(*SymtabOrErr)->sh_type));457458Expected<StringRef> StrTabOrErr = Obj.getLinkAsStrtab(**SymtabOrErr);459if (!StrTabOrErr)460return createError(461"can't get a string table for the symbol table linked to " +462describe(Obj, Sec) + ": " + toString(StrTabOrErr.takeError()));463464Expected<typename ELFT::SymRange> SymsOrErr = Obj.symbols(*SymtabOrErr);465if (!SymsOrErr)466return createError("unable to read symbols from the " + describe(Obj, Sec) +467": " + toString(SymsOrErr.takeError()));468469return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr};470}471472} // namespace473474template <class ELFT>475Expected<ArrayRef<typename ELFT::Versym>>476ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,477StringRef *StrTab,478const Elf_Shdr **SymTabSec) const {479assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec));480if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) %481sizeof(uint16_t) !=4820)483return createError("the " + describe(Sec) + " is misaligned");484485Expected<ArrayRef<Elf_Versym>> VersionsOrErr =486Obj.template getSectionContentsAsArray<Elf_Versym>(Sec);487if (!VersionsOrErr)488return createError("cannot read content of " + describe(Sec) + ": " +489toString(VersionsOrErr.takeError()));490491Expected<SymtabLink<ELFT>> SymTabOrErr =492getLinkAsSymtab(Obj, Sec, SHT_DYNSYM);493if (!SymTabOrErr) {494reportUniqueWarning(SymTabOrErr.takeError());495return *VersionsOrErr;496}497498if (SymTabOrErr->Symbols.size() != VersionsOrErr->size())499reportUniqueWarning(describe(Sec) + ": the number of entries (" +500Twine(VersionsOrErr->size()) +501") does not match the number of symbols (" +502Twine(SymTabOrErr->Symbols.size()) +503") in the symbol table with index " +504Twine(Sec.sh_link));505506if (SymTab) {507*SymTab = SymTabOrErr->Symbols;508*StrTab = SymTabOrErr->StringTable;509*SymTabSec = SymTabOrErr->SymTab;510}511return *VersionsOrErr;512}513514template <class ELFT>515std::pair<typename ELFDumper<ELFT>::Elf_Sym_Range, std::optional<StringRef>>516ELFDumper<ELFT>::getSymtabAndStrtab() const {517assert(DotSymtabSec);518Elf_Sym_Range Syms(nullptr, nullptr);519std::optional<StringRef> StrTable;520if (Expected<StringRef> StrTableOrErr =521Obj.getStringTableForSymtab(*DotSymtabSec))522StrTable = *StrTableOrErr;523else524reportUniqueWarning(525"unable to get the string table for the SHT_SYMTAB section: " +526toString(StrTableOrErr.takeError()));527528if (Expected<Elf_Sym_Range> SymsOrErr = Obj.symbols(DotSymtabSec))529Syms = *SymsOrErr;530else531reportUniqueWarning("unable to read symbols from the SHT_SYMTAB section: " +532toString(SymsOrErr.takeError()));533return {Syms, StrTable};534}535536template <class ELFT>537void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic,538bool ExtraSymInfo) const {539std::optional<StringRef> StrTable;540size_t Entries = 0;541Elf_Sym_Range Syms(nullptr, nullptr);542const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec;543544if (IsDynamic) {545StrTable = DynamicStringTable;546Syms = dynamic_symbols();547Entries = Syms.size();548} else if (DotSymtabSec) {549std::tie(Syms, StrTable) = getSymtabAndStrtab();550Entries = DotSymtabSec->getEntityCount();551}552if (Syms.empty())553return;554555// The st_other field has 2 logical parts. The first two bits hold the symbol556// visibility (STV_*) and the remainder hold other platform-specific values.557bool NonVisibilityBitsUsed =558llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; });559560DataRegion<Elf_Word> ShndxTable =561IsDynamic ? DataRegion<Elf_Word>(562(const Elf_Word *)this->DynSymTabShndxRegion.Addr,563this->getElfObject().getELFFile().end())564: DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));565566printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo);567for (const Elf_Sym &Sym : Syms)568printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,569NonVisibilityBitsUsed, ExtraSymInfo);570}571572template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {573formatted_raw_ostream &OS;574575public:576LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)577578GNUELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)579: ELFDumper<ELFT>(ObjF, Writer),580OS(static_cast<formatted_raw_ostream &>(Writer.getOStream())) {581assert(&this->W.getOStream() == &llvm::fouts());582}583584void printFileSummary(StringRef FileStr, ObjectFile &Obj,585ArrayRef<std::string> InputFilenames,586const Archive *A) override;587void printFileHeaders() override;588void printGroupSections() override;589void printRelocations() override;590void printSectionHeaders() override;591void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,592bool ExtraSymInfo) override;593void printHashSymbols() override;594void printSectionDetails() override;595void printDependentLibs() override;596void printDynamicTable() override;597void printDynamicRelocations() override;598void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,599bool NonVisibilityBitsUsed,600bool ExtraSymInfo) const override;601void printProgramHeaders(bool PrintProgramHeaders,602cl::boolOrDefault PrintSectionMapping) override;603void printVersionSymbolSection(const Elf_Shdr *Sec) override;604void printVersionDefinitionSection(const Elf_Shdr *Sec) override;605void printVersionDependencySection(const Elf_Shdr *Sec) override;606void printCGProfile() override;607void printBBAddrMaps(bool PrettyPGOAnalysis) override;608void printAddrsig() override;609void printNotes() override;610void printELFLinkerOptions() override;611void printStackSizes() override;612void printMemtag(613const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,614const ArrayRef<uint8_t> AndroidNoteDesc,615const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;616void printHashHistogramStats(size_t NBucket, size_t MaxChain,617size_t TotalSyms, ArrayRef<size_t> Count,618bool IsGnu) const override;619620private:621void printHashTableSymbols(const Elf_Hash &HashTable);622void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable);623624struct Field {625std::string Str;626unsigned Column;627628Field(StringRef S, unsigned Col) : Str(std::string(S)), Column(Col) {}629Field(unsigned Col) : Column(Col) {}630};631632template <typename T, typename TEnum>633std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues,634TEnum EnumMask1 = {}, TEnum EnumMask2 = {},635TEnum EnumMask3 = {}) const {636std::string Str;637for (const EnumEntry<TEnum> &Flag : EnumValues) {638if (Flag.Value == 0)639continue;640641TEnum EnumMask{};642if (Flag.Value & EnumMask1)643EnumMask = EnumMask1;644else if (Flag.Value & EnumMask2)645EnumMask = EnumMask2;646else if (Flag.Value & EnumMask3)647EnumMask = EnumMask3;648bool IsEnum = (Flag.Value & EnumMask) != 0;649if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||650(IsEnum && (Value & EnumMask) == Flag.Value)) {651if (!Str.empty())652Str += ", ";653Str += Flag.AltName;654}655}656return Str;657}658659formatted_raw_ostream &printField(struct Field F) const {660if (F.Column != 0)661OS.PadToColumn(F.Column);662OS << F.Str;663OS.flush();664return OS;665}666void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex,667DataRegion<Elf_Word> ShndxTable, StringRef StrTable,668uint32_t Bucket);669void printRelr(const Elf_Shdr &Sec);670void printRelRelaReloc(const Relocation<ELFT> &R,671const RelSymbol<ELFT> &RelSym) override;672void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,673DataRegion<Elf_Word> ShndxTable,674std::optional<StringRef> StrTable, bool IsDynamic,675bool NonVisibilityBitsUsed,676bool ExtraSymInfo) const override;677void printDynamicRelocHeader(unsigned Type, StringRef Name,678const DynRegionInfo &Reg) override;679680std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,681DataRegion<Elf_Word> ShndxTable,682bool ExtraSymInfo = false) const;683void printProgramHeaders() override;684void printSectionMapping() override;685void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,686const Twine &Label, unsigned EntriesNum);687688void printStackSizeEntry(uint64_t Size,689ArrayRef<std::string> FuncNames) override;690691void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;692void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;693void printMipsABIFlags() override;694};695696template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {697public:698LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)699700LLVMELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)701: ELFDumper<ELFT>(ObjF, Writer), W(Writer) {}702703void printFileHeaders() override;704void printGroupSections() override;705void printRelocations() override;706void printSectionHeaders() override;707void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,708bool ExtraSymInfo) override;709void printDependentLibs() override;710void printDynamicTable() override;711void printDynamicRelocations() override;712void printProgramHeaders(bool PrintProgramHeaders,713cl::boolOrDefault PrintSectionMapping) override;714void printVersionSymbolSection(const Elf_Shdr *Sec) override;715void printVersionDefinitionSection(const Elf_Shdr *Sec) override;716void printVersionDependencySection(const Elf_Shdr *Sec) override;717void printCGProfile() override;718void printBBAddrMaps(bool PrettyPGOAnalysis) override;719void printAddrsig() override;720void printNotes() override;721void printELFLinkerOptions() override;722void printStackSizes() override;723void printMemtag(724const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,725const ArrayRef<uint8_t> AndroidNoteDesc,726const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;727void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,728DataRegion<Elf_Word> ShndxTable) const;729void printHashHistogramStats(size_t NBucket, size_t MaxChain,730size_t TotalSyms, ArrayRef<size_t> Count,731bool IsGnu) const override;732733private:734void printRelRelaReloc(const Relocation<ELFT> &R,735const RelSymbol<ELFT> &RelSym) override;736737void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,738DataRegion<Elf_Word> ShndxTable,739std::optional<StringRef> StrTable, bool IsDynamic,740bool /*NonVisibilityBitsUsed*/,741bool /*ExtraSymInfo*/) const override;742void printProgramHeaders() override;743void printSectionMapping() override {}744void printStackSizeEntry(uint64_t Size,745ArrayRef<std::string> FuncNames) override;746747void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;748void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;749void printMipsABIFlags() override;750virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const;751752protected:753virtual std::string getGroupSectionHeaderName() const;754void printSymbolOtherField(const Elf_Sym &Symbol) const;755virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R,756StringRef SymbolName,757StringRef RelocName);758virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R,759StringRef SymbolName,760StringRef RelocName);761virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,762const unsigned SecNdx);763virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const;764virtual void printEmptyGroupMessage() const;765766ScopedPrinter &W;767};768769// JSONELFDumper shares most of the same implementation as LLVMELFDumper except770// it uses a JSONScopedPrinter.771template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {772public:773LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)774775JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)776: LLVMELFDumper<ELFT>(ObjF, Writer) {}777778std::string getGroupSectionHeaderName() const override;779780void printFileSummary(StringRef FileStr, ObjectFile &Obj,781ArrayRef<std::string> InputFilenames,782const Archive *A) override;783virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override;784785void printDefaultRelRelaReloc(const Relocation<ELFT> &R,786StringRef SymbolName,787StringRef RelocName) override;788789void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,790const unsigned SecNdx) override;791792void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override;793794void printEmptyGroupMessage() const override;795796void printDynamicTable() override;797798private:799void printAuxillaryDynamicTableEntryInfo(const Elf_Dyn &Entry);800801std::unique_ptr<DictScope> FileScope;802};803804} // end anonymous namespace805806namespace llvm {807808template <class ELFT>809static std::unique_ptr<ObjDumper>810createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) {811if (opts::Output == opts::GNU)812return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer);813else if (opts::Output == opts::JSON)814return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer);815return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer);816}817818std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj,819ScopedPrinter &Writer) {820// Little-endian 32-bit821if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(&Obj))822return createELFDumper(*ELFObj, Writer);823824// Big-endian 32-bit825if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(&Obj))826return createELFDumper(*ELFObj, Writer);827828// Little-endian 64-bit829if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj))830return createELFDumper(*ELFObj, Writer);831832// Big-endian 64-bit833return createELFDumper(*cast<ELF64BEObjectFile>(&Obj), Writer);834}835836} // end namespace llvm837838template <class ELFT>839Expected<SmallVector<std::optional<VersionEntry>, 0> *>840ELFDumper<ELFT>::getVersionMap() const {841// If the VersionMap has already been loaded or if there is no dynamic symtab842// or version table, there is nothing to do.843if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection)844return &VersionMap;845846Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr =847Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection);848if (MapOrErr)849VersionMap = *MapOrErr;850else851return MapOrErr.takeError();852853return &VersionMap;854}855856template <typename ELFT>857Expected<StringRef> ELFDumper<ELFT>::getSymbolVersion(const Elf_Sym &Sym,858bool &IsDefault) const {859// This is a dynamic symbol. Look in the GNU symbol version table.860if (!SymbolVersionSection) {861// No version table.862IsDefault = false;863return "";864}865866assert(DynSymRegion && "DynSymRegion has not been initialised");867// Determine the position in the symbol table of this entry.868size_t EntryIndex = (reinterpret_cast<uintptr_t>(&Sym) -869reinterpret_cast<uintptr_t>(DynSymRegion->Addr)) /870sizeof(Elf_Sym);871872// Get the corresponding version index entry.873Expected<const Elf_Versym *> EntryOrErr =874Obj.template getEntry<Elf_Versym>(*SymbolVersionSection, EntryIndex);875if (!EntryOrErr)876return EntryOrErr.takeError();877878unsigned Version = (*EntryOrErr)->vs_index;879if (Version == VER_NDX_LOCAL || Version == VER_NDX_GLOBAL) {880IsDefault = false;881return "";882}883884Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =885getVersionMap();886if (!MapOrErr)887return MapOrErr.takeError();888889return Obj.getSymbolVersionByIndex(Version, IsDefault, **MapOrErr,890Sym.st_shndx == ELF::SHN_UNDEF);891}892893template <typename ELFT>894Expected<RelSymbol<ELFT>>895ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R,896const Elf_Shdr *SymTab) const {897if (R.Symbol == 0)898return RelSymbol<ELFT>(nullptr, "");899900Expected<const Elf_Sym *> SymOrErr =901Obj.template getEntry<Elf_Sym>(*SymTab, R.Symbol);902if (!SymOrErr)903return createError("unable to read an entry with index " + Twine(R.Symbol) +904" from " + describe(*SymTab) + ": " +905toString(SymOrErr.takeError()));906const Elf_Sym *Sym = *SymOrErr;907if (!Sym)908return RelSymbol<ELFT>(nullptr, "");909910Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*SymTab);911if (!StrTableOrErr)912return StrTableOrErr.takeError();913914const Elf_Sym *FirstSym =915cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0));916std::string SymbolName =917getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab),918*StrTableOrErr, SymTab->sh_type == SHT_DYNSYM);919return RelSymbol<ELFT>(Sym, SymbolName);920}921922template <typename ELFT>923ArrayRef<typename ELFT::Word>924ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const {925if (Symtab) {926auto It = ShndxTables.find(Symtab);927if (It != ShndxTables.end())928return It->second;929}930return {};931}932933static std::string maybeDemangle(StringRef Name) {934return opts::Demangle ? demangle(Name) : Name.str();935}936937template <typename ELFT>938std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {939auto Warn = [&](Error E) -> std::string {940reportUniqueWarning("unable to read the name of symbol with index " +941Twine(Index) + ": " + toString(std::move(E)));942return "<?>";943};944945Expected<const typename ELFT::Sym *> SymOrErr =946Obj.getSymbol(DotSymtabSec, Index);947if (!SymOrErr)948return Warn(SymOrErr.takeError());949950Expected<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*DotSymtabSec);951if (!StrTabOrErr)952return Warn(StrTabOrErr.takeError());953954Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr);955if (!NameOrErr)956return Warn(NameOrErr.takeError());957return maybeDemangle(*NameOrErr);958}959960template <typename ELFT>961std::string ELFDumper<ELFT>::getFullSymbolName(962const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,963std::optional<StringRef> StrTable, bool IsDynamic) const {964if (!StrTable)965return "<?>";966967std::string SymbolName;968if (Expected<StringRef> NameOrErr = Symbol.getName(*StrTable)) {969SymbolName = maybeDemangle(*NameOrErr);970} else {971reportUniqueWarning(NameOrErr.takeError());972return "<?>";973}974975if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) {976Expected<unsigned> SectionIndex =977getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);978if (!SectionIndex) {979reportUniqueWarning(SectionIndex.takeError());980return "<?>";981}982Expected<StringRef> NameOrErr = getSymbolSectionName(Symbol, *SectionIndex);983if (!NameOrErr) {984reportUniqueWarning(NameOrErr.takeError());985return ("<section " + Twine(*SectionIndex) + ">").str();986}987return std::string(*NameOrErr);988}989990if (!IsDynamic)991return SymbolName;992993bool IsDefault;994Expected<StringRef> VersionOrErr = getSymbolVersion(Symbol, IsDefault);995if (!VersionOrErr) {996reportUniqueWarning(VersionOrErr.takeError());997return SymbolName + "@<corrupt>";998}9991000if (!VersionOrErr->empty()) {1001SymbolName += (IsDefault ? "@@" : "@");1002SymbolName += *VersionOrErr;1003}1004return SymbolName;1005}10061007template <typename ELFT>1008Expected<unsigned>1009ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,1010DataRegion<Elf_Word> ShndxTable) const {1011unsigned Ndx = Symbol.st_shndx;1012if (Ndx == SHN_XINDEX)1013return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex,1014ShndxTable);1015if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE)1016return Ndx;10171018auto CreateErr = [&](const Twine &Name,1019std::optional<unsigned> Offset = std::nullopt) {1020std::string Desc;1021if (Offset)1022Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str();1023else1024Desc = Name.str();1025return createError(1026"unable to get section index for symbol with st_shndx = 0x" +1027Twine::utohexstr(Ndx) + " (" + Desc + ")");1028};10291030if (Ndx >= ELF::SHN_LOPROC && Ndx <= ELF::SHN_HIPROC)1031return CreateErr("SHN_LOPROC", Ndx - ELF::SHN_LOPROC);1032if (Ndx >= ELF::SHN_LOOS && Ndx <= ELF::SHN_HIOS)1033return CreateErr("SHN_LOOS", Ndx - ELF::SHN_LOOS);1034if (Ndx == ELF::SHN_UNDEF)1035return CreateErr("SHN_UNDEF");1036if (Ndx == ELF::SHN_ABS)1037return CreateErr("SHN_ABS");1038if (Ndx == ELF::SHN_COMMON)1039return CreateErr("SHN_COMMON");1040return CreateErr("SHN_LORESERVE", Ndx - SHN_LORESERVE);1041}10421043template <typename ELFT>1044Expected<StringRef>1045ELFDumper<ELFT>::getSymbolSectionName(const Elf_Sym &Symbol,1046unsigned SectionIndex) const {1047Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(SectionIndex);1048if (!SecOrErr)1049return SecOrErr.takeError();1050return Obj.getSectionName(**SecOrErr);1051}10521053template <class ELFO>1054static const typename ELFO::Elf_Shdr *1055findNotEmptySectionByAddress(const ELFO &Obj, StringRef FileName,1056uint64_t Addr) {1057for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections()))1058if (Shdr.sh_addr == Addr && Shdr.sh_size > 0)1059return &Shdr;1060return nullptr;1061}10621063const EnumEntry<unsigned> ElfClass[] = {1064{"None", "none", ELF::ELFCLASSNONE},1065{"32-bit", "ELF32", ELF::ELFCLASS32},1066{"64-bit", "ELF64", ELF::ELFCLASS64},1067};10681069const EnumEntry<unsigned> ElfDataEncoding[] = {1070{"None", "none", ELF::ELFDATANONE},1071{"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB},1072{"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB},1073};10741075const EnumEntry<unsigned> ElfObjectFileType[] = {1076{"None", "NONE (none)", ELF::ET_NONE},1077{"Relocatable", "REL (Relocatable file)", ELF::ET_REL},1078{"Executable", "EXEC (Executable file)", ELF::ET_EXEC},1079{"SharedObject", "DYN (Shared object file)", ELF::ET_DYN},1080{"Core", "CORE (Core file)", ELF::ET_CORE},1081};10821083const EnumEntry<unsigned> ElfOSABI[] = {1084{"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE},1085{"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX},1086{"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD},1087{"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX},1088{"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD},1089{"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS},1090{"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX},1091{"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX},1092{"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD},1093{"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64},1094{"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO},1095{"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD},1096{"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS},1097{"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},1098{"AROS", "AROS", ELF::ELFOSABI_AROS},1099{"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},1100{"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},1101{"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA},1102{"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}1103};11041105const EnumEntry<unsigned> AMDGPUElfOSABI[] = {1106{"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},1107{"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL},1108{"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}1109};11101111const EnumEntry<unsigned> ARMElfOSABI[] = {1112{"ARM", "ARM", ELF::ELFOSABI_ARM},1113{"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC},1114};11151116const EnumEntry<unsigned> C6000ElfOSABI[] = {1117{"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},1118{"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX}1119};11201121const EnumEntry<unsigned> ElfMachineType[] = {1122ENUM_ENT(EM_NONE, "None"),1123ENUM_ENT(EM_M32, "WE32100"),1124ENUM_ENT(EM_SPARC, "Sparc"),1125ENUM_ENT(EM_386, "Intel 80386"),1126ENUM_ENT(EM_68K, "MC68000"),1127ENUM_ENT(EM_88K, "MC88000"),1128ENUM_ENT(EM_IAMCU, "EM_IAMCU"),1129ENUM_ENT(EM_860, "Intel 80860"),1130ENUM_ENT(EM_MIPS, "MIPS R3000"),1131ENUM_ENT(EM_S370, "IBM System/370"),1132ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"),1133ENUM_ENT(EM_PARISC, "HPPA"),1134ENUM_ENT(EM_VPP500, "Fujitsu VPP500"),1135ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"),1136ENUM_ENT(EM_960, "Intel 80960"),1137ENUM_ENT(EM_PPC, "PowerPC"),1138ENUM_ENT(EM_PPC64, "PowerPC64"),1139ENUM_ENT(EM_S390, "IBM S/390"),1140ENUM_ENT(EM_SPU, "SPU"),1141ENUM_ENT(EM_V800, "NEC V800 series"),1142ENUM_ENT(EM_FR20, "Fujistsu FR20"),1143ENUM_ENT(EM_RH32, "TRW RH-32"),1144ENUM_ENT(EM_RCE, "Motorola RCE"),1145ENUM_ENT(EM_ARM, "ARM"),1146ENUM_ENT(EM_ALPHA, "EM_ALPHA"),1147ENUM_ENT(EM_SH, "Hitachi SH"),1148ENUM_ENT(EM_SPARCV9, "Sparc v9"),1149ENUM_ENT(EM_TRICORE, "Siemens Tricore"),1150ENUM_ENT(EM_ARC, "ARC"),1151ENUM_ENT(EM_H8_300, "Hitachi H8/300"),1152ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"),1153ENUM_ENT(EM_H8S, "Hitachi H8S"),1154ENUM_ENT(EM_H8_500, "Hitachi H8/500"),1155ENUM_ENT(EM_IA_64, "Intel IA-64"),1156ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"),1157ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"),1158ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"),1159ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"),1160ENUM_ENT(EM_PCP, "Siemens PCP"),1161ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"),1162ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"),1163ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"),1164ENUM_ENT(EM_ME16, "Toyota ME16 processor"),1165ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"),1166ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"),1167ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"),1168ENUM_ENT(EM_PDSP, "Sony DSP processor"),1169ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"),1170ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"),1171ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"),1172ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"),1173ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"),1174ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"),1175ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"),1176ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"),1177ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"),1178ENUM_ENT(EM_SVX, "Silicon Graphics SVx"),1179ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"),1180ENUM_ENT(EM_VAX, "Digital VAX"),1181ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"),1182ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"),1183ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"),1184ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"),1185ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"),1186ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"),1187ENUM_ENT(EM_PRISM, "Vitesse Prism"),1188ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"),1189ENUM_ENT(EM_FR30, "Fujitsu FR30"),1190ENUM_ENT(EM_D10V, "Mitsubishi D10V"),1191ENUM_ENT(EM_D30V, "Mitsubishi D30V"),1192ENUM_ENT(EM_V850, "NEC v850"),1193ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"),1194ENUM_ENT(EM_MN10300, "Matsushita MN10300"),1195ENUM_ENT(EM_MN10200, "Matsushita MN10200"),1196ENUM_ENT(EM_PJ, "picoJava"),1197ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"),1198ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"),1199ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"),1200ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"),1201ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"),1202ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"),1203ENUM_ENT(EM_TPC, "Tenor Network TPC processor"),1204ENUM_ENT(EM_SNP1K, "EM_SNP1K"),1205ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"),1206ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"),1207ENUM_ENT(EM_MAX, "MAX Processor"),1208ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"),1209ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"),1210ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"),1211ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"),1212ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"),1213ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"),1214ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"),1215ENUM_ENT(EM_UNICORE, "Unicore"),1216ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"),1217ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"),1218ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"),1219ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"),1220ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"),1221ENUM_ENT(EM_C166, "Infineon Technologies xc16x"),1222ENUM_ENT(EM_M16C, "Renesas M16C"),1223ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"),1224ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"),1225ENUM_ENT(EM_M32C, "Renesas M32C"),1226ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"),1227ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"),1228ENUM_ENT(EM_SHARC, "EM_SHARC"),1229ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"),1230ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"),1231ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"),1232ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"),1233ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"),1234ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"),1235ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"),1236ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"),1237ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"),1238ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"),1239ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"),1240ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"),1241ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"),1242ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"),1243ENUM_ENT(EM_8051, "Intel 8051 and variants"),1244ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"),1245ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"),1246ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"),1247// FIXME: Following EM_ECOG1X definitions is dead code since EM_ECOG1X has1248// an identical number to EM_ECOG1.1249ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"),1250ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"),1251ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"),1252ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"),1253ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"),1254ENUM_ENT(EM_RX, "Renesas RX"),1255ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"),1256ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"),1257ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"),1258ENUM_ENT(EM_CR16, "National Semiconductor CompactRISC 16-bit processor"),1259ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"),1260ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"),1261ENUM_ENT(EM_L10M, "EM_L10M"),1262ENUM_ENT(EM_K10M, "EM_K10M"),1263ENUM_ENT(EM_AARCH64, "AArch64"),1264ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"),1265ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"),1266ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"),1267ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"),1268ENUM_ENT(EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core"),1269ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"),1270ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"),1271ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"),1272ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"),1273ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"),1274ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"),1275ENUM_ENT(EM_OPEN8, "EM_OPEN8"),1276ENUM_ENT(EM_RL78, "Renesas RL78"),1277ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"),1278ENUM_ENT(EM_78KOR, "EM_78KOR"),1279ENUM_ENT(EM_56800EX, "EM_56800EX"),1280ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"),1281ENUM_ENT(EM_RISCV, "RISC-V"),1282ENUM_ENT(EM_LANAI, "EM_LANAI"),1283ENUM_ENT(EM_BPF, "EM_BPF"),1284ENUM_ENT(EM_VE, "NEC SX-Aurora Vector Engine"),1285ENUM_ENT(EM_LOONGARCH, "LoongArch"),1286};12871288const EnumEntry<unsigned> ElfSymbolBindings[] = {1289{"Local", "LOCAL", ELF::STB_LOCAL},1290{"Global", "GLOBAL", ELF::STB_GLOBAL},1291{"Weak", "WEAK", ELF::STB_WEAK},1292{"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}};12931294const EnumEntry<unsigned> ElfSymbolVisibilities[] = {1295{"DEFAULT", "DEFAULT", ELF::STV_DEFAULT},1296{"INTERNAL", "INTERNAL", ELF::STV_INTERNAL},1297{"HIDDEN", "HIDDEN", ELF::STV_HIDDEN},1298{"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};12991300const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {1301{ "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }1302};13031304static const char *getGroupType(uint32_t Flag) {1305if (Flag & ELF::GRP_COMDAT)1306return "COMDAT";1307else1308return "(unknown)";1309}13101311const EnumEntry<unsigned> ElfSectionFlags[] = {1312ENUM_ENT(SHF_WRITE, "W"),1313ENUM_ENT(SHF_ALLOC, "A"),1314ENUM_ENT(SHF_EXECINSTR, "X"),1315ENUM_ENT(SHF_MERGE, "M"),1316ENUM_ENT(SHF_STRINGS, "S"),1317ENUM_ENT(SHF_INFO_LINK, "I"),1318ENUM_ENT(SHF_LINK_ORDER, "L"),1319ENUM_ENT(SHF_OS_NONCONFORMING, "O"),1320ENUM_ENT(SHF_GROUP, "G"),1321ENUM_ENT(SHF_TLS, "T"),1322ENUM_ENT(SHF_COMPRESSED, "C"),1323ENUM_ENT(SHF_EXCLUDE, "E"),1324};13251326const EnumEntry<unsigned> ElfGNUSectionFlags[] = {1327ENUM_ENT(SHF_GNU_RETAIN, "R")1328};13291330const EnumEntry<unsigned> ElfSolarisSectionFlags[] = {1331ENUM_ENT(SHF_SUNW_NODISCARD, "R")1332};13331334const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {1335ENUM_ENT(XCORE_SHF_CP_SECTION, ""),1336ENUM_ENT(XCORE_SHF_DP_SECTION, "")1337};13381339const EnumEntry<unsigned> ElfARMSectionFlags[] = {1340ENUM_ENT(SHF_ARM_PURECODE, "y")1341};13421343const EnumEntry<unsigned> ElfHexagonSectionFlags[] = {1344ENUM_ENT(SHF_HEX_GPREL, "")1345};13461347const EnumEntry<unsigned> ElfMipsSectionFlags[] = {1348ENUM_ENT(SHF_MIPS_NODUPES, ""),1349ENUM_ENT(SHF_MIPS_NAMES, ""),1350ENUM_ENT(SHF_MIPS_LOCAL, ""),1351ENUM_ENT(SHF_MIPS_NOSTRIP, ""),1352ENUM_ENT(SHF_MIPS_GPREL, ""),1353ENUM_ENT(SHF_MIPS_MERGE, ""),1354ENUM_ENT(SHF_MIPS_ADDR, ""),1355ENUM_ENT(SHF_MIPS_STRING, "")1356};13571358const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {1359ENUM_ENT(SHF_X86_64_LARGE, "l")1360};13611362static std::vector<EnumEntry<unsigned>>1363getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) {1364std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags),1365std::end(ElfSectionFlags));1366switch (EOSAbi) {1367case ELFOSABI_SOLARIS:1368Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags),1369std::end(ElfSolarisSectionFlags));1370break;1371default:1372Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags),1373std::end(ElfGNUSectionFlags));1374break;1375}1376switch (EMachine) {1377case EM_ARM:1378Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags),1379std::end(ElfARMSectionFlags));1380break;1381case EM_HEXAGON:1382Ret.insert(Ret.end(), std::begin(ElfHexagonSectionFlags),1383std::end(ElfHexagonSectionFlags));1384break;1385case EM_MIPS:1386Ret.insert(Ret.end(), std::begin(ElfMipsSectionFlags),1387std::end(ElfMipsSectionFlags));1388break;1389case EM_X86_64:1390Ret.insert(Ret.end(), std::begin(ElfX86_64SectionFlags),1391std::end(ElfX86_64SectionFlags));1392break;1393case EM_XCORE:1394Ret.insert(Ret.end(), std::begin(ElfXCoreSectionFlags),1395std::end(ElfXCoreSectionFlags));1396break;1397default:1398break;1399}1400return Ret;1401}14021403static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine,1404uint64_t Flags) {1405// Here we are trying to build the flags string in the same way as GNU does.1406// It is not that straightforward. Imagine we have sh_flags == 0x90000000.1407// SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000.1408// GNU readelf will not print "E" or "Ep" in this case, but will print just1409// "p". It only will print "E" when no other processor flag is set.1410std::string Str;1411bool HasUnknownFlag = false;1412bool HasOSFlag = false;1413bool HasProcFlag = false;1414std::vector<EnumEntry<unsigned>> FlagsList =1415getSectionFlagsForTarget(EOSAbi, EMachine);1416while (Flags) {1417// Take the least significant bit as a flag.1418uint64_t Flag = Flags & -Flags;1419Flags -= Flag;14201421// Find the flag in the known flags list.1422auto I = llvm::find_if(FlagsList, [=](const EnumEntry<unsigned> &E) {1423// Flags with empty names are not printed in GNU style output.1424return E.Value == Flag && !E.AltName.empty();1425});1426if (I != FlagsList.end()) {1427Str += I->AltName;1428continue;1429}14301431// If we did not find a matching regular flag, then we deal with an OS1432// specific flag, processor specific flag or an unknown flag.1433if (Flag & ELF::SHF_MASKOS) {1434HasOSFlag = true;1435Flags &= ~ELF::SHF_MASKOS;1436} else if (Flag & ELF::SHF_MASKPROC) {1437HasProcFlag = true;1438// Mask off all the processor-specific bits. This removes the SHF_EXCLUDE1439// bit if set so that it doesn't also get printed.1440Flags &= ~ELF::SHF_MASKPROC;1441} else {1442HasUnknownFlag = true;1443}1444}14451446// "o", "p" and "x" are printed last.1447if (HasOSFlag)1448Str += "o";1449if (HasProcFlag)1450Str += "p";1451if (HasUnknownFlag)1452Str += "x";1453return Str;1454}14551456static StringRef segmentTypeToString(unsigned Arch, unsigned Type) {1457// Check potentially overlapped processor-specific program header type.1458switch (Arch) {1459case ELF::EM_ARM:1460switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); }1461break;1462case ELF::EM_MIPS:1463case ELF::EM_MIPS_RS3_LE:1464switch (Type) {1465LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);1466LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);1467LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);1468LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS);1469}1470break;1471case ELF::EM_RISCV:1472switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_RISCV_ATTRIBUTES); }1473}14741475switch (Type) {1476LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL);1477LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD);1478LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC);1479LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP);1480LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE);1481LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB);1482LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR);1483LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS);14841485LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME);1486LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND);14871488LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK);1489LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);1490LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY);14911492LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);1493LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);1494LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);1495LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI);1496LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS);1497LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);1498default:1499return "";1500}1501}15021503static std::string getGNUPtType(unsigned Arch, unsigned Type) {1504StringRef Seg = segmentTypeToString(Arch, Type);1505if (Seg.empty())1506return std::string("<unknown>: ") + to_string(format_hex(Type, 1));15071508// E.g. "PT_ARM_EXIDX" -> "EXIDX".1509if (Seg.consume_front("PT_ARM_"))1510return Seg.str();15111512// E.g. "PT_MIPS_REGINFO" -> "REGINFO".1513if (Seg.consume_front("PT_MIPS_"))1514return Seg.str();15151516// E.g. "PT_RISCV_ATTRIBUTES"1517if (Seg.consume_front("PT_RISCV_"))1518return Seg.str();15191520// E.g. "PT_LOAD" -> "LOAD".1521assert(Seg.starts_with("PT_"));1522return Seg.drop_front(3).str();1523}15241525const EnumEntry<unsigned> ElfSegmentFlags[] = {1526LLVM_READOBJ_ENUM_ENT(ELF, PF_X),1527LLVM_READOBJ_ENUM_ENT(ELF, PF_W),1528LLVM_READOBJ_ENUM_ENT(ELF, PF_R)1529};15301531const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {1532ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"),1533ENUM_ENT(EF_MIPS_PIC, "pic"),1534ENUM_ENT(EF_MIPS_CPIC, "cpic"),1535ENUM_ENT(EF_MIPS_ABI2, "abi2"),1536ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"),1537ENUM_ENT(EF_MIPS_FP64, "fp64"),1538ENUM_ENT(EF_MIPS_NAN2008, "nan2008"),1539ENUM_ENT(EF_MIPS_ABI_O32, "o32"),1540ENUM_ENT(EF_MIPS_ABI_O64, "o64"),1541ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"),1542ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"),1543ENUM_ENT(EF_MIPS_MACH_3900, "3900"),1544ENUM_ENT(EF_MIPS_MACH_4010, "4010"),1545ENUM_ENT(EF_MIPS_MACH_4100, "4100"),1546ENUM_ENT(EF_MIPS_MACH_4650, "4650"),1547ENUM_ENT(EF_MIPS_MACH_4120, "4120"),1548ENUM_ENT(EF_MIPS_MACH_4111, "4111"),1549ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"),1550ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"),1551ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"),1552ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"),1553ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"),1554ENUM_ENT(EF_MIPS_MACH_5400, "5400"),1555ENUM_ENT(EF_MIPS_MACH_5900, "5900"),1556ENUM_ENT(EF_MIPS_MACH_5500, "5500"),1557ENUM_ENT(EF_MIPS_MACH_9000, "9000"),1558ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"),1559ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"),1560ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"),1561ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"),1562ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"),1563ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"),1564ENUM_ENT(EF_MIPS_ARCH_1, "mips1"),1565ENUM_ENT(EF_MIPS_ARCH_2, "mips2"),1566ENUM_ENT(EF_MIPS_ARCH_3, "mips3"),1567ENUM_ENT(EF_MIPS_ARCH_4, "mips4"),1568ENUM_ENT(EF_MIPS_ARCH_5, "mips5"),1569ENUM_ENT(EF_MIPS_ARCH_32, "mips32"),1570ENUM_ENT(EF_MIPS_ARCH_64, "mips64"),1571ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"),1572ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"),1573ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"),1574ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6")1575};15761577// clang-format off1578#define AMDGPU_MACH_ENUM_ENTS \1579ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"), \1580ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"), \1581ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"), \1582ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"), \1583ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"), \1584ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"), \1585ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"), \1586ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"), \1587ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"), \1588ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"), \1589ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"), \1590ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"), \1591ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"), \1592ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"), \1593ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"), \1594ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"), \1595ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"), \1596ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"), \1597ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"), \1598ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"), \1599ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"), \1600ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"), \1601ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"), \1602ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"), \1603ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"), \1604ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"), \1605ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"), \1606ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"), \1607ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"), \1608ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"), \1609ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"), \1610ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"), \1611ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"), \1612ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"), \1613ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"), \1614ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"), \1615ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"), \1616ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"), \1617ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"), \1618ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"), \1619ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"), \1620ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"), \1621ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"), \1622ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"), \1623ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"), \1624ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"), \1625ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"), \1626ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"), \1627ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"), \1628ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"), \1629ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"), \1630ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"), \1631ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"), \1632ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"), \1633ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"), \1634ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"), \1635ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"), \1636ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"), \1637ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"), \1638ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1152, "gfx1152"), \1639ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"), \1640ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"), \1641ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC, "gfx9-generic"), \1642ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC, "gfx10-1-generic"), \1643ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC, "gfx10-3-generic"), \1644ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC, "gfx11-generic"), \1645ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC, "gfx12-generic")1646// clang-format on16471648const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {1649AMDGPU_MACH_ENUM_ENTS,1650ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_V3, "xnack"),1651ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_V3, "sramecc"),1652};16531654const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {1655AMDGPU_MACH_ENUM_ENTS,1656ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ANY_V4, "xnack"),1657ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_OFF_V4, "xnack-"),1658ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ON_V4, "xnack+"),1659ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ANY_V4, "sramecc"),1660ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_OFF_V4, "sramecc-"),1661ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ON_V4, "sramecc+"),1662};16631664const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = {1665ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),1666ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),1667ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),1668ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),1669ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),1670ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),1671ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),1672ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),1673ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),1674ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),1675};16761677const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {1678ENUM_ENT(EF_RISCV_RVC, "RVC"),1679ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"),1680ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"),1681ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"),1682ENUM_ENT(EF_RISCV_RVE, "RVE"),1683ENUM_ENT(EF_RISCV_TSO, "TSO"),1684};16851686const EnumEntry<unsigned> ElfHeaderAVRFlags[] = {1687LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1),1688LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2),1689LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25),1690LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3),1691LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31),1692LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35),1693LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4),1694LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5),1695LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51),1696LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6),1697LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY),1698LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1),1699LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2),1700LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3),1701LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4),1702LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5),1703LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6),1704LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7),1705ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"),1706};17071708const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = {1709ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"),1710ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"),1711ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"),1712ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"),1713ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"),1714};17151716static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = {1717LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE),1718LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN),1719LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT)1720};17211722const EnumEntry<unsigned> ElfSymOtherFlags[] = {1723LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),1724LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),1725LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED)1726};17271728const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = {1729LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),1730LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),1731LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC),1732LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS)1733};17341735const EnumEntry<unsigned> ElfAArch64SymOtherFlags[] = {1736LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS)1737};17381739const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = {1740LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),1741LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),1742LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16)1743};17441745const EnumEntry<unsigned> ElfRISCVSymOtherFlags[] = {1746LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)};17471748static const char *getElfMipsOptionsOdkType(unsigned Odk) {1749switch (Odk) {1750LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL);1751LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO);1752LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS);1753LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD);1754LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH);1755LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL);1756LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS);1757LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND);1758LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR);1759LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP);1760LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT);1761LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE);1762default:1763return "Unknown";1764}1765}17661767template <typename ELFT>1768std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *>1769ELFDumper<ELFT>::findDynamic() {1770// Try to locate the PT_DYNAMIC header.1771const Elf_Phdr *DynamicPhdr = nullptr;1772if (Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = Obj.program_headers()) {1773for (const Elf_Phdr &Phdr : *PhdrsOrErr) {1774if (Phdr.p_type != ELF::PT_DYNAMIC)1775continue;1776DynamicPhdr = &Phdr;1777break;1778}1779} else {1780reportUniqueWarning(1781"unable to read program headers to locate the PT_DYNAMIC segment: " +1782toString(PhdrsOrErr.takeError()));1783}17841785// Try to locate the .dynamic section in the sections header table.1786const Elf_Shdr *DynamicSec = nullptr;1787for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {1788if (Sec.sh_type != ELF::SHT_DYNAMIC)1789continue;1790DynamicSec = &Sec;1791break;1792}17931794if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz >1795ObjF.getMemoryBufferRef().getBufferSize()) ||1796(DynamicPhdr->p_offset + DynamicPhdr->p_filesz <1797DynamicPhdr->p_offset))) {1798reportUniqueWarning(1799"PT_DYNAMIC segment offset (0x" +1800Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" +1801Twine::utohexstr(DynamicPhdr->p_filesz) +1802") exceeds the size of the file (0x" +1803Twine::utohexstr(ObjF.getMemoryBufferRef().getBufferSize()) + ")");1804// Don't use the broken dynamic header.1805DynamicPhdr = nullptr;1806}18071808if (DynamicPhdr && DynamicSec) {1809if (DynamicSec->sh_addr + DynamicSec->sh_size >1810DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||1811DynamicSec->sh_addr < DynamicPhdr->p_vaddr)1812reportUniqueWarning(describe(*DynamicSec) +1813" is not contained within the "1814"PT_DYNAMIC segment");18151816if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)1817reportUniqueWarning(describe(*DynamicSec) + " is not at the start of "1818"PT_DYNAMIC segment");1819}18201821return std::make_pair(DynamicPhdr, DynamicSec);1822}18231824template <typename ELFT>1825void ELFDumper<ELFT>::loadDynamicTable() {1826const Elf_Phdr *DynamicPhdr;1827const Elf_Shdr *DynamicSec;1828std::tie(DynamicPhdr, DynamicSec) = findDynamic();1829if (!DynamicPhdr && !DynamicSec)1830return;18311832DynRegionInfo FromPhdr(ObjF, *this);1833bool IsPhdrTableValid = false;1834if (DynamicPhdr) {1835// Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are1836// validated in findDynamic() and so createDRI() is not expected to fail.1837FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz,1838sizeof(Elf_Dyn)));1839FromPhdr.SizePrintName = "PT_DYNAMIC size";1840FromPhdr.EntSizePrintName = "";1841IsPhdrTableValid = !FromPhdr.template getAsArrayRef<Elf_Dyn>().empty();1842}18431844// Locate the dynamic table described in a section header.1845// Ignore sh_entsize and use the expected value for entry size explicitly.1846// This allows us to dump dynamic sections with a broken sh_entsize1847// field.1848DynRegionInfo FromSec(ObjF, *this);1849bool IsSecTableValid = false;1850if (DynamicSec) {1851Expected<DynRegionInfo> RegOrErr =1852createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn));1853if (RegOrErr) {1854FromSec = *RegOrErr;1855FromSec.Context = describe(*DynamicSec);1856FromSec.EntSizePrintName = "";1857IsSecTableValid = !FromSec.template getAsArrayRef<Elf_Dyn>().empty();1858} else {1859reportUniqueWarning("unable to read the dynamic table from " +1860describe(*DynamicSec) + ": " +1861toString(RegOrErr.takeError()));1862}1863}18641865// When we only have information from one of the SHT_DYNAMIC section header or1866// PT_DYNAMIC program header, just use that.1867if (!DynamicPhdr || !DynamicSec) {1868if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) {1869DynamicTable = DynamicPhdr ? FromPhdr : FromSec;1870parseDynamicTable();1871} else {1872reportUniqueWarning("no valid dynamic table was found");1873}1874return;1875}18761877// At this point we have tables found from the section header and from the1878// dynamic segment. Usually they match, but we have to do sanity checks to1879// verify that.18801881if (FromPhdr.Addr != FromSec.Addr)1882reportUniqueWarning("SHT_DYNAMIC section header and PT_DYNAMIC "1883"program header disagree about "1884"the location of the dynamic table");18851886if (!IsPhdrTableValid && !IsSecTableValid) {1887reportUniqueWarning("no valid dynamic table was found");1888return;1889}18901891// Information in the PT_DYNAMIC program header has priority over the1892// information in a section header.1893if (IsPhdrTableValid) {1894if (!IsSecTableValid)1895reportUniqueWarning(1896"SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used");1897DynamicTable = FromPhdr;1898} else {1899reportUniqueWarning(1900"PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used");1901DynamicTable = FromSec;1902}19031904parseDynamicTable();1905}19061907template <typename ELFT>1908ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,1909ScopedPrinter &Writer)1910: ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()),1911FileName(O.getFileName()), DynRelRegion(O, *this),1912DynRelaRegion(O, *this), DynCrelRegion(O, *this), DynRelrRegion(O, *this),1913DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this),1914DynamicTable(O, *this) {1915if (!O.IsContentValid())1916return;19171918typename ELFT::ShdrRange Sections = cantFail(Obj.sections());1919for (const Elf_Shdr &Sec : Sections) {1920switch (Sec.sh_type) {1921case ELF::SHT_SYMTAB:1922if (!DotSymtabSec)1923DotSymtabSec = &Sec;1924break;1925case ELF::SHT_DYNSYM:1926if (!DotDynsymSec)1927DotDynsymSec = &Sec;19281929if (!DynSymRegion) {1930Expected<DynRegionInfo> RegOrErr =1931createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize);1932if (RegOrErr) {1933DynSymRegion = *RegOrErr;1934DynSymRegion->Context = describe(Sec);19351936if (Expected<StringRef> E = Obj.getStringTableForSymtab(Sec))1937DynamicStringTable = *E;1938else1939reportUniqueWarning("unable to get the string table for the " +1940describe(Sec) + ": " + toString(E.takeError()));1941} else {1942reportUniqueWarning("unable to read dynamic symbols from " +1943describe(Sec) + ": " +1944toString(RegOrErr.takeError()));1945}1946}1947break;1948case ELF::SHT_SYMTAB_SHNDX: {1949uint32_t SymtabNdx = Sec.sh_link;1950if (SymtabNdx >= Sections.size()) {1951reportUniqueWarning(1952"unable to get the associated symbol table for " + describe(Sec) +1953": sh_link (" + Twine(SymtabNdx) +1954") is greater than or equal to the total number of sections (" +1955Twine(Sections.size()) + ")");1956continue;1957}19581959if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =1960Obj.getSHNDXTable(Sec)) {1961if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr})1962.second)1963reportUniqueWarning(1964"multiple SHT_SYMTAB_SHNDX sections are linked to " +1965describe(Sec));1966} else {1967reportUniqueWarning(ShndxTableOrErr.takeError());1968}1969break;1970}1971case ELF::SHT_GNU_versym:1972if (!SymbolVersionSection)1973SymbolVersionSection = &Sec;1974break;1975case ELF::SHT_GNU_verdef:1976if (!SymbolVersionDefSection)1977SymbolVersionDefSection = &Sec;1978break;1979case ELF::SHT_GNU_verneed:1980if (!SymbolVersionNeedSection)1981SymbolVersionNeedSection = &Sec;1982break;1983case ELF::SHT_LLVM_ADDRSIG:1984if (!DotAddrsigSec)1985DotAddrsigSec = &Sec;1986break;1987}1988}19891990loadDynamicTable();1991}19921993template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {1994auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {1995auto MappedAddrOrError = Obj.toMappedAddr(VAddr, [&](const Twine &Msg) {1996this->reportUniqueWarning(Msg);1997return Error::success();1998});1999if (!MappedAddrOrError) {2000this->reportUniqueWarning("unable to parse DT_" +2001Obj.getDynamicTagAsString(Tag) + ": " +2002llvm::toString(MappedAddrOrError.takeError()));2003return nullptr;2004}2005return MappedAddrOrError.get();2006};20072008const char *StringTableBegin = nullptr;2009uint64_t StringTableSize = 0;2010std::optional<DynRegionInfo> DynSymFromTable;2011for (const Elf_Dyn &Dyn : dynamic_table()) {2012if (Obj.getHeader().e_machine == EM_AARCH64) {2013switch (Dyn.d_tag) {2014case ELF::DT_AARCH64_AUTH_RELRSZ:2015DynRelrRegion.Size = Dyn.getVal();2016DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";2017continue;2018case ELF::DT_AARCH64_AUTH_RELRENT:2019DynRelrRegion.EntSize = Dyn.getVal();2020DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";2021continue;2022}2023}2024switch (Dyn.d_tag) {2025case ELF::DT_HASH:2026HashTable = reinterpret_cast<const Elf_Hash *>(2027toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2028break;2029case ELF::DT_GNU_HASH:2030GnuHashTable = reinterpret_cast<const Elf_GnuHash *>(2031toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2032break;2033case ELF::DT_STRTAB:2034StringTableBegin = reinterpret_cast<const char *>(2035toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2036break;2037case ELF::DT_STRSZ:2038StringTableSize = Dyn.getVal();2039break;2040case ELF::DT_SYMTAB: {2041// If we can't map the DT_SYMTAB value to an address (e.g. when there are2042// no program headers), we ignore its value.2043if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) {2044DynSymFromTable.emplace(ObjF, *this);2045DynSymFromTable->Addr = VA;2046DynSymFromTable->EntSize = sizeof(Elf_Sym);2047DynSymFromTable->EntSizePrintName = "";2048}2049break;2050}2051case ELF::DT_SYMENT: {2052uint64_t Val = Dyn.getVal();2053if (Val != sizeof(Elf_Sym))2054this->reportUniqueWarning("DT_SYMENT value of 0x" +2055Twine::utohexstr(Val) +2056" is not the size of a symbol (0x" +2057Twine::utohexstr(sizeof(Elf_Sym)) + ")");2058break;2059}2060case ELF::DT_RELA:2061DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2062break;2063case ELF::DT_RELASZ:2064DynRelaRegion.Size = Dyn.getVal();2065DynRelaRegion.SizePrintName = "DT_RELASZ value";2066break;2067case ELF::DT_RELAENT:2068DynRelaRegion.EntSize = Dyn.getVal();2069DynRelaRegion.EntSizePrintName = "DT_RELAENT value";2070break;2071case ELF::DT_CREL:2072DynCrelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2073break;2074case ELF::DT_SONAME:2075SONameOffset = Dyn.getVal();2076break;2077case ELF::DT_REL:2078DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2079break;2080case ELF::DT_RELSZ:2081DynRelRegion.Size = Dyn.getVal();2082DynRelRegion.SizePrintName = "DT_RELSZ value";2083break;2084case ELF::DT_RELENT:2085DynRelRegion.EntSize = Dyn.getVal();2086DynRelRegion.EntSizePrintName = "DT_RELENT value";2087break;2088case ELF::DT_RELR:2089case ELF::DT_ANDROID_RELR:2090case ELF::DT_AARCH64_AUTH_RELR:2091DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2092break;2093case ELF::DT_RELRSZ:2094case ELF::DT_ANDROID_RELRSZ:2095case ELF::DT_AARCH64_AUTH_RELRSZ:2096DynRelrRegion.Size = Dyn.getVal();2097DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ2098? "DT_RELRSZ value"2099: "DT_ANDROID_RELRSZ value";2100break;2101case ELF::DT_RELRENT:2102case ELF::DT_ANDROID_RELRENT:2103case ELF::DT_AARCH64_AUTH_RELRENT:2104DynRelrRegion.EntSize = Dyn.getVal();2105DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT2106? "DT_RELRENT value"2107: "DT_ANDROID_RELRENT value";2108break;2109case ELF::DT_PLTREL:2110if (Dyn.getVal() == DT_REL)2111DynPLTRelRegion.EntSize = sizeof(Elf_Rel);2112else if (Dyn.getVal() == DT_RELA)2113DynPLTRelRegion.EntSize = sizeof(Elf_Rela);2114else if (Dyn.getVal() == DT_CREL)2115DynPLTRelRegion.EntSize = 1;2116else2117reportUniqueWarning(Twine("unknown DT_PLTREL value of ") +2118Twine((uint64_t)Dyn.getVal()));2119DynPLTRelRegion.EntSizePrintName = "PLTREL entry size";2120break;2121case ELF::DT_JMPREL:2122DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2123break;2124case ELF::DT_PLTRELSZ:2125DynPLTRelRegion.Size = Dyn.getVal();2126DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value";2127break;2128case ELF::DT_SYMTAB_SHNDX:2129DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2130DynSymTabShndxRegion.EntSize = sizeof(Elf_Word);2131break;2132}2133}21342135if (StringTableBegin) {2136const uint64_t FileSize = Obj.getBufSize();2137const uint64_t Offset = (const uint8_t *)StringTableBegin - Obj.base();2138if (StringTableSize > FileSize - Offset)2139reportUniqueWarning(2140"the dynamic string table at 0x" + Twine::utohexstr(Offset) +2141" goes past the end of the file (0x" + Twine::utohexstr(FileSize) +2142") with DT_STRSZ = 0x" + Twine::utohexstr(StringTableSize));2143else2144DynamicStringTable = StringRef(StringTableBegin, StringTableSize);2145}21462147const bool IsHashTableSupported = getHashTableEntSize() == 4;2148if (DynSymRegion) {2149// Often we find the information about the dynamic symbol table2150// location in the SHT_DYNSYM section header. However, the value in2151// DT_SYMTAB has priority, because it is used by dynamic loaders to2152// locate .dynsym at runtime. The location we find in the section header2153// and the location we find here should match.2154if (DynSymFromTable && DynSymFromTable->Addr != DynSymRegion->Addr)2155reportUniqueWarning(2156createError("SHT_DYNSYM section header and DT_SYMTAB disagree about "2157"the location of the dynamic symbol table"));21582159// According to the ELF gABI: "The number of symbol table entries should2160// equal nchain". Check to see if the DT_HASH hash table nchain value2161// conflicts with the number of symbols in the dynamic symbol table2162// according to the section header.2163if (HashTable && IsHashTableSupported) {2164if (DynSymRegion->EntSize == 0)2165reportUniqueWarning("SHT_DYNSYM section has sh_entsize == 0");2166else if (HashTable->nchain != DynSymRegion->Size / DynSymRegion->EntSize)2167reportUniqueWarning(2168"hash table nchain (" + Twine(HashTable->nchain) +2169") differs from symbol count derived from SHT_DYNSYM section "2170"header (" +2171Twine(DynSymRegion->Size / DynSymRegion->EntSize) + ")");2172}2173}21742175// Delay the creation of the actual dynamic symbol table until now, so that2176// checks can always be made against the section header-based properties,2177// without worrying about tag order.2178if (DynSymFromTable) {2179if (!DynSymRegion) {2180DynSymRegion = DynSymFromTable;2181} else {2182DynSymRegion->Addr = DynSymFromTable->Addr;2183DynSymRegion->EntSize = DynSymFromTable->EntSize;2184DynSymRegion->EntSizePrintName = DynSymFromTable->EntSizePrintName;2185}2186}21872188// Derive the dynamic symbol table size from the DT_HASH hash table, if2189// present.2190if (HashTable && IsHashTableSupported && DynSymRegion) {2191const uint64_t FileSize = Obj.getBufSize();2192const uint64_t DerivedSize =2193(uint64_t)HashTable->nchain * DynSymRegion->EntSize;2194const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base();2195if (DerivedSize > FileSize - Offset)2196reportUniqueWarning(2197"the size (0x" + Twine::utohexstr(DerivedSize) +2198") of the dynamic symbol table at 0x" + Twine::utohexstr(Offset) +2199", derived from the hash table, goes past the end of the file (0x" +2200Twine::utohexstr(FileSize) + ") and will be ignored");2201else2202DynSymRegion->Size = HashTable->nchain * DynSymRegion->EntSize;2203}2204}22052206template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {2207// Dump version symbol section.2208printVersionSymbolSection(SymbolVersionSection);22092210// Dump version definition section.2211printVersionDefinitionSection(SymbolVersionDefSection);22122213// Dump version dependency section.2214printVersionDependencySection(SymbolVersionNeedSection);2215}22162217#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \2218{ #enum, prefix##_##enum }22192220const EnumEntry<unsigned> ElfDynamicDTFlags[] = {2221LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),2222LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),2223LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),2224LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),2225LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)2226};22272228const EnumEntry<unsigned> ElfDynamicDTFlags1[] = {2229LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW),2230LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL),2231LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP),2232LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE),2233LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR),2234LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST),2235LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN),2236LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN),2237LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT),2238LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS),2239LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE),2240LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB),2241LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP),2242LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT),2243LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE),2244LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE),2245LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND),2246LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT),2247LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF),2248LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS),2249LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR),2250LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED),2251LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC),2252LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE),2253LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT),2254LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON),2255LLVM_READOBJ_DT_FLAG_ENT(DF_1, PIE),2256};22572258const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {2259LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),2260LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),2261LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),2262LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),2263LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),2264LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),2265LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),2266LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),2267LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),2268LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),2269LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),2270LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),2271LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),2272LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),2273LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),2274LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)2275};22762277#undef LLVM_READOBJ_DT_FLAG_ENT22782279template <typename T, typename TFlag>2280void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {2281SmallVector<EnumEntry<TFlag>, 10> SetFlags;2282for (const EnumEntry<TFlag> &Flag : Flags)2283if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)2284SetFlags.push_back(Flag);22852286for (const EnumEntry<TFlag> &Flag : SetFlags)2287OS << Flag.Name << " ";2288}22892290template <class ELFT>2291const typename ELFT::Shdr *2292ELFDumper<ELFT>::findSectionByName(StringRef Name) const {2293for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {2294if (Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr)) {2295if (*NameOrErr == Name)2296return &Shdr;2297} else {2298reportUniqueWarning("unable to read the name of " + describe(Shdr) +2299": " + toString(NameOrErr.takeError()));2300}2301}2302return nullptr;2303}23042305template <class ELFT>2306std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,2307uint64_t Value) const {2308auto FormatHexValue = [](uint64_t V) {2309std::string Str;2310raw_string_ostream OS(Str);2311const char *ConvChar =2312(opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;2313OS << format(ConvChar, V);2314return OS.str();2315};23162317auto FormatFlags = [](uint64_t V,2318llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) {2319std::string Str;2320raw_string_ostream OS(Str);2321printFlags(V, Array, OS);2322return OS.str();2323};23242325// Handle custom printing of architecture specific tags2326switch (Obj.getHeader().e_machine) {2327case EM_AARCH64:2328switch (Type) {2329case DT_AARCH64_BTI_PLT:2330case DT_AARCH64_PAC_PLT:2331case DT_AARCH64_VARIANT_PCS:2332case DT_AARCH64_MEMTAG_GLOBALSSZ:2333return std::to_string(Value);2334case DT_AARCH64_MEMTAG_MODE:2335switch (Value) {2336case 0:2337return "Synchronous (0)";2338case 1:2339return "Asynchronous (1)";2340default:2341return (Twine("Unknown (") + Twine(Value) + ")").str();2342}2343case DT_AARCH64_MEMTAG_HEAP:2344case DT_AARCH64_MEMTAG_STACK:2345switch (Value) {2346case 0:2347return "Disabled (0)";2348case 1:2349return "Enabled (1)";2350default:2351return (Twine("Unknown (") + Twine(Value) + ")").str();2352}2353case DT_AARCH64_MEMTAG_GLOBALS:2354return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str();2355default:2356break;2357}2358break;2359case EM_HEXAGON:2360switch (Type) {2361case DT_HEXAGON_VER:2362return std::to_string(Value);2363case DT_HEXAGON_SYMSZ:2364case DT_HEXAGON_PLT:2365return FormatHexValue(Value);2366default:2367break;2368}2369break;2370case EM_MIPS:2371switch (Type) {2372case DT_MIPS_RLD_VERSION:2373case DT_MIPS_LOCAL_GOTNO:2374case DT_MIPS_SYMTABNO:2375case DT_MIPS_UNREFEXTNO:2376return std::to_string(Value);2377case DT_MIPS_TIME_STAMP:2378case DT_MIPS_ICHECKSUM:2379case DT_MIPS_IVERSION:2380case DT_MIPS_BASE_ADDRESS:2381case DT_MIPS_MSYM:2382case DT_MIPS_CONFLICT:2383case DT_MIPS_LIBLIST:2384case DT_MIPS_CONFLICTNO:2385case DT_MIPS_LIBLISTNO:2386case DT_MIPS_GOTSYM:2387case DT_MIPS_HIPAGENO:2388case DT_MIPS_RLD_MAP:2389case DT_MIPS_DELTA_CLASS:2390case DT_MIPS_DELTA_CLASS_NO:2391case DT_MIPS_DELTA_INSTANCE:2392case DT_MIPS_DELTA_RELOC:2393case DT_MIPS_DELTA_RELOC_NO:2394case DT_MIPS_DELTA_SYM:2395case DT_MIPS_DELTA_SYM_NO:2396case DT_MIPS_DELTA_CLASSSYM:2397case DT_MIPS_DELTA_CLASSSYM_NO:2398case DT_MIPS_CXX_FLAGS:2399case DT_MIPS_PIXIE_INIT:2400case DT_MIPS_SYMBOL_LIB:2401case DT_MIPS_LOCALPAGE_GOTIDX:2402case DT_MIPS_LOCAL_GOTIDX:2403case DT_MIPS_HIDDEN_GOTIDX:2404case DT_MIPS_PROTECTED_GOTIDX:2405case DT_MIPS_OPTIONS:2406case DT_MIPS_INTERFACE:2407case DT_MIPS_DYNSTR_ALIGN:2408case DT_MIPS_INTERFACE_SIZE:2409case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:2410case DT_MIPS_PERF_SUFFIX:2411case DT_MIPS_COMPACT_SIZE:2412case DT_MIPS_GP_VALUE:2413case DT_MIPS_AUX_DYNAMIC:2414case DT_MIPS_PLTGOT:2415case DT_MIPS_RWPLT:2416case DT_MIPS_RLD_MAP_REL:2417case DT_MIPS_XHASH:2418return FormatHexValue(Value);2419case DT_MIPS_FLAGS:2420return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags));2421default:2422break;2423}2424break;2425default:2426break;2427}24282429switch (Type) {2430case DT_PLTREL:2431if (Value == DT_REL)2432return "REL";2433if (Value == DT_RELA)2434return "RELA";2435if (Value == DT_CREL)2436return "CREL";2437[[fallthrough]];2438case DT_PLTGOT:2439case DT_HASH:2440case DT_STRTAB:2441case DT_SYMTAB:2442case DT_RELA:2443case DT_INIT:2444case DT_FINI:2445case DT_REL:2446case DT_JMPREL:2447case DT_INIT_ARRAY:2448case DT_FINI_ARRAY:2449case DT_PREINIT_ARRAY:2450case DT_DEBUG:2451case DT_CREL:2452case DT_VERDEF:2453case DT_VERNEED:2454case DT_VERSYM:2455case DT_GNU_HASH:2456case DT_NULL:2457return FormatHexValue(Value);2458case DT_RELACOUNT:2459case DT_RELCOUNT:2460case DT_VERDEFNUM:2461case DT_VERNEEDNUM:2462return std::to_string(Value);2463case DT_PLTRELSZ:2464case DT_RELASZ:2465case DT_RELAENT:2466case DT_STRSZ:2467case DT_SYMENT:2468case DT_RELSZ:2469case DT_RELENT:2470case DT_INIT_ARRAYSZ:2471case DT_FINI_ARRAYSZ:2472case DT_PREINIT_ARRAYSZ:2473case DT_RELRSZ:2474case DT_RELRENT:2475case DT_AARCH64_AUTH_RELRSZ:2476case DT_AARCH64_AUTH_RELRENT:2477case DT_ANDROID_RELSZ:2478case DT_ANDROID_RELASZ:2479return std::to_string(Value) + " (bytes)";2480case DT_NEEDED:2481case DT_SONAME:2482case DT_AUXILIARY:2483case DT_USED:2484case DT_FILTER:2485case DT_RPATH:2486case DT_RUNPATH: {2487const std::map<uint64_t, const char *> TagNames = {2488{DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"},2489{DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"},2490{DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"},2491{DT_RUNPATH, "Library runpath"},2492};24932494return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]")2495.str();2496}2497case DT_FLAGS:2498return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags));2499case DT_FLAGS_1:2500return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1));2501default:2502return FormatHexValue(Value);2503}2504}25052506template <class ELFT>2507StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {2508if (DynamicStringTable.empty() && !DynamicStringTable.data()) {2509reportUniqueWarning("string table was not found");2510return "<?>";2511}25122513auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) {2514reportUniqueWarning("string table at offset 0x" + Twine::utohexstr(Offset) +2515Msg);2516return "<?>";2517};25182519const uint64_t FileSize = Obj.getBufSize();2520const uint64_t Offset =2521(const uint8_t *)DynamicStringTable.data() - Obj.base();2522if (DynamicStringTable.size() > FileSize - Offset)2523return WarnAndReturn(" with size 0x" +2524Twine::utohexstr(DynamicStringTable.size()) +2525" goes past the end of the file (0x" +2526Twine::utohexstr(FileSize) + ")",2527Offset);25282529if (Value >= DynamicStringTable.size())2530return WarnAndReturn(2531": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +2532": it goes past the end of the table (0x" +2533Twine::utohexstr(Offset + DynamicStringTable.size()) + ")",2534Offset);25352536if (DynamicStringTable.back() != '\0')2537return WarnAndReturn(": unable to read the string at 0x" +2538Twine::utohexstr(Offset + Value) +2539": the string table is not null-terminated",2540Offset);25412542return DynamicStringTable.data() + Value;2543}25442545template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {2546DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF);2547Ctx.printUnwindInformation();2548}25492550// The namespace is needed to fix the compilation with GCC older than 7.0+.2551namespace {2552template <> void ELFDumper<ELF32LE>::printUnwindInfo() {2553if (Obj.getHeader().e_machine == EM_ARM) {2554ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF.getFileName(),2555DotSymtabSec);2556Ctx.PrintUnwindInformation();2557}2558DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF);2559Ctx.printUnwindInformation();2560}2561} // namespace25622563template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {2564ListScope D(W, "NeededLibraries");25652566std::vector<StringRef> Libs;2567for (const auto &Entry : dynamic_table())2568if (Entry.d_tag == ELF::DT_NEEDED)2569Libs.push_back(getDynamicString(Entry.d_un.d_val));25702571llvm::sort(Libs);25722573for (StringRef L : Libs)2574W.printString(L);2575}25762577template <class ELFT>2578static Error checkHashTable(const ELFDumper<ELFT> &Dumper,2579const typename ELFT::Hash *H,2580bool *IsHeaderValid = nullptr) {2581const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();2582const uint64_t SecOffset = (const uint8_t *)H - Obj.base();2583if (Dumper.getHashTableEntSize() == 8) {2584auto It = llvm::find_if(ElfMachineType, [&](const EnumEntry<unsigned> &E) {2585return E.Value == Obj.getHeader().e_machine;2586});2587if (IsHeaderValid)2588*IsHeaderValid = false;2589return createError("the hash table at 0x" + Twine::utohexstr(SecOffset) +2590" is not supported: it contains non-standard 8 "2591"byte entries on " +2592It->AltName + " platform");2593}25942595auto MakeError = [&](const Twine &Msg = "") {2596return createError("the hash table at offset 0x" +2597Twine::utohexstr(SecOffset) +2598" goes past the end of the file (0x" +2599Twine::utohexstr(Obj.getBufSize()) + ")" + Msg);2600};26012602// Each SHT_HASH section starts from two 32-bit fields: nbucket and nchain.2603const unsigned HeaderSize = 2 * sizeof(typename ELFT::Word);26042605if (IsHeaderValid)2606*IsHeaderValid = Obj.getBufSize() - SecOffset >= HeaderSize;26072608if (Obj.getBufSize() - SecOffset < HeaderSize)2609return MakeError();26102611if (Obj.getBufSize() - SecOffset - HeaderSize <2612((uint64_t)H->nbucket + H->nchain) * sizeof(typename ELFT::Word))2613return MakeError(", nbucket = " + Twine(H->nbucket) +2614", nchain = " + Twine(H->nchain));2615return Error::success();2616}26172618template <class ELFT>2619static Error checkGNUHashTable(const ELFFile<ELFT> &Obj,2620const typename ELFT::GnuHash *GnuHashTable,2621bool *IsHeaderValid = nullptr) {2622const uint8_t *TableData = reinterpret_cast<const uint8_t *>(GnuHashTable);2623assert(TableData >= Obj.base() && TableData < Obj.base() + Obj.getBufSize() &&2624"GnuHashTable must always point to a location inside the file");26252626uint64_t TableOffset = TableData - Obj.base();2627if (IsHeaderValid)2628*IsHeaderValid = TableOffset + /*Header size:*/ 16 < Obj.getBufSize();2629if (TableOffset + 16 + (uint64_t)GnuHashTable->nbuckets * 4 +2630(uint64_t)GnuHashTable->maskwords * sizeof(typename ELFT::Off) >=2631Obj.getBufSize())2632return createError("unable to dump the SHT_GNU_HASH "2633"section at 0x" +2634Twine::utohexstr(TableOffset) +2635": it goes past the end of the file");2636return Error::success();2637}26382639template <typename ELFT> void ELFDumper<ELFT>::printHashTable() {2640DictScope D(W, "HashTable");2641if (!HashTable)2642return;26432644bool IsHeaderValid;2645Error Err = checkHashTable(*this, HashTable, &IsHeaderValid);2646if (IsHeaderValid) {2647W.printNumber("Num Buckets", HashTable->nbucket);2648W.printNumber("Num Chains", HashTable->nchain);2649}26502651if (Err) {2652reportUniqueWarning(std::move(Err));2653return;2654}26552656W.printList("Buckets", HashTable->buckets());2657W.printList("Chains", HashTable->chains());2658}26592660template <class ELFT>2661static Expected<ArrayRef<typename ELFT::Word>>2662getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion,2663const typename ELFT::GnuHash *GnuHashTable) {2664if (!DynSymRegion)2665return createError("no dynamic symbol table found");26662667ArrayRef<typename ELFT::Sym> DynSymTable =2668DynSymRegion->template getAsArrayRef<typename ELFT::Sym>();2669size_t NumSyms = DynSymTable.size();2670if (!NumSyms)2671return createError("the dynamic symbol table is empty");26722673if (GnuHashTable->symndx < NumSyms)2674return GnuHashTable->values(NumSyms);26752676// A normal empty GNU hash table section produced by linker might have2677// symndx set to the number of dynamic symbols + 1 (for the zero symbol)2678// and have dummy null values in the Bloom filter and in the buckets2679// vector (or no values at all). It happens because the value of symndx is not2680// important for dynamic loaders when the GNU hash table is empty. They just2681// skip the whole object during symbol lookup. In such cases, the symndx value2682// is irrelevant and we should not report a warning.2683ArrayRef<typename ELFT::Word> Buckets = GnuHashTable->buckets();2684if (!llvm::all_of(Buckets, [](typename ELFT::Word V) { return V == 0; }))2685return createError(2686"the first hashed symbol index (" + Twine(GnuHashTable->symndx) +2687") is greater than or equal to the number of dynamic symbols (" +2688Twine(NumSyms) + ")");2689// There is no way to represent an array of (dynamic symbols count - symndx)2690// length.2691return ArrayRef<typename ELFT::Word>();2692}26932694template <typename ELFT>2695void ELFDumper<ELFT>::printGnuHashTable() {2696DictScope D(W, "GnuHashTable");2697if (!GnuHashTable)2698return;26992700bool IsHeaderValid;2701Error Err = checkGNUHashTable<ELFT>(Obj, GnuHashTable, &IsHeaderValid);2702if (IsHeaderValid) {2703W.printNumber("Num Buckets", GnuHashTable->nbuckets);2704W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);2705W.printNumber("Num Mask Words", GnuHashTable->maskwords);2706W.printNumber("Shift Count", GnuHashTable->shift2);2707}27082709if (Err) {2710reportUniqueWarning(std::move(Err));2711return;2712}27132714ArrayRef<typename ELFT::Off> BloomFilter = GnuHashTable->filter();2715W.printHexList("Bloom Filter", BloomFilter);27162717ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets();2718W.printList("Buckets", Buckets);27192720Expected<ArrayRef<Elf_Word>> Chains =2721getGnuHashTableChains<ELFT>(DynSymRegion, GnuHashTable);2722if (!Chains) {2723reportUniqueWarning("unable to dump 'Values' for the SHT_GNU_HASH "2724"section: " +2725toString(Chains.takeError()));2726return;2727}27282729W.printHexList("Values", *Chains);2730}27312732template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() {2733// Print histogram for the .hash section.2734if (this->HashTable) {2735if (Error E = checkHashTable<ELFT>(*this, this->HashTable))2736this->reportUniqueWarning(std::move(E));2737else2738printHashHistogram(*this->HashTable);2739}27402741// Print histogram for the .gnu.hash section.2742if (this->GnuHashTable) {2743if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))2744this->reportUniqueWarning(std::move(E));2745else2746printGnuHashHistogram(*this->GnuHashTable);2747}2748}27492750template <typename ELFT>2751void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const {2752size_t NBucket = HashTable.nbucket;2753size_t NChain = HashTable.nchain;2754ArrayRef<Elf_Word> Buckets = HashTable.buckets();2755ArrayRef<Elf_Word> Chains = HashTable.chains();2756size_t TotalSyms = 0;2757// If hash table is correct, we have at least chains with 0 length.2758size_t MaxChain = 1;27592760if (NChain == 0 || NBucket == 0)2761return;27622763std::vector<size_t> ChainLen(NBucket, 0);2764// Go over all buckets and note chain lengths of each bucket (total2765// unique chain lengths).2766for (size_t B = 0; B < NBucket; ++B) {2767BitVector Visited(NChain);2768for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {2769if (C == ELF::STN_UNDEF)2770break;2771if (Visited[C]) {2772this->reportUniqueWarning(2773".hash section is invalid: bucket " + Twine(C) +2774": a cycle was detected in the linked chain");2775break;2776}2777Visited[C] = true;2778if (MaxChain <= ++ChainLen[B])2779++MaxChain;2780}2781TotalSyms += ChainLen[B];2782}27832784if (!TotalSyms)2785return;27862787std::vector<size_t> Count(MaxChain, 0);2788// Count how long is the chain for each bucket.2789for (size_t B = 0; B < NBucket; B++)2790++Count[ChainLen[B]];2791// Print Number of buckets with each chain lengths and their cumulative2792// coverage of the symbols.2793printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false);2794}27952796template <class ELFT>2797void ELFDumper<ELFT>::printGnuHashHistogram(2798const Elf_GnuHash &GnuHashTable) const {2799Expected<ArrayRef<Elf_Word>> ChainsOrErr =2800getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable);2801if (!ChainsOrErr) {2802this->reportUniqueWarning("unable to print the GNU hash table histogram: " +2803toString(ChainsOrErr.takeError()));2804return;2805}28062807ArrayRef<Elf_Word> Chains = *ChainsOrErr;2808size_t Symndx = GnuHashTable.symndx;2809size_t TotalSyms = 0;2810size_t MaxChain = 1;28112812size_t NBucket = GnuHashTable.nbuckets;2813if (Chains.empty() || NBucket == 0)2814return;28152816ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets();2817std::vector<size_t> ChainLen(NBucket, 0);2818for (size_t B = 0; B < NBucket; ++B) {2819if (!Buckets[B])2820continue;2821size_t Len = 1;2822for (size_t C = Buckets[B] - Symndx;2823C < Chains.size() && (Chains[C] & 1) == 0; ++C)2824if (MaxChain < ++Len)2825++MaxChain;2826ChainLen[B] = Len;2827TotalSyms += Len;2828}2829++MaxChain;28302831if (!TotalSyms)2832return;28332834std::vector<size_t> Count(MaxChain, 0);2835for (size_t B = 0; B < NBucket; ++B)2836++Count[ChainLen[B]];2837// Print Number of buckets with each chain lengths and their cumulative2838// coverage of the symbols.2839printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true);2840}28412842template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {2843StringRef SOName = "<Not found>";2844if (SONameOffset)2845SOName = getDynamicString(*SONameOffset);2846W.printString("LoadName", SOName);2847}28482849template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {2850switch (Obj.getHeader().e_machine) {2851case EM_HEXAGON:2852printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES,2853std::make_unique<HexagonAttributeParser>(&W),2854llvm::endianness::little);2855break;2856case EM_ARM:2857printAttributes(2858ELF::SHT_ARM_ATTRIBUTES, std::make_unique<ARMAttributeParser>(&W),2859Obj.isLE() ? llvm::endianness::little : llvm::endianness::big);2860break;2861case EM_RISCV:2862if (Obj.isLE())2863printAttributes(ELF::SHT_RISCV_ATTRIBUTES,2864std::make_unique<RISCVAttributeParser>(&W),2865llvm::endianness::little);2866else2867reportUniqueWarning("attribute printing not implemented for big-endian "2868"RISC-V objects");2869break;2870case EM_MSP430:2871printAttributes(ELF::SHT_MSP430_ATTRIBUTES,2872std::make_unique<MSP430AttributeParser>(&W),2873llvm::endianness::little);2874break;2875case EM_MIPS: {2876printMipsABIFlags();2877printMipsOptions();2878printMipsReginfo();2879MipsGOTParser<ELFT> Parser(*this);2880if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols()))2881reportUniqueWarning(std::move(E));2882else if (!Parser.isGotEmpty())2883printMipsGOT(Parser);28842885if (Error E = Parser.findPLT(dynamic_table()))2886reportUniqueWarning(std::move(E));2887else if (!Parser.isPltEmpty())2888printMipsPLT(Parser);2889break;2890}2891default:2892break;2893}2894}28952896template <class ELFT>2897void ELFDumper<ELFT>::printAttributes(2898unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser,2899llvm::endianness Endianness) {2900assert((AttrShType != ELF::SHT_NULL) && AttrParser &&2901"Incomplete ELF attribute implementation");2902DictScope BA(W, "BuildAttributes");2903for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {2904if (Sec.sh_type != AttrShType)2905continue;29062907ArrayRef<uint8_t> Contents;2908if (Expected<ArrayRef<uint8_t>> ContentOrErr =2909Obj.getSectionContents(Sec)) {2910Contents = *ContentOrErr;2911if (Contents.empty()) {2912reportUniqueWarning("the " + describe(Sec) + " is empty");2913continue;2914}2915} else {2916reportUniqueWarning("unable to read the content of the " + describe(Sec) +2917": " + toString(ContentOrErr.takeError()));2918continue;2919}29202921W.printHex("FormatVersion", Contents[0]);29222923if (Error E = AttrParser->parse(Contents, Endianness))2924reportUniqueWarning("unable to dump attributes from the " +2925describe(Sec) + ": " + toString(std::move(E)));2926}2927}29282929namespace {29302931template <class ELFT> class MipsGOTParser {2932public:2933LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)2934using Entry = typename ELFT::Addr;2935using Entries = ArrayRef<Entry>;29362937const bool IsStatic;2938const ELFFile<ELFT> &Obj;2939const ELFDumper<ELFT> &Dumper;29402941MipsGOTParser(const ELFDumper<ELFT> &D);2942Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);2943Error findPLT(Elf_Dyn_Range DynTable);29442945bool isGotEmpty() const { return GotEntries.empty(); }2946bool isPltEmpty() const { return PltEntries.empty(); }29472948uint64_t getGp() const;29492950const Entry *getGotLazyResolver() const;2951const Entry *getGotModulePointer() const;2952const Entry *getPltLazyResolver() const;2953const Entry *getPltModulePointer() const;29542955Entries getLocalEntries() const;2956Entries getGlobalEntries() const;2957Entries getOtherEntries() const;2958Entries getPltEntries() const;29592960uint64_t getGotAddress(const Entry * E) const;2961int64_t getGotOffset(const Entry * E) const;2962const Elf_Sym *getGotSym(const Entry *E) const;29632964uint64_t getPltAddress(const Entry * E) const;2965const Elf_Sym *getPltSym(const Entry *E) const;29662967StringRef getPltStrTable() const { return PltStrTable; }2968const Elf_Shdr *getPltSymTable() const { return PltSymTable; }29692970private:2971const Elf_Shdr *GotSec;2972size_t LocalNum;2973size_t GlobalNum;29742975const Elf_Shdr *PltSec;2976const Elf_Shdr *PltRelSec;2977const Elf_Shdr *PltSymTable;2978StringRef FileName;29792980Elf_Sym_Range GotDynSyms;2981StringRef PltStrTable;29822983Entries GotEntries;2984Entries PltEntries;2985};29862987} // end anonymous namespace29882989template <class ELFT>2990MipsGOTParser<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &D)2991: IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject().getELFFile()),2992Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr),2993PltRelSec(nullptr), PltSymTable(nullptr),2994FileName(D.getElfObject().getFileName()) {}29952996template <class ELFT>2997Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable,2998Elf_Sym_Range DynSyms) {2999// See "Global Offset Table" in Chapter 5 in the following document3000// for detailed GOT description.3001// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf30023003// Find static GOT secton.3004if (IsStatic) {3005GotSec = Dumper.findSectionByName(".got");3006if (!GotSec)3007return Error::success();30083009ArrayRef<uint8_t> Content =3010unwrapOrError(FileName, Obj.getSectionContents(*GotSec));3011GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),3012Content.size() / sizeof(Entry));3013LocalNum = GotEntries.size();3014return Error::success();3015}30163017// Lookup dynamic table tags which define the GOT layout.3018std::optional<uint64_t> DtPltGot;3019std::optional<uint64_t> DtLocalGotNum;3020std::optional<uint64_t> DtGotSym;3021for (const auto &Entry : DynTable) {3022switch (Entry.getTag()) {3023case ELF::DT_PLTGOT:3024DtPltGot = Entry.getVal();3025break;3026case ELF::DT_MIPS_LOCAL_GOTNO:3027DtLocalGotNum = Entry.getVal();3028break;3029case ELF::DT_MIPS_GOTSYM:3030DtGotSym = Entry.getVal();3031break;3032}3033}30343035if (!DtPltGot && !DtLocalGotNum && !DtGotSym)3036return Error::success();30373038if (!DtPltGot)3039return createError("cannot find PLTGOT dynamic tag");3040if (!DtLocalGotNum)3041return createError("cannot find MIPS_LOCAL_GOTNO dynamic tag");3042if (!DtGotSym)3043return createError("cannot find MIPS_GOTSYM dynamic tag");30443045size_t DynSymTotal = DynSyms.size();3046if (*DtGotSym > DynSymTotal)3047return createError("DT_MIPS_GOTSYM value (" + Twine(*DtGotSym) +3048") exceeds the number of dynamic symbols (" +3049Twine(DynSymTotal) + ")");30503051GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot);3052if (!GotSec)3053return createError("there is no non-empty GOT section at 0x" +3054Twine::utohexstr(*DtPltGot));30553056LocalNum = *DtLocalGotNum;3057GlobalNum = DynSymTotal - *DtGotSym;30583059ArrayRef<uint8_t> Content =3060unwrapOrError(FileName, Obj.getSectionContents(*GotSec));3061GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),3062Content.size() / sizeof(Entry));3063GotDynSyms = DynSyms.drop_front(*DtGotSym);30643065return Error::success();3066}30673068template <class ELFT>3069Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) {3070// Lookup dynamic table tags which define the PLT layout.3071std::optional<uint64_t> DtMipsPltGot;3072std::optional<uint64_t> DtJmpRel;3073for (const auto &Entry : DynTable) {3074switch (Entry.getTag()) {3075case ELF::DT_MIPS_PLTGOT:3076DtMipsPltGot = Entry.getVal();3077break;3078case ELF::DT_JMPREL:3079DtJmpRel = Entry.getVal();3080break;3081}3082}30833084if (!DtMipsPltGot && !DtJmpRel)3085return Error::success();30863087// Find PLT section.3088if (!DtMipsPltGot)3089return createError("cannot find MIPS_PLTGOT dynamic tag");3090if (!DtJmpRel)3091return createError("cannot find JMPREL dynamic tag");30923093PltSec = findNotEmptySectionByAddress(Obj, FileName, *DtMipsPltGot);3094if (!PltSec)3095return createError("there is no non-empty PLTGOT section at 0x" +3096Twine::utohexstr(*DtMipsPltGot));30973098PltRelSec = findNotEmptySectionByAddress(Obj, FileName, *DtJmpRel);3099if (!PltRelSec)3100return createError("there is no non-empty RELPLT section at 0x" +3101Twine::utohexstr(*DtJmpRel));31023103if (Expected<ArrayRef<uint8_t>> PltContentOrErr =3104Obj.getSectionContents(*PltSec))3105PltEntries =3106Entries(reinterpret_cast<const Entry *>(PltContentOrErr->data()),3107PltContentOrErr->size() / sizeof(Entry));3108else3109return createError("unable to read PLTGOT section content: " +3110toString(PltContentOrErr.takeError()));31113112if (Expected<const Elf_Shdr *> PltSymTableOrErr =3113Obj.getSection(PltRelSec->sh_link))3114PltSymTable = *PltSymTableOrErr;3115else3116return createError("unable to get a symbol table linked to the " +3117describe(Obj, *PltRelSec) + ": " +3118toString(PltSymTableOrErr.takeError()));31193120if (Expected<StringRef> StrTabOrErr =3121Obj.getStringTableForSymtab(*PltSymTable))3122PltStrTable = *StrTabOrErr;3123else3124return createError("unable to get a string table for the " +3125describe(Obj, *PltSymTable) + ": " +3126toString(StrTabOrErr.takeError()));31273128return Error::success();3129}31303131template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const {3132return GotSec->sh_addr + 0x7ff0;3133}31343135template <class ELFT>3136const typename MipsGOTParser<ELFT>::Entry *3137MipsGOTParser<ELFT>::getGotLazyResolver() const {3138return LocalNum > 0 ? &GotEntries[0] : nullptr;3139}31403141template <class ELFT>3142const typename MipsGOTParser<ELFT>::Entry *3143MipsGOTParser<ELFT>::getGotModulePointer() const {3144if (LocalNum < 2)3145return nullptr;3146const Entry &E = GotEntries[1];3147if ((E >> (sizeof(Entry) * 8 - 1)) == 0)3148return nullptr;3149return &E;3150}31513152template <class ELFT>3153typename MipsGOTParser<ELFT>::Entries3154MipsGOTParser<ELFT>::getLocalEntries() const {3155size_t Skip = getGotModulePointer() ? 2 : 1;3156if (LocalNum - Skip <= 0)3157return Entries();3158return GotEntries.slice(Skip, LocalNum - Skip);3159}31603161template <class ELFT>3162typename MipsGOTParser<ELFT>::Entries3163MipsGOTParser<ELFT>::getGlobalEntries() const {3164if (GlobalNum == 0)3165return Entries();3166return GotEntries.slice(LocalNum, GlobalNum);3167}31683169template <class ELFT>3170typename MipsGOTParser<ELFT>::Entries3171MipsGOTParser<ELFT>::getOtherEntries() const {3172size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;3173if (OtherNum == 0)3174return Entries();3175return GotEntries.slice(LocalNum + GlobalNum, OtherNum);3176}31773178template <class ELFT>3179uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const {3180int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);3181return GotSec->sh_addr + Offset;3182}31833184template <class ELFT>3185int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const {3186int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);3187return Offset - 0x7ff0;3188}31893190template <class ELFT>3191const typename MipsGOTParser<ELFT>::Elf_Sym *3192MipsGOTParser<ELFT>::getGotSym(const Entry *E) const {3193int64_t Offset = std::distance(GotEntries.data(), E);3194return &GotDynSyms[Offset - LocalNum];3195}31963197template <class ELFT>3198const typename MipsGOTParser<ELFT>::Entry *3199MipsGOTParser<ELFT>::getPltLazyResolver() const {3200return PltEntries.empty() ? nullptr : &PltEntries[0];3201}32023203template <class ELFT>3204const typename MipsGOTParser<ELFT>::Entry *3205MipsGOTParser<ELFT>::getPltModulePointer() const {3206return PltEntries.size() < 2 ? nullptr : &PltEntries[1];3207}32083209template <class ELFT>3210typename MipsGOTParser<ELFT>::Entries3211MipsGOTParser<ELFT>::getPltEntries() const {3212if (PltEntries.size() <= 2)3213return Entries();3214return PltEntries.slice(2, PltEntries.size() - 2);3215}32163217template <class ELFT>3218uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const {3219int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);3220return PltSec->sh_addr + Offset;3221}32223223template <class ELFT>3224const typename MipsGOTParser<ELFT>::Elf_Sym *3225MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {3226int64_t Offset = std::distance(getPltEntries().data(), E);3227if (PltRelSec->sh_type == ELF::SHT_REL) {3228Elf_Rel_Range Rels = unwrapOrError(FileName, Obj.rels(*PltRelSec));3229return unwrapOrError(FileName,3230Obj.getRelocationSymbol(Rels[Offset], PltSymTable));3231} else {3232Elf_Rela_Range Rels = unwrapOrError(FileName, Obj.relas(*PltRelSec));3233return unwrapOrError(FileName,3234Obj.getRelocationSymbol(Rels[Offset], PltSymTable));3235}3236}32373238const EnumEntry<unsigned> ElfMipsISAExtType[] = {3239{"None", Mips::AFL_EXT_NONE},3240{"Broadcom SB-1", Mips::AFL_EXT_SB1},3241{"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON},3242{"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2},3243{"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP},3244{"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3},3245{"LSI R4010", Mips::AFL_EXT_4010},3246{"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E},3247{"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F},3248{"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A},3249{"MIPS R4650", Mips::AFL_EXT_4650},3250{"MIPS R5900", Mips::AFL_EXT_5900},3251{"MIPS R10000", Mips::AFL_EXT_10000},3252{"NEC VR4100", Mips::AFL_EXT_4100},3253{"NEC VR4111/VR4181", Mips::AFL_EXT_4111},3254{"NEC VR4120", Mips::AFL_EXT_4120},3255{"NEC VR5400", Mips::AFL_EXT_5400},3256{"NEC VR5500", Mips::AFL_EXT_5500},3257{"RMI Xlr", Mips::AFL_EXT_XLR},3258{"Toshiba R3900", Mips::AFL_EXT_3900}3259};32603261const EnumEntry<unsigned> ElfMipsASEFlags[] = {3262{"DSP", Mips::AFL_ASE_DSP},3263{"DSPR2", Mips::AFL_ASE_DSPR2},3264{"Enhanced VA Scheme", Mips::AFL_ASE_EVA},3265{"MCU", Mips::AFL_ASE_MCU},3266{"MDMX", Mips::AFL_ASE_MDMX},3267{"MIPS-3D", Mips::AFL_ASE_MIPS3D},3268{"MT", Mips::AFL_ASE_MT},3269{"SmartMIPS", Mips::AFL_ASE_SMARTMIPS},3270{"VZ", Mips::AFL_ASE_VIRT},3271{"MSA", Mips::AFL_ASE_MSA},3272{"MIPS16", Mips::AFL_ASE_MIPS16},3273{"microMIPS", Mips::AFL_ASE_MICROMIPS},3274{"XPA", Mips::AFL_ASE_XPA},3275{"CRC", Mips::AFL_ASE_CRC},3276{"GINV", Mips::AFL_ASE_GINV},3277};32783279const EnumEntry<unsigned> ElfMipsFpABIType[] = {3280{"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY},3281{"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE},3282{"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE},3283{"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT},3284{"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)",3285Mips::Val_GNU_MIPS_ABI_FP_OLD_64},3286{"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX},3287{"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64},3288{"Hard float compat (32-bit CPU, 64-bit FPU)",3289Mips::Val_GNU_MIPS_ABI_FP_64A}3290};32913292static const EnumEntry<unsigned> ElfMipsFlags1[] {3293{"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG},3294};32953296static int getMipsRegisterSize(uint8_t Flag) {3297switch (Flag) {3298case Mips::AFL_REG_NONE:3299return 0;3300case Mips::AFL_REG_32:3301return 32;3302case Mips::AFL_REG_64:3303return 64;3304case Mips::AFL_REG_128:3305return 128;3306default:3307return -1;3308}3309}33103311template <class ELFT>3312static void printMipsReginfoData(ScopedPrinter &W,3313const Elf_Mips_RegInfo<ELFT> &Reginfo) {3314W.printHex("GP", Reginfo.ri_gp_value);3315W.printHex("General Mask", Reginfo.ri_gprmask);3316W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]);3317W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]);3318W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]);3319W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]);3320}33213322template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {3323const Elf_Shdr *RegInfoSec = findSectionByName(".reginfo");3324if (!RegInfoSec) {3325W.startLine() << "There is no .reginfo section in the file.\n";3326return;3327}33283329Expected<ArrayRef<uint8_t>> ContentsOrErr =3330Obj.getSectionContents(*RegInfoSec);3331if (!ContentsOrErr) {3332this->reportUniqueWarning(3333"unable to read the content of the .reginfo section (" +3334describe(*RegInfoSec) + "): " + toString(ContentsOrErr.takeError()));3335return;3336}33373338if (ContentsOrErr->size() < sizeof(Elf_Mips_RegInfo<ELFT>)) {3339this->reportUniqueWarning("the .reginfo section has an invalid size (0x" +3340Twine::utohexstr(ContentsOrErr->size()) + ")");3341return;3342}33433344DictScope GS(W, "MIPS RegInfo");3345printMipsReginfoData(W, *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(3346ContentsOrErr->data()));3347}33483349template <class ELFT>3350static Expected<const Elf_Mips_Options<ELFT> *>3351readMipsOptions(const uint8_t *SecBegin, ArrayRef<uint8_t> &SecData,3352bool &IsSupported) {3353if (SecData.size() < sizeof(Elf_Mips_Options<ELFT>))3354return createError("the .MIPS.options section has an invalid size (0x" +3355Twine::utohexstr(SecData.size()) + ")");33563357const Elf_Mips_Options<ELFT> *O =3358reinterpret_cast<const Elf_Mips_Options<ELFT> *>(SecData.data());3359const uint8_t Size = O->size;3360if (Size > SecData.size()) {3361const uint64_t Offset = SecData.data() - SecBegin;3362const uint64_t SecSize = Offset + SecData.size();3363return createError("a descriptor of size 0x" + Twine::utohexstr(Size) +3364" at offset 0x" + Twine::utohexstr(Offset) +3365" goes past the end of the .MIPS.options "3366"section of size 0x" +3367Twine::utohexstr(SecSize));3368}33693370IsSupported = O->kind == ODK_REGINFO;3371const size_t ExpectedSize =3372sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>);33733374if (IsSupported)3375if (Size < ExpectedSize)3376return createError(3377"a .MIPS.options entry of kind " +3378Twine(getElfMipsOptionsOdkType(O->kind)) +3379" has an invalid size (0x" + Twine::utohexstr(Size) +3380"), the expected size is 0x" + Twine::utohexstr(ExpectedSize));33813382SecData = SecData.drop_front(Size);3383return O;3384}33853386template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {3387const Elf_Shdr *MipsOpts = findSectionByName(".MIPS.options");3388if (!MipsOpts) {3389W.startLine() << "There is no .MIPS.options section in the file.\n";3390return;3391}33923393DictScope GS(W, "MIPS Options");33943395ArrayRef<uint8_t> Data =3396unwrapOrError(ObjF.getFileName(), Obj.getSectionContents(*MipsOpts));3397const uint8_t *const SecBegin = Data.begin();3398while (!Data.empty()) {3399bool IsSupported;3400Expected<const Elf_Mips_Options<ELFT> *> OptsOrErr =3401readMipsOptions<ELFT>(SecBegin, Data, IsSupported);3402if (!OptsOrErr) {3403reportUniqueWarning(OptsOrErr.takeError());3404break;3405}34063407unsigned Kind = (*OptsOrErr)->kind;3408const char *Type = getElfMipsOptionsOdkType(Kind);3409if (!IsSupported) {3410W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind3411<< ")\n";3412continue;3413}34143415DictScope GS(W, Type);3416if (Kind == ODK_REGINFO)3417printMipsReginfoData(W, (*OptsOrErr)->getRegInfo());3418else3419llvm_unreachable("unexpected .MIPS.options section descriptor kind");3420}3421}34223423template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {3424const Elf_Shdr *StackMapSection = findSectionByName(".llvm_stackmaps");3425if (!StackMapSection)3426return;34273428auto Warn = [&](Error &&E) {3429this->reportUniqueWarning("unable to read the stack map from " +3430describe(*StackMapSection) + ": " +3431toString(std::move(E)));3432};34333434Expected<ArrayRef<uint8_t>> ContentOrErr =3435Obj.getSectionContents(*StackMapSection);3436if (!ContentOrErr) {3437Warn(ContentOrErr.takeError());3438return;3439}34403441if (Error E =3442StackMapParser<ELFT::Endianness>::validateHeader(*ContentOrErr)) {3443Warn(std::move(E));3444return;3445}34463447prettyPrintStackMap(W, StackMapParser<ELFT::Endianness>(*ContentOrErr));3448}34493450template <class ELFT>3451void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex,3452const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {3453Expected<RelSymbol<ELFT>> Target = getRelocationTarget(R, SymTab);3454if (!Target)3455reportUniqueWarning("unable to print relocation " + Twine(RelIndex) +3456" in " + describe(Sec) + ": " +3457toString(Target.takeError()));3458else3459printRelRelaReloc(R, *Target);3460}34613462template <class ELFT>3463std::vector<EnumEntry<unsigned>>3464ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header,3465const Elf_Sym &Symbol) const {3466std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),3467std::end(ElfSymOtherFlags));3468if (Header.e_machine == EM_MIPS) {3469// Someone in their infinite wisdom decided to make STO_MIPS_MIPS163470// flag overlap with other ST_MIPS_xxx flags. So consider both3471// cases separately.3472if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)3473SymOtherFlags.insert(SymOtherFlags.end(),3474std::begin(ElfMips16SymOtherFlags),3475std::end(ElfMips16SymOtherFlags));3476else3477SymOtherFlags.insert(SymOtherFlags.end(),3478std::begin(ElfMipsSymOtherFlags),3479std::end(ElfMipsSymOtherFlags));3480} else if (Header.e_machine == EM_AARCH64) {3481SymOtherFlags.insert(SymOtherFlags.end(),3482std::begin(ElfAArch64SymOtherFlags),3483std::end(ElfAArch64SymOtherFlags));3484} else if (Header.e_machine == EM_RISCV) {3485SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags),3486std::end(ElfRISCVSymOtherFlags));3487}3488return SymOtherFlags;3489}34903491static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,3492StringRef Str2) {3493OS.PadToColumn(2u);3494OS << Str1;3495OS.PadToColumn(37u);3496OS << Str2 << "\n";3497OS.flush();3498}34993500template <class ELFT>3501static std::string getSectionHeadersNumString(const ELFFile<ELFT> &Obj,3502StringRef FileName) {3503const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();3504if (ElfHeader.e_shnum != 0)3505return to_string(ElfHeader.e_shnum);35063507Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();3508if (!ArrOrErr) {3509// In this case we can ignore an error, because we have already reported a3510// warning about the broken section header table earlier.3511consumeError(ArrOrErr.takeError());3512return "<?>";3513}35143515if (ArrOrErr->empty())3516return "0";3517return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")";3518}35193520template <class ELFT>3521static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> &Obj,3522StringRef FileName) {3523const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();3524if (ElfHeader.e_shstrndx != SHN_XINDEX)3525return to_string(ElfHeader.e_shstrndx);35263527Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();3528if (!ArrOrErr) {3529// In this case we can ignore an error, because we have already reported a3530// warning about the broken section header table earlier.3531consumeError(ArrOrErr.takeError());3532return "<?>";3533}35343535if (ArrOrErr->empty())3536return "65535 (corrupt: out of range)";3537return to_string(ElfHeader.e_shstrndx) + " (" +3538to_string((*ArrOrErr)[0].sh_link) + ")";3539}35403541static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) {3542auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) {3543return E.Value == Type;3544});3545if (It != ArrayRef(ElfObjectFileType).end())3546return It;3547return nullptr;3548}35493550template <class ELFT>3551void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,3552ArrayRef<std::string> InputFilenames,3553const Archive *A) {3554if (InputFilenames.size() > 1 || A) {3555this->W.startLine() << "\n";3556this->W.printString("File", FileStr);3557}3558}35593560template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() {3561const Elf_Ehdr &e = this->Obj.getHeader();3562OS << "ELF Header:\n";3563OS << " Magic: ";3564std::string Str;3565for (int i = 0; i < ELF::EI_NIDENT; i++)3566OS << format(" %02x", static_cast<int>(e.e_ident[i]));3567OS << "\n";3568Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));3569printFields(OS, "Class:", Str);3570Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding));3571printFields(OS, "Data:", Str);3572OS.PadToColumn(2u);3573OS << "Version:";3574OS.PadToColumn(37u);3575OS << utohexstr(e.e_ident[ELF::EI_VERSION]);3576if (e.e_version == ELF::EV_CURRENT)3577OS << " (current)";3578OS << "\n";3579auto OSABI = ArrayRef(ElfOSABI);3580if (e.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&3581e.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {3582switch (e.e_machine) {3583case ELF::EM_ARM:3584OSABI = ArrayRef(ARMElfOSABI);3585break;3586case ELF::EM_AMDGPU:3587OSABI = ArrayRef(AMDGPUElfOSABI);3588break;3589default:3590break;3591}3592}3593Str = enumToString(e.e_ident[ELF::EI_OSABI], OSABI);3594printFields(OS, "OS/ABI:", Str);3595printFields(OS,3596"ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION]));35973598if (const EnumEntry<unsigned> *E = getObjectFileEnumEntry(e.e_type)) {3599Str = E->AltName.str();3600} else {3601if (e.e_type >= ET_LOPROC)3602Str = "Processor Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";3603else if (e.e_type >= ET_LOOS)3604Str = "OS Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";3605else3606Str = "<unknown>: " + utohexstr(e.e_type, /*LowerCase=*/true);3607}3608printFields(OS, "Type:", Str);36093610Str = enumToString(e.e_machine, ArrayRef(ElfMachineType));3611printFields(OS, "Machine:", Str);3612Str = "0x" + utohexstr(e.e_version);3613printFields(OS, "Version:", Str);3614Str = "0x" + utohexstr(e.e_entry);3615printFields(OS, "Entry point address:", Str);3616Str = to_string(e.e_phoff) + " (bytes into file)";3617printFields(OS, "Start of program headers:", Str);3618Str = to_string(e.e_shoff) + " (bytes into file)";3619printFields(OS, "Start of section headers:", Str);3620std::string ElfFlags;3621if (e.e_machine == EM_MIPS)3622ElfFlags = printFlags(3623e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH),3624unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH));3625else if (e.e_machine == EM_RISCV)3626ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags));3627else if (e.e_machine == EM_AVR)3628ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags),3629unsigned(ELF::EF_AVR_ARCH_MASK));3630else if (e.e_machine == EM_LOONGARCH)3631ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags),3632unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),3633unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));3634else if (e.e_machine == EM_XTENSA)3635ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),3636unsigned(ELF::EF_XTENSA_MACH));3637else if (e.e_machine == EM_CUDA)3638ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags),3639unsigned(ELF::EF_CUDA_SM));3640else if (e.e_machine == EM_AMDGPU) {3641switch (e.e_ident[ELF::EI_ABIVERSION]) {3642default:3643break;3644case 0:3645// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.3646[[fallthrough]];3647case ELF::ELFABIVERSION_AMDGPU_HSA_V3:3648ElfFlags =3649printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),3650unsigned(ELF::EF_AMDGPU_MACH));3651break;3652case ELF::ELFABIVERSION_AMDGPU_HSA_V4:3653case ELF::ELFABIVERSION_AMDGPU_HSA_V5:3654ElfFlags =3655printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),3656unsigned(ELF::EF_AMDGPU_MACH),3657unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),3658unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));3659break;3660case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {3661ElfFlags =3662printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),3663unsigned(ELF::EF_AMDGPU_MACH),3664unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),3665unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));3666if (auto GenericV = e.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {3667ElfFlags +=3668", generic_v" +3669to_string(GenericV >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET);3670}3671} break;3672}3673}3674Str = "0x" + utohexstr(e.e_flags);3675if (!ElfFlags.empty())3676Str = Str + ", " + ElfFlags;3677printFields(OS, "Flags:", Str);3678Str = to_string(e.e_ehsize) + " (bytes)";3679printFields(OS, "Size of this header:", Str);3680Str = to_string(e.e_phentsize) + " (bytes)";3681printFields(OS, "Size of program headers:", Str);3682Str = to_string(e.e_phnum);3683printFields(OS, "Number of program headers:", Str);3684Str = to_string(e.e_shentsize) + " (bytes)";3685printFields(OS, "Size of section headers:", Str);3686Str = getSectionHeadersNumString(this->Obj, this->FileName);3687printFields(OS, "Number of section headers:", Str);3688Str = getSectionHeaderTableIndexString(this->Obj, this->FileName);3689printFields(OS, "Section header string table index:", Str);3690}36913692template <class ELFT> std::vector<GroupSection> ELFDumper<ELFT>::getGroups() {3693auto GetSignature = [&](const Elf_Sym &Sym, unsigned SymNdx,3694const Elf_Shdr &Symtab) -> StringRef {3695Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab);3696if (!StrTableOrErr) {3697reportUniqueWarning("unable to get the string table for " +3698describe(Symtab) + ": " +3699toString(StrTableOrErr.takeError()));3700return "<?>";3701}37023703StringRef Strings = *StrTableOrErr;3704if (Sym.st_name >= Strings.size()) {3705reportUniqueWarning("unable to get the name of the symbol with index " +3706Twine(SymNdx) + ": st_name (0x" +3707Twine::utohexstr(Sym.st_name) +3708") is past the end of the string table of size 0x" +3709Twine::utohexstr(Strings.size()));3710return "<?>";3711}37123713return StrTableOrErr->data() + Sym.st_name;3714};37153716std::vector<GroupSection> Ret;3717uint64_t I = 0;3718for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {3719++I;3720if (Sec.sh_type != ELF::SHT_GROUP)3721continue;37223723StringRef Signature = "<?>";3724if (Expected<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Sec.sh_link)) {3725if (Expected<const Elf_Sym *> SymOrErr =3726Obj.template getEntry<Elf_Sym>(**SymtabOrErr, Sec.sh_info))3727Signature = GetSignature(**SymOrErr, Sec.sh_info, **SymtabOrErr);3728else3729reportUniqueWarning("unable to get the signature symbol for " +3730describe(Sec) + ": " +3731toString(SymOrErr.takeError()));3732} else {3733reportUniqueWarning("unable to get the symbol table for " +3734describe(Sec) + ": " +3735toString(SymtabOrErr.takeError()));3736}37373738ArrayRef<Elf_Word> Data;3739if (Expected<ArrayRef<Elf_Word>> ContentsOrErr =3740Obj.template getSectionContentsAsArray<Elf_Word>(Sec)) {3741if (ContentsOrErr->empty())3742reportUniqueWarning("unable to read the section group flag from the " +3743describe(Sec) + ": the section is empty");3744else3745Data = *ContentsOrErr;3746} else {3747reportUniqueWarning("unable to get the content of the " + describe(Sec) +3748": " + toString(ContentsOrErr.takeError()));3749}37503751Ret.push_back({getPrintableSectionName(Sec),3752maybeDemangle(Signature),3753Sec.sh_name,3754I - 1,3755Sec.sh_link,3756Sec.sh_info,3757Data.empty() ? Elf_Word(0) : Data[0],3758{}});37593760if (Data.empty())3761continue;37623763std::vector<GroupMember> &GM = Ret.back().Members;3764for (uint32_t Ndx : Data.slice(1)) {3765if (Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(Ndx)) {3766GM.push_back({getPrintableSectionName(**SecOrErr), Ndx});3767} else {3768reportUniqueWarning("unable to get the section with index " +3769Twine(Ndx) + " when dumping the " + describe(Sec) +3770": " + toString(SecOrErr.takeError()));3771GM.push_back({"<?>", Ndx});3772}3773}3774}3775return Ret;3776}37773778static DenseMap<uint64_t, const GroupSection *>3779mapSectionsToGroups(ArrayRef<GroupSection> Groups) {3780DenseMap<uint64_t, const GroupSection *> Ret;3781for (const GroupSection &G : Groups)3782for (const GroupMember &GM : G.Members)3783Ret.insert({GM.Index, &G});3784return Ret;3785}37863787template <class ELFT> void GNUELFDumper<ELFT>::printGroupSections() {3788std::vector<GroupSection> V = this->getGroups();3789DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);3790for (const GroupSection &G : V) {3791OS << "\n"3792<< getGroupType(G.Type) << " group section ["3793<< format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature3794<< "] contains " << G.Members.size() << " sections:\n"3795<< " [Index] Name\n";3796for (const GroupMember &GM : G.Members) {3797const GroupSection *MainGroup = Map[GM.Index];3798if (MainGroup != &G)3799this->reportUniqueWarning(3800"section with index " + Twine(GM.Index) +3801", included in the group section with index " +3802Twine(MainGroup->Index) +3803", was also found in the group section with index " +3804Twine(G.Index));3805OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n";3806}3807}38083809if (V.empty())3810OS << "There are no section groups in this file.\n";3811}38123813template <class ELFT>3814void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,3815const RelSymbol<ELFT> &RelSym) {3816// First two fields are bit width dependent. The rest of them are fixed width.3817unsigned Bias = ELFT::Is64Bits ? 8 : 0;3818Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias};3819unsigned Width = ELFT::Is64Bits ? 16 : 8;38203821Fields[0].Str = to_string(format_hex_no_prefix(R.Offset, Width));3822Fields[1].Str = to_string(format_hex_no_prefix(R.Info, Width));38233824SmallString<32> RelocName;3825this->Obj.getRelocationTypeName(R.Type, RelocName);3826Fields[2].Str = RelocName.c_str();38273828if (RelSym.Sym)3829Fields[3].Str =3830to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width));3831if (RelSym.Sym && RelSym.Name.empty())3832Fields[4].Str = "<null>";3833else3834Fields[4].Str = std::string(RelSym.Name);38353836for (const Field &F : Fields)3837printField(F);38383839std::string Addend;3840if (std::optional<int64_t> A = R.Addend) {3841int64_t RelAddend = *A;3842if (!Fields[4].Str.empty()) {3843if (RelAddend < 0) {3844Addend = " - ";3845RelAddend = -static_cast<uint64_t>(RelAddend);3846} else {3847Addend = " + ";3848}3849}3850Addend += utohexstr(RelAddend, /*LowerCase=*/true);3851}3852OS << Addend << "\n";3853}38543855template <class ELFT>3856static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType,3857const typename ELFT::Ehdr &EHeader,3858uint64_t CrelHdr = 0) {3859bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;3860if (ELFT::Is64Bits)3861OS << " Offset Info Type Symbol's "3862"Value Symbol's Name";3863else3864OS << " Offset Info Type Sym. Value Symbol's Name";3865if (IsRela || (SType == ELF::SHT_CREL && (CrelHdr & CREL_HDR_ADDEND)))3866OS << " + Addend";3867OS << "\n";3868}38693870template <class ELFT>3871void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name,3872const DynRegionInfo &Reg) {3873uint64_t Offset = Reg.Addr - this->Obj.base();3874OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x"3875<< utohexstr(Offset, /*LowerCase=*/true);3876if (Type != ELF::SHT_CREL)3877OS << " contains " << Reg.Size << " bytes";3878OS << ":\n";3879printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader());3880}38813882template <class ELFT>3883static bool isRelocationSec(const typename ELFT::Shdr &Sec,3884const typename ELFT::Ehdr &EHeader) {3885return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||3886Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_CREL ||3887Sec.sh_type == ELF::SHT_ANDROID_REL ||3888Sec.sh_type == ELF::SHT_ANDROID_RELA ||3889Sec.sh_type == ELF::SHT_ANDROID_RELR ||3890(EHeader.e_machine == EM_AARCH64 &&3891Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);3892}38933894template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {3895auto PrintAsRelr = [&](const Elf_Shdr &Sec) {3896return Sec.sh_type == ELF::SHT_RELR ||3897Sec.sh_type == ELF::SHT_ANDROID_RELR ||3898(this->Obj.getHeader().e_machine == EM_AARCH64 &&3899Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);3900};3901auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> {3902// Android's packed relocation section needs to be unpacked first3903// to get the actual number of entries.3904if (Sec.sh_type == ELF::SHT_ANDROID_REL ||3905Sec.sh_type == ELF::SHT_ANDROID_RELA) {3906Expected<std::vector<typename ELFT::Rela>> RelasOrErr =3907this->Obj.android_relas(Sec);3908if (!RelasOrErr)3909return RelasOrErr.takeError();3910return RelasOrErr->size();3911}39123913if (Sec.sh_type == ELF::SHT_CREL) {3914Expected<ArrayRef<uint8_t>> ContentsOrErr =3915this->Obj.getSectionContents(Sec);3916if (!ContentsOrErr)3917return ContentsOrErr.takeError();3918auto NumOrErr = this->Obj.getCrelHeader(*ContentsOrErr);3919if (!NumOrErr)3920return NumOrErr.takeError();3921return *NumOrErr / 8;3922}39233924if (PrintAsRelr(Sec)) {3925Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);3926if (!RelrsOrErr)3927return RelrsOrErr.takeError();3928return this->Obj.decode_relrs(*RelrsOrErr).size();3929}39303931return Sec.getEntityCount();3932};39333934bool HasRelocSections = false;3935for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {3936if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))3937continue;3938HasRelocSections = true;39393940std::string EntriesNum = "<?>";3941if (Expected<size_t> NumOrErr = GetEntriesNum(Sec))3942EntriesNum = std::to_string(*NumOrErr);3943else3944this->reportUniqueWarning("unable to get the number of relocations in " +3945this->describe(Sec) + ": " +3946toString(NumOrErr.takeError()));39473948uintX_t Offset = Sec.sh_offset;3949StringRef Name = this->getPrintableSectionName(Sec);3950OS << "\nRelocation section '" << Name << "' at offset 0x"3951<< utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum3952<< " entries:\n";39533954if (PrintAsRelr(Sec)) {3955printRelr(Sec);3956} else {3957uint64_t CrelHdr = 0;3958// For CREL, read the header and call printRelocationsHelper only if3959// GetEntriesNum(Sec) succeeded.3960if (Sec.sh_type == ELF::SHT_CREL && EntriesNum != "<?>") {3961CrelHdr = cantFail(this->Obj.getCrelHeader(3962cantFail(this->Obj.getSectionContents(Sec))));3963}3964printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader(),3965CrelHdr);3966if (Sec.sh_type != ELF::SHT_CREL || EntriesNum != "<?>")3967this->printRelocationsHelper(Sec);3968}3969}3970if (!HasRelocSections)3971OS << "\nThere are no relocations in this file.\n";3972}39733974template <class ELFT> void GNUELFDumper<ELFT>::printRelr(const Elf_Shdr &Sec) {3975Expected<Elf_Relr_Range> RangeOrErr = this->Obj.relrs(Sec);3976if (!RangeOrErr) {3977this->reportUniqueWarning("unable to read relocations from " +3978this->describe(Sec) + ": " +3979toString(RangeOrErr.takeError()));3980return;3981}3982if (ELFT::Is64Bits)3983OS << "Index: Entry Address Symbolic Address\n";3984else3985OS << "Index: Entry Address Symbolic Address\n";39863987// If .symtab is available, collect its defined symbols and sort them by3988// st_value.3989SmallVector<std::pair<uint64_t, std::string>, 0> Syms;3990if (this->DotSymtabSec) {3991Elf_Sym_Range Symtab;3992std::optional<StringRef> Strtab;3993std::tie(Symtab, Strtab) = this->getSymtabAndStrtab();3994if (Symtab.size() && Strtab) {3995for (auto [I, Sym] : enumerate(Symtab)) {3996if (!Sym.st_shndx)3997continue;3998Syms.emplace_back(Sym.st_value,3999this->getFullSymbolName(Sym, I, ArrayRef<Elf_Word>(),4000*Strtab, false));4001}4002}4003}4004llvm::stable_sort(Syms);40054006typename ELFT::uint Base = 0;4007size_t I = 0;4008auto Print = [&](uint64_t Where) {4009OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8);4010for (; I < Syms.size() && Syms[I].first <= Where; ++I)4011;4012// Try symbolizing the address. Find the nearest symbol before or at the4013// address and print the symbol and the address difference.4014if (I) {4015OS << " " << Syms[I - 1].second;4016if (Syms[I - 1].first < Where)4017OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first);4018}4019OS << '\n';4020};4021for (auto [Index, R] : enumerate(*RangeOrErr)) {4022typename ELFT::uint Entry = R;4023OS << formatv("{0:4}: ", Index)4024<< format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' ';4025if ((Entry & 1) == 0) {4026Print(Entry);4027Base = Entry + sizeof(typename ELFT::uint);4028} else {4029bool First = true;4030for (auto Where = Base; Entry >>= 1;4031Where += sizeof(typename ELFT::uint)) {4032if (Entry & 1) {4033if (First)4034First = false;4035else4036OS.indent(ELFT::Is64Bits ? 24 : 16);4037Print(Where);4038}4039}4040Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint);4041}4042}4043}40444045// Print the offset of a particular section from anyone of the ranges:4046// [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER].4047// If 'Type' does not fall within any of those ranges, then a string is4048// returned as '<unknown>' followed by the type value.4049static std::string getSectionTypeOffsetString(unsigned Type) {4050if (Type >= SHT_LOOS && Type <= SHT_HIOS)4051return "LOOS+0x" + utohexstr(Type - SHT_LOOS);4052else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC)4053return "LOPROC+0x" + utohexstr(Type - SHT_LOPROC);4054else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER)4055return "LOUSER+0x" + utohexstr(Type - SHT_LOUSER);4056return "0x" + utohexstr(Type) + ": <unknown>";4057}40584059static std::string getSectionTypeString(unsigned Machine, unsigned Type) {4060StringRef Name = getELFSectionTypeName(Machine, Type);40614062// Handle SHT_GNU_* type names.4063if (Name.consume_front("SHT_GNU_")) {4064if (Name == "HASH")4065return "GNU_HASH";4066// E.g. SHT_GNU_verneed -> VERNEED.4067return Name.upper();4068}40694070if (Name == "SHT_SYMTAB_SHNDX")4071return "SYMTAB SECTION INDICES";40724073if (Name.consume_front("SHT_"))4074return Name.str();4075return getSectionTypeOffsetString(Type);4076}40774078static void printSectionDescription(formatted_raw_ostream &OS,4079unsigned EMachine) {4080OS << "Key to Flags:\n";4081OS << " W (write), A (alloc), X (execute), M (merge), S (strings), I "4082"(info),\n";4083OS << " L (link order), O (extra OS processing required), G (group), T "4084"(TLS),\n";4085OS << " C (compressed), x (unknown), o (OS specific), E (exclude),\n";4086OS << " R (retain)";40874088if (EMachine == EM_X86_64)4089OS << ", l (large)";4090else if (EMachine == EM_ARM)4091OS << ", y (purecode)";40924093OS << ", p (processor specific)\n";4094}40954096template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {4097ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());4098if (Sections.empty()) {4099OS << "\nThere are no sections in this file.\n";4100Expected<StringRef> SecStrTableOrErr =4101this->Obj.getSectionStringTable(Sections, this->WarningHandler);4102if (!SecStrTableOrErr)4103this->reportUniqueWarning(SecStrTableOrErr.takeError());4104return;4105}4106unsigned Bias = ELFT::Is64Bits ? 0 : 8;4107OS << "There are " << to_string(Sections.size())4108<< " section headers, starting at offset "4109<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";4110OS << "Section Headers:\n";4111Field Fields[11] = {4112{"[Nr]", 2}, {"Name", 7}, {"Type", 25},4113{"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias},4114{"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias},4115{"Inf", 82 - Bias}, {"Al", 86 - Bias}};4116for (const Field &F : Fields)4117printField(F);4118OS << "\n";41194120StringRef SecStrTable;4121if (Expected<StringRef> SecStrTableOrErr =4122this->Obj.getSectionStringTable(Sections, this->WarningHandler))4123SecStrTable = *SecStrTableOrErr;4124else4125this->reportUniqueWarning(SecStrTableOrErr.takeError());41264127size_t SectionIndex = 0;4128for (const Elf_Shdr &Sec : Sections) {4129Fields[0].Str = to_string(SectionIndex);4130if (SecStrTable.empty())4131Fields[1].Str = "<no-strings>";4132else4133Fields[1].Str = std::string(unwrapOrError<StringRef>(4134this->FileName, this->Obj.getSectionName(Sec, SecStrTable)));4135Fields[2].Str =4136getSectionTypeString(this->Obj.getHeader().e_machine, Sec.sh_type);4137Fields[3].Str =4138to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8));4139Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6));4140Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6));4141Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2));4142Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI],4143this->Obj.getHeader().e_machine, Sec.sh_flags);4144Fields[8].Str = to_string(Sec.sh_link);4145Fields[9].Str = to_string(Sec.sh_info);4146Fields[10].Str = to_string(Sec.sh_addralign);41474148OS.PadToColumn(Fields[0].Column);4149OS << "[" << right_justify(Fields[0].Str, 2) << "]";4150for (int i = 1; i < 7; i++)4151printField(Fields[i]);4152OS.PadToColumn(Fields[7].Column);4153OS << right_justify(Fields[7].Str, 3);4154OS.PadToColumn(Fields[8].Column);4155OS << right_justify(Fields[8].Str, 2);4156OS.PadToColumn(Fields[9].Column);4157OS << right_justify(Fields[9].Str, 3);4158OS.PadToColumn(Fields[10].Column);4159OS << right_justify(Fields[10].Str, 2);4160OS << "\n";4161++SectionIndex;4162}4163printSectionDescription(OS, this->Obj.getHeader().e_machine);4164}41654166template <class ELFT>4167void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,4168size_t Entries,4169bool NonVisibilityBitsUsed,4170bool ExtraSymInfo) const {4171StringRef Name;4172if (Symtab)4173Name = this->getPrintableSectionName(*Symtab);4174if (!Name.empty())4175OS << "\nSymbol table '" << Name << "'";4176else4177OS << "\nSymbol table for image";4178OS << " contains " << Entries << " entries:\n";41794180if (ELFT::Is64Bits) {4181OS << " Num: Value Size Type Bind Vis";4182if (ExtraSymInfo)4183OS << "+Other";4184} else {4185OS << " Num: Value Size Type Bind Vis";4186if (ExtraSymInfo)4187OS << "+Other";4188}41894190OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0));4191if (ExtraSymInfo)4192OS << "Ndx(SecName) Name [+ Version Info]\n";4193else4194OS << "Ndx Name\n";4195}41964197template <class ELFT>4198std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(4199const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,4200bool ExtraSymInfo) const {4201unsigned SectionIndex = Symbol.st_shndx;4202switch (SectionIndex) {4203case ELF::SHN_UNDEF:4204return "UND";4205case ELF::SHN_ABS:4206return "ABS";4207case ELF::SHN_COMMON:4208return "COM";4209case ELF::SHN_XINDEX: {4210Expected<uint32_t> IndexOrErr =4211object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable);4212if (!IndexOrErr) {4213assert(Symbol.st_shndx == SHN_XINDEX &&4214"getExtendedSymbolTableIndex should only fail due to an invalid "4215"SHT_SYMTAB_SHNDX table/reference");4216this->reportUniqueWarning(IndexOrErr.takeError());4217return "RSV[0xffff]";4218}4219SectionIndex = *IndexOrErr;4220break;4221}4222default:4223// Find if:4224// Processor specific4225if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC)4226return std::string("PRC[0x") +4227to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4228// OS specific4229if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS)4230return std::string("OS[0x") +4231to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4232// Architecture reserved:4233if (SectionIndex >= ELF::SHN_LORESERVE &&4234SectionIndex <= ELF::SHN_HIRESERVE)4235return std::string("RSV[0x") +4236to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4237break;4238}42394240std::string Extra;4241if (ExtraSymInfo) {4242auto Sec = this->Obj.getSection(SectionIndex);4243if (!Sec) {4244this->reportUniqueWarning(Sec.takeError());4245} else {4246auto SecName = this->Obj.getSectionName(**Sec);4247if (!SecName)4248this->reportUniqueWarning(SecName.takeError());4249else4250Extra = Twine(" (" + *SecName + ")").str();4251}4252}4253return to_string(format_decimal(SectionIndex, 3)) + Extra;4254}42554256template <class ELFT>4257void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,4258DataRegion<Elf_Word> ShndxTable,4259std::optional<StringRef> StrTable,4260bool IsDynamic, bool NonVisibilityBitsUsed,4261bool ExtraSymInfo) const {4262unsigned Bias = ELFT::Is64Bits ? 8 : 0;4263Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,426431 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};4265Fields[0].Str = to_string(format_decimal(SymIndex, 6)) + ":";4266Fields[1].Str =4267to_string(format_hex_no_prefix(Symbol.st_value, ELFT::Is64Bits ? 16 : 8));4268Fields[2].Str = to_string(format_decimal(Symbol.st_size, 5));42694270unsigned char SymbolType = Symbol.getType();4271if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&4272SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)4273Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));4274else4275Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));42764277Fields[4].Str =4278enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings));4279Fields[5].Str =4280enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities));42814282if (Symbol.st_other & ~0x3) {4283if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) {4284uint8_t Other = Symbol.st_other & ~0x3;4285if (Other & STO_AARCH64_VARIANT_PCS) {4286Other &= ~STO_AARCH64_VARIANT_PCS;4287Fields[5].Str += " [VARIANT_PCS";4288if (Other != 0)4289Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));4290Fields[5].Str.append("]");4291}4292} else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) {4293uint8_t Other = Symbol.st_other & ~0x3;4294if (Other & STO_RISCV_VARIANT_CC) {4295Other &= ~STO_RISCV_VARIANT_CC;4296Fields[5].Str += " [VARIANT_CC";4297if (Other != 0)4298Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));4299Fields[5].Str.append("]");4300}4301} else {4302Fields[5].Str +=4303" [<other: " + to_string(format_hex(Symbol.st_other, 2)) + ">]";4304}4305}43064307Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;4308Fields[6].Str =4309getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo);43104311Fields[7].Column += ExtraSymInfo ? 10 : 0;4312Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,4313StrTable, IsDynamic);4314for (const Field &Entry : Fields)4315printField(Entry);4316OS << "\n";4317}43184319template <class ELFT>4320void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,4321unsigned SymIndex,4322DataRegion<Elf_Word> ShndxTable,4323StringRef StrTable,4324uint32_t Bucket) {4325unsigned Bias = ELFT::Is64Bits ? 8 : 0;4326Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias,432734 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};4328Fields[0].Str = to_string(format_decimal(SymIndex, 5));4329Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":";43304331Fields[2].Str = to_string(4332format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));4333Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5));43344335unsigned char SymbolType = Symbol->getType();4336if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&4337SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)4338Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));4339else4340Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));43414342Fields[5].Str =4343enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings));4344Fields[6].Str =4345enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities));4346Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable);4347Fields[8].Str =4348this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true);43494350for (const Field &Entry : Fields)4351printField(Entry);4352OS << "\n";4353}43544355template <class ELFT>4356void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols,4357bool PrintDynamicSymbols,4358bool ExtraSymInfo) {4359if (!PrintSymbols && !PrintDynamicSymbols)4360return;4361// GNU readelf prints both the .dynsym and .symtab with --symbols.4362this->printSymbolsHelper(true, ExtraSymInfo);4363if (PrintSymbols)4364this->printSymbolsHelper(false, ExtraSymInfo);4365}43664367template <class ELFT>4368void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) {4369if (this->DynamicStringTable.empty())4370return;43714372if (ELFT::Is64Bits)4373OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4374else4375OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4376OS << "\n";43774378Elf_Sym_Range DynSyms = this->dynamic_symbols();4379const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];4380if (!FirstSym) {4381this->reportUniqueWarning(4382Twine("unable to print symbols for the .hash table: the "4383"dynamic symbol table ") +4384(this->DynSymRegion ? "is empty" : "was not found"));4385return;4386}43874388DataRegion<Elf_Word> ShndxTable(4389(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());4390auto Buckets = SysVHash.buckets();4391auto Chains = SysVHash.chains();4392for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) {4393if (Buckets[Buc] == ELF::STN_UNDEF)4394continue;4395BitVector Visited(SysVHash.nchain);4396for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) {4397if (Ch == ELF::STN_UNDEF)4398break;43994400if (Visited[Ch]) {4401this->reportUniqueWarning(".hash section is invalid: bucket " +4402Twine(Ch) +4403": a cycle was detected in the linked chain");4404break;4405}44064407printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable,4408Buc);4409Visited[Ch] = true;4410}4411}4412}44134414template <class ELFT>4415void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) {4416if (this->DynamicStringTable.empty())4417return;44184419Elf_Sym_Range DynSyms = this->dynamic_symbols();4420const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];4421if (!FirstSym) {4422this->reportUniqueWarning(4423Twine("unable to print symbols for the .gnu.hash table: the "4424"dynamic symbol table ") +4425(this->DynSymRegion ? "is empty" : "was not found"));4426return;4427}44284429auto GetSymbol = [&](uint64_t SymIndex,4430uint64_t SymsTotal) -> const Elf_Sym * {4431if (SymIndex >= SymsTotal) {4432this->reportUniqueWarning(4433"unable to print hashed symbol with index " + Twine(SymIndex) +4434", which is greater than or equal to the number of dynamic symbols "4435"(" +4436Twine::utohexstr(SymsTotal) + ")");4437return nullptr;4438}4439return FirstSym + SymIndex;4440};44414442Expected<ArrayRef<Elf_Word>> ValuesOrErr =4443getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHash);4444ArrayRef<Elf_Word> Values;4445if (!ValuesOrErr)4446this->reportUniqueWarning("unable to get hash values for the SHT_GNU_HASH "4447"section: " +4448toString(ValuesOrErr.takeError()));4449else4450Values = *ValuesOrErr;44514452DataRegion<Elf_Word> ShndxTable(4453(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());4454ArrayRef<Elf_Word> Buckets = GnuHash.buckets();4455for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) {4456if (Buckets[Buc] == ELF::STN_UNDEF)4457continue;4458uint32_t Index = Buckets[Buc];4459// Print whole chain.4460while (true) {4461uint32_t SymIndex = Index++;4462if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size()))4463printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable,4464Buc);4465else4466break;44674468if (SymIndex < GnuHash.symndx) {4469this->reportUniqueWarning(4470"unable to read the hash value for symbol with index " +4471Twine(SymIndex) +4472", which is less than the index of the first hashed symbol (" +4473Twine(GnuHash.symndx) + ")");4474break;4475}44764477// Chain ends at symbol with stopper bit.4478if ((Values[SymIndex - GnuHash.symndx] & 1) == 1)4479break;4480}4481}4482}44834484template <class ELFT> void GNUELFDumper<ELFT>::printHashSymbols() {4485if (this->HashTable) {4486OS << "\n Symbol table of .hash for image:\n";4487if (Error E = checkHashTable<ELFT>(*this, this->HashTable))4488this->reportUniqueWarning(std::move(E));4489else4490printHashTableSymbols(*this->HashTable);4491}44924493// Try printing the .gnu.hash table.4494if (this->GnuHashTable) {4495OS << "\n Symbol table of .gnu.hash for image:\n";4496if (ELFT::Is64Bits)4497OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4498else4499OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4500OS << "\n";45014502if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))4503this->reportUniqueWarning(std::move(E));4504else4505printGnuHashTableSymbols(*this->GnuHashTable);4506}4507}45084509template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() {4510ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());4511if (Sections.empty()) {4512OS << "\nThere are no sections in this file.\n";4513Expected<StringRef> SecStrTableOrErr =4514this->Obj.getSectionStringTable(Sections, this->WarningHandler);4515if (!SecStrTableOrErr)4516this->reportUniqueWarning(SecStrTableOrErr.takeError());4517return;4518}4519OS << "There are " << to_string(Sections.size())4520<< " section headers, starting at offset "4521<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";45224523OS << "Section Headers:\n";45244525auto PrintFields = [&](ArrayRef<Field> V) {4526for (const Field &F : V)4527printField(F);4528OS << "\n";4529};45304531PrintFields({{"[Nr]", 2}, {"Name", 7}});45324533constexpr bool Is64 = ELFT::Is64Bits;4534PrintFields({{"Type", 7},4535{Is64 ? "Address" : "Addr", 23},4536{"Off", Is64 ? 40 : 32},4537{"Size", Is64 ? 47 : 39},4538{"ES", Is64 ? 54 : 46},4539{"Lk", Is64 ? 59 : 51},4540{"Inf", Is64 ? 62 : 54},4541{"Al", Is64 ? 66 : 57}});4542PrintFields({{"Flags", 7}});45434544StringRef SecStrTable;4545if (Expected<StringRef> SecStrTableOrErr =4546this->Obj.getSectionStringTable(Sections, this->WarningHandler))4547SecStrTable = *SecStrTableOrErr;4548else4549this->reportUniqueWarning(SecStrTableOrErr.takeError());45504551size_t SectionIndex = 0;4552const unsigned AddrSize = Is64 ? 16 : 8;4553for (const Elf_Shdr &S : Sections) {4554StringRef Name = "<?>";4555if (Expected<StringRef> NameOrErr =4556this->Obj.getSectionName(S, SecStrTable))4557Name = *NameOrErr;4558else4559this->reportUniqueWarning(NameOrErr.takeError());45604561OS.PadToColumn(2);4562OS << "[" << right_justify(to_string(SectionIndex), 2) << "]";4563PrintFields({{Name, 7}});4564PrintFields(4565{{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7},4566{to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23},4567{to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32},4568{to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39},4569{to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46},4570{to_string(S.sh_link), Is64 ? 59 : 51},4571{to_string(S.sh_info), Is64 ? 63 : 55},4572{to_string(S.sh_addralign), Is64 ? 66 : 58}});45734574OS.PadToColumn(7);4575OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: ";45764577DenseMap<unsigned, StringRef> FlagToName = {4578{SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"},4579{SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"},4580{SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"},4581{SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"},4582{SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"},4583{SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}};45844585uint64_t Flags = S.sh_flags;4586uint64_t UnknownFlags = 0;4587ListSeparator LS;4588while (Flags) {4589// Take the least significant bit as a flag.4590uint64_t Flag = Flags & -Flags;4591Flags -= Flag;45924593auto It = FlagToName.find(Flag);4594if (It != FlagToName.end())4595OS << LS << It->second;4596else4597UnknownFlags |= Flag;4598}45994600auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) {4601uint64_t FlagsToPrint = UnknownFlags & Mask;4602if (!FlagsToPrint)4603return;46044605OS << LS << Name << " ("4606<< to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")";4607UnknownFlags &= ~Mask;4608};46094610PrintUnknownFlags(SHF_MASKOS, "OS");4611PrintUnknownFlags(SHF_MASKPROC, "PROC");4612PrintUnknownFlags(uint64_t(-1), "UNKNOWN");46134614OS << "\n";4615++SectionIndex;46164617if (!(S.sh_flags & SHF_COMPRESSED))4618continue;4619Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S);4620if (!Data || Data->size() < sizeof(Elf_Chdr)) {4621consumeError(Data.takeError());4622reportWarning(createError("SHF_COMPRESSED section '" + Name +4623"' does not have an Elf_Chdr header"),4624this->FileName);4625OS.indent(7);4626OS << "[<corrupt>]";4627} else {4628OS.indent(7);4629auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data());4630if (Chdr->ch_type == ELFCOMPRESS_ZLIB)4631OS << "ZLIB";4632else if (Chdr->ch_type == ELFCOMPRESS_ZSTD)4633OS << "ZSTD";4634else4635OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type));4636OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8)4637<< ", " << Chdr->ch_addralign;4638}4639OS << '\n';4640}4641}46424643static inline std::string printPhdrFlags(unsigned Flag) {4644std::string Str;4645Str = (Flag & PF_R) ? "R" : " ";4646Str += (Flag & PF_W) ? "W" : " ";4647Str += (Flag & PF_X) ? "E" : " ";4648return Str;4649}46504651template <class ELFT>4652static bool checkTLSSections(const typename ELFT::Phdr &Phdr,4653const typename ELFT::Shdr &Sec) {4654if (Sec.sh_flags & ELF::SHF_TLS) {4655// .tbss must only be shown in the PT_TLS segment.4656if (Sec.sh_type == ELF::SHT_NOBITS)4657return Phdr.p_type == ELF::PT_TLS;46584659// SHF_TLS sections are only shown in PT_TLS, PT_LOAD or PT_GNU_RELRO4660// segments.4661return (Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||4662(Phdr.p_type == ELF::PT_GNU_RELRO);4663}46644665// PT_TLS must only have SHF_TLS sections.4666return Phdr.p_type != ELF::PT_TLS;4667}46684669template <class ELFT>4670static bool checkPTDynamic(const typename ELFT::Phdr &Phdr,4671const typename ELFT::Shdr &Sec) {4672if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0)4673return true;46744675// We get here when we have an empty section. Only non-empty sections can be4676// at the start or at the end of PT_DYNAMIC.4677// Is section within the phdr both based on offset and VMA?4678bool CheckOffset = (Sec.sh_type == ELF::SHT_NOBITS) ||4679(Sec.sh_offset > Phdr.p_offset &&4680Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz);4681bool CheckVA = !(Sec.sh_flags & ELF::SHF_ALLOC) ||4682(Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz);4683return CheckOffset && CheckVA;4684}46854686template <class ELFT>4687void GNUELFDumper<ELFT>::printProgramHeaders(4688bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {4689const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE);4690// Exit early if no program header or section mapping details were requested.4691if (!PrintProgramHeaders && !ShouldPrintSectionMapping)4692return;46934694if (PrintProgramHeaders) {4695const Elf_Ehdr &Header = this->Obj.getHeader();4696if (Header.e_phnum == 0) {4697OS << "\nThere are no program headers in this file.\n";4698} else {4699printProgramHeaders();4700}4701}47024703if (ShouldPrintSectionMapping)4704printSectionMapping();4705}47064707template <class ELFT> void GNUELFDumper<ELFT>::printProgramHeaders() {4708unsigned Bias = ELFT::Is64Bits ? 8 : 0;4709const Elf_Ehdr &Header = this->Obj.getHeader();4710Field Fields[8] = {2, 17, 26, 37 + Bias,471148 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};4712OS << "\nElf file type is "4713<< enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n"4714<< "Entry point " << format_hex(Header.e_entry, 3) << "\n"4715<< "There are " << Header.e_phnum << " program headers,"4716<< " starting at offset " << Header.e_phoff << "\n\n"4717<< "Program Headers:\n";4718if (ELFT::Is64Bits)4719OS << " Type Offset VirtAddr PhysAddr "4720<< " FileSiz MemSiz Flg Align\n";4721else4722OS << " Type Offset VirtAddr PhysAddr FileSiz "4723<< "MemSiz Flg Align\n";47244725unsigned Width = ELFT::Is64Bits ? 18 : 10;4726unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7;47274728Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();4729if (!PhdrsOrErr) {4730this->reportUniqueWarning("unable to dump program headers: " +4731toString(PhdrsOrErr.takeError()));4732return;4733}47344735for (const Elf_Phdr &Phdr : *PhdrsOrErr) {4736Fields[0].Str = getGNUPtType(Header.e_machine, Phdr.p_type);4737Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8));4738Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width));4739Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width));4740Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth));4741Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth));4742Fields[6].Str = printPhdrFlags(Phdr.p_flags);4743Fields[7].Str = to_string(format_hex(Phdr.p_align, 1));4744for (const Field &F : Fields)4745printField(F);4746if (Phdr.p_type == ELF::PT_INTERP) {4747OS << "\n";4748auto ReportBadInterp = [&](const Twine &Msg) {4749this->reportUniqueWarning(4750"unable to read program interpreter name at offset 0x" +4751Twine::utohexstr(Phdr.p_offset) + ": " + Msg);4752};47534754if (Phdr.p_offset >= this->Obj.getBufSize()) {4755ReportBadInterp("it goes past the end of the file (0x" +4756Twine::utohexstr(this->Obj.getBufSize()) + ")");4757continue;4758}47594760const char *Data =4761reinterpret_cast<const char *>(this->Obj.base()) + Phdr.p_offset;4762size_t MaxSize = this->Obj.getBufSize() - Phdr.p_offset;4763size_t Len = strnlen(Data, MaxSize);4764if (Len == MaxSize) {4765ReportBadInterp("it is not null-terminated");4766continue;4767}47684769OS << " [Requesting program interpreter: ";4770OS << StringRef(Data, Len) << "]";4771}4772OS << "\n";4773}4774}47754776template <class ELFT> void GNUELFDumper<ELFT>::printSectionMapping() {4777OS << "\n Section to Segment mapping:\n Segment Sections...\n";4778DenseSet<const Elf_Shdr *> BelongsToSegment;4779int Phnum = 0;47804781Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();4782if (!PhdrsOrErr) {4783this->reportUniqueWarning(4784"can't read program headers to build section to segment mapping: " +4785toString(PhdrsOrErr.takeError()));4786return;4787}47884789for (const Elf_Phdr &Phdr : *PhdrsOrErr) {4790std::string Sections;4791OS << format(" %2.2d ", Phnum++);4792// Check if each section is in a segment and then print mapping.4793for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {4794if (Sec.sh_type == ELF::SHT_NULL)4795continue;47964797// readelf additionally makes sure it does not print zero sized sections4798// at end of segments and for PT_DYNAMIC both start and end of section4799// .tbss must only be shown in PT_TLS section.4800if (isSectionInSegment<ELFT>(Phdr, Sec) &&4801checkTLSSections<ELFT>(Phdr, Sec) &&4802checkPTDynamic<ELFT>(Phdr, Sec)) {4803Sections +=4804unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +4805" ";4806BelongsToSegment.insert(&Sec);4807}4808}4809OS << Sections << "\n";4810OS.flush();4811}48124813// Display sections that do not belong to a segment.4814std::string Sections;4815for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {4816if (BelongsToSegment.find(&Sec) == BelongsToSegment.end())4817Sections +=4818unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +4819' ';4820}4821if (!Sections.empty()) {4822OS << " None " << Sections << '\n';4823OS.flush();4824}4825}48264827namespace {48284829template <class ELFT>4830RelSymbol<ELFT> getSymbolForReloc(const ELFDumper<ELFT> &Dumper,4831const Relocation<ELFT> &Reloc) {4832using Elf_Sym = typename ELFT::Sym;4833auto WarnAndReturn = [&](const Elf_Sym *Sym,4834const Twine &Reason) -> RelSymbol<ELFT> {4835Dumper.reportUniqueWarning(4836"unable to get name of the dynamic symbol with index " +4837Twine(Reloc.Symbol) + ": " + Reason);4838return {Sym, "<corrupt>"};4839};48404841ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols();4842const Elf_Sym *FirstSym = Symbols.begin();4843if (!FirstSym)4844return WarnAndReturn(nullptr, "no dynamic symbol table found");48454846// We might have an object without a section header. In this case the size of4847// Symbols is zero, because there is no way to know the size of the dynamic4848// table. We should allow this case and not print a warning.4849if (!Symbols.empty() && Reloc.Symbol >= Symbols.size())4850return WarnAndReturn(4851nullptr,4852"index is greater than or equal to the number of dynamic symbols (" +4853Twine(Symbols.size()) + ")");48544855const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();4856const uint64_t FileSize = Obj.getBufSize();4857const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) +4858(uint64_t)Reloc.Symbol * sizeof(Elf_Sym);4859if (SymOffset + sizeof(Elf_Sym) > FileSize)4860return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) +4861" goes past the end of the file (0x" +4862Twine::utohexstr(FileSize) + ")");48634864const Elf_Sym *Sym = FirstSym + Reloc.Symbol;4865Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable());4866if (!ErrOrName)4867return WarnAndReturn(Sym, toString(ErrOrName.takeError()));48684869return {Sym == FirstSym ? nullptr : Sym, maybeDemangle(*ErrOrName)};4870}4871} // namespace48724873template <class ELFT>4874static size_t getMaxDynamicTagSize(const ELFFile<ELFT> &Obj,4875typename ELFT::DynRange Tags) {4876size_t Max = 0;4877for (const typename ELFT::Dyn &Dyn : Tags)4878Max = std::max(Max, Obj.getDynamicTagAsString(Dyn.d_tag).size());4879return Max;4880}48814882template <class ELFT> void GNUELFDumper<ELFT>::printDynamicTable() {4883Elf_Dyn_Range Table = this->dynamic_table();4884if (Table.empty())4885return;48864887OS << "Dynamic section at offset "4888<< format_hex(reinterpret_cast<const uint8_t *>(this->DynamicTable.Addr) -4889this->Obj.base(),48901)4891<< " contains " << Table.size() << " entries:\n";48924893// The type name is surrounded with round brackets, hence add 2.4894size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table) + 2;4895// The "Name/Value" column should be indented from the "Type" column by N4896// spaces, where N = MaxTagSize - length of "Type" (4) + trailing4897// space (1) = 3.4898OS << " Tag" + std::string(ELFT::Is64Bits ? 16 : 8, ' ') + "Type"4899<< std::string(MaxTagSize - 3, ' ') << "Name/Value\n";49004901std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s ";4902for (auto Entry : Table) {4903uintX_t Tag = Entry.getTag();4904std::string Type =4905std::string("(") + this->Obj.getDynamicTagAsString(Tag) + ")";4906std::string Value = this->getDynamicEntry(Tag, Entry.getVal());4907OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10)4908<< format(ValueFmt.c_str(), Type.c_str()) << Value << "\n";4909}4910}49114912template <class ELFT> void GNUELFDumper<ELFT>::printDynamicRelocations() {4913this->printDynamicRelocationsHelper();4914}49154916template <class ELFT>4917void ELFDumper<ELFT>::printDynamicReloc(const Relocation<ELFT> &R) {4918printRelRelaReloc(R, getSymbolForReloc(*this, R));4919}49204921template <class ELFT>4922void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) {4923this->forEachRelocationDo(4924Sec, [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec,4925const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); });4926}49274928template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() {4929const bool IsMips64EL = this->Obj.isMips64EL();4930auto DumpCrelRegion = [&](DynRegionInfo &Region) {4931// While the size is unknown, a valid CREL has at least one byte. We can4932// check whether Addr is in bounds, and then decode CREL until the file4933// end.4934Region.Size = Region.EntSize = 1;4935if (!Region.template getAsArrayRef<uint8_t>().empty()) {4936const uint64_t Offset =4937Region.Addr - reinterpret_cast<const uint8_t *>(4938ObjF.getMemoryBufferRef().getBufferStart());4939const uint64_t ObjSize = ObjF.getMemoryBufferRef().getBufferSize();4940auto RelsOrRelas =4941Obj.decodeCrel(ArrayRef<uint8_t>(Region.Addr, ObjSize - Offset));4942if (!RelsOrRelas) {4943reportUniqueWarning(toString(RelsOrRelas.takeError()));4944} else {4945for (const Elf_Rel &R : RelsOrRelas->first)4946printDynamicReloc(Relocation<ELFT>(R, false));4947for (const Elf_Rela &R : RelsOrRelas->second)4948printDynamicReloc(Relocation<ELFT>(R, false));4949}4950}4951};49524953if (this->DynCrelRegion.Addr) {4954printDynamicRelocHeader(ELF::SHT_CREL, "CREL", this->DynCrelRegion);4955DumpCrelRegion(this->DynCrelRegion);4956}49574958if (this->DynRelaRegion.Size > 0) {4959printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion);4960for (const Elf_Rela &Rela :4961this->DynRelaRegion.template getAsArrayRef<Elf_Rela>())4962printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));4963}49644965if (this->DynRelRegion.Size > 0) {4966printDynamicRelocHeader(ELF::SHT_REL, "REL", this->DynRelRegion);4967for (const Elf_Rel &Rel :4968this->DynRelRegion.template getAsArrayRef<Elf_Rel>())4969printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4970}49714972if (this->DynRelrRegion.Size > 0) {4973printDynamicRelocHeader(ELF::SHT_REL, "RELR", this->DynRelrRegion);4974Elf_Relr_Range Relrs =4975this->DynRelrRegion.template getAsArrayRef<Elf_Relr>();4976for (const Elf_Rel &Rel : Obj.decode_relrs(Relrs))4977printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4978}49794980if (this->DynPLTRelRegion.Size) {4981if (this->DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {4982printDynamicRelocHeader(ELF::SHT_RELA, "PLT", this->DynPLTRelRegion);4983for (const Elf_Rela &Rela :4984this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>())4985printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));4986} else if (this->DynPLTRelRegion.EntSize == 1) {4987DumpCrelRegion(this->DynPLTRelRegion);4988} else {4989printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion);4990for (const Elf_Rel &Rel :4991this->DynPLTRelRegion.template getAsArrayRef<Elf_Rel>())4992printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4993}4994}4995}49964997template <class ELFT>4998void GNUELFDumper<ELFT>::printGNUVersionSectionProlog(4999const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) {5000// Don't inline the SecName, because it might report a warning to stderr and5001// corrupt the output.5002StringRef SecName = this->getPrintableSectionName(Sec);5003OS << Label << " section '" << SecName << "' "5004<< "contains " << EntriesNum << " entries:\n";50055006StringRef LinkedSecName = "<corrupt>";5007if (Expected<const typename ELFT::Shdr *> LinkedSecOrErr =5008this->Obj.getSection(Sec.sh_link))5009LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr);5010else5011this->reportUniqueWarning("invalid section linked to " +5012this->describe(Sec) + ": " +5013toString(LinkedSecOrErr.takeError()));50145015OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16)5016<< " Offset: " << format_hex(Sec.sh_offset, 8)5017<< " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n";5018}50195020template <class ELFT>5021void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {5022if (!Sec)5023return;50245025printGNUVersionSectionProlog(*Sec, "Version symbols",5026Sec->sh_size / sizeof(Elf_Versym));5027Expected<ArrayRef<Elf_Versym>> VerTableOrErr =5028this->getVersionTable(*Sec, /*SymTab=*/nullptr,5029/*StrTab=*/nullptr, /*SymTabSec=*/nullptr);5030if (!VerTableOrErr) {5031this->reportUniqueWarning(VerTableOrErr.takeError());5032return;5033}50345035SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr;5036if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =5037this->getVersionMap())5038VersionMap = *MapOrErr;5039else5040this->reportUniqueWarning(MapOrErr.takeError());50415042ArrayRef<Elf_Versym> VerTable = *VerTableOrErr;5043std::vector<StringRef> Versions;5044for (size_t I = 0, E = VerTable.size(); I < E; ++I) {5045unsigned Ndx = VerTable[I].vs_index;5046if (Ndx == VER_NDX_LOCAL || Ndx == VER_NDX_GLOBAL) {5047Versions.emplace_back(Ndx == VER_NDX_LOCAL ? "*local*" : "*global*");5048continue;5049}50505051if (!VersionMap) {5052Versions.emplace_back("<corrupt>");5053continue;5054}50555056bool IsDefault;5057Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex(5058Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt);5059if (!NameOrErr) {5060this->reportUniqueWarning("unable to get a version for entry " +5061Twine(I) + " of " + this->describe(*Sec) +5062": " + toString(NameOrErr.takeError()));5063Versions.emplace_back("<corrupt>");5064continue;5065}5066Versions.emplace_back(*NameOrErr);5067}50685069// readelf prints 4 entries per line.5070uint64_t Entries = VerTable.size();5071for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {5072OS << " " << format_hex_no_prefix(VersymRow, 3) << ":";5073for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) {5074unsigned Ndx = VerTable[VersymRow + I].vs_index;5075OS << format("%4x%c", Ndx & VERSYM_VERSION,5076Ndx & VERSYM_HIDDEN ? 'h' : ' ');5077OS << left_justify("(" + std::string(Versions[VersymRow + I]) + ")", 13);5078}5079OS << '\n';5080}5081OS << '\n';5082}50835084static std::string versionFlagToString(unsigned Flags) {5085if (Flags == 0)5086return "none";50875088std::string Ret;5089auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) {5090if (!(Flags & Flag))5091return;5092if (!Ret.empty())5093Ret += " | ";5094Ret += Name;5095Flags &= ~Flag;5096};50975098AddFlag(VER_FLG_BASE, "BASE");5099AddFlag(VER_FLG_WEAK, "WEAK");5100AddFlag(VER_FLG_INFO, "INFO");5101AddFlag(~0, "<unknown>");5102return Ret;5103}51045105template <class ELFT>5106void GNUELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {5107if (!Sec)5108return;51095110printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info);51115112Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);5113if (!V) {5114this->reportUniqueWarning(V.takeError());5115return;5116}51175118for (const VerDef &Def : *V) {5119OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u Name: %s\n",5120Def.Offset, Def.Version,5121versionFlagToString(Def.Flags).c_str(), Def.Ndx, Def.Cnt,5122Def.Name.data());5123unsigned I = 0;5124for (const VerdAux &Aux : Def.AuxV)5125OS << format(" 0x%04x: Parent %u: %s\n", Aux.Offset, ++I,5126Aux.Name.data());5127}51285129OS << '\n';5130}51315132template <class ELFT>5133void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {5134if (!Sec)5135return;51365137unsigned VerneedNum = Sec->sh_info;5138printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum);51395140Expected<std::vector<VerNeed>> V =5141this->Obj.getVersionDependencies(*Sec, this->WarningHandler);5142if (!V) {5143this->reportUniqueWarning(V.takeError());5144return;5145}51465147for (const VerNeed &VN : *V) {5148OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset,5149VN.Version, VN.File.data(), VN.Cnt);5150for (const VernAux &Aux : VN.AuxV)5151OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset,5152Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(),5153Aux.Other);5154}5155OS << '\n';5156}51575158template <class ELFT>5159void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,5160size_t MaxChain,5161size_t TotalSyms,5162ArrayRef<size_t> Count,5163bool IsGnu) const {5164size_t CumulativeNonZero = 0;5165OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "")5166<< " bucket list length (total of " << NBucket << " buckets)\n"5167<< " Length Number % of total Coverage\n";5168for (size_t I = 0; I < MaxChain; ++I) {5169CumulativeNonZero += Count[I] * I;5170OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I],5171(Count[I] * 100.0) / NBucket,5172(CumulativeNonZero * 100.0) / TotalSyms);5173}5174}51755176template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {5177OS << "GNUStyle::printCGProfile not implemented\n";5178}51795180template <class ELFT>5181void GNUELFDumper<ELFT>::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) {5182OS << "GNUStyle::printBBAddrMaps not implemented\n";5183}51845185static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {5186std::vector<uint64_t> Ret;5187const uint8_t *Cur = Data.begin();5188const uint8_t *End = Data.end();5189while (Cur != End) {5190unsigned Size;5191const char *Err = nullptr;5192Ret.push_back(decodeULEB128(Cur, &Size, End, &Err));5193if (Err)5194return createError(Err);5195Cur += Size;5196}5197return Ret;5198}51995200template <class ELFT>5201static Expected<std::vector<uint64_t>>5202decodeAddrsigSection(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) {5203Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Sec);5204if (!ContentsOrErr)5205return ContentsOrErr.takeError();52065207if (Expected<std::vector<uint64_t>> SymsOrErr =5208toULEB128Array(*ContentsOrErr))5209return *SymsOrErr;5210else5211return createError("unable to decode " + describe(Obj, Sec) + ": " +5212toString(SymsOrErr.takeError()));5213}52145215template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() {5216if (!this->DotAddrsigSec)5217return;52185219Expected<std::vector<uint64_t>> SymsOrErr =5220decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);5221if (!SymsOrErr) {5222this->reportUniqueWarning(SymsOrErr.takeError());5223return;5224}52255226StringRef Name = this->getPrintableSectionName(*this->DotAddrsigSec);5227OS << "\nAddress-significant symbols section '" << Name << "'"5228<< " contains " << SymsOrErr->size() << " entries:\n";5229OS << " Num: Name\n";52305231Field Fields[2] = {0, 8};5232size_t SymIndex = 0;5233for (uint64_t Sym : *SymsOrErr) {5234Fields[0].Str = to_string(format_decimal(++SymIndex, 6)) + ":";5235Fields[1].Str = this->getStaticSymbolName(Sym);5236for (const Field &Entry : Fields)5237printField(Entry);5238OS << "\n";5239}5240}52415242template <class ELFT>5243static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,5244ArrayRef<uint8_t> Desc) {5245OS << " AArch64 PAuth ABI core info: ";5246// DataSize - size without padding, Desc.size() - size with padding5247if (DataSize != 16) {5248OS << format("<corrupted size: expected 16, got %d>", DataSize);5249return false;5250}52515252uint64_t Platform =5253support::endian::read64<ELFT::Endianness>(Desc.data() + 0);5254uint64_t Version = support::endian::read64<ELFT::Endianness>(Desc.data() + 8);52555256const char *PlatformDesc = [Platform]() {5257switch (Platform) {5258case AARCH64_PAUTH_PLATFORM_INVALID:5259return "invalid";5260case AARCH64_PAUTH_PLATFORM_BAREMETAL:5261return "baremetal";5262case AARCH64_PAUTH_PLATFORM_LLVM_LINUX:5263return "llvm_linux";5264default:5265return "unknown";5266}5267}();52685269std::string VersionDesc = [Platform, Version]() -> std::string {5270if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX)5271return "";5272if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1)))5273return "unknown";52745275std::array<StringRef, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1>5276Flags;5277Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS] = "Intrinsics";5278Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS] = "Calls";5279Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS] = "Returns";5280Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS] = "AuthTraps";5281Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR] =5282"VTPtrAddressDiscrimination";5283Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] =5284"VTPtrTypeDiscrimination";5285Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini";52865287static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI ==5288AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,5289"Update when new enum items are defined");52905291std::string Desc;5292for (uint32_t I = 0, End = Flags.size(); I < End; ++I) {5293if (!(Version & (1ULL << I)))5294Desc += '!';5295Desc +=5296Twine("PointerAuth" + Flags[I] + (I == End - 1 ? "" : ", ")).str();5297}5298return Desc;5299}();53005301OS << format("platform 0x%" PRIx64 " (%s), version 0x%" PRIx64, Platform,5302PlatformDesc, Version);5303if (!VersionDesc.empty())5304OS << format(" (%s)", VersionDesc.c_str());53055306return true;5307}53085309template <typename ELFT>5310static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,5311ArrayRef<uint8_t> Data) {5312std::string str;5313raw_string_ostream OS(str);5314uint32_t PrData;5315auto DumpBit = [&](uint32_t Flag, StringRef Name) {5316if (PrData & Flag) {5317PrData &= ~Flag;5318OS << Name;5319if (PrData)5320OS << ", ";5321}5322};53235324switch (Type) {5325default:5326OS << format("<application-specific type 0x%x>", Type);5327return OS.str();5328case GNU_PROPERTY_STACK_SIZE: {5329OS << "stack size: ";5330if (DataSize == sizeof(typename ELFT::uint))5331OS << formatv("{0:x}",5332(uint64_t)(*(const typename ELFT::Addr *)Data.data()));5333else5334OS << format("<corrupt length: 0x%x>", DataSize);5335return OS.str();5336}5337case GNU_PROPERTY_NO_COPY_ON_PROTECTED:5338OS << "no copy on protected";5339if (DataSize)5340OS << format(" <corrupt length: 0x%x>", DataSize);5341return OS.str();5342case GNU_PROPERTY_AARCH64_FEATURE_1_AND:5343case GNU_PROPERTY_X86_FEATURE_1_AND:5344OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "5345: "x86 feature: ");5346if (DataSize != 4) {5347OS << format("<corrupt length: 0x%x>", DataSize);5348return OS.str();5349}5350PrData = endian::read32<ELFT::Endianness>(Data.data());5351if (PrData == 0) {5352OS << "<None>";5353return OS.str();5354}5355if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {5356DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");5357DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");5358DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");5359} else {5360DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");5361DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");5362}5363if (PrData)5364OS << format("<unknown flags: 0x%x>", PrData);5365return OS.str();5366case GNU_PROPERTY_AARCH64_FEATURE_PAUTH:5367printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data);5368return OS.str();5369case GNU_PROPERTY_X86_FEATURE_2_NEEDED:5370case GNU_PROPERTY_X86_FEATURE_2_USED:5371OS << "x86 feature "5372<< (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: ");5373if (DataSize != 4) {5374OS << format("<corrupt length: 0x%x>", DataSize);5375return OS.str();5376}5377PrData = endian::read32<ELFT::Endianness>(Data.data());5378if (PrData == 0) {5379OS << "<None>";5380return OS.str();5381}5382DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86");5383DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87");5384DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX");5385DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM");5386DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM");5387DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM");5388DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR");5389DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE");5390DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT");5391DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC");5392if (PrData)5393OS << format("<unknown flags: 0x%x>", PrData);5394return OS.str();5395case GNU_PROPERTY_X86_ISA_1_NEEDED:5396case GNU_PROPERTY_X86_ISA_1_USED:5397OS << "x86 ISA "5398<< (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");5399if (DataSize != 4) {5400OS << format("<corrupt length: 0x%x>", DataSize);5401return OS.str();5402}5403PrData = endian::read32<ELFT::Endianness>(Data.data());5404if (PrData == 0) {5405OS << "<None>";5406return OS.str();5407}5408DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline");5409DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2");5410DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3");5411DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4");5412if (PrData)5413OS << format("<unknown flags: 0x%x>", PrData);5414return OS.str();5415}5416}54175418template <typename ELFT>5419static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {5420using Elf_Word = typename ELFT::Word;54215422SmallVector<std::string, 4> Properties;5423while (Arr.size() >= 8) {5424uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());5425uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);5426Arr = Arr.drop_front(8);54275428// Take padding size into account if present.5429uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));5430std::string str;5431raw_string_ostream OS(str);5432if (Arr.size() < PaddedSize) {5433OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize);5434Properties.push_back(OS.str());5435break;5436}5437Properties.push_back(5438getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));5439Arr = Arr.drop_front(PaddedSize);5440}54415442if (!Arr.empty())5443Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>");54445445return Properties;5446}54475448struct GNUAbiTag {5449std::string OSName;5450std::string ABI;5451bool IsValid;5452};54535454template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) {5455typedef typename ELFT::Word Elf_Word;54565457ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()),5458reinterpret_cast<const Elf_Word *>(Desc.end()));54595460if (Words.size() < 4)5461return {"", "", /*IsValid=*/false};54625463static const char *OSNames[] = {5464"Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",5465};5466StringRef OSName = "Unknown";5467if (Words[0] < std::size(OSNames))5468OSName = OSNames[Words[0]];5469uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3];5470std::string str;5471raw_string_ostream ABI(str);5472ABI << Major << "." << Minor << "." << Patch;5473return {std::string(OSName), ABI.str(), /*IsValid=*/true};5474}54755476static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) {5477std::string str;5478raw_string_ostream OS(str);5479for (uint8_t B : Desc)5480OS << format_hex_no_prefix(B, 2);5481return OS.str();5482}54835484static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {5485return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());5486}54875488template <typename ELFT>5489static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,5490ArrayRef<uint8_t> Desc) {5491// Return true if we were able to pretty-print the note, false otherwise.5492switch (NoteType) {5493default:5494return false;5495case ELF::NT_GNU_ABI_TAG: {5496const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);5497if (!AbiTag.IsValid)5498OS << " <corrupt GNU_ABI_TAG>";5499else5500OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI;5501break;5502}5503case ELF::NT_GNU_BUILD_ID: {5504OS << " Build ID: " << getGNUBuildId(Desc);5505break;5506}5507case ELF::NT_GNU_GOLD_VERSION:5508OS << " Version: " << getDescAsStringRef(Desc);5509break;5510case ELF::NT_GNU_PROPERTY_TYPE_0:5511OS << " Properties:";5512for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))5513OS << " " << Property << "\n";5514break;5515}5516OS << '\n';5517return true;5518}55195520using AndroidNoteProperties = std::vector<std::pair<StringRef, std::string>>;5521static AndroidNoteProperties getAndroidNoteProperties(uint32_t NoteType,5522ArrayRef<uint8_t> Desc) {5523AndroidNoteProperties Props;5524switch (NoteType) {5525case ELF::NT_ANDROID_TYPE_MEMTAG:5526if (Desc.empty()) {5527Props.emplace_back("Invalid .note.android.memtag", "");5528return Props;5529}55305531switch (Desc[0] & NT_MEMTAG_LEVEL_MASK) {5532case NT_MEMTAG_LEVEL_NONE:5533Props.emplace_back("Tagging Mode", "NONE");5534break;5535case NT_MEMTAG_LEVEL_ASYNC:5536Props.emplace_back("Tagging Mode", "ASYNC");5537break;5538case NT_MEMTAG_LEVEL_SYNC:5539Props.emplace_back("Tagging Mode", "SYNC");5540break;5541default:5542Props.emplace_back(5543"Tagging Mode",5544("Unknown (" + Twine::utohexstr(Desc[0] & NT_MEMTAG_LEVEL_MASK) + ")")5545.str());5546break;5547}5548Props.emplace_back("Heap",5549(Desc[0] & NT_MEMTAG_HEAP) ? "Enabled" : "Disabled");5550Props.emplace_back("Stack",5551(Desc[0] & NT_MEMTAG_STACK) ? "Enabled" : "Disabled");5552break;5553default:5554return Props;5555}5556return Props;5557}55585559static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,5560ArrayRef<uint8_t> Desc) {5561// Return true if we were able to pretty-print the note, false otherwise.5562AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);5563if (Props.empty())5564return false;5565for (const auto &KV : Props)5566OS << " " << KV.first << ": " << KV.second << '\n';5567return true;5568}55695570template <class ELFT>5571void GNUELFDumper<ELFT>::printMemtag(5572const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,5573const ArrayRef<uint8_t> AndroidNoteDesc,5574const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {5575OS << "Memtag Dynamic Entries:\n";5576if (DynamicEntries.empty())5577OS << " < none found >\n";5578for (const auto &DynamicEntryKV : DynamicEntries)5579OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second5580<< "\n";55815582if (!AndroidNoteDesc.empty()) {5583OS << "Memtag Android Note:\n";5584printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc);5585}55865587if (Descriptors.empty())5588return;55895590OS << "Memtag Global Descriptors:\n";5591for (const auto &[Addr, BytesToTag] : Descriptors) {5592OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x"5593<< utohexstr(BytesToTag, /*LowerCase=*/true) << "\n";5594}5595}55965597template <typename ELFT>5598static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType,5599ArrayRef<uint8_t> Desc) {5600switch (NoteType) {5601default:5602return false;5603case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:5604OS << " Version: " << getDescAsStringRef(Desc);5605break;5606case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:5607OS << " Producer: " << getDescAsStringRef(Desc);5608break;5609case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:5610OS << " Producer version: " << getDescAsStringRef(Desc);5611break;5612}5613OS << '\n';5614return true;5615}56165617const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = {5618{"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE},5619{"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE},5620{"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE},5621{"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED},5622{"LA48", NT_FREEBSD_FCTL_LA48},5623{"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE},5624};56255626struct FreeBSDNote {5627std::string Type;5628std::string Value;5629};56305631template <typename ELFT>5632static std::optional<FreeBSDNote>5633getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) {5634if (IsCore)5635return std::nullopt; // No pretty-printing yet.5636switch (NoteType) {5637case ELF::NT_FREEBSD_ABI_TAG:5638if (Desc.size() != 4)5639return std::nullopt;5640return FreeBSDNote{"ABI tag",5641utostr(endian::read32<ELFT::Endianness>(Desc.data()))};5642case ELF::NT_FREEBSD_ARCH_TAG:5643return FreeBSDNote{"Arch tag", toStringRef(Desc).str()};5644case ELF::NT_FREEBSD_FEATURE_CTL: {5645if (Desc.size() != 4)5646return std::nullopt;5647unsigned Value = endian::read32<ELFT::Endianness>(Desc.data());5648std::string FlagsStr;5649raw_string_ostream OS(FlagsStr);5650printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS);5651if (OS.str().empty())5652OS << "0x" << utohexstr(Value);5653else5654OS << "(0x" << utohexstr(Value) << ")";5655return FreeBSDNote{"Feature flags", OS.str()};5656}5657default:5658return std::nullopt;5659}5660}56615662struct AMDNote {5663std::string Type;5664std::string Value;5665};56665667template <typename ELFT>5668static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {5669switch (NoteType) {5670default:5671return {"", ""};5672case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: {5673struct CodeObjectVersion {5674support::aligned_ulittle32_t MajorVersion;5675support::aligned_ulittle32_t MinorVersion;5676};5677if (Desc.size() != sizeof(CodeObjectVersion))5678return {"AMD HSA Code Object Version",5679"Invalid AMD HSA Code Object Version"};5680std::string VersionString;5681raw_string_ostream StrOS(VersionString);5682auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data());5683StrOS << "[Major: " << Version->MajorVersion5684<< ", Minor: " << Version->MinorVersion << "]";5685return {"AMD HSA Code Object Version", VersionString};5686}5687case ELF::NT_AMD_HSA_HSAIL: {5688struct HSAILProperties {5689support::aligned_ulittle32_t HSAILMajorVersion;5690support::aligned_ulittle32_t HSAILMinorVersion;5691uint8_t Profile;5692uint8_t MachineModel;5693uint8_t DefaultFloatRound;5694};5695if (Desc.size() != sizeof(HSAILProperties))5696return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"};5697auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data());5698std::string HSAILPropetiesString;5699raw_string_ostream StrOS(HSAILPropetiesString);5700StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion5701<< ", HSAIL Minor: " << Properties->HSAILMinorVersion5702<< ", Profile: " << uint32_t(Properties->Profile)5703<< ", Machine Model: " << uint32_t(Properties->MachineModel)5704<< ", Default Float Round: "5705<< uint32_t(Properties->DefaultFloatRound) << "]";5706return {"AMD HSA HSAIL Properties", HSAILPropetiesString};5707}5708case ELF::NT_AMD_HSA_ISA_VERSION: {5709struct IsaVersion {5710support::aligned_ulittle16_t VendorNameSize;5711support::aligned_ulittle16_t ArchitectureNameSize;5712support::aligned_ulittle32_t Major;5713support::aligned_ulittle32_t Minor;5714support::aligned_ulittle32_t Stepping;5715};5716if (Desc.size() < sizeof(IsaVersion))5717return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};5718auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data());5719if (Desc.size() < sizeof(IsaVersion) +5720Isa->VendorNameSize + Isa->ArchitectureNameSize ||5721Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0)5722return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};5723std::string IsaString;5724raw_string_ostream StrOS(IsaString);5725StrOS << "[Vendor: "5726<< StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1)5727<< ", Architecture: "5728<< StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize,5729Isa->ArchitectureNameSize - 1)5730<< ", Major: " << Isa->Major << ", Minor: " << Isa->Minor5731<< ", Stepping: " << Isa->Stepping << "]";5732return {"AMD HSA ISA Version", IsaString};5733}5734case ELF::NT_AMD_HSA_METADATA: {5735if (Desc.size() == 0)5736return {"AMD HSA Metadata", ""};5737return {5738"AMD HSA Metadata",5739std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)};5740}5741case ELF::NT_AMD_HSA_ISA_NAME: {5742if (Desc.size() == 0)5743return {"AMD HSA ISA Name", ""};5744return {5745"AMD HSA ISA Name",5746std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};5747}5748case ELF::NT_AMD_PAL_METADATA: {5749struct PALMetadata {5750support::aligned_ulittle32_t Key;5751support::aligned_ulittle32_t Value;5752};5753if (Desc.size() % sizeof(PALMetadata) != 0)5754return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"};5755auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data());5756std::string MetadataString;5757raw_string_ostream StrOS(MetadataString);5758for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) {5759StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]";5760}5761return {"AMD PAL Metadata", MetadataString};5762}5763}5764}57655766struct AMDGPUNote {5767std::string Type;5768std::string Value;5769};57705771template <typename ELFT>5772static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {5773switch (NoteType) {5774default:5775return {"", ""};5776case ELF::NT_AMDGPU_METADATA: {5777StringRef MsgPackString =5778StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());5779msgpack::Document MsgPackDoc;5780if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))5781return {"", ""};57825783std::string MetadataString;57845785// FIXME: Metadata Verifier only works with AMDHSA.5786// This is an ugly workaround to avoid the verifier for other MD5787// formats (e.g. amdpal)5788if (MsgPackString.contains("amdhsa.")) {5789AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);5790if (!Verifier.verify(MsgPackDoc.getRoot()))5791MetadataString = "Invalid AMDGPU Metadata\n";5792}57935794raw_string_ostream StrOS(MetadataString);5795if (MsgPackDoc.getRoot().isScalar()) {5796// TODO: passing a scalar root to toYAML() asserts:5797// (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar &&5798// "plain scalar documents are not supported")5799// To avoid this crash we print the raw data instead.5800return {"", ""};5801}5802MsgPackDoc.toYAML(StrOS);5803return {"AMDGPU Metadata", StrOS.str()};5804}5805}5806}58075808struct CoreFileMapping {5809uint64_t Start, End, Offset;5810StringRef Filename;5811};58125813struct CoreNote {5814uint64_t PageSize;5815std::vector<CoreFileMapping> Mappings;5816};58175818static Expected<CoreNote> readCoreNote(DataExtractor Desc) {5819// Expected format of the NT_FILE note description:5820// 1. # of file mappings (call it N)5821// 2. Page size5822// 3. N (start, end, offset) triples5823// 4. N packed filenames (null delimited)5824// Each field is an Elf_Addr, except for filenames which are char* strings.58255826CoreNote Ret;5827const int Bytes = Desc.getAddressSize();58285829if (!Desc.isValidOffsetForAddress(2))5830return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) +5831" is too short, expected at least 0x" +5832Twine::utohexstr(Bytes * 2));5833if (Desc.getData().back() != 0)5834return createError("the note is not NUL terminated");58355836uint64_t DescOffset = 0;5837uint64_t FileCount = Desc.getAddress(&DescOffset);5838Ret.PageSize = Desc.getAddress(&DescOffset);58395840if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes))5841return createError("unable to read file mappings (found " +5842Twine(FileCount) + "): the note of size 0x" +5843Twine::utohexstr(Desc.size()) + " is too short");58445845uint64_t FilenamesOffset = 0;5846DataExtractor Filenames(5847Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes),5848Desc.isLittleEndian(), Desc.getAddressSize());58495850Ret.Mappings.resize(FileCount);5851size_t I = 0;5852for (CoreFileMapping &Mapping : Ret.Mappings) {5853++I;5854if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1))5855return createError(5856"unable to read the file name for the mapping with index " +5857Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) +5858" is truncated");5859Mapping.Start = Desc.getAddress(&DescOffset);5860Mapping.End = Desc.getAddress(&DescOffset);5861Mapping.Offset = Desc.getAddress(&DescOffset);5862Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset);5863}58645865return Ret;5866}58675868template <typename ELFT>5869static void printCoreNote(raw_ostream &OS, const CoreNote &Note) {5870// Length of "0x<address>" string.5871const int FieldWidth = ELFT::Is64Bits ? 18 : 10;58725873OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n';5874OS << " " << right_justify("Start", FieldWidth) << " "5875<< right_justify("End", FieldWidth) << " "5876<< right_justify("Page Offset", FieldWidth) << '\n';5877for (const CoreFileMapping &Mapping : Note.Mappings) {5878OS << " " << format_hex(Mapping.Start, FieldWidth) << " "5879<< format_hex(Mapping.End, FieldWidth) << " "5880<< format_hex(Mapping.Offset, FieldWidth) << "\n "5881<< Mapping.Filename << '\n';5882}5883}58845885const NoteType GenericNoteTypes[] = {5886{ELF::NT_VERSION, "NT_VERSION (version)"},5887{ELF::NT_ARCH, "NT_ARCH (architecture)"},5888{ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"},5889{ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"},5890};58915892const NoteType GNUNoteTypes[] = {5893{ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"},5894{ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},5895{ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},5896{ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},5897{ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},5898};58995900const NoteType FreeBSDCoreNoteTypes[] = {5901{ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},5902{ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},5903{ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"},5904{ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"},5905{ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"},5906{ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"},5907{ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"},5908{ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"},5909{ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS,5910"NT_PROCSTAT_PSSTRINGS (ps_strings data)"},5911{ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"},5912};59135914const NoteType FreeBSDNoteTypes[] = {5915{ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"},5916{ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"},5917{ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"},5918{ELF::NT_FREEBSD_FEATURE_CTL,5919"NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},5920};59215922const NoteType NetBSDCoreNoteTypes[] = {5923{ELF::NT_NETBSDCORE_PROCINFO,5924"NT_NETBSDCORE_PROCINFO (procinfo structure)"},5925{ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"},5926{ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"},5927};59285929const NoteType OpenBSDCoreNoteTypes[] = {5930{ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"},5931{ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"},5932{ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"},5933{ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"},5934{ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"},5935};59365937const NoteType AMDNoteTypes[] = {5938{ELF::NT_AMD_HSA_CODE_OBJECT_VERSION,5939"NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"},5940{ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"},5941{ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"},5942{ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"},5943{ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"},5944{ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"},5945};59465947const NoteType AMDGPUNoteTypes[] = {5948{ELF::NT_AMDGPU_METADATA, "NT_AMDGPU_METADATA (AMDGPU Metadata)"},5949};59505951const NoteType LLVMOMPOFFLOADNoteTypes[] = {5952{ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION,5953"NT_LLVM_OPENMP_OFFLOAD_VERSION (image format version)"},5954{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER,5955"NT_LLVM_OPENMP_OFFLOAD_PRODUCER (producing toolchain)"},5956{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION,5957"NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION (producing toolchain version)"},5958};59595960const NoteType AndroidNoteTypes[] = {5961{ELF::NT_ANDROID_TYPE_IDENT, "NT_ANDROID_TYPE_IDENT"},5962{ELF::NT_ANDROID_TYPE_KUSER, "NT_ANDROID_TYPE_KUSER"},5963{ELF::NT_ANDROID_TYPE_MEMTAG,5964"NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"},5965};59665967const NoteType CoreNoteTypes[] = {5968{ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},5969{ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},5970{ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"},5971{ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"},5972{ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"},5973{ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"},5974{ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"},5975{ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"},5976{ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"},5977{ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"},5978{ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"},59795980{ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"},5981{ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"},5982{ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"},5983{ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"},5984{ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"},5985{ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"},5986{ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"},5987{ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"},5988{ELF::NT_PPC_TM_CFPR,5989"NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"},5990{ELF::NT_PPC_TM_CVMX,5991"NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"},5992{ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"},5993{ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"},5994{ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"},5995{ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"},5996{ELF::NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"},59975998{ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"},5999{ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"},6000{ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"},60016002{ELF::NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS (s390 upper register halves)"},6003{ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"},6004{ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"},6005{ELF::NT_S390_TODPREG, "NT_S390_TODPREG (s390 TOD programmable register)"},6006{ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"},6007{ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"},6008{ELF::NT_S390_LAST_BREAK,6009"NT_S390_LAST_BREAK (s390 last breaking event address)"},6010{ELF::NT_S390_SYSTEM_CALL,6011"NT_S390_SYSTEM_CALL (s390 system call restart data)"},6012{ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"},6013{ELF::NT_S390_VXRS_LOW,6014"NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"},6015{ELF::NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"},6016{ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"},6017{ELF::NT_S390_GS_BC,6018"NT_S390_GS_BC (s390 guarded-storage broadcast control)"},60196020{ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"},6021{ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"},6022{ELF::NT_ARM_HW_BREAK,6023"NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"},6024{ELF::NT_ARM_HW_WATCH,6025"NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"},6026{ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"},6027{ELF::NT_ARM_PAC_MASK,6028"NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"},6029{ELF::NT_ARM_TAGGED_ADDR_CTRL,6030"NT_ARM_TAGGED_ADDR_CTRL (AArch64 Tagged Address Control)"},6031{ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"},6032{ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"},6033{ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"},60346035{ELF::NT_FILE, "NT_FILE (mapped files)"},6036{ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"},6037{ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"},6038};60396040template <class ELFT>6041StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {6042uint32_t Type = Note.getType();6043auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef {6044for (const NoteType &N : V)6045if (N.ID == Type)6046return N.Name;6047return "";6048};60496050StringRef Name = Note.getName();6051if (Name == "GNU")6052return FindNote(GNUNoteTypes);6053if (Name == "FreeBSD") {6054if (ELFType == ELF::ET_CORE) {6055// FreeBSD also places the generic core notes in the FreeBSD namespace.6056StringRef Result = FindNote(FreeBSDCoreNoteTypes);6057if (!Result.empty())6058return Result;6059return FindNote(CoreNoteTypes);6060} else {6061return FindNote(FreeBSDNoteTypes);6062}6063}6064if (ELFType == ELF::ET_CORE && Name.starts_with("NetBSD-CORE")) {6065StringRef Result = FindNote(NetBSDCoreNoteTypes);6066if (!Result.empty())6067return Result;6068return FindNote(CoreNoteTypes);6069}6070if (ELFType == ELF::ET_CORE && Name.starts_with("OpenBSD")) {6071// OpenBSD also places the generic core notes in the OpenBSD namespace.6072StringRef Result = FindNote(OpenBSDCoreNoteTypes);6073if (!Result.empty())6074return Result;6075return FindNote(CoreNoteTypes);6076}6077if (Name == "AMD")6078return FindNote(AMDNoteTypes);6079if (Name == "AMDGPU")6080return FindNote(AMDGPUNoteTypes);6081if (Name == "LLVMOMPOFFLOAD")6082return FindNote(LLVMOMPOFFLOADNoteTypes);6083if (Name == "Android")6084return FindNote(AndroidNoteTypes);60856086if (ELFType == ELF::ET_CORE)6087return FindNote(CoreNoteTypes);6088return FindNote(GenericNoteTypes);6089}60906091template <class ELFT>6092static void processNotesHelper(6093const ELFDumper<ELFT> &Dumper,6094llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,6095typename ELFT::Addr, size_t)>6096StartNotesFn,6097llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,6098llvm::function_ref<void()> FinishNotesFn) {6099const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();6100bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE;61016102ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections());6103if (!IsCoreFile && !Sections.empty()) {6104for (const typename ELFT::Shdr &S : Sections) {6105if (S.sh_type != SHT_NOTE)6106continue;6107StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,6108S.sh_size, S.sh_addralign);6109Error Err = Error::success();6110size_t I = 0;6111for (const typename ELFT::Note Note : Obj.notes(S, Err)) {6112if (Error E = ProcessNoteFn(Note, IsCoreFile))6113Dumper.reportUniqueWarning(6114"unable to read note with index " + Twine(I) + " from the " +6115describe(Obj, S) + ": " + toString(std::move(E)));6116++I;6117}6118if (Err)6119Dumper.reportUniqueWarning("unable to read notes from the " +6120describe(Obj, S) + ": " +6121toString(std::move(Err)));6122FinishNotesFn();6123}6124return;6125}61266127Expected<ArrayRef<typename ELFT::Phdr>> PhdrsOrErr = Obj.program_headers();6128if (!PhdrsOrErr) {6129Dumper.reportUniqueWarning(6130"unable to read program headers to locate the PT_NOTE segment: " +6131toString(PhdrsOrErr.takeError()));6132return;6133}61346135for (size_t I = 0, E = (*PhdrsOrErr).size(); I != E; ++I) {6136const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];6137if (P.p_type != PT_NOTE)6138continue;6139StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align);6140Error Err = Error::success();6141size_t Index = 0;6142for (const typename ELFT::Note Note : Obj.notes(P, Err)) {6143if (Error E = ProcessNoteFn(Note, IsCoreFile))6144Dumper.reportUniqueWarning("unable to read note with index " +6145Twine(Index) +6146" from the PT_NOTE segment with index " +6147Twine(I) + ": " + toString(std::move(E)));6148++Index;6149}6150if (Err)6151Dumper.reportUniqueWarning(6152"unable to read notes from the PT_NOTE segment with index " +6153Twine(I) + ": " + toString(std::move(Err)));6154FinishNotesFn();6155}6156}61576158template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {6159size_t Align = 0;6160bool IsFirstHeader = true;6161auto PrintHeader = [&](std::optional<StringRef> SecName,6162const typename ELFT::Off Offset,6163const typename ELFT::Addr Size, size_t Al) {6164Align = std::max<size_t>(Al, 4);6165// Print a newline between notes sections to match GNU readelf.6166if (!IsFirstHeader) {6167OS << '\n';6168} else {6169IsFirstHeader = false;6170}61716172OS << "Displaying notes found ";61736174if (SecName)6175OS << "in: " << *SecName << "\n";6176else6177OS << "at file offset " << format_hex(Offset, 10) << " with length "6178<< format_hex(Size, 10) << ":\n";61796180OS << " Owner Data size \tDescription\n";6181};61826183auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {6184StringRef Name = Note.getName();6185ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);6186Elf_Word Type = Note.getType();61876188// Print the note owner/type.6189OS << " " << left_justify(Name, 20) << ' '6190<< format_hex(Descriptor.size(), 10) << '\t';61916192StringRef NoteType =6193getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);6194if (!NoteType.empty())6195OS << NoteType << '\n';6196else6197OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";61986199// Print the description, or fallback to printing raw bytes for unknown6200// owners/if we fail to pretty-print the contents.6201if (Name == "GNU") {6202if (printGNUNote<ELFT>(OS, Type, Descriptor))6203return Error::success();6204} else if (Name == "FreeBSD") {6205if (std::optional<FreeBSDNote> N =6206getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {6207OS << " " << N->Type << ": " << N->Value << '\n';6208return Error::success();6209}6210} else if (Name == "AMD") {6211const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);6212if (!N.Type.empty()) {6213OS << " " << N.Type << ":\n " << N.Value << '\n';6214return Error::success();6215}6216} else if (Name == "AMDGPU") {6217const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);6218if (!N.Type.empty()) {6219OS << " " << N.Type << ":\n " << N.Value << '\n';6220return Error::success();6221}6222} else if (Name == "LLVMOMPOFFLOAD") {6223if (printLLVMOMPOFFLOADNote<ELFT>(OS, Type, Descriptor))6224return Error::success();6225} else if (Name == "CORE") {6226if (Type == ELF::NT_FILE) {6227DataExtractor DescExtractor(6228Descriptor, ELFT::Endianness == llvm::endianness::little,6229sizeof(Elf_Addr));6230if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {6231printCoreNote<ELFT>(OS, *NoteOrErr);6232return Error::success();6233} else {6234return NoteOrErr.takeError();6235}6236}6237} else if (Name == "Android") {6238if (printAndroidNote(OS, Type, Descriptor))6239return Error::success();6240}6241if (!Descriptor.empty()) {6242OS << " description data:";6243for (uint8_t B : Descriptor)6244OS << " " << format("%02x", B);6245OS << '\n';6246}6247return Error::success();6248};62496250processNotesHelper(*this, /*StartNotesFn=*/PrintHeader,6251/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {});6252}62536254template <class ELFT>6255ArrayRef<uint8_t>6256ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) {6257for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) {6258if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC)6259continue;6260if (Sec.sh_addr != ExpectedAddr) {6261reportUniqueWarning(6262"SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" +6263Twine::utohexstr(Sec.sh_addr) +6264", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" +6265Twine::utohexstr(ExpectedAddr));6266return ArrayRef<uint8_t>();6267}6268Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec);6269if (auto E = Contents.takeError()) {6270reportUniqueWarning(6271"couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " +6272toString(std::move(E)));6273return ArrayRef<uint8_t>();6274}6275return Contents.get();6276}6277return ArrayRef<uint8_t>();6278}62796280// Reserve the lower three bits of the first byte of the step distance when6281// encoding the memtag descriptors. Found to be the best overall size tradeoff6282// when compiling Android T with full MTE globals enabled.6283constexpr uint64_t MemtagStepVarintReservedBits = 3;6284constexpr uint64_t MemtagGranuleSize = 16;62856286template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {6287if (Obj.getHeader().e_machine != EM_AARCH64) return;6288std::vector<std::pair<std::string, std::string>> DynamicEntries;6289uint64_t MemtagGlobalsSz = 0;6290uint64_t MemtagGlobals = 0;6291for (const typename ELFT::Dyn &Entry : dynamic_table()) {6292uintX_t Tag = Entry.getTag();6293switch (Tag) {6294case DT_AARCH64_MEMTAG_GLOBALSSZ:6295MemtagGlobalsSz = Entry.getVal();6296DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6297getDynamicEntry(Tag, Entry.getVal()));6298break;6299case DT_AARCH64_MEMTAG_GLOBALS:6300MemtagGlobals = Entry.getVal();6301DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6302getDynamicEntry(Tag, Entry.getVal()));6303break;6304case DT_AARCH64_MEMTAG_MODE:6305case DT_AARCH64_MEMTAG_HEAP:6306case DT_AARCH64_MEMTAG_STACK:6307DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6308getDynamicEntry(Tag, Entry.getVal()));6309break;6310}6311}63126313ArrayRef<uint8_t> AndroidNoteDesc;6314auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error {6315if (Note.getName() == "Android" &&6316Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG)6317AndroidNoteDesc = Note.getDesc(4);6318return Error::success();6319};63206321processNotesHelper(6322*this,6323/*StartNotesFn=*/6324[](std::optional<StringRef>, const typename ELFT::Off,6325const typename ELFT::Addr, size_t) {},6326/*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {});63276328ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals);6329if (Contents.size() != MemtagGlobalsSz) {6330reportUniqueWarning(6331"mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" +6332Twine::utohexstr(MemtagGlobalsSz) +6333") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" +6334Twine::utohexstr(Contents.size()) + ")");6335Contents = ArrayRef<uint8_t>();6336}63376338std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors;6339uint64_t Address = 0;6340// See the AArch64 MemtagABI document for a description of encoding scheme:6341// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic6342for (size_t I = 0; I < Contents.size();) {6343const char *Error = nullptr;6344unsigned DecodedBytes = 0;6345uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes,6346Contents.end(), &Error);6347I += DecodedBytes;6348if (Error) {6349reportUniqueWarning(6350"error decoding distance uleb, " + Twine(DecodedBytes) +6351" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));6352GlobalDescriptors.clear();6353break;6354}6355uint64_t Distance = Value >> MemtagStepVarintReservedBits;6356uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1);6357if (GranulesToTag == 0) {6358GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes,6359Contents.end(), &Error) +63601;6361I += DecodedBytes;6362if (Error) {6363reportUniqueWarning(6364"error decoding size-only uleb, " + Twine(DecodedBytes) +6365" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));6366GlobalDescriptors.clear();6367break;6368}6369}6370Address += Distance * MemtagGranuleSize;6371GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize);6372Address += GranulesToTag * MemtagGranuleSize;6373}63746375printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors);6376}63776378template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() {6379OS << "printELFLinkerOptions not implemented!\n";6380}63816382template <class ELFT>6383void ELFDumper<ELFT>::printDependentLibsHelper(6384function_ref<void(const Elf_Shdr &)> OnSectionStart,6385function_ref<void(StringRef, uint64_t)> OnLibEntry) {6386auto Warn = [this](unsigned SecNdx, StringRef Msg) {6387this->reportUniqueWarning("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +6388Twine(SecNdx) + " is broken: " + Msg);6389};63906391unsigned I = -1;6392for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {6393++I;6394if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)6395continue;63966397OnSectionStart(Shdr);63986399Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Shdr);6400if (!ContentsOrErr) {6401Warn(I, toString(ContentsOrErr.takeError()));6402continue;6403}64046405ArrayRef<uint8_t> Contents = *ContentsOrErr;6406if (!Contents.empty() && Contents.back() != 0) {6407Warn(I, "the content is not null-terminated");6408continue;6409}64106411for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {6412StringRef Lib((const char *)I);6413OnLibEntry(Lib, I - Contents.begin());6414I += Lib.size() + 1;6415}6416}6417}64186419template <class ELFT>6420void ELFDumper<ELFT>::forEachRelocationDo(6421const Elf_Shdr &Sec,6422llvm::function_ref<void(const Relocation<ELFT> &, unsigned,6423const Elf_Shdr &, const Elf_Shdr *)>6424RelRelaFn) {6425auto Warn = [&](Error &&E,6426const Twine &Prefix = "unable to read relocations from") {6427this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " +6428toString(std::move(E)));6429};64306431// SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an6432// associated symbol table. For them we should not treat the value of the6433// sh_link field as an index of a symbol table.6434const Elf_Shdr *SymTab;6435if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&6436!(Obj.getHeader().e_machine == EM_AARCH64 &&6437Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {6438Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);6439if (!SymTabOrErr) {6440Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");6441return;6442}6443SymTab = *SymTabOrErr;6444}64456446unsigned RelNdx = 0;6447const bool IsMips64EL = this->Obj.isMips64EL();6448switch (Sec.sh_type) {6449case ELF::SHT_REL:6450if (Expected<Elf_Rel_Range> RangeOrErr = Obj.rels(Sec)) {6451for (const Elf_Rel &R : *RangeOrErr)6452RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6453} else {6454Warn(RangeOrErr.takeError());6455}6456break;6457case ELF::SHT_RELA:6458if (Expected<Elf_Rela_Range> RangeOrErr = Obj.relas(Sec)) {6459for (const Elf_Rela &R : *RangeOrErr)6460RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6461} else {6462Warn(RangeOrErr.takeError());6463}6464break;6465case ELF::SHT_AARCH64_AUTH_RELR:6466if (Obj.getHeader().e_machine != EM_AARCH64)6467break;6468[[fallthrough]];6469case ELF::SHT_RELR:6470case ELF::SHT_ANDROID_RELR: {6471Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);6472if (!RangeOrErr) {6473Warn(RangeOrErr.takeError());6474break;6475}64766477for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr))6478RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec,6479/*SymTab=*/nullptr);6480break;6481}6482case ELF::SHT_CREL: {6483if (auto RelsOrRelas = Obj.crels(Sec)) {6484for (const Elf_Rel &R : RelsOrRelas->first)6485RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);6486for (const Elf_Rela &R : RelsOrRelas->second)6487RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);6488} else {6489Warn(RelsOrRelas.takeError());6490}6491break;6492}6493case ELF::SHT_ANDROID_REL:6494case ELF::SHT_ANDROID_RELA:6495if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) {6496for (const Elf_Rela &R : *RelasOrErr)6497RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6498} else {6499Warn(RelasOrErr.takeError());6500}6501break;6502}6503}65046505template <class ELFT>6506StringRef ELFDumper<ELFT>::getPrintableSectionName(const Elf_Shdr &Sec) const {6507StringRef Name = "<?>";6508if (Expected<StringRef> SecNameOrErr =6509Obj.getSectionName(Sec, this->WarningHandler))6510Name = *SecNameOrErr;6511else6512this->reportUniqueWarning("unable to get the name of " + describe(Sec) +6513": " + toString(SecNameOrErr.takeError()));6514return Name;6515}65166517template <class ELFT> void GNUELFDumper<ELFT>::printDependentLibs() {6518bool SectionStarted = false;6519struct NameOffset {6520StringRef Name;6521uint64_t Offset;6522};6523std::vector<NameOffset> SecEntries;6524NameOffset Current;6525auto PrintSection = [&]() {6526OS << "Dependent libraries section " << Current.Name << " at offset "6527<< format_hex(Current.Offset, 1) << " contains " << SecEntries.size()6528<< " entries:\n";6529for (NameOffset Entry : SecEntries)6530OS << " [" << format("%6" PRIx64, Entry.Offset) << "] " << Entry.Name6531<< "\n";6532OS << "\n";6533SecEntries.clear();6534};65356536auto OnSectionStart = [&](const Elf_Shdr &Shdr) {6537if (SectionStarted)6538PrintSection();6539SectionStarted = true;6540Current.Offset = Shdr.sh_offset;6541Current.Name = this->getPrintableSectionName(Shdr);6542};6543auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {6544SecEntries.push_back(NameOffset{Lib, Offset});6545};65466547this->printDependentLibsHelper(OnSectionStart, OnLibEntry);6548if (SectionStarted)6549PrintSection();6550}65516552template <class ELFT>6553SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress(6554uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) {6555SmallVector<uint32_t> SymbolIndexes;6556if (!this->AddressToIndexMap) {6557// Populate the address to index map upon the first invocation of this6558// function.6559this->AddressToIndexMap.emplace();6560if (this->DotSymtabSec) {6561if (Expected<Elf_Sym_Range> SymsOrError =6562Obj.symbols(this->DotSymtabSec)) {6563uint32_t Index = (uint32_t)-1;6564for (const Elf_Sym &Sym : *SymsOrError) {6565++Index;65666567if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC)6568continue;65696570Expected<uint64_t> SymAddrOrErr =6571ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress();6572if (!SymAddrOrErr) {6573std::string Name = this->getStaticSymbolName(Index);6574reportUniqueWarning("unable to get address of symbol '" + Name +6575"': " + toString(SymAddrOrErr.takeError()));6576return SymbolIndexes;6577}65786579(*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index);6580}6581} else {6582reportUniqueWarning("unable to read the symbol table: " +6583toString(SymsOrError.takeError()));6584}6585}6586}65876588auto Symbols = this->AddressToIndexMap->find(SymValue);6589if (Symbols == this->AddressToIndexMap->end())6590return SymbolIndexes;65916592for (uint32_t Index : Symbols->second) {6593// Check if the symbol is in the right section. FunctionSec == None6594// means "any section".6595if (FunctionSec) {6596const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index));6597if (Expected<const Elf_Shdr *> SecOrErr =6598Obj.getSection(Sym, this->DotSymtabSec,6599this->getShndxTable(this->DotSymtabSec))) {6600if (*FunctionSec != *SecOrErr)6601continue;6602} else {6603std::string Name = this->getStaticSymbolName(Index);6604// Note: it is impossible to trigger this error currently, it is6605// untested.6606reportUniqueWarning("unable to get section of symbol '" + Name +6607"': " + toString(SecOrErr.takeError()));6608return SymbolIndexes;6609}6610}66116612SymbolIndexes.push_back(Index);6613}66146615return SymbolIndexes;6616}66176618template <class ELFT>6619bool ELFDumper<ELFT>::printFunctionStackSize(6620uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec,6621const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {6622SmallVector<uint32_t> FuncSymIndexes =6623this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec);6624if (FuncSymIndexes.empty())6625reportUniqueWarning(6626"could not identify function symbol for stack size entry in " +6627describe(StackSizeSec));66286629// Extract the size. The expectation is that Offset is pointing to the right6630// place, i.e. past the function address.6631Error Err = Error::success();6632uint64_t StackSize = Data.getULEB128(Offset, &Err);6633if (Err) {6634reportUniqueWarning("could not extract a valid stack size from " +6635describe(StackSizeSec) + ": " +6636toString(std::move(Err)));6637return false;6638}66396640if (FuncSymIndexes.empty()) {6641printStackSizeEntry(StackSize, {"?"});6642} else {6643SmallVector<std::string> FuncSymNames;6644for (uint32_t Index : FuncSymIndexes)6645FuncSymNames.push_back(this->getStaticSymbolName(Index));6646printStackSizeEntry(StackSize, FuncSymNames);6647}66486649return true;6650}66516652template <class ELFT>6653void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,6654ArrayRef<std::string> FuncNames) {6655OS.PadToColumn(2);6656OS << format_decimal(Size, 11);6657OS.PadToColumn(18);66586659OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n";6660}66616662template <class ELFT>6663void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R,6664const Elf_Shdr &RelocSec, unsigned Ndx,6665const Elf_Shdr *SymTab,6666const Elf_Shdr *FunctionSec,6667const Elf_Shdr &StackSizeSec,6668const RelocationResolver &Resolver,6669DataExtractor Data) {6670// This function ignores potentially erroneous input, unless it is directly6671// related to stack size reporting.6672const Elf_Sym *Sym = nullptr;6673Expected<RelSymbol<ELFT>> TargetOrErr = this->getRelocationTarget(R, SymTab);6674if (!TargetOrErr)6675reportUniqueWarning("unable to get the target of relocation with index " +6676Twine(Ndx) + " in " + describe(RelocSec) + ": " +6677toString(TargetOrErr.takeError()));6678else6679Sym = TargetOrErr->Sym;66806681uint64_t RelocSymValue = 0;6682if (Sym) {6683Expected<const Elf_Shdr *> SectionOrErr =6684this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab));6685if (!SectionOrErr) {6686reportUniqueWarning(6687"cannot identify the section for relocation symbol '" +6688(*TargetOrErr).Name + "': " + toString(SectionOrErr.takeError()));6689} else if (*SectionOrErr != FunctionSec) {6690reportUniqueWarning("relocation symbol '" + (*TargetOrErr).Name +6691"' is not in the expected section");6692// Pretend that the symbol is in the correct section and report its6693// stack size anyway.6694FunctionSec = *SectionOrErr;6695}66966697RelocSymValue = Sym->st_value;6698}66996700uint64_t Offset = R.Offset;6701if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {6702reportUniqueWarning("found invalid relocation offset (0x" +6703Twine::utohexstr(Offset) + ") into " +6704describe(StackSizeSec) +6705" while trying to extract a stack size entry");6706return;6707}67086709uint64_t SymValue = Resolver(R.Type, Offset, RelocSymValue,6710Data.getAddress(&Offset), R.Addend.value_or(0));6711this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data,6712&Offset);6713}67146715template <class ELFT>6716void ELFDumper<ELFT>::printNonRelocatableStackSizes(6717std::function<void()> PrintHeader) {6718// This function ignores potentially erroneous input, unless it is directly6719// related to stack size reporting.6720for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {6721if (this->getPrintableSectionName(Sec) != ".stack_sizes")6722continue;6723PrintHeader();6724ArrayRef<uint8_t> Contents =6725unwrapOrError(this->FileName, Obj.getSectionContents(Sec));6726DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));6727uint64_t Offset = 0;6728while (Offset < Contents.size()) {6729// The function address is followed by a ULEB representing the stack6730// size. Check for an extra byte before we try to process the entry.6731if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {6732reportUniqueWarning(6733describe(Sec) +6734" ended while trying to extract a stack size entry");6735break;6736}6737uint64_t SymValue = Data.getAddress(&Offset);6738if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec,6739Data, &Offset))6740break;6741}6742}6743}67446745template <class ELFT>6746void ELFDumper<ELFT>::printRelocatableStackSizes(6747std::function<void()> PrintHeader) {6748// Build a map between stack size sections and their corresponding relocation6749// sections.6750auto IsMatch = [&](const Elf_Shdr &Sec) -> bool {6751StringRef SectionName;6752if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))6753SectionName = *NameOrErr;6754else6755consumeError(NameOrErr.takeError());67566757return SectionName == ".stack_sizes";6758};67596760Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>>6761StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch);6762if (!StackSizeRelocMapOrErr) {6763reportUniqueWarning("unable to get stack size map section(s): " +6764toString(StackSizeRelocMapOrErr.takeError()));6765return;6766}67676768for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) {6769PrintHeader();6770const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first;6771const Elf_Shdr *RelocSec = StackSizeMapEntry.second;67726773// Warn about stack size sections without a relocation section.6774if (!RelocSec) {6775reportWarning(createError(".stack_sizes (" + describe(*StackSizesELFSec) +6776") does not have a corresponding "6777"relocation section"),6778FileName);6779continue;6780}67816782// A .stack_sizes section header's sh_link field is supposed to point6783// to the section that contains the functions whose stack sizes are6784// described in it.6785const Elf_Shdr *FunctionSec = unwrapOrError(6786this->FileName, Obj.getSection(StackSizesELFSec->sh_link));67876788SupportsRelocation IsSupportedFn;6789RelocationResolver Resolver;6790std::tie(IsSupportedFn, Resolver) = getRelocationResolver(this->ObjF);6791ArrayRef<uint8_t> Contents =6792unwrapOrError(this->FileName, Obj.getSectionContents(*StackSizesELFSec));6793DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));67946795forEachRelocationDo(6796*RelocSec, [&](const Relocation<ELFT> &R, unsigned Ndx,6797const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {6798if (!IsSupportedFn || !IsSupportedFn(R.Type)) {6799reportUniqueWarning(6800describe(*RelocSec) +6801" contains an unsupported relocation with index " + Twine(Ndx) +6802": " + Obj.getRelocationTypeName(R.Type));6803return;6804}68056806this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec,6807*StackSizesELFSec, Resolver, Data);6808});6809}6810}68116812template <class ELFT>6813void GNUELFDumper<ELFT>::printStackSizes() {6814bool HeaderHasBeenPrinted = false;6815auto PrintHeader = [&]() {6816if (HeaderHasBeenPrinted)6817return;6818OS << "\nStack Sizes:\n";6819OS.PadToColumn(9);6820OS << "Size";6821OS.PadToColumn(18);6822OS << "Functions\n";6823HeaderHasBeenPrinted = true;6824};68256826// For non-relocatable objects, look directly for sections whose name starts6827// with .stack_sizes and process the contents.6828if (this->Obj.getHeader().e_type == ELF::ET_REL)6829this->printRelocatableStackSizes(PrintHeader);6830else6831this->printNonRelocatableStackSizes(PrintHeader);6832}68336834template <class ELFT>6835void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {6836size_t Bias = ELFT::Is64Bits ? 8 : 0;6837auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {6838OS.PadToColumn(2);6839OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);6840OS.PadToColumn(11 + Bias);6841OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";6842OS.PadToColumn(22 + Bias);6843OS << format_hex_no_prefix(*E, 8 + Bias);6844OS.PadToColumn(31 + 2 * Bias);6845OS << Purpose << "\n";6846};68476848OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");6849OS << " Canonical gp value: "6850<< format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";68516852OS << " Reserved entries:\n";6853if (ELFT::Is64Bits)6854OS << " Address Access Initial Purpose\n";6855else6856OS << " Address Access Initial Purpose\n";6857PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");6858if (Parser.getGotModulePointer())6859PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");68606861if (!Parser.getLocalEntries().empty()) {6862OS << "\n";6863OS << " Local entries:\n";6864if (ELFT::Is64Bits)6865OS << " Address Access Initial\n";6866else6867OS << " Address Access Initial\n";6868for (auto &E : Parser.getLocalEntries())6869PrintEntry(&E, "");6870}68716872if (Parser.IsStatic)6873return;68746875if (!Parser.getGlobalEntries().empty()) {6876OS << "\n";6877OS << " Global entries:\n";6878if (ELFT::Is64Bits)6879OS << " Address Access Initial Sym.Val."6880<< " Type Ndx Name\n";6881else6882OS << " Address Access Initial Sym.Val. Type Ndx Name\n";68836884DataRegion<Elf_Word> ShndxTable(6885(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());6886for (auto &E : Parser.getGlobalEntries()) {6887const Elf_Sym &Sym = *Parser.getGotSym(&E);6888const Elf_Sym &FirstSym = this->dynamic_symbols()[0];6889std::string SymName = this->getFullSymbolName(6890Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);68916892OS.PadToColumn(2);6893OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));6894OS.PadToColumn(11 + Bias);6895OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";6896OS.PadToColumn(22 + Bias);6897OS << to_string(format_hex_no_prefix(E, 8 + Bias));6898OS.PadToColumn(31 + 2 * Bias);6899OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));6900OS.PadToColumn(40 + 3 * Bias);6901OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));6902OS.PadToColumn(48 + 3 * Bias);6903OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),6904ShndxTable);6905OS.PadToColumn(52 + 3 * Bias);6906OS << SymName << "\n";6907}6908}69096910if (!Parser.getOtherEntries().empty())6911OS << "\n Number of TLS and multi-GOT entries "6912<< Parser.getOtherEntries().size() << "\n";6913}69146915template <class ELFT>6916void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {6917size_t Bias = ELFT::Is64Bits ? 8 : 0;6918auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {6919OS.PadToColumn(2);6920OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias);6921OS.PadToColumn(11 + Bias);6922OS << format_hex_no_prefix(*E, 8 + Bias);6923OS.PadToColumn(20 + 2 * Bias);6924OS << Purpose << "\n";6925};69266927OS << "PLT GOT:\n\n";69286929OS << " Reserved entries:\n";6930OS << " Address Initial Purpose\n";6931PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");6932if (Parser.getPltModulePointer())6933PrintEntry(Parser.getPltModulePointer(), "Module pointer");69346935if (!Parser.getPltEntries().empty()) {6936OS << "\n";6937OS << " Entries:\n";6938OS << " Address Initial Sym.Val. Type Ndx Name\n";6939DataRegion<Elf_Word> ShndxTable(6940(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());6941for (auto &E : Parser.getPltEntries()) {6942const Elf_Sym &Sym = *Parser.getPltSym(&E);6943const Elf_Sym &FirstSym = *cantFail(6944this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));6945std::string SymName = this->getFullSymbolName(6946Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);69476948OS.PadToColumn(2);6949OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias));6950OS.PadToColumn(11 + Bias);6951OS << to_string(format_hex_no_prefix(E, 8 + Bias));6952OS.PadToColumn(20 + 2 * Bias);6953OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));6954OS.PadToColumn(29 + 3 * Bias);6955OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));6956OS.PadToColumn(37 + 3 * Bias);6957OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),6958ShndxTable);6959OS.PadToColumn(41 + 3 * Bias);6960OS << SymName << "\n";6961}6962}6963}69646965template <class ELFT>6966Expected<const Elf_Mips_ABIFlags<ELFT> *>6967getMipsAbiFlagsSection(const ELFDumper<ELFT> &Dumper) {6968const typename ELFT::Shdr *Sec = Dumper.findSectionByName(".MIPS.abiflags");6969if (Sec == nullptr)6970return nullptr;69716972constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: ";6973Expected<ArrayRef<uint8_t>> DataOrErr =6974Dumper.getElfObject().getELFFile().getSectionContents(*Sec);6975if (!DataOrErr)6976return createError(ErrPrefix + toString(DataOrErr.takeError()));69776978if (DataOrErr->size() != sizeof(Elf_Mips_ABIFlags<ELFT>))6979return createError(ErrPrefix + "it has a wrong size (" +6980Twine(DataOrErr->size()) + ")");6981return reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(DataOrErr->data());6982}69836984template <class ELFT> void GNUELFDumper<ELFT>::printMipsABIFlags() {6985const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;6986if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =6987getMipsAbiFlagsSection(*this))6988Flags = *SecOrErr;6989else6990this->reportUniqueWarning(SecOrErr.takeError());6991if (!Flags)6992return;69936994OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n";6995OS << "ISA: MIPS" << int(Flags->isa_level);6996if (Flags->isa_rev > 1)6997OS << "r" << int(Flags->isa_rev);6998OS << "\n";6999OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n";7000OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n";7001OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n";7002OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType))7003<< "\n";7004OS << "ISA Extension: "7005<< enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n";7006if (Flags->ases == 0)7007OS << "ASEs: None\n";7008else7009// FIXME: Print each flag on a separate line.7010OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags))7011<< "\n";7012OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n";7013OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n";7014OS << "\n";7015}70167017template <class ELFT> void LLVMELFDumper<ELFT>::printFileHeaders() {7018const Elf_Ehdr &E = this->Obj.getHeader();7019{7020DictScope D(W, "ElfHeader");7021{7022DictScope D(W, "Ident");7023W.printBinary("Magic",7024ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4));7025W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));7026W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA],7027ArrayRef(ElfDataEncoding));7028W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]);70297030auto OSABI = ArrayRef(ElfOSABI);7031if (E.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&7032E.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {7033switch (E.e_machine) {7034case ELF::EM_AMDGPU:7035OSABI = ArrayRef(AMDGPUElfOSABI);7036break;7037case ELF::EM_ARM:7038OSABI = ArrayRef(ARMElfOSABI);7039break;7040case ELF::EM_TI_C6000:7041OSABI = ArrayRef(C6000ElfOSABI);7042break;7043}7044}7045W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI);7046W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]);7047W.printBinary("Unused",7048ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD));7049}70507051std::string TypeStr;7052if (const EnumEntry<unsigned> *Ent = getObjectFileEnumEntry(E.e_type)) {7053TypeStr = Ent->Name.str();7054} else {7055if (E.e_type >= ET_LOPROC)7056TypeStr = "Processor Specific";7057else if (E.e_type >= ET_LOOS)7058TypeStr = "OS Specific";7059else7060TypeStr = "Unknown";7061}7062W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")");70637064W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType));7065W.printNumber("Version", E.e_version);7066W.printHex("Entry", E.e_entry);7067W.printHex("ProgramHeaderOffset", E.e_phoff);7068W.printHex("SectionHeaderOffset", E.e_shoff);7069if (E.e_machine == EM_MIPS)7070W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags),7071unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),7072unsigned(ELF::EF_MIPS_MACH));7073else if (E.e_machine == EM_AMDGPU) {7074switch (E.e_ident[ELF::EI_ABIVERSION]) {7075default:7076W.printHex("Flags", E.e_flags);7077break;7078case 0:7079// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.7080[[fallthrough]];7081case ELF::ELFABIVERSION_AMDGPU_HSA_V3:7082W.printFlags("Flags", E.e_flags,7083ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),7084unsigned(ELF::EF_AMDGPU_MACH));7085break;7086case ELF::ELFABIVERSION_AMDGPU_HSA_V4:7087case ELF::ELFABIVERSION_AMDGPU_HSA_V5:7088W.printFlags("Flags", E.e_flags,7089ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),7090unsigned(ELF::EF_AMDGPU_MACH),7091unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),7092unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));7093break;7094case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {7095std::optional<FlagEntry> VerFlagEntry;7096// The string needs to remain alive from the moment we create a7097// FlagEntry until printFlags is done.7098std::string FlagStr;7099if (auto VersionFlag = E.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {7100unsigned Version =7101VersionFlag >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET;7102FlagStr = "EF_AMDGPU_GENERIC_VERSION_V" + std::to_string(Version);7103VerFlagEntry = FlagEntry(FlagStr, VersionFlag);7104}7105W.printFlags(7106"Flags", E.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),7107unsigned(ELF::EF_AMDGPU_MACH),7108unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),7109unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4),7110VerFlagEntry ? ArrayRef(*VerFlagEntry) : ArrayRef<FlagEntry>());7111break;7112}7113}7114} else if (E.e_machine == EM_RISCV)7115W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags));7116else if (E.e_machine == EM_AVR)7117W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags),7118unsigned(ELF::EF_AVR_ARCH_MASK));7119else if (E.e_machine == EM_LOONGARCH)7120W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags),7121unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),7122unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));7123else if (E.e_machine == EM_XTENSA)7124W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags),7125unsigned(ELF::EF_XTENSA_MACH));7126else if (E.e_machine == EM_CUDA)7127W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderNVPTXFlags),7128unsigned(ELF::EF_CUDA_SM));7129else7130W.printFlags("Flags", E.e_flags);7131W.printNumber("HeaderSize", E.e_ehsize);7132W.printNumber("ProgramHeaderEntrySize", E.e_phentsize);7133W.printNumber("ProgramHeaderCount", E.e_phnum);7134W.printNumber("SectionHeaderEntrySize", E.e_shentsize);7135W.printString("SectionHeaderCount",7136getSectionHeadersNumString(this->Obj, this->FileName));7137W.printString("StringTableSectionIndex",7138getSectionHeaderTableIndexString(this->Obj, this->FileName));7139}7140}71417142template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() {7143DictScope Lists(W, "Groups");7144std::vector<GroupSection> V = this->getGroups();7145DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);7146for (const GroupSection &G : V) {7147DictScope D(W, "Group");7148W.printNumber("Name", G.Name, G.ShName);7149W.printNumber("Index", G.Index);7150W.printNumber("Link", G.Link);7151W.printNumber("Info", G.Info);7152W.printHex("Type", getGroupType(G.Type), G.Type);7153W.printString("Signature", G.Signature);71547155ListScope L(W, getGroupSectionHeaderName());7156for (const GroupMember &GM : G.Members) {7157const GroupSection *MainGroup = Map[GM.Index];7158if (MainGroup != &G)7159this->reportUniqueWarning(7160"section with index " + Twine(GM.Index) +7161", included in the group section with index " +7162Twine(MainGroup->Index) +7163", was also found in the group section with index " +7164Twine(G.Index));7165printSectionGroupMembers(GM.Name, GM.Index);7166}7167}71687169if (V.empty())7170printEmptyGroupMessage();7171}71727173template <class ELFT>7174std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const {7175return "Section(s) in group";7176}71777178template <class ELFT>7179void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,7180uint64_t Idx) const {7181W.startLine() << Name << " (" << Idx << ")\n";7182}71837184template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {7185ListScope D(W, "Relocations");71867187for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {7188if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))7189continue;71907191StringRef Name = this->getPrintableSectionName(Sec);7192unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front();7193printRelocationSectionInfo(Sec, Name, SecNdx);7194}7195}71967197template <class ELFT>7198void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R,7199StringRef SymbolName,7200StringRef RelocName) {7201DictScope Group(W, "Relocation");7202W.printHex("Offset", R.Offset);7203W.printNumber("Type", RelocName, R.Type);7204W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol);7205if (R.Addend)7206W.printHex("Addend", (uintX_t)*R.Addend);7207}72087209template <class ELFT>7210void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,7211StringRef SymbolName,7212StringRef RelocName) {7213raw_ostream &OS = W.startLine();7214OS << W.hex(R.Offset) << " " << RelocName << " "7215<< (!SymbolName.empty() ? SymbolName : "-");7216if (R.Addend)7217OS << " " << W.hex((uintX_t)*R.Addend);7218OS << "\n";7219}72207221template <class ELFT>7222void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,7223StringRef Name,7224const unsigned SecNdx) {7225DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str());7226this->printRelocationsHelper(Sec);7227}72287229template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const {7230W.startLine() << "There are no group sections in the file.\n";7231}72327233template <class ELFT>7234void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,7235const RelSymbol<ELFT> &RelSym) {7236StringRef SymbolName = RelSym.Name;7237if (RelSym.Sym && RelSym.Name.empty())7238SymbolName = "<null>";7239SmallString<32> RelocName;7240this->Obj.getRelocationTypeName(R.Type, RelocName);72417242if (opts::ExpandRelocs) {7243printExpandedRelRelaReloc(R, SymbolName, RelocName);7244} else {7245printDefaultRelRelaReloc(R, SymbolName, RelocName);7246}7247}72487249template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {7250ListScope SectionsD(W, "Sections");72517252int SectionIndex = -1;7253std::vector<EnumEntry<unsigned>> FlagsList =7254getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI],7255this->Obj.getHeader().e_machine);7256for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {7257DictScope SectionD(W, "Section");7258W.printNumber("Index", ++SectionIndex);7259W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name);7260W.printHex("Type",7261object::getELFSectionTypeName(this->Obj.getHeader().e_machine,7262Sec.sh_type),7263Sec.sh_type);7264W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList));7265W.printHex("Address", Sec.sh_addr);7266W.printHex("Offset", Sec.sh_offset);7267W.printNumber("Size", Sec.sh_size);7268W.printNumber("Link", Sec.sh_link);7269W.printNumber("Info", Sec.sh_info);7270W.printNumber("AddressAlignment", Sec.sh_addralign);7271W.printNumber("EntrySize", Sec.sh_entsize);72727273if (opts::SectionRelocations) {7274ListScope D(W, "Relocations");7275this->printRelocationsHelper(Sec);7276}72777278if (opts::SectionSymbols) {7279ListScope D(W, "Symbols");7280if (this->DotSymtabSec) {7281StringRef StrTable = unwrapOrError(7282this->FileName,7283this->Obj.getStringTableForSymtab(*this->DotSymtabSec));7284ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec);72857286typename ELFT::SymRange Symbols = unwrapOrError(7287this->FileName, this->Obj.symbols(this->DotSymtabSec));7288for (const Elf_Sym &Sym : Symbols) {7289const Elf_Shdr *SymSec = unwrapOrError(7290this->FileName,7291this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));7292if (SymSec == &Sec)7293printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,7294/*NonVisibilityBitsUsed=*/false,7295/*ExtraSymInfo=*/false);7296}7297}7298}72997300if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) {7301ArrayRef<uint8_t> Data =7302unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec));7303W.printBinaryBlock(7304"SectionData",7305StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()));7306}7307}7308}73097310template <class ELFT>7311void LLVMELFDumper<ELFT>::printSymbolSection(7312const Elf_Sym &Symbol, unsigned SymIndex,7313DataRegion<Elf_Word> ShndxTable) const {7314auto GetSectionSpecialType = [&]() -> std::optional<StringRef> {7315if (Symbol.isUndefined())7316return StringRef("Undefined");7317if (Symbol.isProcessorSpecific())7318return StringRef("Processor Specific");7319if (Symbol.isOSSpecific())7320return StringRef("Operating System Specific");7321if (Symbol.isAbsolute())7322return StringRef("Absolute");7323if (Symbol.isCommon())7324return StringRef("Common");7325if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX)7326return StringRef("Reserved");7327return std::nullopt;7328};73297330if (std::optional<StringRef> Type = GetSectionSpecialType()) {7331W.printHex("Section", *Type, Symbol.st_shndx);7332return;7333}73347335Expected<unsigned> SectionIndex =7336this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);7337if (!SectionIndex) {7338assert(Symbol.st_shndx == SHN_XINDEX &&7339"getSymbolSectionIndex should only fail due to an invalid "7340"SHT_SYMTAB_SHNDX table/reference");7341this->reportUniqueWarning(SectionIndex.takeError());7342W.printHex("Section", "Reserved", SHN_XINDEX);7343return;7344}73457346Expected<StringRef> SectionName =7347this->getSymbolSectionName(Symbol, *SectionIndex);7348if (!SectionName) {7349// Don't report an invalid section name if the section headers are missing.7350// In such situations, all sections will be "invalid".7351if (!this->ObjF.sections().empty())7352this->reportUniqueWarning(SectionName.takeError());7353else7354consumeError(SectionName.takeError());7355W.printHex("Section", "<?>", *SectionIndex);7356} else {7357W.printHex("Section", *SectionName, *SectionIndex);7358}7359}73607361template <class ELFT>7362void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const {7363std::vector<EnumEntry<unsigned>> SymOtherFlags =7364this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol);7365W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);7366}73677368template <class ELFT>7369void LLVMELFDumper<ELFT>::printZeroSymbolOtherField(7370const Elf_Sym &Symbol) const {7371assert(Symbol.st_other == 0 && "non-zero Other Field");7372// Usually st_other flag is zero. Do not pollute the output7373// by flags enumeration in that case.7374W.printNumber("Other", 0);7375}73767377template <class ELFT>7378void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,7379DataRegion<Elf_Word> ShndxTable,7380std::optional<StringRef> StrTable,7381bool IsDynamic,7382bool /*NonVisibilityBitsUsed*/,7383bool /*ExtraSymInfo*/) const {7384std::string FullSymbolName = this->getFullSymbolName(7385Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);7386unsigned char SymbolType = Symbol.getType();73877388DictScope D(W, "Symbol");7389W.printNumber("Name", FullSymbolName, Symbol.st_name);7390W.printHex("Value", Symbol.st_value);7391W.printNumber("Size", Symbol.st_size);7392W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings));7393if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&7394SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)7395W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes));7396else7397W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes));7398if (Symbol.st_other == 0)7399printZeroSymbolOtherField(Symbol);7400else7401printSymbolOtherField(Symbol);7402printSymbolSection(Symbol, SymIndex, ShndxTable);7403}74047405template <class ELFT>7406void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols,7407bool PrintDynamicSymbols,7408bool ExtraSymInfo) {7409if (PrintSymbols) {7410ListScope Group(W, "Symbols");7411this->printSymbolsHelper(false, ExtraSymInfo);7412}7413if (PrintDynamicSymbols) {7414ListScope Group(W, "DynamicSymbols");7415this->printSymbolsHelper(true, ExtraSymInfo);7416}7417}74187419template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() {7420Elf_Dyn_Range Table = this->dynamic_table();7421if (Table.empty())7422return;74237424W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";74257426size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table);7427// The "Name/Value" column should be indented from the "Type" column by N7428// spaces, where N = MaxTagSize - length of "Type" (4) + trailing7429// space (1) = -3.7430W.startLine() << " Tag" << std::string(ELFT::Is64Bits ? 16 : 8, ' ')7431<< "Type" << std::string(MaxTagSize - 3, ' ') << "Name/Value\n";74327433std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s ";7434for (auto Entry : Table) {7435uintX_t Tag = Entry.getTag();7436std::string Value = this->getDynamicEntry(Tag, Entry.getVal());7437W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true)7438<< " "7439<< format(ValueFmt.c_str(),7440this->Obj.getDynamicTagAsString(Tag).c_str())7441<< Value << "\n";7442}7443W.startLine() << "]\n";7444}74457446template <class ELFT>7447void JSONELFDumper<ELFT>::printAuxillaryDynamicTableEntryInfo(7448const Elf_Dyn &Entry) {7449auto FormatFlags = [this, Value = Entry.getVal()](auto Flags) {7450ListScope L(this->W, "Flags");7451for (const auto &Flag : Flags) {7452if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)7453this->W.printString(Flag.Name);7454}7455};7456switch (Entry.getTag()) {7457case DT_SONAME:7458this->W.printString("Name", this->getDynamicString(Entry.getVal()));7459break;7460case DT_AUXILIARY:7461case DT_FILTER:7462case DT_NEEDED:7463this->W.printString("Library", this->getDynamicString(Entry.getVal()));7464break;7465case DT_USED:7466this->W.printString("Object", this->getDynamicString(Entry.getVal()));7467break;7468case DT_RPATH:7469case DT_RUNPATH: {7470StringRef Value = this->getDynamicString(Entry.getVal());7471ListScope L(this->W, "Path");7472while (!Value.empty()) {7473auto [Front, Back] = Value.split(':');7474this->W.printString(Front);7475Value = Back;7476}7477break;7478}7479case DT_FLAGS:7480FormatFlags(ArrayRef(ElfDynamicDTFlags));7481break;7482case DT_FLAGS_1:7483FormatFlags(ArrayRef(ElfDynamicDTFlags1));7484break;7485default:7486return;7487}7488}74897490template <class ELFT> void JSONELFDumper<ELFT>::printDynamicTable() {7491Elf_Dyn_Range Table = this->dynamic_table();7492ListScope L(this->W, "DynamicSection");7493for (const auto &Entry : Table) {7494DictScope D(this->W);7495uintX_t Tag = Entry.getTag();7496this->W.printHex("Tag", Tag);7497this->W.printString("Type", this->Obj.getDynamicTagAsString(Tag));7498this->W.printHex("Value", Entry.getVal());7499this->printAuxillaryDynamicTableEntryInfo(Entry);7500}7501}75027503template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() {7504W.startLine() << "Dynamic Relocations {\n";7505W.indent();7506this->printDynamicRelocationsHelper();7507W.unindent();7508W.startLine() << "}\n";7509}75107511template <class ELFT>7512void LLVMELFDumper<ELFT>::printProgramHeaders(7513bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {7514if (PrintProgramHeaders)7515printProgramHeaders();7516if (PrintSectionMapping == cl::BOU_TRUE)7517printSectionMapping();7518}75197520template <class ELFT> void LLVMELFDumper<ELFT>::printProgramHeaders() {7521ListScope L(W, "ProgramHeaders");75227523Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();7524if (!PhdrsOrErr) {7525this->reportUniqueWarning("unable to dump program headers: " +7526toString(PhdrsOrErr.takeError()));7527return;7528}75297530for (const Elf_Phdr &Phdr : *PhdrsOrErr) {7531DictScope P(W, "ProgramHeader");7532StringRef Type =7533segmentTypeToString(this->Obj.getHeader().e_machine, Phdr.p_type);75347535W.printHex("Type", Type.empty() ? "Unknown" : Type, Phdr.p_type);7536W.printHex("Offset", Phdr.p_offset);7537W.printHex("VirtualAddress", Phdr.p_vaddr);7538W.printHex("PhysicalAddress", Phdr.p_paddr);7539W.printNumber("FileSize", Phdr.p_filesz);7540W.printNumber("MemSize", Phdr.p_memsz);7541W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags));7542W.printNumber("Alignment", Phdr.p_align);7543}7544}75457546template <class ELFT>7547void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {7548ListScope SS(W, "VersionSymbols");7549if (!Sec)7550return;75517552StringRef StrTable;7553ArrayRef<Elf_Sym> Syms;7554const Elf_Shdr *SymTabSec;7555Expected<ArrayRef<Elf_Versym>> VerTableOrErr =7556this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec);7557if (!VerTableOrErr) {7558this->reportUniqueWarning(VerTableOrErr.takeError());7559return;7560}75617562if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size())7563return;75647565ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec);7566for (size_t I = 0, E = Syms.size(); I < E; ++I) {7567DictScope S(W, "Symbol");7568W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION);7569W.printString("Name",7570this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable,7571/*IsDynamic=*/true));7572}7573}75747575const EnumEntry<unsigned> SymVersionFlags[] = {7576{"Base", "BASE", VER_FLG_BASE},7577{"Weak", "WEAK", VER_FLG_WEAK},7578{"Info", "INFO", VER_FLG_INFO}};75797580template <class ELFT>7581void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {7582ListScope SD(W, "VersionDefinitions");7583if (!Sec)7584return;75857586Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);7587if (!V) {7588this->reportUniqueWarning(V.takeError());7589return;7590}75917592for (const VerDef &D : *V) {7593DictScope Def(W, "Definition");7594W.printNumber("Version", D.Version);7595W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags));7596W.printNumber("Index", D.Ndx);7597W.printNumber("Hash", D.Hash);7598W.printString("Name", D.Name.c_str());7599W.printList(7600"Predecessors", D.AuxV,7601[](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); });7602}7603}76047605template <class ELFT>7606void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {7607ListScope SD(W, "VersionRequirements");7608if (!Sec)7609return;76107611Expected<std::vector<VerNeed>> V =7612this->Obj.getVersionDependencies(*Sec, this->WarningHandler);7613if (!V) {7614this->reportUniqueWarning(V.takeError());7615return;7616}76177618for (const VerNeed &VN : *V) {7619DictScope Entry(W, "Dependency");7620W.printNumber("Version", VN.Version);7621W.printNumber("Count", VN.Cnt);7622W.printString("FileName", VN.File.c_str());76237624ListScope L(W, "Entries");7625for (const VernAux &Aux : VN.AuxV) {7626DictScope Entry(W, "Entry");7627W.printNumber("Hash", Aux.Hash);7628W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags));7629W.printNumber("Index", Aux.Other);7630W.printString("Name", Aux.Name.c_str());7631}7632}7633}76347635template <class ELFT>7636void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,7637size_t MaxChain,7638size_t TotalSyms,7639ArrayRef<size_t> Count,7640bool IsGnu) const {7641StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram";7642StringRef BucketName = IsGnu ? "Bucket" : "Chain";7643StringRef ListName = IsGnu ? "Buckets" : "Chains";7644DictScope Outer(W, HistName);7645W.printNumber("TotalBuckets", NBucket);7646ListScope Buckets(W, ListName);7647size_t CumulativeNonZero = 0;7648for (size_t I = 0; I < MaxChain; ++I) {7649CumulativeNonZero += Count[I] * I;7650DictScope Bucket(W, BucketName);7651W.printNumber("Length", I);7652W.printNumber("Count", Count[I]);7653W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket);7654W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms);7655}7656}76577658// Returns true if rel/rela section exists, and populates SymbolIndices.7659// Otherwise returns false.7660template <class ELFT>7661static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,7662const ELFFile<ELFT> &Obj,7663const LLVMELFDumper<ELFT> *Dumper,7664SmallVector<uint32_t, 128> &SymbolIndices) {7665if (!CGRelSection) {7666Dumper->reportUniqueWarning(7667"relocation section for a call graph section doesn't exist");7668return false;7669}76707671if (CGRelSection->sh_type == SHT_REL) {7672typename ELFT::RelRange CGProfileRel;7673Expected<typename ELFT::RelRange> CGProfileRelOrError =7674Obj.rels(*CGRelSection);7675if (!CGProfileRelOrError) {7676Dumper->reportUniqueWarning("unable to load relocations for "7677"SHT_LLVM_CALL_GRAPH_PROFILE section: " +7678toString(CGProfileRelOrError.takeError()));7679return false;7680}76817682CGProfileRel = *CGProfileRelOrError;7683for (const typename ELFT::Rel &Rel : CGProfileRel)7684SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL()));7685} else {7686// MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert7687// the format to SHT_RELA7688// (https://sourceware.org/bugzilla/show_bug.cgi?id=28035)7689typename ELFT::RelaRange CGProfileRela;7690Expected<typename ELFT::RelaRange> CGProfileRelaOrError =7691Obj.relas(*CGRelSection);7692if (!CGProfileRelaOrError) {7693Dumper->reportUniqueWarning("unable to load relocations for "7694"SHT_LLVM_CALL_GRAPH_PROFILE section: " +7695toString(CGProfileRelaOrError.takeError()));7696return false;7697}76987699CGProfileRela = *CGProfileRelaOrError;7700for (const typename ELFT::Rela &Rela : CGProfileRela)7701SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL()));7702}77037704return true;7705}77067707template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {7708auto IsMatch = [](const Elf_Shdr &Sec) -> bool {7709return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE;7710};77117712Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =7713this->Obj.getSectionAndRelocations(IsMatch);7714if (!SecToRelocMapOrErr) {7715this->reportUniqueWarning("unable to get CG Profile section(s): " +7716toString(SecToRelocMapOrErr.takeError()));7717return;7718}77197720for (const auto &CGMapEntry : *SecToRelocMapOrErr) {7721const Elf_Shdr *CGSection = CGMapEntry.first;7722const Elf_Shdr *CGRelSection = CGMapEntry.second;77237724Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr =7725this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection);7726if (!CGProfileOrErr) {7727this->reportUniqueWarning(7728"unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " +7729toString(CGProfileOrErr.takeError()));7730return;7731}77327733SmallVector<uint32_t, 128> SymbolIndices;7734bool UseReloc =7735getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices);7736if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) {7737this->reportUniqueWarning(7738"number of from/to pairs does not match number of frequencies");7739UseReloc = false;7740}77417742ListScope L(W, "CGProfile");7743for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) {7744const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I];7745DictScope D(W, "CGProfileEntry");7746if (UseReloc) {7747uint32_t From = SymbolIndices[I * 2];7748uint32_t To = SymbolIndices[I * 2 + 1];7749W.printNumber("From", this->getStaticSymbolName(From), From);7750W.printNumber("To", this->getStaticSymbolName(To), To);7751}7752W.printNumber("Weight", CGPE.cgp_weight);7753}7754}7755}77567757template <class ELFT>7758void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {7759bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;7760using Elf_Shdr = typename ELFT::Shdr;7761auto IsMatch = [](const Elf_Shdr &Sec) -> bool {7762return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP;7763};7764Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr =7765this->Obj.getSectionAndRelocations(IsMatch);7766if (!SecRelocMapOrErr) {7767this->reportUniqueWarning(7768"failed to get SHT_LLVM_BB_ADDR_MAP section(s): " +7769toString(SecRelocMapOrErr.takeError()));7770return;7771}7772for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) {7773std::optional<const Elf_Shdr *> FunctionSec;7774if (IsRelocatable)7775FunctionSec =7776unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link));7777ListScope L(W, "BBAddrMap");7778if (IsRelocatable && !RelocSec) {7779this->reportUniqueWarning("unable to get relocation section for " +7780this->describe(*Sec));7781continue;7782}7783std::vector<PGOAnalysisMap> PGOAnalyses;7784Expected<std::vector<BBAddrMap>> BBAddrMapOrErr =7785this->Obj.decodeBBAddrMap(*Sec, RelocSec, &PGOAnalyses);7786if (!BBAddrMapOrErr) {7787this->reportUniqueWarning("unable to dump " + this->describe(*Sec) +7788": " + toString(BBAddrMapOrErr.takeError()));7789continue;7790}7791for (const auto &[AM, PAM] : zip_equal(*BBAddrMapOrErr, PGOAnalyses)) {7792DictScope D(W, "Function");7793W.printHex("At", AM.getFunctionAddress());7794SmallVector<uint32_t> FuncSymIndex =7795this->getSymbolIndexesForFunctionAddress(AM.getFunctionAddress(),7796FunctionSec);7797std::string FuncName = "<?>";7798if (FuncSymIndex.empty())7799this->reportUniqueWarning(7800"could not identify function symbol for address (0x" +7801Twine::utohexstr(AM.getFunctionAddress()) + ") in " +7802this->describe(*Sec));7803else7804FuncName = this->getStaticSymbolName(FuncSymIndex.front());7805W.printString("Name", FuncName);7806{7807ListScope BBRL(W, "BB Ranges");7808for (const BBAddrMap::BBRangeEntry &BBR : AM.BBRanges) {7809DictScope BBRD(W);7810W.printHex("Base Address", BBR.BaseAddress);7811ListScope BBEL(W, "BB Entries");7812for (const BBAddrMap::BBEntry &BBE : BBR.BBEntries) {7813DictScope BBED(W);7814W.printNumber("ID", BBE.ID);7815W.printHex("Offset", BBE.Offset);7816W.printHex("Size", BBE.Size);7817W.printBoolean("HasReturn", BBE.hasReturn());7818W.printBoolean("HasTailCall", BBE.hasTailCall());7819W.printBoolean("IsEHPad", BBE.isEHPad());7820W.printBoolean("CanFallThrough", BBE.canFallThrough());7821W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch());7822}7823}7824}78257826if (PAM.FeatEnable.hasPGOAnalysis()) {7827DictScope PD(W, "PGO analyses");78287829if (PAM.FeatEnable.FuncEntryCount)7830W.printNumber("FuncEntryCount", PAM.FuncEntryCount);78317832if (PAM.FeatEnable.hasPGOAnalysisBBData()) {7833ListScope L(W, "PGO BB entries");7834for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) {7835DictScope L(W);78367837if (PAM.FeatEnable.BBFreq) {7838if (PrettyPGOAnalysis) {7839std::string BlockFreqStr;7840raw_string_ostream SS(BlockFreqStr);7841printRelativeBlockFreq(SS, PAM.BBEntries.front().BlockFreq,7842PBBE.BlockFreq);7843W.printString("Frequency", BlockFreqStr);7844} else {7845W.printNumber("Frequency", PBBE.BlockFreq.getFrequency());7846}7847}78487849if (PAM.FeatEnable.BrProb) {7850ListScope L(W, "Successors");7851for (const auto &Succ : PBBE.Successors) {7852DictScope L(W);7853W.printNumber("ID", Succ.ID);7854if (PrettyPGOAnalysis) {7855W.printObject("Probability", Succ.Prob);7856} else {7857W.printHex("Probability", Succ.Prob.getNumerator());7858}7859}7860}7861}7862}7863}7864}7865}7866}78677868template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {7869ListScope L(W, "Addrsig");7870if (!this->DotAddrsigSec)7871return;78727873Expected<std::vector<uint64_t>> SymsOrErr =7874decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);7875if (!SymsOrErr) {7876this->reportUniqueWarning(SymsOrErr.takeError());7877return;7878}78797880for (uint64_t Sym : *SymsOrErr)7881W.printNumber("Sym", this->getStaticSymbolName(Sym), Sym);7882}78837884template <typename ELFT>7885static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,7886ScopedPrinter &W) {7887// Return true if we were able to pretty-print the note, false otherwise.7888switch (NoteType) {7889default:7890return false;7891case ELF::NT_GNU_ABI_TAG: {7892const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);7893if (!AbiTag.IsValid) {7894W.printString("ABI", "<corrupt GNU_ABI_TAG>");7895return false;7896} else {7897W.printString("OS", AbiTag.OSName);7898W.printString("ABI", AbiTag.ABI);7899}7900break;7901}7902case ELF::NT_GNU_BUILD_ID: {7903W.printString("Build ID", getGNUBuildId(Desc));7904break;7905}7906case ELF::NT_GNU_GOLD_VERSION:7907W.printString("Version", getDescAsStringRef(Desc));7908break;7909case ELF::NT_GNU_PROPERTY_TYPE_0:7910ListScope D(W, "Property");7911for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))7912W.printString(Property);7913break;7914}7915return true;7916}79177918static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,7919ScopedPrinter &W) {7920// Return true if we were able to pretty-print the note, false otherwise.7921AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);7922if (Props.empty())7923return false;7924for (const auto &KV : Props)7925W.printString(KV.first, KV.second);7926return true;7927}79287929template <class ELFT>7930void LLVMELFDumper<ELFT>::printMemtag(7931const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,7932const ArrayRef<uint8_t> AndroidNoteDesc,7933const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {7934{7935ListScope L(W, "Memtag Dynamic Entries:");7936if (DynamicEntries.empty())7937W.printString("< none found >");7938for (const auto &DynamicEntryKV : DynamicEntries)7939W.printString(DynamicEntryKV.first, DynamicEntryKV.second);7940}79417942if (!AndroidNoteDesc.empty()) {7943ListScope L(W, "Memtag Android Note:");7944printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W);7945}79467947if (Descriptors.empty())7948return;79497950{7951ListScope L(W, "Memtag Global Descriptors:");7952for (const auto &[Addr, BytesToTag] : Descriptors) {7953W.printHex("0x" + utohexstr(Addr), BytesToTag);7954}7955}7956}79577958template <typename ELFT>7959static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType,7960ArrayRef<uint8_t> Desc,7961ScopedPrinter &W) {7962switch (NoteType) {7963default:7964return false;7965case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:7966W.printString("Version", getDescAsStringRef(Desc));7967break;7968case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:7969W.printString("Producer", getDescAsStringRef(Desc));7970break;7971case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:7972W.printString("Producer version", getDescAsStringRef(Desc));7973break;7974}7975return true;7976}79777978static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {7979W.printNumber("Page Size", Note.PageSize);7980ListScope D(W, "Mappings");7981for (const CoreFileMapping &Mapping : Note.Mappings) {7982DictScope D(W);7983W.printHex("Start", Mapping.Start);7984W.printHex("End", Mapping.End);7985W.printHex("Offset", Mapping.Offset);7986W.printString("Filename", Mapping.Filename);7987}7988}79897990template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {7991ListScope L(W, "NoteSections");79927993std::unique_ptr<DictScope> NoteSectionScope;7994std::unique_ptr<ListScope> NotesScope;7995size_t Align = 0;7996auto StartNotes = [&](std::optional<StringRef> SecName,7997const typename ELFT::Off Offset,7998const typename ELFT::Addr Size, size_t Al) {7999Align = std::max<size_t>(Al, 4);8000NoteSectionScope = std::make_unique<DictScope>(W, "NoteSection");8001W.printString("Name", SecName ? *SecName : "<?>");8002W.printHex("Offset", Offset);8003W.printHex("Size", Size);8004NotesScope = std::make_unique<ListScope>(W, "Notes");8005};80068007auto EndNotes = [&] {8008NotesScope.reset();8009NoteSectionScope.reset();8010};80118012auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {8013DictScope D2(W);8014StringRef Name = Note.getName();8015ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);8016Elf_Word Type = Note.getType();80178018// Print the note owner/type.8019W.printString("Owner", Name);8020W.printHex("Data size", Descriptor.size());80218022StringRef NoteType =8023getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);8024if (!NoteType.empty())8025W.printString("Type", NoteType);8026else8027W.printString("Type",8028"Unknown (" + to_string(format_hex(Type, 10)) + ")");80298030// Print the description, or fallback to printing raw bytes for unknown8031// owners/if we fail to pretty-print the contents.8032if (Name == "GNU") {8033if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))8034return Error::success();8035} else if (Name == "FreeBSD") {8036if (std::optional<FreeBSDNote> N =8037getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {8038W.printString(N->Type, N->Value);8039return Error::success();8040}8041} else if (Name == "AMD") {8042const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);8043if (!N.Type.empty()) {8044W.printString(N.Type, N.Value);8045return Error::success();8046}8047} else if (Name == "AMDGPU") {8048const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);8049if (!N.Type.empty()) {8050W.printString(N.Type, N.Value);8051return Error::success();8052}8053} else if (Name == "LLVMOMPOFFLOAD") {8054if (printLLVMOMPOFFLOADNoteLLVMStyle<ELFT>(Type, Descriptor, W))8055return Error::success();8056} else if (Name == "CORE") {8057if (Type == ELF::NT_FILE) {8058DataExtractor DescExtractor(8059Descriptor, ELFT::Endianness == llvm::endianness::little,8060sizeof(Elf_Addr));8061if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {8062printCoreNoteLLVMStyle(*N, W);8063return Error::success();8064} else {8065return N.takeError();8066}8067}8068} else if (Name == "Android") {8069if (printAndroidNoteLLVMStyle(Type, Descriptor, W))8070return Error::success();8071}8072if (!Descriptor.empty()) {8073W.printBinaryBlock("Description data", Descriptor);8074}8075return Error::success();8076};80778078processNotesHelper(*this, /*StartNotesFn=*/StartNotes,8079/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes);8080}80818082template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() {8083ListScope L(W, "LinkerOptions");80848085unsigned I = -1;8086for (const Elf_Shdr &Shdr : cantFail(this->Obj.sections())) {8087++I;8088if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)8089continue;80908091Expected<ArrayRef<uint8_t>> ContentsOrErr =8092this->Obj.getSectionContents(Shdr);8093if (!ContentsOrErr) {8094this->reportUniqueWarning("unable to read the content of the "8095"SHT_LLVM_LINKER_OPTIONS section: " +8096toString(ContentsOrErr.takeError()));8097continue;8098}8099if (ContentsOrErr->empty())8100continue;81018102if (ContentsOrErr->back() != 0) {8103this->reportUniqueWarning("SHT_LLVM_LINKER_OPTIONS section at index " +8104Twine(I) +8105" is broken: the "8106"content is not null-terminated");8107continue;8108}81098110SmallVector<StringRef, 16> Strings;8111toStringRef(ContentsOrErr->drop_back()).split(Strings, '\0');8112if (Strings.size() % 2 != 0) {8113this->reportUniqueWarning(8114"SHT_LLVM_LINKER_OPTIONS section at index " + Twine(I) +8115" is broken: an incomplete "8116"key-value pair was found. The last possible key was: \"" +8117Strings.back() + "\"");8118continue;8119}81208121for (size_t I = 0; I < Strings.size(); I += 2)8122W.printString(Strings[I], Strings[I + 1]);8123}8124}81258126template <class ELFT> void LLVMELFDumper<ELFT>::printDependentLibs() {8127ListScope L(W, "DependentLibs");8128this->printDependentLibsHelper(8129[](const Elf_Shdr &) {},8130[this](StringRef Lib, uint64_t) { W.printString(Lib); });8131}81328133template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() {8134ListScope L(W, "StackSizes");8135if (this->Obj.getHeader().e_type == ELF::ET_REL)8136this->printRelocatableStackSizes([]() {});8137else8138this->printNonRelocatableStackSizes([]() {});8139}81408141template <class ELFT>8142void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,8143ArrayRef<std::string> FuncNames) {8144DictScope D(W, "Entry");8145W.printList("Functions", FuncNames);8146W.printHex("Size", Size);8147}81488149template <class ELFT>8150void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {8151auto PrintEntry = [&](const Elf_Addr *E) {8152W.printHex("Address", Parser.getGotAddress(E));8153W.printNumber("Access", Parser.getGotOffset(E));8154W.printHex("Initial", *E);8155};81568157DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");81588159W.printHex("Canonical gp value", Parser.getGp());8160{8161ListScope RS(W, "Reserved entries");8162{8163DictScope D(W, "Entry");8164PrintEntry(Parser.getGotLazyResolver());8165W.printString("Purpose", StringRef("Lazy resolver"));8166}81678168if (Parser.getGotModulePointer()) {8169DictScope D(W, "Entry");8170PrintEntry(Parser.getGotModulePointer());8171W.printString("Purpose", StringRef("Module pointer (GNU extension)"));8172}8173}8174{8175ListScope LS(W, "Local entries");8176for (auto &E : Parser.getLocalEntries()) {8177DictScope D(W, "Entry");8178PrintEntry(&E);8179}8180}81818182if (Parser.IsStatic)8183return;81848185{8186ListScope GS(W, "Global entries");8187for (auto &E : Parser.getGlobalEntries()) {8188DictScope D(W, "Entry");81898190PrintEntry(&E);81918192const Elf_Sym &Sym = *Parser.getGotSym(&E);8193W.printHex("Value", Sym.st_value);8194W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));81958196const unsigned SymIndex = &Sym - this->dynamic_symbols().begin();8197DataRegion<Elf_Word> ShndxTable(8198(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());8199printSymbolSection(Sym, SymIndex, ShndxTable);82008201std::string SymName = this->getFullSymbolName(8202Sym, SymIndex, ShndxTable, this->DynamicStringTable, true);8203W.printNumber("Name", SymName, Sym.st_name);8204}8205}82068207W.printNumber("Number of TLS and multi-GOT entries",8208uint64_t(Parser.getOtherEntries().size()));8209}82108211template <class ELFT>8212void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {8213auto PrintEntry = [&](const Elf_Addr *E) {8214W.printHex("Address", Parser.getPltAddress(E));8215W.printHex("Initial", *E);8216};82178218DictScope GS(W, "PLT GOT");82198220{8221ListScope RS(W, "Reserved entries");8222{8223DictScope D(W, "Entry");8224PrintEntry(Parser.getPltLazyResolver());8225W.printString("Purpose", StringRef("PLT lazy resolver"));8226}82278228if (auto E = Parser.getPltModulePointer()) {8229DictScope D(W, "Entry");8230PrintEntry(E);8231W.printString("Purpose", StringRef("Module pointer"));8232}8233}8234{8235ListScope LS(W, "Entries");8236DataRegion<Elf_Word> ShndxTable(8237(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());8238for (auto &E : Parser.getPltEntries()) {8239DictScope D(W, "Entry");8240PrintEntry(&E);82418242const Elf_Sym &Sym = *Parser.getPltSym(&E);8243W.printHex("Value", Sym.st_value);8244W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));8245printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(),8246ShndxTable);82478248const Elf_Sym *FirstSym = cantFail(8249this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));8250std::string SymName = this->getFullSymbolName(8251Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true);8252W.printNumber("Name", SymName, Sym.st_name);8253}8254}8255}82568257template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() {8258const Elf_Mips_ABIFlags<ELFT> *Flags;8259if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =8260getMipsAbiFlagsSection(*this)) {8261Flags = *SecOrErr;8262if (!Flags) {8263W.startLine() << "There is no .MIPS.abiflags section in the file.\n";8264return;8265}8266} else {8267this->reportUniqueWarning(SecOrErr.takeError());8268return;8269}82708271raw_ostream &OS = W.getOStream();8272DictScope GS(W, "MIPS ABI Flags");82738274W.printNumber("Version", Flags->version);8275W.startLine() << "ISA: ";8276if (Flags->isa_rev <= 1)8277OS << format("MIPS%u", Flags->isa_level);8278else8279OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);8280OS << "\n";8281W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType));8282W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags));8283W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType));8284W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));8285W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));8286W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));8287W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1));8288W.printHex("Flags 2", Flags->flags2);8289}82908291template <class ELFT>8292void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,8293ArrayRef<std::string> InputFilenames,8294const Archive *A) {8295FileScope = std::make_unique<DictScope>(this->W);8296DictScope D(this->W, "FileSummary");8297this->W.printString("File", FileStr);8298this->W.printString("Format", Obj.getFileFormatName());8299this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));8300this->W.printString(8301"AddressSize",8302std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));8303this->printLoadName();8304}83058306template <class ELFT>8307void JSONELFDumper<ELFT>::printZeroSymbolOtherField(8308const Elf_Sym &Symbol) const {8309// We want the JSON format to be uniform, since it is machine readable, so8310// always print the `Other` field the same way.8311this->printSymbolOtherField(Symbol);8312}83138314template <class ELFT>8315void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,8316StringRef SymbolName,8317StringRef RelocName) {8318this->printExpandedRelRelaReloc(R, SymbolName, RelocName);8319}83208321template <class ELFT>8322void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,8323StringRef Name,8324const unsigned SecNdx) {8325DictScope Group(this->W);8326this->W.printNumber("SectionIndex", SecNdx);8327ListScope D(this->W, "Relocs");8328this->printRelocationsHelper(Sec);8329}83308331template <class ELFT>8332std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const {8333return "GroupSections";8334}83358336template <class ELFT>8337void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,8338uint64_t Idx) const {8339DictScope Grp(this->W);8340this->W.printString("Name", Name);8341this->W.printNumber("Index", Idx);8342}83438344template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const {8345// JSON output does not need to print anything for empty groups8346}834783488349