llvm-project
8347 строк · 302.5 Кб
1//===- ELFDumper.cpp - ELF-specific dumper --------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the ELF-specific dumper for llvm-readobj.
11///
12//===----------------------------------------------------------------------===//
13
14#include "ARMEHABIPrinter.h"15#include "DwarfCFIEHPrinter.h"16#include "ObjDumper.h"17#include "StackMapPrinter.h"18#include "llvm-readobj.h"19#include "llvm/ADT/ArrayRef.h"20#include "llvm/ADT/BitVector.h"21#include "llvm/ADT/DenseMap.h"22#include "llvm/ADT/DenseSet.h"23#include "llvm/ADT/MapVector.h"24#include "llvm/ADT/STLExtras.h"25#include "llvm/ADT/SmallString.h"26#include "llvm/ADT/SmallVector.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/ADT/StringRef.h"29#include "llvm/ADT/Twine.h"30#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"31#include "llvm/BinaryFormat/ELF.h"32#include "llvm/BinaryFormat/MsgPackDocument.h"33#include "llvm/Demangle/Demangle.h"34#include "llvm/Object/Archive.h"35#include "llvm/Object/ELF.h"36#include "llvm/Object/ELFObjectFile.h"37#include "llvm/Object/ELFTypes.h"38#include "llvm/Object/Error.h"39#include "llvm/Object/ObjectFile.h"40#include "llvm/Object/RelocationResolver.h"41#include "llvm/Object/StackMapParser.h"42#include "llvm/Support/AMDGPUMetadata.h"43#include "llvm/Support/ARMAttributeParser.h"44#include "llvm/Support/ARMBuildAttributes.h"45#include "llvm/Support/Casting.h"46#include "llvm/Support/Compiler.h"47#include "llvm/Support/Endian.h"48#include "llvm/Support/ErrorHandling.h"49#include "llvm/Support/Format.h"50#include "llvm/Support/FormatVariadic.h"51#include "llvm/Support/FormattedStream.h"52#include "llvm/Support/HexagonAttributeParser.h"53#include "llvm/Support/LEB128.h"54#include "llvm/Support/MSP430AttributeParser.h"55#include "llvm/Support/MSP430Attributes.h"56#include "llvm/Support/MathExtras.h"57#include "llvm/Support/MipsABIFlags.h"58#include "llvm/Support/RISCVAttributeParser.h"59#include "llvm/Support/RISCVAttributes.h"60#include "llvm/Support/ScopedPrinter.h"61#include "llvm/Support/SystemZ/zOSSupport.h"62#include "llvm/Support/raw_ostream.h"63#include <algorithm>64#include <array>65#include <cinttypes>66#include <cstddef>67#include <cstdint>68#include <cstdlib>69#include <iterator>70#include <memory>71#include <optional>72#include <string>73#include <system_error>74#include <vector>75
76using namespace llvm;77using namespace llvm::object;78using namespace llvm::support;79using namespace ELF;80
81#define LLVM_READOBJ_ENUM_CASE(ns, enum) \82case ns::enum: \83return #enum;84
85#define ENUM_ENT(enum, altName) \86{ #enum, altName, ELF::enum }87
88#define ENUM_ENT_1(enum) \89{ #enum, #enum, ELF::enum }90
91namespace {92
93template <class ELFT> struct RelSymbol {94RelSymbol(const typename ELFT::Sym *S, StringRef N)95: Sym(S), Name(N.str()) {}96const typename ELFT::Sym *Sym;97std::string Name;98};99
100/// Represents a contiguous uniform range in the file. We cannot just create a
101/// range directly because when creating one of these from the .dynamic table
102/// the size, entity size and virtual address are different entries in arbitrary
103/// order (DT_REL, DT_RELSZ, DT_RELENT for example).
104struct DynRegionInfo {105DynRegionInfo(const Binary &Owner, const ObjDumper &D)106: Obj(&Owner), Dumper(&D) {}107DynRegionInfo(const Binary &Owner, const ObjDumper &D, const uint8_t *A,108uint64_t S, uint64_t ES)109: Addr(A), Size(S), EntSize(ES), Obj(&Owner), Dumper(&D) {}110
111/// Address in current address space.112const uint8_t *Addr = nullptr;113/// Size in bytes of the region.114uint64_t Size = 0;115/// Size of each entity in the region.116uint64_t EntSize = 0;117
118/// Owner object. Used for error reporting.119const Binary *Obj;120/// Dumper used for error reporting.121const ObjDumper *Dumper;122/// Error prefix. Used for error reporting to provide more information.123std::string Context;124/// Region size name. Used for error reporting.125StringRef SizePrintName = "size";126/// Entry size name. Used for error reporting. If this field is empty, errors127/// will not mention the entry size.128StringRef EntSizePrintName = "entry size";129
130template <typename Type> ArrayRef<Type> getAsArrayRef() const {131const Type *Start = reinterpret_cast<const Type *>(Addr);132if (!Start)133return {Start, Start};134
135const uint64_t Offset =136Addr - (const uint8_t *)Obj->getMemoryBufferRef().getBufferStart();137const uint64_t ObjSize = Obj->getMemoryBufferRef().getBufferSize();138
139if (Size > ObjSize - Offset) {140Dumper->reportUniqueWarning(141"unable to read data at 0x" + Twine::utohexstr(Offset) +142" of size 0x" + Twine::utohexstr(Size) + " (" + SizePrintName +143"): it goes past the end of the file of size 0x" +144Twine::utohexstr(ObjSize));145return {Start, Start};146}147
148if (EntSize == sizeof(Type) && (Size % EntSize == 0))149return {Start, Start + (Size / EntSize)};150
151std::string Msg;152if (!Context.empty())153Msg += Context + " has ";154
155Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")")156.str();157if (!EntSizePrintName.empty())158Msg +=159(" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")")160.str();161
162Dumper->reportUniqueWarning(Msg);163return {Start, Start};164}165};166
167struct GroupMember {168StringRef Name;169uint64_t Index;170};171
172struct GroupSection {173StringRef Name;174std::string Signature;175uint64_t ShName;176uint64_t Index;177uint32_t Link;178uint32_t Info;179uint32_t Type;180std::vector<GroupMember> Members;181};182
183namespace {184
185struct NoteType {186uint32_t ID;187StringRef Name;188};189
190} // namespace191
192template <class ELFT> class Relocation {193public:194Relocation(const typename ELFT::Rel &R, bool IsMips64EL)195: Type(R.getType(IsMips64EL)), Symbol(R.getSymbol(IsMips64EL)),196Offset(R.r_offset), Info(R.r_info) {}197
198Relocation(const typename ELFT::Rela &R, bool IsMips64EL)199: Relocation((const typename ELFT::Rel &)R, IsMips64EL) {200Addend = R.r_addend;201}202
203uint32_t Type;204uint32_t Symbol;205typename ELFT::uint Offset;206typename ELFT::uint Info;207std::optional<int64_t> Addend;208};209
210template <class ELFT> class MipsGOTParser;211
212template <typename ELFT> class ELFDumper : public ObjDumper {213LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)214
215public:216ELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer);217
218void printUnwindInfo() override;219void printNeededLibraries() override;220void printHashTable() override;221void printGnuHashTable() override;222void printLoadName() override;223void printVersionInfo() override;224void printArchSpecificInfo() override;225void printStackMap() const override;226void printMemtag() override;227ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr);228
229// Hash histogram shows statistics of how efficient the hash was for the230// dynamic symbol table. The table shows the number of hash buckets for231// different lengths of chains as an absolute number and percentage of the232// total buckets, and the cumulative coverage of symbols for each set of233// buckets.234void printHashHistograms() override;235
236const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; };237
238std::string describe(const Elf_Shdr &Sec) const;239
240unsigned getHashTableEntSize() const {241// EM_S390 and ELF::EM_ALPHA platforms use 8-bytes entries in SHT_HASH242// sections. This violates the ELF specification.243if (Obj.getHeader().e_machine == ELF::EM_S390 ||244Obj.getHeader().e_machine == ELF::EM_ALPHA)245return 8;246return 4;247}248
249std::vector<EnumEntry<unsigned>>250getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const;251
252Elf_Dyn_Range dynamic_table() const {253// A valid .dynamic section contains an array of entries terminated254// with a DT_NULL entry. However, sometimes the section content may255// continue past the DT_NULL entry, so to dump the section correctly,256// we first find the end of the entries by iterating over them.257Elf_Dyn_Range Table = DynamicTable.template getAsArrayRef<Elf_Dyn>();258
259size_t Size = 0;260while (Size < Table.size())261if (Table[Size++].getTag() == DT_NULL)262break;263
264return Table.slice(0, Size);265}266
267Elf_Sym_Range dynamic_symbols() const {268if (!DynSymRegion)269return Elf_Sym_Range();270return DynSymRegion->template getAsArrayRef<Elf_Sym>();271}272
273const Elf_Shdr *findSectionByName(StringRef Name) const;274
275StringRef getDynamicStringTable() const { return DynamicStringTable; }276
277protected:278virtual void printVersionSymbolSection(const Elf_Shdr *Sec) = 0;279virtual void printVersionDefinitionSection(const Elf_Shdr *Sec) = 0;280virtual void printVersionDependencySection(const Elf_Shdr *Sec) = 0;281
282void283printDependentLibsHelper(function_ref<void(const Elf_Shdr &)> OnSectionStart,284function_ref<void(StringRef, uint64_t)> OnLibEntry);285
286virtual void printRelRelaReloc(const Relocation<ELFT> &R,287const RelSymbol<ELFT> &RelSym) = 0;288virtual void printDynamicRelocHeader(unsigned Type, StringRef Name,289const DynRegionInfo &Reg) {}290void printReloc(const Relocation<ELFT> &R, unsigned RelIndex,291const Elf_Shdr &Sec, const Elf_Shdr *SymTab);292void printDynamicReloc(const Relocation<ELFT> &R);293void printDynamicRelocationsHelper();294void printRelocationsHelper(const Elf_Shdr &Sec);295void forEachRelocationDo(296const Elf_Shdr &Sec,297llvm::function_ref<void(const Relocation<ELFT> &, unsigned,298const Elf_Shdr &, const Elf_Shdr *)>299RelRelaFn);300
301virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,302bool NonVisibilityBitsUsed,303bool ExtraSymInfo) const {};304virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,305DataRegion<Elf_Word> ShndxTable,306std::optional<StringRef> StrTable, bool IsDynamic,307bool NonVisibilityBitsUsed,308bool ExtraSymInfo) const = 0;309
310virtual void printMipsABIFlags() = 0;311virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;312virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;313
314virtual void printMemtag(315const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,316const ArrayRef<uint8_t> AndroidNoteDesc,317const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0;318
319virtual void printHashHistogram(const Elf_Hash &HashTable) const;320virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const;321virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain,322size_t TotalSyms, ArrayRef<size_t> Count,323bool IsGnu) const = 0;324
325Expected<ArrayRef<Elf_Versym>>326getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,327StringRef *StrTab, const Elf_Shdr **SymTabSec) const;328StringRef getPrintableSectionName(const Elf_Shdr &Sec) const;329
330std::vector<GroupSection> getGroups();331
332// Returns the function symbol index for the given address. Matches the333// symbol's section with FunctionSec when specified.334// Returns std::nullopt if no function symbol can be found for the address or335// in case it is not defined in the specified section.336SmallVector<uint32_t> getSymbolIndexesForFunctionAddress(337uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec);338bool printFunctionStackSize(uint64_t SymValue,339std::optional<const Elf_Shdr *> FunctionSec,340const Elf_Shdr &StackSizeSec, DataExtractor Data,341uint64_t *Offset);342void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec,343unsigned Ndx, const Elf_Shdr *SymTab,344const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec,345const RelocationResolver &Resolver, DataExtractor Data);346virtual void printStackSizeEntry(uint64_t Size,347ArrayRef<std::string> FuncNames) = 0;348
349void printRelocatableStackSizes(std::function<void()> PrintHeader);350void printNonRelocatableStackSizes(std::function<void()> PrintHeader);351
352const object::ELFObjectFile<ELFT> &ObjF;353const ELFFile<ELFT> &Obj;354StringRef FileName;355
356Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size,357uint64_t EntSize) {358if (Offset + Size < Offset || Offset + Size > Obj.getBufSize())359return createError("offset (0x" + Twine::utohexstr(Offset) +360") + size (0x" + Twine::utohexstr(Size) +361") is greater than the file size (0x" +362Twine::utohexstr(Obj.getBufSize()) + ")");363return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize);364}365
366void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>,367llvm::endianness);368void printMipsReginfo();369void printMipsOptions();370
371std::pair<const Elf_Phdr *, const Elf_Shdr *> findDynamic();372void loadDynamicTable();373void parseDynamicTable();374
375Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym,376bool &IsDefault) const;377Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const;378
379DynRegionInfo DynRelRegion;380DynRegionInfo DynRelaRegion;381DynRegionInfo DynCrelRegion;382DynRegionInfo DynRelrRegion;383DynRegionInfo DynPLTRelRegion;384std::optional<DynRegionInfo> DynSymRegion;385DynRegionInfo DynSymTabShndxRegion;386DynRegionInfo DynamicTable;387StringRef DynamicStringTable;388const Elf_Hash *HashTable = nullptr;389const Elf_GnuHash *GnuHashTable = nullptr;390const Elf_Shdr *DotSymtabSec = nullptr;391const Elf_Shdr *DotDynsymSec = nullptr;392const Elf_Shdr *DotAddrsigSec = nullptr;393DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;394std::optional<uint64_t> SONameOffset;395std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;396
397const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version398const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r399const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d400
401std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex,402DataRegion<Elf_Word> ShndxTable,403std::optional<StringRef> StrTable,404bool IsDynamic) const;405Expected<unsigned>406getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,407DataRegion<Elf_Word> ShndxTable) const;408Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol,409unsigned SectionIndex) const;410std::string getStaticSymbolName(uint32_t Index) const;411StringRef getDynamicString(uint64_t Value) const;412
413std::pair<Elf_Sym_Range, std::optional<StringRef>> getSymtabAndStrtab() const;414void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const;415std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;416
417Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,418const Elf_Shdr *SymTab) const;419
420ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;421
422private:423mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;424};425
426template <class ELFT>427std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const {428return ::describe(Obj, Sec);429}
430
431namespace {432
433template <class ELFT> struct SymtabLink {434typename ELFT::SymRange Symbols;435StringRef StringTable;436const typename ELFT::Shdr *SymTab;437};438
439// Returns the linked symbol table, symbols and associated string table for a
440// given section.
441template <class ELFT>442Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj,443const typename ELFT::Shdr &Sec,444unsigned ExpectedType) {445Expected<const typename ELFT::Shdr *> SymtabOrErr =446Obj.getSection(Sec.sh_link);447if (!SymtabOrErr)448return createError("invalid section linked to " + describe(Obj, Sec) +449": " + toString(SymtabOrErr.takeError()));450
451if ((*SymtabOrErr)->sh_type != ExpectedType)452return createError(453"invalid section linked to " + describe(Obj, Sec) + ": expected " +454object::getELFSectionTypeName(Obj.getHeader().e_machine, ExpectedType) +455", but got " +456object::getELFSectionTypeName(Obj.getHeader().e_machine,457(*SymtabOrErr)->sh_type));458
459Expected<StringRef> StrTabOrErr = Obj.getLinkAsStrtab(**SymtabOrErr);460if (!StrTabOrErr)461return createError(462"can't get a string table for the symbol table linked to " +463describe(Obj, Sec) + ": " + toString(StrTabOrErr.takeError()));464
465Expected<typename ELFT::SymRange> SymsOrErr = Obj.symbols(*SymtabOrErr);466if (!SymsOrErr)467return createError("unable to read symbols from the " + describe(Obj, Sec) +468": " + toString(SymsOrErr.takeError()));469
470return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr};471}
472
473} // namespace474
475template <class ELFT>476Expected<ArrayRef<typename ELFT::Versym>>477ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,478StringRef *StrTab,479const Elf_Shdr **SymTabSec) const {480assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec));481if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) %482sizeof(uint16_t) !=4830)484return createError("the " + describe(Sec) + " is misaligned");485
486Expected<ArrayRef<Elf_Versym>> VersionsOrErr =487Obj.template getSectionContentsAsArray<Elf_Versym>(Sec);488if (!VersionsOrErr)489return createError("cannot read content of " + describe(Sec) + ": " +490toString(VersionsOrErr.takeError()));491
492Expected<SymtabLink<ELFT>> SymTabOrErr =493getLinkAsSymtab(Obj, Sec, SHT_DYNSYM);494if (!SymTabOrErr) {495reportUniqueWarning(SymTabOrErr.takeError());496return *VersionsOrErr;497}498
499if (SymTabOrErr->Symbols.size() != VersionsOrErr->size())500reportUniqueWarning(describe(Sec) + ": the number of entries (" +501Twine(VersionsOrErr->size()) +502") does not match the number of symbols (" +503Twine(SymTabOrErr->Symbols.size()) +504") in the symbol table with index " +505Twine(Sec.sh_link));506
507if (SymTab) {508*SymTab = SymTabOrErr->Symbols;509*StrTab = SymTabOrErr->StringTable;510*SymTabSec = SymTabOrErr->SymTab;511}512return *VersionsOrErr;513}
514
515template <class ELFT>516std::pair<typename ELFDumper<ELFT>::Elf_Sym_Range, std::optional<StringRef>>517ELFDumper<ELFT>::getSymtabAndStrtab() const {518assert(DotSymtabSec);519Elf_Sym_Range Syms(nullptr, nullptr);520std::optional<StringRef> StrTable;521if (Expected<StringRef> StrTableOrErr =522Obj.getStringTableForSymtab(*DotSymtabSec))523StrTable = *StrTableOrErr;524else525reportUniqueWarning(526"unable to get the string table for the SHT_SYMTAB section: " +527toString(StrTableOrErr.takeError()));528
529if (Expected<Elf_Sym_Range> SymsOrErr = Obj.symbols(DotSymtabSec))530Syms = *SymsOrErr;531else532reportUniqueWarning("unable to read symbols from the SHT_SYMTAB section: " +533toString(SymsOrErr.takeError()));534return {Syms, StrTable};535}
536
537template <class ELFT>538void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic,539bool ExtraSymInfo) const {540std::optional<StringRef> StrTable;541size_t Entries = 0;542Elf_Sym_Range Syms(nullptr, nullptr);543const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec;544
545if (IsDynamic) {546StrTable = DynamicStringTable;547Syms = dynamic_symbols();548Entries = Syms.size();549} else if (DotSymtabSec) {550std::tie(Syms, StrTable) = getSymtabAndStrtab();551Entries = DotSymtabSec->getEntityCount();552}553if (Syms.empty())554return;555
556// The st_other field has 2 logical parts. The first two bits hold the symbol557// visibility (STV_*) and the remainder hold other platform-specific values.558bool NonVisibilityBitsUsed =559llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; });560
561DataRegion<Elf_Word> ShndxTable =562IsDynamic ? DataRegion<Elf_Word>(563(const Elf_Word *)this->DynSymTabShndxRegion.Addr,564this->getElfObject().getELFFile().end())565: DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));566
567printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo);568for (const Elf_Sym &Sym : Syms)569printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,570NonVisibilityBitsUsed, ExtraSymInfo);571}
572
573template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {574formatted_raw_ostream &OS;575
576public:577LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)578
579GNUELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)580: ELFDumper<ELFT>(ObjF, Writer),581OS(static_cast<formatted_raw_ostream &>(Writer.getOStream())) {582assert(&this->W.getOStream() == &llvm::fouts());583}584
585void printFileSummary(StringRef FileStr, ObjectFile &Obj,586ArrayRef<std::string> InputFilenames,587const Archive *A) override;588void printFileHeaders() override;589void printGroupSections() override;590void printRelocations() override;591void printSectionHeaders() override;592void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,593bool ExtraSymInfo) override;594void printHashSymbols() override;595void printSectionDetails() override;596void printDependentLibs() override;597void printDynamicTable() override;598void printDynamicRelocations() override;599void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,600bool NonVisibilityBitsUsed,601bool ExtraSymInfo) const override;602void printProgramHeaders(bool PrintProgramHeaders,603cl::boolOrDefault PrintSectionMapping) override;604void printVersionSymbolSection(const Elf_Shdr *Sec) override;605void printVersionDefinitionSection(const Elf_Shdr *Sec) override;606void printVersionDependencySection(const Elf_Shdr *Sec) override;607void printCGProfile() override;608void printBBAddrMaps(bool PrettyPGOAnalysis) override;609void printAddrsig() override;610void printNotes() override;611void printELFLinkerOptions() override;612void printStackSizes() override;613void printMemtag(614const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,615const ArrayRef<uint8_t> AndroidNoteDesc,616const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;617void printHashHistogramStats(size_t NBucket, size_t MaxChain,618size_t TotalSyms, ArrayRef<size_t> Count,619bool IsGnu) const override;620
621private:622void printHashTableSymbols(const Elf_Hash &HashTable);623void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable);624
625struct Field {626std::string Str;627unsigned Column;628
629Field(StringRef S, unsigned Col) : Str(std::string(S)), Column(Col) {}630Field(unsigned Col) : Column(Col) {}631};632
633template <typename T, typename TEnum>634std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues,635TEnum EnumMask1 = {}, TEnum EnumMask2 = {},636TEnum EnumMask3 = {}) const {637std::string Str;638for (const EnumEntry<TEnum> &Flag : EnumValues) {639if (Flag.Value == 0)640continue;641
642TEnum EnumMask{};643if (Flag.Value & EnumMask1)644EnumMask = EnumMask1;645else if (Flag.Value & EnumMask2)646EnumMask = EnumMask2;647else if (Flag.Value & EnumMask3)648EnumMask = EnumMask3;649bool IsEnum = (Flag.Value & EnumMask) != 0;650if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||651(IsEnum && (Value & EnumMask) == Flag.Value)) {652if (!Str.empty())653Str += ", ";654Str += Flag.AltName;655}656}657return Str;658}659
660formatted_raw_ostream &printField(struct Field F) const {661if (F.Column != 0)662OS.PadToColumn(F.Column);663OS << F.Str;664OS.flush();665return OS;666}667void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex,668DataRegion<Elf_Word> ShndxTable, StringRef StrTable,669uint32_t Bucket);670void printRelr(const Elf_Shdr &Sec);671void printRelRelaReloc(const Relocation<ELFT> &R,672const RelSymbol<ELFT> &RelSym) override;673void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,674DataRegion<Elf_Word> ShndxTable,675std::optional<StringRef> StrTable, bool IsDynamic,676bool NonVisibilityBitsUsed,677bool ExtraSymInfo) const override;678void printDynamicRelocHeader(unsigned Type, StringRef Name,679const DynRegionInfo &Reg) override;680
681std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,682DataRegion<Elf_Word> ShndxTable,683bool ExtraSymInfo = false) const;684void printProgramHeaders() override;685void printSectionMapping() override;686void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,687const Twine &Label, unsigned EntriesNum);688
689void printStackSizeEntry(uint64_t Size,690ArrayRef<std::string> FuncNames) override;691
692void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;693void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;694void printMipsABIFlags() override;695};696
697template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {698public:699LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)700
701LLVMELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)702: ELFDumper<ELFT>(ObjF, Writer), W(Writer) {}703
704void printFileHeaders() override;705void printGroupSections() override;706void printRelocations() override;707void printSectionHeaders() override;708void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,709bool ExtraSymInfo) override;710void printDependentLibs() override;711void printDynamicTable() override;712void printDynamicRelocations() override;713void printProgramHeaders(bool PrintProgramHeaders,714cl::boolOrDefault PrintSectionMapping) override;715void printVersionSymbolSection(const Elf_Shdr *Sec) override;716void printVersionDefinitionSection(const Elf_Shdr *Sec) override;717void printVersionDependencySection(const Elf_Shdr *Sec) override;718void printCGProfile() override;719void printBBAddrMaps(bool PrettyPGOAnalysis) override;720void printAddrsig() override;721void printNotes() override;722void printELFLinkerOptions() override;723void printStackSizes() override;724void printMemtag(725const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,726const ArrayRef<uint8_t> AndroidNoteDesc,727const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;728void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,729DataRegion<Elf_Word> ShndxTable) const;730void printHashHistogramStats(size_t NBucket, size_t MaxChain,731size_t TotalSyms, ArrayRef<size_t> Count,732bool IsGnu) const override;733
734private:735void printRelRelaReloc(const Relocation<ELFT> &R,736const RelSymbol<ELFT> &RelSym) override;737
738void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,739DataRegion<Elf_Word> ShndxTable,740std::optional<StringRef> StrTable, bool IsDynamic,741bool /*NonVisibilityBitsUsed*/,742bool /*ExtraSymInfo*/) const override;743void printProgramHeaders() override;744void printSectionMapping() override {}745void printStackSizeEntry(uint64_t Size,746ArrayRef<std::string> FuncNames) override;747
748void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;749void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;750void printMipsABIFlags() override;751virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const;752
753protected:754virtual std::string getGroupSectionHeaderName() const;755void printSymbolOtherField(const Elf_Sym &Symbol) const;756virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R,757StringRef SymbolName,758StringRef RelocName);759virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R,760StringRef SymbolName,761StringRef RelocName);762virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,763const unsigned SecNdx);764virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const;765virtual void printEmptyGroupMessage() const;766
767ScopedPrinter &W;768};769
770// JSONELFDumper shares most of the same implementation as LLVMELFDumper except
771// it uses a JSONScopedPrinter.
772template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {773public:774LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)775
776JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)777: LLVMELFDumper<ELFT>(ObjF, Writer) {}778
779std::string getGroupSectionHeaderName() const override;780
781void printFileSummary(StringRef FileStr, ObjectFile &Obj,782ArrayRef<std::string> InputFilenames,783const Archive *A) override;784virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override;785
786void printDefaultRelRelaReloc(const Relocation<ELFT> &R,787StringRef SymbolName,788StringRef RelocName) override;789
790void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,791const unsigned SecNdx) override;792
793void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override;794
795void printEmptyGroupMessage() const override;796
797void printDynamicTable() override;798
799private:800void printAuxillaryDynamicTableEntryInfo(const Elf_Dyn &Entry);801
802std::unique_ptr<DictScope> FileScope;803};804
805} // end anonymous namespace806
807namespace llvm {808
809template <class ELFT>810static std::unique_ptr<ObjDumper>811createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) {812if (opts::Output == opts::GNU)813return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer);814else if (opts::Output == opts::JSON)815return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer);816return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer);817}
818
819std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj,820ScopedPrinter &Writer) {821// Little-endian 32-bit822if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(&Obj))823return createELFDumper(*ELFObj, Writer);824
825// Big-endian 32-bit826if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(&Obj))827return createELFDumper(*ELFObj, Writer);828
829// Little-endian 64-bit830if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj))831return createELFDumper(*ELFObj, Writer);832
833// Big-endian 64-bit834return createELFDumper(*cast<ELF64BEObjectFile>(&Obj), Writer);835}
836
837} // end namespace llvm838
839template <class ELFT>840Expected<SmallVector<std::optional<VersionEntry>, 0> *>841ELFDumper<ELFT>::getVersionMap() const {842// If the VersionMap has already been loaded or if there is no dynamic symtab843// or version table, there is nothing to do.844if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection)845return &VersionMap;846
847Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr =848Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection);849if (MapOrErr)850VersionMap = *MapOrErr;851else852return MapOrErr.takeError();853
854return &VersionMap;855}
856
857template <typename ELFT>858Expected<StringRef> ELFDumper<ELFT>::getSymbolVersion(const Elf_Sym &Sym,859bool &IsDefault) const {860// This is a dynamic symbol. Look in the GNU symbol version table.861if (!SymbolVersionSection) {862// No version table.863IsDefault = false;864return "";865}866
867assert(DynSymRegion && "DynSymRegion has not been initialised");868// Determine the position in the symbol table of this entry.869size_t EntryIndex = (reinterpret_cast<uintptr_t>(&Sym) -870reinterpret_cast<uintptr_t>(DynSymRegion->Addr)) /871sizeof(Elf_Sym);872
873// Get the corresponding version index entry.874Expected<const Elf_Versym *> EntryOrErr =875Obj.template getEntry<Elf_Versym>(*SymbolVersionSection, EntryIndex);876if (!EntryOrErr)877return EntryOrErr.takeError();878
879unsigned Version = (*EntryOrErr)->vs_index;880if (Version == VER_NDX_LOCAL || Version == VER_NDX_GLOBAL) {881IsDefault = false;882return "";883}884
885Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =886getVersionMap();887if (!MapOrErr)888return MapOrErr.takeError();889
890return Obj.getSymbolVersionByIndex(Version, IsDefault, **MapOrErr,891Sym.st_shndx == ELF::SHN_UNDEF);892}
893
894template <typename ELFT>895Expected<RelSymbol<ELFT>>896ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R,897const Elf_Shdr *SymTab) const {898if (R.Symbol == 0)899return RelSymbol<ELFT>(nullptr, "");900
901Expected<const Elf_Sym *> SymOrErr =902Obj.template getEntry<Elf_Sym>(*SymTab, R.Symbol);903if (!SymOrErr)904return createError("unable to read an entry with index " + Twine(R.Symbol) +905" from " + describe(*SymTab) + ": " +906toString(SymOrErr.takeError()));907const Elf_Sym *Sym = *SymOrErr;908if (!Sym)909return RelSymbol<ELFT>(nullptr, "");910
911Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*SymTab);912if (!StrTableOrErr)913return StrTableOrErr.takeError();914
915const Elf_Sym *FirstSym =916cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0));917std::string SymbolName =918getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab),919*StrTableOrErr, SymTab->sh_type == SHT_DYNSYM);920return RelSymbol<ELFT>(Sym, SymbolName);921}
922
923template <typename ELFT>924ArrayRef<typename ELFT::Word>925ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const {926if (Symtab) {927auto It = ShndxTables.find(Symtab);928if (It != ShndxTables.end())929return It->second;930}931return {};932}
933
934static std::string maybeDemangle(StringRef Name) {935return opts::Demangle ? demangle(Name) : Name.str();936}
937
938template <typename ELFT>939std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {940auto Warn = [&](Error E) -> std::string {941reportUniqueWarning("unable to read the name of symbol with index " +942Twine(Index) + ": " + toString(std::move(E)));943return "<?>";944};945
946Expected<const typename ELFT::Sym *> SymOrErr =947Obj.getSymbol(DotSymtabSec, Index);948if (!SymOrErr)949return Warn(SymOrErr.takeError());950
951Expected<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*DotSymtabSec);952if (!StrTabOrErr)953return Warn(StrTabOrErr.takeError());954
955Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr);956if (!NameOrErr)957return Warn(NameOrErr.takeError());958return maybeDemangle(*NameOrErr);959}
960
961template <typename ELFT>962std::string ELFDumper<ELFT>::getFullSymbolName(963const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,964std::optional<StringRef> StrTable, bool IsDynamic) const {965if (!StrTable)966return "<?>";967
968std::string SymbolName;969if (Expected<StringRef> NameOrErr = Symbol.getName(*StrTable)) {970SymbolName = maybeDemangle(*NameOrErr);971} else {972reportUniqueWarning(NameOrErr.takeError());973return "<?>";974}975
976if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) {977Expected<unsigned> SectionIndex =978getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);979if (!SectionIndex) {980reportUniqueWarning(SectionIndex.takeError());981return "<?>";982}983Expected<StringRef> NameOrErr = getSymbolSectionName(Symbol, *SectionIndex);984if (!NameOrErr) {985reportUniqueWarning(NameOrErr.takeError());986return ("<section " + Twine(*SectionIndex) + ">").str();987}988return std::string(*NameOrErr);989}990
991if (!IsDynamic)992return SymbolName;993
994bool IsDefault;995Expected<StringRef> VersionOrErr = getSymbolVersion(Symbol, IsDefault);996if (!VersionOrErr) {997reportUniqueWarning(VersionOrErr.takeError());998return SymbolName + "@<corrupt>";999}1000
1001if (!VersionOrErr->empty()) {1002SymbolName += (IsDefault ? "@@" : "@");1003SymbolName += *VersionOrErr;1004}1005return SymbolName;1006}
1007
1008template <typename ELFT>1009Expected<unsigned>1010ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,1011DataRegion<Elf_Word> ShndxTable) const {1012unsigned Ndx = Symbol.st_shndx;1013if (Ndx == SHN_XINDEX)1014return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex,1015ShndxTable);1016if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE)1017return Ndx;1018
1019auto CreateErr = [&](const Twine &Name,1020std::optional<unsigned> Offset = std::nullopt) {1021std::string Desc;1022if (Offset)1023Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str();1024else1025Desc = Name.str();1026return createError(1027"unable to get section index for symbol with st_shndx = 0x" +1028Twine::utohexstr(Ndx) + " (" + Desc + ")");1029};1030
1031if (Ndx >= ELF::SHN_LOPROC && Ndx <= ELF::SHN_HIPROC)1032return CreateErr("SHN_LOPROC", Ndx - ELF::SHN_LOPROC);1033if (Ndx >= ELF::SHN_LOOS && Ndx <= ELF::SHN_HIOS)1034return CreateErr("SHN_LOOS", Ndx - ELF::SHN_LOOS);1035if (Ndx == ELF::SHN_UNDEF)1036return CreateErr("SHN_UNDEF");1037if (Ndx == ELF::SHN_ABS)1038return CreateErr("SHN_ABS");1039if (Ndx == ELF::SHN_COMMON)1040return CreateErr("SHN_COMMON");1041return CreateErr("SHN_LORESERVE", Ndx - SHN_LORESERVE);1042}
1043
1044template <typename ELFT>1045Expected<StringRef>1046ELFDumper<ELFT>::getSymbolSectionName(const Elf_Sym &Symbol,1047unsigned SectionIndex) const {1048Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(SectionIndex);1049if (!SecOrErr)1050return SecOrErr.takeError();1051return Obj.getSectionName(**SecOrErr);1052}
1053
1054template <class ELFO>1055static const typename ELFO::Elf_Shdr *1056findNotEmptySectionByAddress(const ELFO &Obj, StringRef FileName,1057uint64_t Addr) {1058for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections()))1059if (Shdr.sh_addr == Addr && Shdr.sh_size > 0)1060return &Shdr;1061return nullptr;1062}
1063
1064const EnumEntry<unsigned> ElfClass[] = {1065{"None", "none", ELF::ELFCLASSNONE},1066{"32-bit", "ELF32", ELF::ELFCLASS32},1067{"64-bit", "ELF64", ELF::ELFCLASS64},1068};1069
1070const EnumEntry<unsigned> ElfDataEncoding[] = {1071{"None", "none", ELF::ELFDATANONE},1072{"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB},1073{"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB},1074};1075
1076const EnumEntry<unsigned> ElfObjectFileType[] = {1077{"None", "NONE (none)", ELF::ET_NONE},1078{"Relocatable", "REL (Relocatable file)", ELF::ET_REL},1079{"Executable", "EXEC (Executable file)", ELF::ET_EXEC},1080{"SharedObject", "DYN (Shared object file)", ELF::ET_DYN},1081{"Core", "CORE (Core file)", ELF::ET_CORE},1082};1083
1084const EnumEntry<unsigned> ElfOSABI[] = {1085{"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE},1086{"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX},1087{"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD},1088{"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX},1089{"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD},1090{"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS},1091{"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX},1092{"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX},1093{"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD},1094{"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64},1095{"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO},1096{"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD},1097{"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS},1098{"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},1099{"AROS", "AROS", ELF::ELFOSABI_AROS},1100{"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},1101{"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},1102{"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA},1103{"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}1104};1105
1106const EnumEntry<unsigned> AMDGPUElfOSABI[] = {1107{"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},1108{"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL},1109{"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}1110};1111
1112const EnumEntry<unsigned> ARMElfOSABI[] = {1113{"ARM", "ARM", ELF::ELFOSABI_ARM},1114{"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC},1115};1116
1117const EnumEntry<unsigned> C6000ElfOSABI[] = {1118{"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},1119{"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX}1120};1121
1122const EnumEntry<unsigned> ElfMachineType[] = {1123ENUM_ENT(EM_NONE, "None"),1124ENUM_ENT(EM_M32, "WE32100"),1125ENUM_ENT(EM_SPARC, "Sparc"),1126ENUM_ENT(EM_386, "Intel 80386"),1127ENUM_ENT(EM_68K, "MC68000"),1128ENUM_ENT(EM_88K, "MC88000"),1129ENUM_ENT(EM_IAMCU, "EM_IAMCU"),1130ENUM_ENT(EM_860, "Intel 80860"),1131ENUM_ENT(EM_MIPS, "MIPS R3000"),1132ENUM_ENT(EM_S370, "IBM System/370"),1133ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"),1134ENUM_ENT(EM_PARISC, "HPPA"),1135ENUM_ENT(EM_VPP500, "Fujitsu VPP500"),1136ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"),1137ENUM_ENT(EM_960, "Intel 80960"),1138ENUM_ENT(EM_PPC, "PowerPC"),1139ENUM_ENT(EM_PPC64, "PowerPC64"),1140ENUM_ENT(EM_S390, "IBM S/390"),1141ENUM_ENT(EM_SPU, "SPU"),1142ENUM_ENT(EM_V800, "NEC V800 series"),1143ENUM_ENT(EM_FR20, "Fujistsu FR20"),1144ENUM_ENT(EM_RH32, "TRW RH-32"),1145ENUM_ENT(EM_RCE, "Motorola RCE"),1146ENUM_ENT(EM_ARM, "ARM"),1147ENUM_ENT(EM_ALPHA, "EM_ALPHA"),1148ENUM_ENT(EM_SH, "Hitachi SH"),1149ENUM_ENT(EM_SPARCV9, "Sparc v9"),1150ENUM_ENT(EM_TRICORE, "Siemens Tricore"),1151ENUM_ENT(EM_ARC, "ARC"),1152ENUM_ENT(EM_H8_300, "Hitachi H8/300"),1153ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"),1154ENUM_ENT(EM_H8S, "Hitachi H8S"),1155ENUM_ENT(EM_H8_500, "Hitachi H8/500"),1156ENUM_ENT(EM_IA_64, "Intel IA-64"),1157ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"),1158ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"),1159ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"),1160ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"),1161ENUM_ENT(EM_PCP, "Siemens PCP"),1162ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"),1163ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"),1164ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"),1165ENUM_ENT(EM_ME16, "Toyota ME16 processor"),1166ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"),1167ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"),1168ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"),1169ENUM_ENT(EM_PDSP, "Sony DSP processor"),1170ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"),1171ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"),1172ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"),1173ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"),1174ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"),1175ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"),1176ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"),1177ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"),1178ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"),1179ENUM_ENT(EM_SVX, "Silicon Graphics SVx"),1180ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"),1181ENUM_ENT(EM_VAX, "Digital VAX"),1182ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"),1183ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"),1184ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"),1185ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"),1186ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"),1187ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"),1188ENUM_ENT(EM_PRISM, "Vitesse Prism"),1189ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"),1190ENUM_ENT(EM_FR30, "Fujitsu FR30"),1191ENUM_ENT(EM_D10V, "Mitsubishi D10V"),1192ENUM_ENT(EM_D30V, "Mitsubishi D30V"),1193ENUM_ENT(EM_V850, "NEC v850"),1194ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"),1195ENUM_ENT(EM_MN10300, "Matsushita MN10300"),1196ENUM_ENT(EM_MN10200, "Matsushita MN10200"),1197ENUM_ENT(EM_PJ, "picoJava"),1198ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"),1199ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"),1200ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"),1201ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"),1202ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"),1203ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"),1204ENUM_ENT(EM_TPC, "Tenor Network TPC processor"),1205ENUM_ENT(EM_SNP1K, "EM_SNP1K"),1206ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"),1207ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"),1208ENUM_ENT(EM_MAX, "MAX Processor"),1209ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"),1210ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"),1211ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"),1212ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"),1213ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"),1214ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"),1215ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"),1216ENUM_ENT(EM_UNICORE, "Unicore"),1217ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"),1218ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"),1219ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"),1220ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"),1221ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"),1222ENUM_ENT(EM_C166, "Infineon Technologies xc16x"),1223ENUM_ENT(EM_M16C, "Renesas M16C"),1224ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"),1225ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"),1226ENUM_ENT(EM_M32C, "Renesas M32C"),1227ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"),1228ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"),1229ENUM_ENT(EM_SHARC, "EM_SHARC"),1230ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"),1231ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"),1232ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"),1233ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"),1234ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"),1235ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"),1236ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"),1237ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"),1238ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"),1239ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"),1240ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"),1241ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"),1242ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"),1243ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"),1244ENUM_ENT(EM_8051, "Intel 8051 and variants"),1245ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"),1246ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"),1247ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"),1248// FIXME: Following EM_ECOG1X definitions is dead code since EM_ECOG1X has1249// an identical number to EM_ECOG1.1250ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"),1251ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"),1252ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"),1253ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"),1254ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"),1255ENUM_ENT(EM_RX, "Renesas RX"),1256ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"),1257ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"),1258ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"),1259ENUM_ENT(EM_CR16, "National Semiconductor CompactRISC 16-bit processor"),1260ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"),1261ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"),1262ENUM_ENT(EM_L10M, "EM_L10M"),1263ENUM_ENT(EM_K10M, "EM_K10M"),1264ENUM_ENT(EM_AARCH64, "AArch64"),1265ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"),1266ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"),1267ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"),1268ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"),1269ENUM_ENT(EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core"),1270ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"),1271ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"),1272ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"),1273ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"),1274ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"),1275ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"),1276ENUM_ENT(EM_OPEN8, "EM_OPEN8"),1277ENUM_ENT(EM_RL78, "Renesas RL78"),1278ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"),1279ENUM_ENT(EM_78KOR, "EM_78KOR"),1280ENUM_ENT(EM_56800EX, "EM_56800EX"),1281ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"),1282ENUM_ENT(EM_RISCV, "RISC-V"),1283ENUM_ENT(EM_LANAI, "EM_LANAI"),1284ENUM_ENT(EM_BPF, "EM_BPF"),1285ENUM_ENT(EM_VE, "NEC SX-Aurora Vector Engine"),1286ENUM_ENT(EM_LOONGARCH, "LoongArch"),1287};1288
1289const EnumEntry<unsigned> ElfSymbolBindings[] = {1290{"Local", "LOCAL", ELF::STB_LOCAL},1291{"Global", "GLOBAL", ELF::STB_GLOBAL},1292{"Weak", "WEAK", ELF::STB_WEAK},1293{"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}};1294
1295const EnumEntry<unsigned> ElfSymbolVisibilities[] = {1296{"DEFAULT", "DEFAULT", ELF::STV_DEFAULT},1297{"INTERNAL", "INTERNAL", ELF::STV_INTERNAL},1298{"HIDDEN", "HIDDEN", ELF::STV_HIDDEN},1299{"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};1300
1301const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {1302{ "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }1303};1304
1305static const char *getGroupType(uint32_t Flag) {1306if (Flag & ELF::GRP_COMDAT)1307return "COMDAT";1308else1309return "(unknown)";1310}
1311
1312const EnumEntry<unsigned> ElfSectionFlags[] = {1313ENUM_ENT(SHF_WRITE, "W"),1314ENUM_ENT(SHF_ALLOC, "A"),1315ENUM_ENT(SHF_EXECINSTR, "X"),1316ENUM_ENT(SHF_MERGE, "M"),1317ENUM_ENT(SHF_STRINGS, "S"),1318ENUM_ENT(SHF_INFO_LINK, "I"),1319ENUM_ENT(SHF_LINK_ORDER, "L"),1320ENUM_ENT(SHF_OS_NONCONFORMING, "O"),1321ENUM_ENT(SHF_GROUP, "G"),1322ENUM_ENT(SHF_TLS, "T"),1323ENUM_ENT(SHF_COMPRESSED, "C"),1324ENUM_ENT(SHF_EXCLUDE, "E"),1325};1326
1327const EnumEntry<unsigned> ElfGNUSectionFlags[] = {1328ENUM_ENT(SHF_GNU_RETAIN, "R")1329};1330
1331const EnumEntry<unsigned> ElfSolarisSectionFlags[] = {1332ENUM_ENT(SHF_SUNW_NODISCARD, "R")1333};1334
1335const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {1336ENUM_ENT(XCORE_SHF_CP_SECTION, ""),1337ENUM_ENT(XCORE_SHF_DP_SECTION, "")1338};1339
1340const EnumEntry<unsigned> ElfARMSectionFlags[] = {1341ENUM_ENT(SHF_ARM_PURECODE, "y")1342};1343
1344const EnumEntry<unsigned> ElfHexagonSectionFlags[] = {1345ENUM_ENT(SHF_HEX_GPREL, "")1346};1347
1348const EnumEntry<unsigned> ElfMipsSectionFlags[] = {1349ENUM_ENT(SHF_MIPS_NODUPES, ""),1350ENUM_ENT(SHF_MIPS_NAMES, ""),1351ENUM_ENT(SHF_MIPS_LOCAL, ""),1352ENUM_ENT(SHF_MIPS_NOSTRIP, ""),1353ENUM_ENT(SHF_MIPS_GPREL, ""),1354ENUM_ENT(SHF_MIPS_MERGE, ""),1355ENUM_ENT(SHF_MIPS_ADDR, ""),1356ENUM_ENT(SHF_MIPS_STRING, "")1357};1358
1359const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {1360ENUM_ENT(SHF_X86_64_LARGE, "l")1361};1362
1363static std::vector<EnumEntry<unsigned>>1364getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) {1365std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags),1366std::end(ElfSectionFlags));1367switch (EOSAbi) {1368case ELFOSABI_SOLARIS:1369Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags),1370std::end(ElfSolarisSectionFlags));1371break;1372default:1373Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags),1374std::end(ElfGNUSectionFlags));1375break;1376}1377switch (EMachine) {1378case EM_ARM:1379Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags),1380std::end(ElfARMSectionFlags));1381break;1382case EM_HEXAGON:1383Ret.insert(Ret.end(), std::begin(ElfHexagonSectionFlags),1384std::end(ElfHexagonSectionFlags));1385break;1386case EM_MIPS:1387Ret.insert(Ret.end(), std::begin(ElfMipsSectionFlags),1388std::end(ElfMipsSectionFlags));1389break;1390case EM_X86_64:1391Ret.insert(Ret.end(), std::begin(ElfX86_64SectionFlags),1392std::end(ElfX86_64SectionFlags));1393break;1394case EM_XCORE:1395Ret.insert(Ret.end(), std::begin(ElfXCoreSectionFlags),1396std::end(ElfXCoreSectionFlags));1397break;1398default:1399break;1400}1401return Ret;1402}
1403
1404static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine,1405uint64_t Flags) {1406// Here we are trying to build the flags string in the same way as GNU does.1407// It is not that straightforward. Imagine we have sh_flags == 0x90000000.1408// SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000.1409// GNU readelf will not print "E" or "Ep" in this case, but will print just1410// "p". It only will print "E" when no other processor flag is set.1411std::string Str;1412bool HasUnknownFlag = false;1413bool HasOSFlag = false;1414bool HasProcFlag = false;1415std::vector<EnumEntry<unsigned>> FlagsList =1416getSectionFlagsForTarget(EOSAbi, EMachine);1417while (Flags) {1418// Take the least significant bit as a flag.1419uint64_t Flag = Flags & -Flags;1420Flags -= Flag;1421
1422// Find the flag in the known flags list.1423auto I = llvm::find_if(FlagsList, [=](const EnumEntry<unsigned> &E) {1424// Flags with empty names are not printed in GNU style output.1425return E.Value == Flag && !E.AltName.empty();1426});1427if (I != FlagsList.end()) {1428Str += I->AltName;1429continue;1430}1431
1432// If we did not find a matching regular flag, then we deal with an OS1433// specific flag, processor specific flag or an unknown flag.1434if (Flag & ELF::SHF_MASKOS) {1435HasOSFlag = true;1436Flags &= ~ELF::SHF_MASKOS;1437} else if (Flag & ELF::SHF_MASKPROC) {1438HasProcFlag = true;1439// Mask off all the processor-specific bits. This removes the SHF_EXCLUDE1440// bit if set so that it doesn't also get printed.1441Flags &= ~ELF::SHF_MASKPROC;1442} else {1443HasUnknownFlag = true;1444}1445}1446
1447// "o", "p" and "x" are printed last.1448if (HasOSFlag)1449Str += "o";1450if (HasProcFlag)1451Str += "p";1452if (HasUnknownFlag)1453Str += "x";1454return Str;1455}
1456
1457static StringRef segmentTypeToString(unsigned Arch, unsigned Type) {1458// Check potentially overlapped processor-specific program header type.1459switch (Arch) {1460case ELF::EM_ARM:1461switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); }1462break;1463case ELF::EM_MIPS:1464case ELF::EM_MIPS_RS3_LE:1465switch (Type) {1466LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);1467LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);1468LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);1469LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS);1470}1471break;1472case ELF::EM_RISCV:1473switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_RISCV_ATTRIBUTES); }1474}1475
1476switch (Type) {1477LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL);1478LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD);1479LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC);1480LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP);1481LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE);1482LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB);1483LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR);1484LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS);1485
1486LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME);1487LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND);1488
1489LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK);1490LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);1491LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY);1492
1493LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);1494LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);1495LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);1496LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI);1497LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS);1498LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);1499default:1500return "";1501}1502}
1503
1504static std::string getGNUPtType(unsigned Arch, unsigned Type) {1505StringRef Seg = segmentTypeToString(Arch, Type);1506if (Seg.empty())1507return std::string("<unknown>: ") + to_string(format_hex(Type, 1));1508
1509// E.g. "PT_ARM_EXIDX" -> "EXIDX".1510if (Seg.consume_front("PT_ARM_"))1511return Seg.str();1512
1513// E.g. "PT_MIPS_REGINFO" -> "REGINFO".1514if (Seg.consume_front("PT_MIPS_"))1515return Seg.str();1516
1517// E.g. "PT_RISCV_ATTRIBUTES"1518if (Seg.consume_front("PT_RISCV_"))1519return Seg.str();1520
1521// E.g. "PT_LOAD" -> "LOAD".1522assert(Seg.starts_with("PT_"));1523return Seg.drop_front(3).str();1524}
1525
1526const EnumEntry<unsigned> ElfSegmentFlags[] = {1527LLVM_READOBJ_ENUM_ENT(ELF, PF_X),1528LLVM_READOBJ_ENUM_ENT(ELF, PF_W),1529LLVM_READOBJ_ENUM_ENT(ELF, PF_R)1530};1531
1532const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {1533ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"),1534ENUM_ENT(EF_MIPS_PIC, "pic"),1535ENUM_ENT(EF_MIPS_CPIC, "cpic"),1536ENUM_ENT(EF_MIPS_ABI2, "abi2"),1537ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"),1538ENUM_ENT(EF_MIPS_FP64, "fp64"),1539ENUM_ENT(EF_MIPS_NAN2008, "nan2008"),1540ENUM_ENT(EF_MIPS_ABI_O32, "o32"),1541ENUM_ENT(EF_MIPS_ABI_O64, "o64"),1542ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"),1543ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"),1544ENUM_ENT(EF_MIPS_MACH_3900, "3900"),1545ENUM_ENT(EF_MIPS_MACH_4010, "4010"),1546ENUM_ENT(EF_MIPS_MACH_4100, "4100"),1547ENUM_ENT(EF_MIPS_MACH_4650, "4650"),1548ENUM_ENT(EF_MIPS_MACH_4120, "4120"),1549ENUM_ENT(EF_MIPS_MACH_4111, "4111"),1550ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"),1551ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"),1552ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"),1553ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"),1554ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"),1555ENUM_ENT(EF_MIPS_MACH_5400, "5400"),1556ENUM_ENT(EF_MIPS_MACH_5900, "5900"),1557ENUM_ENT(EF_MIPS_MACH_5500, "5500"),1558ENUM_ENT(EF_MIPS_MACH_9000, "9000"),1559ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"),1560ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"),1561ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"),1562ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"),1563ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"),1564ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"),1565ENUM_ENT(EF_MIPS_ARCH_1, "mips1"),1566ENUM_ENT(EF_MIPS_ARCH_2, "mips2"),1567ENUM_ENT(EF_MIPS_ARCH_3, "mips3"),1568ENUM_ENT(EF_MIPS_ARCH_4, "mips4"),1569ENUM_ENT(EF_MIPS_ARCH_5, "mips5"),1570ENUM_ENT(EF_MIPS_ARCH_32, "mips32"),1571ENUM_ENT(EF_MIPS_ARCH_64, "mips64"),1572ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"),1573ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"),1574ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"),1575ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6")1576};1577
1578// clang-format off
1579#define AMDGPU_MACH_ENUM_ENTS \1580ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"), \1581ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"), \1582ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"), \1583ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"), \1584ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"), \1585ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"), \1586ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"), \1587ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"), \1588ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"), \1589ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"), \1590ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"), \1591ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"), \1592ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"), \1593ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"), \1594ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"), \1595ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"), \1596ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"), \1597ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"), \1598ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"), \1599ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"), \1600ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"), \1601ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"), \1602ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"), \1603ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"), \1604ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"), \1605ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"), \1606ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"), \1607ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"), \1608ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"), \1609ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"), \1610ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"), \1611ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"), \1612ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"), \1613ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"), \1614ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"), \1615ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"), \1616ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"), \1617ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"), \1618ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"), \1619ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"), \1620ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"), \1621ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"), \1622ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"), \1623ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"), \1624ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"), \1625ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"), \1626ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"), \1627ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"), \1628ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"), \1629ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"), \1630ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"), \1631ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"), \1632ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"), \1633ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"), \1634ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"), \1635ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"), \1636ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"), \1637ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"), \1638ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"), \1639ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1152, "gfx1152"), \1640ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"), \1641ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"), \1642ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC, "gfx9-generic"), \1643ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC, "gfx10-1-generic"), \1644ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC, "gfx10-3-generic"), \1645ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC, "gfx11-generic"), \1646ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC, "gfx12-generic")1647// clang-format on
1648
1649const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {1650AMDGPU_MACH_ENUM_ENTS,1651ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_V3, "xnack"),1652ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_V3, "sramecc"),1653};1654
1655const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {1656AMDGPU_MACH_ENUM_ENTS,1657ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ANY_V4, "xnack"),1658ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_OFF_V4, "xnack-"),1659ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ON_V4, "xnack+"),1660ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ANY_V4, "sramecc"),1661ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_OFF_V4, "sramecc-"),1662ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ON_V4, "sramecc+"),1663};1664
1665const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = {1666ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),1667ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),1668ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),1669ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),1670ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),1671ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),1672ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),1673ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),1674ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),1675ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),1676};1677
1678const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {1679ENUM_ENT(EF_RISCV_RVC, "RVC"),1680ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"),1681ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"),1682ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"),1683ENUM_ENT(EF_RISCV_RVE, "RVE"),1684ENUM_ENT(EF_RISCV_TSO, "TSO"),1685};1686
1687const EnumEntry<unsigned> ElfHeaderAVRFlags[] = {1688LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1),1689LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2),1690LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25),1691LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3),1692LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31),1693LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35),1694LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4),1695LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5),1696LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51),1697LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6),1698LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY),1699LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1),1700LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2),1701LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3),1702LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4),1703LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5),1704LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6),1705LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7),1706ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"),1707};1708
1709const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = {1710ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"),1711ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"),1712ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"),1713ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"),1714ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"),1715};1716
1717static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = {1718LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE),1719LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN),1720LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT)1721};1722
1723const EnumEntry<unsigned> ElfSymOtherFlags[] = {1724LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),1725LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),1726LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED)1727};1728
1729const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = {1730LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),1731LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),1732LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC),1733LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS)1734};1735
1736const EnumEntry<unsigned> ElfAArch64SymOtherFlags[] = {1737LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS)1738};1739
1740const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = {1741LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),1742LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),1743LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16)1744};1745
1746const EnumEntry<unsigned> ElfRISCVSymOtherFlags[] = {1747LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)};1748
1749static const char *getElfMipsOptionsOdkType(unsigned Odk) {1750switch (Odk) {1751LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL);1752LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO);1753LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS);1754LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD);1755LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH);1756LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL);1757LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS);1758LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND);1759LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR);1760LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP);1761LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT);1762LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE);1763default:1764return "Unknown";1765}1766}
1767
1768template <typename ELFT>1769std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *>1770ELFDumper<ELFT>::findDynamic() {1771// Try to locate the PT_DYNAMIC header.1772const Elf_Phdr *DynamicPhdr = nullptr;1773if (Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = Obj.program_headers()) {1774for (const Elf_Phdr &Phdr : *PhdrsOrErr) {1775if (Phdr.p_type != ELF::PT_DYNAMIC)1776continue;1777DynamicPhdr = &Phdr;1778break;1779}1780} else {1781reportUniqueWarning(1782"unable to read program headers to locate the PT_DYNAMIC segment: " +1783toString(PhdrsOrErr.takeError()));1784}1785
1786// Try to locate the .dynamic section in the sections header table.1787const Elf_Shdr *DynamicSec = nullptr;1788for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {1789if (Sec.sh_type != ELF::SHT_DYNAMIC)1790continue;1791DynamicSec = &Sec;1792break;1793}1794
1795if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz >1796ObjF.getMemoryBufferRef().getBufferSize()) ||1797(DynamicPhdr->p_offset + DynamicPhdr->p_filesz <1798DynamicPhdr->p_offset))) {1799reportUniqueWarning(1800"PT_DYNAMIC segment offset (0x" +1801Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" +1802Twine::utohexstr(DynamicPhdr->p_filesz) +1803") exceeds the size of the file (0x" +1804Twine::utohexstr(ObjF.getMemoryBufferRef().getBufferSize()) + ")");1805// Don't use the broken dynamic header.1806DynamicPhdr = nullptr;1807}1808
1809if (DynamicPhdr && DynamicSec) {1810if (DynamicSec->sh_addr + DynamicSec->sh_size >1811DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||1812DynamicSec->sh_addr < DynamicPhdr->p_vaddr)1813reportUniqueWarning(describe(*DynamicSec) +1814" is not contained within the "1815"PT_DYNAMIC segment");1816
1817if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)1818reportUniqueWarning(describe(*DynamicSec) + " is not at the start of "1819"PT_DYNAMIC segment");1820}1821
1822return std::make_pair(DynamicPhdr, DynamicSec);1823}
1824
1825template <typename ELFT>1826void ELFDumper<ELFT>::loadDynamicTable() {1827const Elf_Phdr *DynamicPhdr;1828const Elf_Shdr *DynamicSec;1829std::tie(DynamicPhdr, DynamicSec) = findDynamic();1830if (!DynamicPhdr && !DynamicSec)1831return;1832
1833DynRegionInfo FromPhdr(ObjF, *this);1834bool IsPhdrTableValid = false;1835if (DynamicPhdr) {1836// Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are1837// validated in findDynamic() and so createDRI() is not expected to fail.1838FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz,1839sizeof(Elf_Dyn)));1840FromPhdr.SizePrintName = "PT_DYNAMIC size";1841FromPhdr.EntSizePrintName = "";1842IsPhdrTableValid = !FromPhdr.template getAsArrayRef<Elf_Dyn>().empty();1843}1844
1845// Locate the dynamic table described in a section header.1846// Ignore sh_entsize and use the expected value for entry size explicitly.1847// This allows us to dump dynamic sections with a broken sh_entsize1848// field.1849DynRegionInfo FromSec(ObjF, *this);1850bool IsSecTableValid = false;1851if (DynamicSec) {1852Expected<DynRegionInfo> RegOrErr =1853createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn));1854if (RegOrErr) {1855FromSec = *RegOrErr;1856FromSec.Context = describe(*DynamicSec);1857FromSec.EntSizePrintName = "";1858IsSecTableValid = !FromSec.template getAsArrayRef<Elf_Dyn>().empty();1859} else {1860reportUniqueWarning("unable to read the dynamic table from " +1861describe(*DynamicSec) + ": " +1862toString(RegOrErr.takeError()));1863}1864}1865
1866// When we only have information from one of the SHT_DYNAMIC section header or1867// PT_DYNAMIC program header, just use that.1868if (!DynamicPhdr || !DynamicSec) {1869if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) {1870DynamicTable = DynamicPhdr ? FromPhdr : FromSec;1871parseDynamicTable();1872} else {1873reportUniqueWarning("no valid dynamic table was found");1874}1875return;1876}1877
1878// At this point we have tables found from the section header and from the1879// dynamic segment. Usually they match, but we have to do sanity checks to1880// verify that.1881
1882if (FromPhdr.Addr != FromSec.Addr)1883reportUniqueWarning("SHT_DYNAMIC section header and PT_DYNAMIC "1884"program header disagree about "1885"the location of the dynamic table");1886
1887if (!IsPhdrTableValid && !IsSecTableValid) {1888reportUniqueWarning("no valid dynamic table was found");1889return;1890}1891
1892// Information in the PT_DYNAMIC program header has priority over the1893// information in a section header.1894if (IsPhdrTableValid) {1895if (!IsSecTableValid)1896reportUniqueWarning(1897"SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used");1898DynamicTable = FromPhdr;1899} else {1900reportUniqueWarning(1901"PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used");1902DynamicTable = FromSec;1903}1904
1905parseDynamicTable();1906}
1907
1908template <typename ELFT>1909ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,1910ScopedPrinter &Writer)1911: ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()),1912FileName(O.getFileName()), DynRelRegion(O, *this),1913DynRelaRegion(O, *this), DynCrelRegion(O, *this), DynRelrRegion(O, *this),1914DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this),1915DynamicTable(O, *this) {1916if (!O.IsContentValid())1917return;1918
1919typename ELFT::ShdrRange Sections = cantFail(Obj.sections());1920for (const Elf_Shdr &Sec : Sections) {1921switch (Sec.sh_type) {1922case ELF::SHT_SYMTAB:1923if (!DotSymtabSec)1924DotSymtabSec = &Sec;1925break;1926case ELF::SHT_DYNSYM:1927if (!DotDynsymSec)1928DotDynsymSec = &Sec;1929
1930if (!DynSymRegion) {1931Expected<DynRegionInfo> RegOrErr =1932createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize);1933if (RegOrErr) {1934DynSymRegion = *RegOrErr;1935DynSymRegion->Context = describe(Sec);1936
1937if (Expected<StringRef> E = Obj.getStringTableForSymtab(Sec))1938DynamicStringTable = *E;1939else1940reportUniqueWarning("unable to get the string table for the " +1941describe(Sec) + ": " + toString(E.takeError()));1942} else {1943reportUniqueWarning("unable to read dynamic symbols from " +1944describe(Sec) + ": " +1945toString(RegOrErr.takeError()));1946}1947}1948break;1949case ELF::SHT_SYMTAB_SHNDX: {1950uint32_t SymtabNdx = Sec.sh_link;1951if (SymtabNdx >= Sections.size()) {1952reportUniqueWarning(1953"unable to get the associated symbol table for " + describe(Sec) +1954": sh_link (" + Twine(SymtabNdx) +1955") is greater than or equal to the total number of sections (" +1956Twine(Sections.size()) + ")");1957continue;1958}1959
1960if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =1961Obj.getSHNDXTable(Sec)) {1962if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr})1963.second)1964reportUniqueWarning(1965"multiple SHT_SYMTAB_SHNDX sections are linked to " +1966describe(Sec));1967} else {1968reportUniqueWarning(ShndxTableOrErr.takeError());1969}1970break;1971}1972case ELF::SHT_GNU_versym:1973if (!SymbolVersionSection)1974SymbolVersionSection = &Sec;1975break;1976case ELF::SHT_GNU_verdef:1977if (!SymbolVersionDefSection)1978SymbolVersionDefSection = &Sec;1979break;1980case ELF::SHT_GNU_verneed:1981if (!SymbolVersionNeedSection)1982SymbolVersionNeedSection = &Sec;1983break;1984case ELF::SHT_LLVM_ADDRSIG:1985if (!DotAddrsigSec)1986DotAddrsigSec = &Sec;1987break;1988}1989}1990
1991loadDynamicTable();1992}
1993
1994template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {1995auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {1996auto MappedAddrOrError = Obj.toMappedAddr(VAddr, [&](const Twine &Msg) {1997this->reportUniqueWarning(Msg);1998return Error::success();1999});2000if (!MappedAddrOrError) {2001this->reportUniqueWarning("unable to parse DT_" +2002Obj.getDynamicTagAsString(Tag) + ": " +2003llvm::toString(MappedAddrOrError.takeError()));2004return nullptr;2005}2006return MappedAddrOrError.get();2007};2008
2009const char *StringTableBegin = nullptr;2010uint64_t StringTableSize = 0;2011std::optional<DynRegionInfo> DynSymFromTable;2012for (const Elf_Dyn &Dyn : dynamic_table()) {2013if (Obj.getHeader().e_machine == EM_AARCH64) {2014switch (Dyn.d_tag) {2015case ELF::DT_AARCH64_AUTH_RELRSZ:2016DynRelrRegion.Size = Dyn.getVal();2017DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";2018continue;2019case ELF::DT_AARCH64_AUTH_RELRENT:2020DynRelrRegion.EntSize = Dyn.getVal();2021DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";2022continue;2023}2024}2025switch (Dyn.d_tag) {2026case ELF::DT_HASH:2027HashTable = reinterpret_cast<const Elf_Hash *>(2028toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2029break;2030case ELF::DT_GNU_HASH:2031GnuHashTable = reinterpret_cast<const Elf_GnuHash *>(2032toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2033break;2034case ELF::DT_STRTAB:2035StringTableBegin = reinterpret_cast<const char *>(2036toMappedAddr(Dyn.getTag(), Dyn.getPtr()));2037break;2038case ELF::DT_STRSZ:2039StringTableSize = Dyn.getVal();2040break;2041case ELF::DT_SYMTAB: {2042// If we can't map the DT_SYMTAB value to an address (e.g. when there are2043// no program headers), we ignore its value.2044if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) {2045DynSymFromTable.emplace(ObjF, *this);2046DynSymFromTable->Addr = VA;2047DynSymFromTable->EntSize = sizeof(Elf_Sym);2048DynSymFromTable->EntSizePrintName = "";2049}2050break;2051}2052case ELF::DT_SYMENT: {2053uint64_t Val = Dyn.getVal();2054if (Val != sizeof(Elf_Sym))2055this->reportUniqueWarning("DT_SYMENT value of 0x" +2056Twine::utohexstr(Val) +2057" is not the size of a symbol (0x" +2058Twine::utohexstr(sizeof(Elf_Sym)) + ")");2059break;2060}2061case ELF::DT_RELA:2062DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2063break;2064case ELF::DT_RELASZ:2065DynRelaRegion.Size = Dyn.getVal();2066DynRelaRegion.SizePrintName = "DT_RELASZ value";2067break;2068case ELF::DT_RELAENT:2069DynRelaRegion.EntSize = Dyn.getVal();2070DynRelaRegion.EntSizePrintName = "DT_RELAENT value";2071break;2072case ELF::DT_CREL:2073DynCrelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2074break;2075case ELF::DT_SONAME:2076SONameOffset = Dyn.getVal();2077break;2078case ELF::DT_REL:2079DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2080break;2081case ELF::DT_RELSZ:2082DynRelRegion.Size = Dyn.getVal();2083DynRelRegion.SizePrintName = "DT_RELSZ value";2084break;2085case ELF::DT_RELENT:2086DynRelRegion.EntSize = Dyn.getVal();2087DynRelRegion.EntSizePrintName = "DT_RELENT value";2088break;2089case ELF::DT_RELR:2090case ELF::DT_ANDROID_RELR:2091case ELF::DT_AARCH64_AUTH_RELR:2092DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2093break;2094case ELF::DT_RELRSZ:2095case ELF::DT_ANDROID_RELRSZ:2096case ELF::DT_AARCH64_AUTH_RELRSZ:2097DynRelrRegion.Size = Dyn.getVal();2098DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ2099? "DT_RELRSZ value"2100: "DT_ANDROID_RELRSZ value";2101break;2102case ELF::DT_RELRENT:2103case ELF::DT_ANDROID_RELRENT:2104case ELF::DT_AARCH64_AUTH_RELRENT:2105DynRelrRegion.EntSize = Dyn.getVal();2106DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT2107? "DT_RELRENT value"2108: "DT_ANDROID_RELRENT value";2109break;2110case ELF::DT_PLTREL:2111if (Dyn.getVal() == DT_REL)2112DynPLTRelRegion.EntSize = sizeof(Elf_Rel);2113else if (Dyn.getVal() == DT_RELA)2114DynPLTRelRegion.EntSize = sizeof(Elf_Rela);2115else if (Dyn.getVal() == DT_CREL)2116DynPLTRelRegion.EntSize = 1;2117else2118reportUniqueWarning(Twine("unknown DT_PLTREL value of ") +2119Twine((uint64_t)Dyn.getVal()));2120DynPLTRelRegion.EntSizePrintName = "PLTREL entry size";2121break;2122case ELF::DT_JMPREL:2123DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2124break;2125case ELF::DT_PLTRELSZ:2126DynPLTRelRegion.Size = Dyn.getVal();2127DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value";2128break;2129case ELF::DT_SYMTAB_SHNDX:2130DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());2131DynSymTabShndxRegion.EntSize = sizeof(Elf_Word);2132break;2133}2134}2135
2136if (StringTableBegin) {2137const uint64_t FileSize = Obj.getBufSize();2138const uint64_t Offset = (const uint8_t *)StringTableBegin - Obj.base();2139if (StringTableSize > FileSize - Offset)2140reportUniqueWarning(2141"the dynamic string table at 0x" + Twine::utohexstr(Offset) +2142" goes past the end of the file (0x" + Twine::utohexstr(FileSize) +2143") with DT_STRSZ = 0x" + Twine::utohexstr(StringTableSize));2144else2145DynamicStringTable = StringRef(StringTableBegin, StringTableSize);2146}2147
2148const bool IsHashTableSupported = getHashTableEntSize() == 4;2149if (DynSymRegion) {2150// Often we find the information about the dynamic symbol table2151// location in the SHT_DYNSYM section header. However, the value in2152// DT_SYMTAB has priority, because it is used by dynamic loaders to2153// locate .dynsym at runtime. The location we find in the section header2154// and the location we find here should match.2155if (DynSymFromTable && DynSymFromTable->Addr != DynSymRegion->Addr)2156reportUniqueWarning(2157createError("SHT_DYNSYM section header and DT_SYMTAB disagree about "2158"the location of the dynamic symbol table"));2159
2160// According to the ELF gABI: "The number of symbol table entries should2161// equal nchain". Check to see if the DT_HASH hash table nchain value2162// conflicts with the number of symbols in the dynamic symbol table2163// according to the section header.2164if (HashTable && IsHashTableSupported) {2165if (DynSymRegion->EntSize == 0)2166reportUniqueWarning("SHT_DYNSYM section has sh_entsize == 0");2167else if (HashTable->nchain != DynSymRegion->Size / DynSymRegion->EntSize)2168reportUniqueWarning(2169"hash table nchain (" + Twine(HashTable->nchain) +2170") differs from symbol count derived from SHT_DYNSYM section "2171"header (" +2172Twine(DynSymRegion->Size / DynSymRegion->EntSize) + ")");2173}2174}2175
2176// Delay the creation of the actual dynamic symbol table until now, so that2177// checks can always be made against the section header-based properties,2178// without worrying about tag order.2179if (DynSymFromTable) {2180if (!DynSymRegion) {2181DynSymRegion = DynSymFromTable;2182} else {2183DynSymRegion->Addr = DynSymFromTable->Addr;2184DynSymRegion->EntSize = DynSymFromTable->EntSize;2185DynSymRegion->EntSizePrintName = DynSymFromTable->EntSizePrintName;2186}2187}2188
2189// Derive the dynamic symbol table size from the DT_HASH hash table, if2190// present.2191if (HashTable && IsHashTableSupported && DynSymRegion) {2192const uint64_t FileSize = Obj.getBufSize();2193const uint64_t DerivedSize =2194(uint64_t)HashTable->nchain * DynSymRegion->EntSize;2195const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base();2196if (DerivedSize > FileSize - Offset)2197reportUniqueWarning(2198"the size (0x" + Twine::utohexstr(DerivedSize) +2199") of the dynamic symbol table at 0x" + Twine::utohexstr(Offset) +2200", derived from the hash table, goes past the end of the file (0x" +2201Twine::utohexstr(FileSize) + ") and will be ignored");2202else2203DynSymRegion->Size = HashTable->nchain * DynSymRegion->EntSize;2204}2205}
2206
2207template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {2208// Dump version symbol section.2209printVersionSymbolSection(SymbolVersionSection);2210
2211// Dump version definition section.2212printVersionDefinitionSection(SymbolVersionDefSection);2213
2214// Dump version dependency section.2215printVersionDependencySection(SymbolVersionNeedSection);2216}
2217
2218#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \2219{ #enum, prefix##_##enum }2220
2221const EnumEntry<unsigned> ElfDynamicDTFlags[] = {2222LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),2223LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),2224LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),2225LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),2226LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)2227};2228
2229const EnumEntry<unsigned> ElfDynamicDTFlags1[] = {2230LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW),2231LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL),2232LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP),2233LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE),2234LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR),2235LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST),2236LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN),2237LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN),2238LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT),2239LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS),2240LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE),2241LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB),2242LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP),2243LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT),2244LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE),2245LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE),2246LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND),2247LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT),2248LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF),2249LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS),2250LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR),2251LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED),2252LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC),2253LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE),2254LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT),2255LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON),2256LLVM_READOBJ_DT_FLAG_ENT(DF_1, PIE),2257};2258
2259const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {2260LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),2261LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),2262LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),2263LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),2264LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),2265LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),2266LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),2267LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),2268LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),2269LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),2270LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),2271LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),2272LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),2273LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),2274LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),2275LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)2276};2277
2278#undef LLVM_READOBJ_DT_FLAG_ENT2279
2280template <typename T, typename TFlag>2281void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {2282SmallVector<EnumEntry<TFlag>, 10> SetFlags;2283for (const EnumEntry<TFlag> &Flag : Flags)2284if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)2285SetFlags.push_back(Flag);2286
2287for (const EnumEntry<TFlag> &Flag : SetFlags)2288OS << Flag.Name << " ";2289}
2290
2291template <class ELFT>2292const typename ELFT::Shdr *2293ELFDumper<ELFT>::findSectionByName(StringRef Name) const {2294for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {2295if (Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr)) {2296if (*NameOrErr == Name)2297return &Shdr;2298} else {2299reportUniqueWarning("unable to read the name of " + describe(Shdr) +2300": " + toString(NameOrErr.takeError()));2301}2302}2303return nullptr;2304}
2305
2306template <class ELFT>2307std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,2308uint64_t Value) const {2309auto FormatHexValue = [](uint64_t V) {2310std::string Str;2311raw_string_ostream OS(Str);2312const char *ConvChar =2313(opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;2314OS << format(ConvChar, V);2315return OS.str();2316};2317
2318auto FormatFlags = [](uint64_t V,2319llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) {2320std::string Str;2321raw_string_ostream OS(Str);2322printFlags(V, Array, OS);2323return OS.str();2324};2325
2326// Handle custom printing of architecture specific tags2327switch (Obj.getHeader().e_machine) {2328case EM_AARCH64:2329switch (Type) {2330case DT_AARCH64_BTI_PLT:2331case DT_AARCH64_PAC_PLT:2332case DT_AARCH64_VARIANT_PCS:2333case DT_AARCH64_MEMTAG_GLOBALSSZ:2334return std::to_string(Value);2335case DT_AARCH64_MEMTAG_MODE:2336switch (Value) {2337case 0:2338return "Synchronous (0)";2339case 1:2340return "Asynchronous (1)";2341default:2342return (Twine("Unknown (") + Twine(Value) + ")").str();2343}2344case DT_AARCH64_MEMTAG_HEAP:2345case DT_AARCH64_MEMTAG_STACK:2346switch (Value) {2347case 0:2348return "Disabled (0)";2349case 1:2350return "Enabled (1)";2351default:2352return (Twine("Unknown (") + Twine(Value) + ")").str();2353}2354case DT_AARCH64_MEMTAG_GLOBALS:2355return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str();2356default:2357break;2358}2359break;2360case EM_HEXAGON:2361switch (Type) {2362case DT_HEXAGON_VER:2363return std::to_string(Value);2364case DT_HEXAGON_SYMSZ:2365case DT_HEXAGON_PLT:2366return FormatHexValue(Value);2367default:2368break;2369}2370break;2371case EM_MIPS:2372switch (Type) {2373case DT_MIPS_RLD_VERSION:2374case DT_MIPS_LOCAL_GOTNO:2375case DT_MIPS_SYMTABNO:2376case DT_MIPS_UNREFEXTNO:2377return std::to_string(Value);2378case DT_MIPS_TIME_STAMP:2379case DT_MIPS_ICHECKSUM:2380case DT_MIPS_IVERSION:2381case DT_MIPS_BASE_ADDRESS:2382case DT_MIPS_MSYM:2383case DT_MIPS_CONFLICT:2384case DT_MIPS_LIBLIST:2385case DT_MIPS_CONFLICTNO:2386case DT_MIPS_LIBLISTNO:2387case DT_MIPS_GOTSYM:2388case DT_MIPS_HIPAGENO:2389case DT_MIPS_RLD_MAP:2390case DT_MIPS_DELTA_CLASS:2391case DT_MIPS_DELTA_CLASS_NO:2392case DT_MIPS_DELTA_INSTANCE:2393case DT_MIPS_DELTA_RELOC:2394case DT_MIPS_DELTA_RELOC_NO:2395case DT_MIPS_DELTA_SYM:2396case DT_MIPS_DELTA_SYM_NO:2397case DT_MIPS_DELTA_CLASSSYM:2398case DT_MIPS_DELTA_CLASSSYM_NO:2399case DT_MIPS_CXX_FLAGS:2400case DT_MIPS_PIXIE_INIT:2401case DT_MIPS_SYMBOL_LIB:2402case DT_MIPS_LOCALPAGE_GOTIDX:2403case DT_MIPS_LOCAL_GOTIDX:2404case DT_MIPS_HIDDEN_GOTIDX:2405case DT_MIPS_PROTECTED_GOTIDX:2406case DT_MIPS_OPTIONS:2407case DT_MIPS_INTERFACE:2408case DT_MIPS_DYNSTR_ALIGN:2409case DT_MIPS_INTERFACE_SIZE:2410case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:2411case DT_MIPS_PERF_SUFFIX:2412case DT_MIPS_COMPACT_SIZE:2413case DT_MIPS_GP_VALUE:2414case DT_MIPS_AUX_DYNAMIC:2415case DT_MIPS_PLTGOT:2416case DT_MIPS_RWPLT:2417case DT_MIPS_RLD_MAP_REL:2418case DT_MIPS_XHASH:2419return FormatHexValue(Value);2420case DT_MIPS_FLAGS:2421return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags));2422default:2423break;2424}2425break;2426default:2427break;2428}2429
2430switch (Type) {2431case DT_PLTREL:2432if (Value == DT_REL)2433return "REL";2434if (Value == DT_RELA)2435return "RELA";2436if (Value == DT_CREL)2437return "CREL";2438[[fallthrough]];2439case DT_PLTGOT:2440case DT_HASH:2441case DT_STRTAB:2442case DT_SYMTAB:2443case DT_RELA:2444case DT_INIT:2445case DT_FINI:2446case DT_REL:2447case DT_JMPREL:2448case DT_INIT_ARRAY:2449case DT_FINI_ARRAY:2450case DT_PREINIT_ARRAY:2451case DT_DEBUG:2452case DT_CREL:2453case DT_VERDEF:2454case DT_VERNEED:2455case DT_VERSYM:2456case DT_GNU_HASH:2457case DT_NULL:2458return FormatHexValue(Value);2459case DT_RELACOUNT:2460case DT_RELCOUNT:2461case DT_VERDEFNUM:2462case DT_VERNEEDNUM:2463return std::to_string(Value);2464case DT_PLTRELSZ:2465case DT_RELASZ:2466case DT_RELAENT:2467case DT_STRSZ:2468case DT_SYMENT:2469case DT_RELSZ:2470case DT_RELENT:2471case DT_INIT_ARRAYSZ:2472case DT_FINI_ARRAYSZ:2473case DT_PREINIT_ARRAYSZ:2474case DT_RELRSZ:2475case DT_RELRENT:2476case DT_AARCH64_AUTH_RELRSZ:2477case DT_AARCH64_AUTH_RELRENT:2478case DT_ANDROID_RELSZ:2479case DT_ANDROID_RELASZ:2480return std::to_string(Value) + " (bytes)";2481case DT_NEEDED:2482case DT_SONAME:2483case DT_AUXILIARY:2484case DT_USED:2485case DT_FILTER:2486case DT_RPATH:2487case DT_RUNPATH: {2488const std::map<uint64_t, const char *> TagNames = {2489{DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"},2490{DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"},2491{DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"},2492{DT_RUNPATH, "Library runpath"},2493};2494
2495return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]")2496.str();2497}2498case DT_FLAGS:2499return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags));2500case DT_FLAGS_1:2501return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1));2502default:2503return FormatHexValue(Value);2504}2505}
2506
2507template <class ELFT>2508StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {2509if (DynamicStringTable.empty() && !DynamicStringTable.data()) {2510reportUniqueWarning("string table was not found");2511return "<?>";2512}2513
2514auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) {2515reportUniqueWarning("string table at offset 0x" + Twine::utohexstr(Offset) +2516Msg);2517return "<?>";2518};2519
2520const uint64_t FileSize = Obj.getBufSize();2521const uint64_t Offset =2522(const uint8_t *)DynamicStringTable.data() - Obj.base();2523if (DynamicStringTable.size() > FileSize - Offset)2524return WarnAndReturn(" with size 0x" +2525Twine::utohexstr(DynamicStringTable.size()) +2526" goes past the end of the file (0x" +2527Twine::utohexstr(FileSize) + ")",2528Offset);2529
2530if (Value >= DynamicStringTable.size())2531return WarnAndReturn(2532": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +2533": it goes past the end of the table (0x" +2534Twine::utohexstr(Offset + DynamicStringTable.size()) + ")",2535Offset);2536
2537if (DynamicStringTable.back() != '\0')2538return WarnAndReturn(": unable to read the string at 0x" +2539Twine::utohexstr(Offset + Value) +2540": the string table is not null-terminated",2541Offset);2542
2543return DynamicStringTable.data() + Value;2544}
2545
2546template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {2547DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF);2548Ctx.printUnwindInformation();2549}
2550
2551// The namespace is needed to fix the compilation with GCC older than 7.0+.
2552namespace {2553template <> void ELFDumper<ELF32LE>::printUnwindInfo() {2554if (Obj.getHeader().e_machine == EM_ARM) {2555ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF.getFileName(),2556DotSymtabSec);2557Ctx.PrintUnwindInformation();2558}2559DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF);2560Ctx.printUnwindInformation();2561}
2562} // namespace2563
2564template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {2565ListScope D(W, "NeededLibraries");2566
2567std::vector<StringRef> Libs;2568for (const auto &Entry : dynamic_table())2569if (Entry.d_tag == ELF::DT_NEEDED)2570Libs.push_back(getDynamicString(Entry.d_un.d_val));2571
2572llvm::sort(Libs);2573
2574for (StringRef L : Libs)2575W.printString(L);2576}
2577
2578template <class ELFT>2579static Error checkHashTable(const ELFDumper<ELFT> &Dumper,2580const typename ELFT::Hash *H,2581bool *IsHeaderValid = nullptr) {2582const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();2583const uint64_t SecOffset = (const uint8_t *)H - Obj.base();2584if (Dumper.getHashTableEntSize() == 8) {2585auto It = llvm::find_if(ElfMachineType, [&](const EnumEntry<unsigned> &E) {2586return E.Value == Obj.getHeader().e_machine;2587});2588if (IsHeaderValid)2589*IsHeaderValid = false;2590return createError("the hash table at 0x" + Twine::utohexstr(SecOffset) +2591" is not supported: it contains non-standard 8 "2592"byte entries on " +2593It->AltName + " platform");2594}2595
2596auto MakeError = [&](const Twine &Msg = "") {2597return createError("the hash table at offset 0x" +2598Twine::utohexstr(SecOffset) +2599" goes past the end of the file (0x" +2600Twine::utohexstr(Obj.getBufSize()) + ")" + Msg);2601};2602
2603// Each SHT_HASH section starts from two 32-bit fields: nbucket and nchain.2604const unsigned HeaderSize = 2 * sizeof(typename ELFT::Word);2605
2606if (IsHeaderValid)2607*IsHeaderValid = Obj.getBufSize() - SecOffset >= HeaderSize;2608
2609if (Obj.getBufSize() - SecOffset < HeaderSize)2610return MakeError();2611
2612if (Obj.getBufSize() - SecOffset - HeaderSize <2613((uint64_t)H->nbucket + H->nchain) * sizeof(typename ELFT::Word))2614return MakeError(", nbucket = " + Twine(H->nbucket) +2615", nchain = " + Twine(H->nchain));2616return Error::success();2617}
2618
2619template <class ELFT>2620static Error checkGNUHashTable(const ELFFile<ELFT> &Obj,2621const typename ELFT::GnuHash *GnuHashTable,2622bool *IsHeaderValid = nullptr) {2623const uint8_t *TableData = reinterpret_cast<const uint8_t *>(GnuHashTable);2624assert(TableData >= Obj.base() && TableData < Obj.base() + Obj.getBufSize() &&2625"GnuHashTable must always point to a location inside the file");2626
2627uint64_t TableOffset = TableData - Obj.base();2628if (IsHeaderValid)2629*IsHeaderValid = TableOffset + /*Header size:*/ 16 < Obj.getBufSize();2630if (TableOffset + 16 + (uint64_t)GnuHashTable->nbuckets * 4 +2631(uint64_t)GnuHashTable->maskwords * sizeof(typename ELFT::Off) >=2632Obj.getBufSize())2633return createError("unable to dump the SHT_GNU_HASH "2634"section at 0x" +2635Twine::utohexstr(TableOffset) +2636": it goes past the end of the file");2637return Error::success();2638}
2639
2640template <typename ELFT> void ELFDumper<ELFT>::printHashTable() {2641DictScope D(W, "HashTable");2642if (!HashTable)2643return;2644
2645bool IsHeaderValid;2646Error Err = checkHashTable(*this, HashTable, &IsHeaderValid);2647if (IsHeaderValid) {2648W.printNumber("Num Buckets", HashTable->nbucket);2649W.printNumber("Num Chains", HashTable->nchain);2650}2651
2652if (Err) {2653reportUniqueWarning(std::move(Err));2654return;2655}2656
2657W.printList("Buckets", HashTable->buckets());2658W.printList("Chains", HashTable->chains());2659}
2660
2661template <class ELFT>2662static Expected<ArrayRef<typename ELFT::Word>>2663getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion,2664const typename ELFT::GnuHash *GnuHashTable) {2665if (!DynSymRegion)2666return createError("no dynamic symbol table found");2667
2668ArrayRef<typename ELFT::Sym> DynSymTable =2669DynSymRegion->template getAsArrayRef<typename ELFT::Sym>();2670size_t NumSyms = DynSymTable.size();2671if (!NumSyms)2672return createError("the dynamic symbol table is empty");2673
2674if (GnuHashTable->symndx < NumSyms)2675return GnuHashTable->values(NumSyms);2676
2677// A normal empty GNU hash table section produced by linker might have2678// symndx set to the number of dynamic symbols + 1 (for the zero symbol)2679// and have dummy null values in the Bloom filter and in the buckets2680// vector (or no values at all). It happens because the value of symndx is not2681// important for dynamic loaders when the GNU hash table is empty. They just2682// skip the whole object during symbol lookup. In such cases, the symndx value2683// is irrelevant and we should not report a warning.2684ArrayRef<typename ELFT::Word> Buckets = GnuHashTable->buckets();2685if (!llvm::all_of(Buckets, [](typename ELFT::Word V) { return V == 0; }))2686return createError(2687"the first hashed symbol index (" + Twine(GnuHashTable->symndx) +2688") is greater than or equal to the number of dynamic symbols (" +2689Twine(NumSyms) + ")");2690// There is no way to represent an array of (dynamic symbols count - symndx)2691// length.2692return ArrayRef<typename ELFT::Word>();2693}
2694
2695template <typename ELFT>2696void ELFDumper<ELFT>::printGnuHashTable() {2697DictScope D(W, "GnuHashTable");2698if (!GnuHashTable)2699return;2700
2701bool IsHeaderValid;2702Error Err = checkGNUHashTable<ELFT>(Obj, GnuHashTable, &IsHeaderValid);2703if (IsHeaderValid) {2704W.printNumber("Num Buckets", GnuHashTable->nbuckets);2705W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);2706W.printNumber("Num Mask Words", GnuHashTable->maskwords);2707W.printNumber("Shift Count", GnuHashTable->shift2);2708}2709
2710if (Err) {2711reportUniqueWarning(std::move(Err));2712return;2713}2714
2715ArrayRef<typename ELFT::Off> BloomFilter = GnuHashTable->filter();2716W.printHexList("Bloom Filter", BloomFilter);2717
2718ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets();2719W.printList("Buckets", Buckets);2720
2721Expected<ArrayRef<Elf_Word>> Chains =2722getGnuHashTableChains<ELFT>(DynSymRegion, GnuHashTable);2723if (!Chains) {2724reportUniqueWarning("unable to dump 'Values' for the SHT_GNU_HASH "2725"section: " +2726toString(Chains.takeError()));2727return;2728}2729
2730W.printHexList("Values", *Chains);2731}
2732
2733template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() {2734// Print histogram for the .hash section.2735if (this->HashTable) {2736if (Error E = checkHashTable<ELFT>(*this, this->HashTable))2737this->reportUniqueWarning(std::move(E));2738else2739printHashHistogram(*this->HashTable);2740}2741
2742// Print histogram for the .gnu.hash section.2743if (this->GnuHashTable) {2744if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))2745this->reportUniqueWarning(std::move(E));2746else2747printGnuHashHistogram(*this->GnuHashTable);2748}2749}
2750
2751template <typename ELFT>2752void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const {2753size_t NBucket = HashTable.nbucket;2754size_t NChain = HashTable.nchain;2755ArrayRef<Elf_Word> Buckets = HashTable.buckets();2756ArrayRef<Elf_Word> Chains = HashTable.chains();2757size_t TotalSyms = 0;2758// If hash table is correct, we have at least chains with 0 length.2759size_t MaxChain = 1;2760
2761if (NChain == 0 || NBucket == 0)2762return;2763
2764std::vector<size_t> ChainLen(NBucket, 0);2765// Go over all buckets and note chain lengths of each bucket (total2766// unique chain lengths).2767for (size_t B = 0; B < NBucket; ++B) {2768BitVector Visited(NChain);2769for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {2770if (C == ELF::STN_UNDEF)2771break;2772if (Visited[C]) {2773this->reportUniqueWarning(2774".hash section is invalid: bucket " + Twine(C) +2775": a cycle was detected in the linked chain");2776break;2777}2778Visited[C] = true;2779if (MaxChain <= ++ChainLen[B])2780++MaxChain;2781}2782TotalSyms += ChainLen[B];2783}2784
2785if (!TotalSyms)2786return;2787
2788std::vector<size_t> Count(MaxChain, 0);2789// Count how long is the chain for each bucket.2790for (size_t B = 0; B < NBucket; B++)2791++Count[ChainLen[B]];2792// Print Number of buckets with each chain lengths and their cumulative2793// coverage of the symbols.2794printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false);2795}
2796
2797template <class ELFT>2798void ELFDumper<ELFT>::printGnuHashHistogram(2799const Elf_GnuHash &GnuHashTable) const {2800Expected<ArrayRef<Elf_Word>> ChainsOrErr =2801getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable);2802if (!ChainsOrErr) {2803this->reportUniqueWarning("unable to print the GNU hash table histogram: " +2804toString(ChainsOrErr.takeError()));2805return;2806}2807
2808ArrayRef<Elf_Word> Chains = *ChainsOrErr;2809size_t Symndx = GnuHashTable.symndx;2810size_t TotalSyms = 0;2811size_t MaxChain = 1;2812
2813size_t NBucket = GnuHashTable.nbuckets;2814if (Chains.empty() || NBucket == 0)2815return;2816
2817ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets();2818std::vector<size_t> ChainLen(NBucket, 0);2819for (size_t B = 0; B < NBucket; ++B) {2820if (!Buckets[B])2821continue;2822size_t Len = 1;2823for (size_t C = Buckets[B] - Symndx;2824C < Chains.size() && (Chains[C] & 1) == 0; ++C)2825if (MaxChain < ++Len)2826++MaxChain;2827ChainLen[B] = Len;2828TotalSyms += Len;2829}2830++MaxChain;2831
2832if (!TotalSyms)2833return;2834
2835std::vector<size_t> Count(MaxChain, 0);2836for (size_t B = 0; B < NBucket; ++B)2837++Count[ChainLen[B]];2838// Print Number of buckets with each chain lengths and their cumulative2839// coverage of the symbols.2840printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true);2841}
2842
2843template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {2844StringRef SOName = "<Not found>";2845if (SONameOffset)2846SOName = getDynamicString(*SONameOffset);2847W.printString("LoadName", SOName);2848}
2849
2850template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {2851switch (Obj.getHeader().e_machine) {2852case EM_HEXAGON:2853printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES,2854std::make_unique<HexagonAttributeParser>(&W),2855llvm::endianness::little);2856break;2857case EM_ARM:2858printAttributes(2859ELF::SHT_ARM_ATTRIBUTES, std::make_unique<ARMAttributeParser>(&W),2860Obj.isLE() ? llvm::endianness::little : llvm::endianness::big);2861break;2862case EM_RISCV:2863if (Obj.isLE())2864printAttributes(ELF::SHT_RISCV_ATTRIBUTES,2865std::make_unique<RISCVAttributeParser>(&W),2866llvm::endianness::little);2867else2868reportUniqueWarning("attribute printing not implemented for big-endian "2869"RISC-V objects");2870break;2871case EM_MSP430:2872printAttributes(ELF::SHT_MSP430_ATTRIBUTES,2873std::make_unique<MSP430AttributeParser>(&W),2874llvm::endianness::little);2875break;2876case EM_MIPS: {2877printMipsABIFlags();2878printMipsOptions();2879printMipsReginfo();2880MipsGOTParser<ELFT> Parser(*this);2881if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols()))2882reportUniqueWarning(std::move(E));2883else if (!Parser.isGotEmpty())2884printMipsGOT(Parser);2885
2886if (Error E = Parser.findPLT(dynamic_table()))2887reportUniqueWarning(std::move(E));2888else if (!Parser.isPltEmpty())2889printMipsPLT(Parser);2890break;2891}2892default:2893break;2894}2895}
2896
2897template <class ELFT>2898void ELFDumper<ELFT>::printAttributes(2899unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser,2900llvm::endianness Endianness) {2901assert((AttrShType != ELF::SHT_NULL) && AttrParser &&2902"Incomplete ELF attribute implementation");2903DictScope BA(W, "BuildAttributes");2904for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {2905if (Sec.sh_type != AttrShType)2906continue;2907
2908ArrayRef<uint8_t> Contents;2909if (Expected<ArrayRef<uint8_t>> ContentOrErr =2910Obj.getSectionContents(Sec)) {2911Contents = *ContentOrErr;2912if (Contents.empty()) {2913reportUniqueWarning("the " + describe(Sec) + " is empty");2914continue;2915}2916} else {2917reportUniqueWarning("unable to read the content of the " + describe(Sec) +2918": " + toString(ContentOrErr.takeError()));2919continue;2920}2921
2922W.printHex("FormatVersion", Contents[0]);2923
2924if (Error E = AttrParser->parse(Contents, Endianness))2925reportUniqueWarning("unable to dump attributes from the " +2926describe(Sec) + ": " + toString(std::move(E)));2927}2928}
2929
2930namespace {2931
2932template <class ELFT> class MipsGOTParser {2933public:2934LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)2935using Entry = typename ELFT::Addr;2936using Entries = ArrayRef<Entry>;2937
2938const bool IsStatic;2939const ELFFile<ELFT> &Obj;2940const ELFDumper<ELFT> &Dumper;2941
2942MipsGOTParser(const ELFDumper<ELFT> &D);2943Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);2944Error findPLT(Elf_Dyn_Range DynTable);2945
2946bool isGotEmpty() const { return GotEntries.empty(); }2947bool isPltEmpty() const { return PltEntries.empty(); }2948
2949uint64_t getGp() const;2950
2951const Entry *getGotLazyResolver() const;2952const Entry *getGotModulePointer() const;2953const Entry *getPltLazyResolver() const;2954const Entry *getPltModulePointer() const;2955
2956Entries getLocalEntries() const;2957Entries getGlobalEntries() const;2958Entries getOtherEntries() const;2959Entries getPltEntries() const;2960
2961uint64_t getGotAddress(const Entry * E) const;2962int64_t getGotOffset(const Entry * E) const;2963const Elf_Sym *getGotSym(const Entry *E) const;2964
2965uint64_t getPltAddress(const Entry * E) const;2966const Elf_Sym *getPltSym(const Entry *E) const;2967
2968StringRef getPltStrTable() const { return PltStrTable; }2969const Elf_Shdr *getPltSymTable() const { return PltSymTable; }2970
2971private:2972const Elf_Shdr *GotSec;2973size_t LocalNum;2974size_t GlobalNum;2975
2976const Elf_Shdr *PltSec;2977const Elf_Shdr *PltRelSec;2978const Elf_Shdr *PltSymTable;2979StringRef FileName;2980
2981Elf_Sym_Range GotDynSyms;2982StringRef PltStrTable;2983
2984Entries GotEntries;2985Entries PltEntries;2986};2987
2988} // end anonymous namespace2989
2990template <class ELFT>2991MipsGOTParser<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &D)2992: IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject().getELFFile()),2993Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr),2994PltRelSec(nullptr), PltSymTable(nullptr),2995FileName(D.getElfObject().getFileName()) {}2996
2997template <class ELFT>2998Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable,2999Elf_Sym_Range DynSyms) {3000// See "Global Offset Table" in Chapter 5 in the following document3001// for detailed GOT description.3002// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf3003
3004// Find static GOT secton.3005if (IsStatic) {3006GotSec = Dumper.findSectionByName(".got");3007if (!GotSec)3008return Error::success();3009
3010ArrayRef<uint8_t> Content =3011unwrapOrError(FileName, Obj.getSectionContents(*GotSec));3012GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),3013Content.size() / sizeof(Entry));3014LocalNum = GotEntries.size();3015return Error::success();3016}3017
3018// Lookup dynamic table tags which define the GOT layout.3019std::optional<uint64_t> DtPltGot;3020std::optional<uint64_t> DtLocalGotNum;3021std::optional<uint64_t> DtGotSym;3022for (const auto &Entry : DynTable) {3023switch (Entry.getTag()) {3024case ELF::DT_PLTGOT:3025DtPltGot = Entry.getVal();3026break;3027case ELF::DT_MIPS_LOCAL_GOTNO:3028DtLocalGotNum = Entry.getVal();3029break;3030case ELF::DT_MIPS_GOTSYM:3031DtGotSym = Entry.getVal();3032break;3033}3034}3035
3036if (!DtPltGot && !DtLocalGotNum && !DtGotSym)3037return Error::success();3038
3039if (!DtPltGot)3040return createError("cannot find PLTGOT dynamic tag");3041if (!DtLocalGotNum)3042return createError("cannot find MIPS_LOCAL_GOTNO dynamic tag");3043if (!DtGotSym)3044return createError("cannot find MIPS_GOTSYM dynamic tag");3045
3046size_t DynSymTotal = DynSyms.size();3047if (*DtGotSym > DynSymTotal)3048return createError("DT_MIPS_GOTSYM value (" + Twine(*DtGotSym) +3049") exceeds the number of dynamic symbols (" +3050Twine(DynSymTotal) + ")");3051
3052GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot);3053if (!GotSec)3054return createError("there is no non-empty GOT section at 0x" +3055Twine::utohexstr(*DtPltGot));3056
3057LocalNum = *DtLocalGotNum;3058GlobalNum = DynSymTotal - *DtGotSym;3059
3060ArrayRef<uint8_t> Content =3061unwrapOrError(FileName, Obj.getSectionContents(*GotSec));3062GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),3063Content.size() / sizeof(Entry));3064GotDynSyms = DynSyms.drop_front(*DtGotSym);3065
3066return Error::success();3067}
3068
3069template <class ELFT>3070Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) {3071// Lookup dynamic table tags which define the PLT layout.3072std::optional<uint64_t> DtMipsPltGot;3073std::optional<uint64_t> DtJmpRel;3074for (const auto &Entry : DynTable) {3075switch (Entry.getTag()) {3076case ELF::DT_MIPS_PLTGOT:3077DtMipsPltGot = Entry.getVal();3078break;3079case ELF::DT_JMPREL:3080DtJmpRel = Entry.getVal();3081break;3082}3083}3084
3085if (!DtMipsPltGot && !DtJmpRel)3086return Error::success();3087
3088// Find PLT section.3089if (!DtMipsPltGot)3090return createError("cannot find MIPS_PLTGOT dynamic tag");3091if (!DtJmpRel)3092return createError("cannot find JMPREL dynamic tag");3093
3094PltSec = findNotEmptySectionByAddress(Obj, FileName, *DtMipsPltGot);3095if (!PltSec)3096return createError("there is no non-empty PLTGOT section at 0x" +3097Twine::utohexstr(*DtMipsPltGot));3098
3099PltRelSec = findNotEmptySectionByAddress(Obj, FileName, *DtJmpRel);3100if (!PltRelSec)3101return createError("there is no non-empty RELPLT section at 0x" +3102Twine::utohexstr(*DtJmpRel));3103
3104if (Expected<ArrayRef<uint8_t>> PltContentOrErr =3105Obj.getSectionContents(*PltSec))3106PltEntries =3107Entries(reinterpret_cast<const Entry *>(PltContentOrErr->data()),3108PltContentOrErr->size() / sizeof(Entry));3109else3110return createError("unable to read PLTGOT section content: " +3111toString(PltContentOrErr.takeError()));3112
3113if (Expected<const Elf_Shdr *> PltSymTableOrErr =3114Obj.getSection(PltRelSec->sh_link))3115PltSymTable = *PltSymTableOrErr;3116else3117return createError("unable to get a symbol table linked to the " +3118describe(Obj, *PltRelSec) + ": " +3119toString(PltSymTableOrErr.takeError()));3120
3121if (Expected<StringRef> StrTabOrErr =3122Obj.getStringTableForSymtab(*PltSymTable))3123PltStrTable = *StrTabOrErr;3124else3125return createError("unable to get a string table for the " +3126describe(Obj, *PltSymTable) + ": " +3127toString(StrTabOrErr.takeError()));3128
3129return Error::success();3130}
3131
3132template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const {3133return GotSec->sh_addr + 0x7ff0;3134}
3135
3136template <class ELFT>3137const typename MipsGOTParser<ELFT>::Entry *3138MipsGOTParser<ELFT>::getGotLazyResolver() const {3139return LocalNum > 0 ? &GotEntries[0] : nullptr;3140}
3141
3142template <class ELFT>3143const typename MipsGOTParser<ELFT>::Entry *3144MipsGOTParser<ELFT>::getGotModulePointer() const {3145if (LocalNum < 2)3146return nullptr;3147const Entry &E = GotEntries[1];3148if ((E >> (sizeof(Entry) * 8 - 1)) == 0)3149return nullptr;3150return &E;3151}
3152
3153template <class ELFT>3154typename MipsGOTParser<ELFT>::Entries3155MipsGOTParser<ELFT>::getLocalEntries() const {3156size_t Skip = getGotModulePointer() ? 2 : 1;3157if (LocalNum - Skip <= 0)3158return Entries();3159return GotEntries.slice(Skip, LocalNum - Skip);3160}
3161
3162template <class ELFT>3163typename MipsGOTParser<ELFT>::Entries3164MipsGOTParser<ELFT>::getGlobalEntries() const {3165if (GlobalNum == 0)3166return Entries();3167return GotEntries.slice(LocalNum, GlobalNum);3168}
3169
3170template <class ELFT>3171typename MipsGOTParser<ELFT>::Entries3172MipsGOTParser<ELFT>::getOtherEntries() const {3173size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;3174if (OtherNum == 0)3175return Entries();3176return GotEntries.slice(LocalNum + GlobalNum, OtherNum);3177}
3178
3179template <class ELFT>3180uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const {3181int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);3182return GotSec->sh_addr + Offset;3183}
3184
3185template <class ELFT>3186int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const {3187int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);3188return Offset - 0x7ff0;3189}
3190
3191template <class ELFT>3192const typename MipsGOTParser<ELFT>::Elf_Sym *3193MipsGOTParser<ELFT>::getGotSym(const Entry *E) const {3194int64_t Offset = std::distance(GotEntries.data(), E);3195return &GotDynSyms[Offset - LocalNum];3196}
3197
3198template <class ELFT>3199const typename MipsGOTParser<ELFT>::Entry *3200MipsGOTParser<ELFT>::getPltLazyResolver() const {3201return PltEntries.empty() ? nullptr : &PltEntries[0];3202}
3203
3204template <class ELFT>3205const typename MipsGOTParser<ELFT>::Entry *3206MipsGOTParser<ELFT>::getPltModulePointer() const {3207return PltEntries.size() < 2 ? nullptr : &PltEntries[1];3208}
3209
3210template <class ELFT>3211typename MipsGOTParser<ELFT>::Entries3212MipsGOTParser<ELFT>::getPltEntries() const {3213if (PltEntries.size() <= 2)3214return Entries();3215return PltEntries.slice(2, PltEntries.size() - 2);3216}
3217
3218template <class ELFT>3219uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const {3220int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);3221return PltSec->sh_addr + Offset;3222}
3223
3224template <class ELFT>3225const typename MipsGOTParser<ELFT>::Elf_Sym *3226MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {3227int64_t Offset = std::distance(getPltEntries().data(), E);3228if (PltRelSec->sh_type == ELF::SHT_REL) {3229Elf_Rel_Range Rels = unwrapOrError(FileName, Obj.rels(*PltRelSec));3230return unwrapOrError(FileName,3231Obj.getRelocationSymbol(Rels[Offset], PltSymTable));3232} else {3233Elf_Rela_Range Rels = unwrapOrError(FileName, Obj.relas(*PltRelSec));3234return unwrapOrError(FileName,3235Obj.getRelocationSymbol(Rels[Offset], PltSymTable));3236}3237}
3238
3239const EnumEntry<unsigned> ElfMipsISAExtType[] = {3240{"None", Mips::AFL_EXT_NONE},3241{"Broadcom SB-1", Mips::AFL_EXT_SB1},3242{"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON},3243{"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2},3244{"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP},3245{"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3},3246{"LSI R4010", Mips::AFL_EXT_4010},3247{"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E},3248{"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F},3249{"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A},3250{"MIPS R4650", Mips::AFL_EXT_4650},3251{"MIPS R5900", Mips::AFL_EXT_5900},3252{"MIPS R10000", Mips::AFL_EXT_10000},3253{"NEC VR4100", Mips::AFL_EXT_4100},3254{"NEC VR4111/VR4181", Mips::AFL_EXT_4111},3255{"NEC VR4120", Mips::AFL_EXT_4120},3256{"NEC VR5400", Mips::AFL_EXT_5400},3257{"NEC VR5500", Mips::AFL_EXT_5500},3258{"RMI Xlr", Mips::AFL_EXT_XLR},3259{"Toshiba R3900", Mips::AFL_EXT_3900}3260};3261
3262const EnumEntry<unsigned> ElfMipsASEFlags[] = {3263{"DSP", Mips::AFL_ASE_DSP},3264{"DSPR2", Mips::AFL_ASE_DSPR2},3265{"Enhanced VA Scheme", Mips::AFL_ASE_EVA},3266{"MCU", Mips::AFL_ASE_MCU},3267{"MDMX", Mips::AFL_ASE_MDMX},3268{"MIPS-3D", Mips::AFL_ASE_MIPS3D},3269{"MT", Mips::AFL_ASE_MT},3270{"SmartMIPS", Mips::AFL_ASE_SMARTMIPS},3271{"VZ", Mips::AFL_ASE_VIRT},3272{"MSA", Mips::AFL_ASE_MSA},3273{"MIPS16", Mips::AFL_ASE_MIPS16},3274{"microMIPS", Mips::AFL_ASE_MICROMIPS},3275{"XPA", Mips::AFL_ASE_XPA},3276{"CRC", Mips::AFL_ASE_CRC},3277{"GINV", Mips::AFL_ASE_GINV},3278};3279
3280const EnumEntry<unsigned> ElfMipsFpABIType[] = {3281{"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY},3282{"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE},3283{"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE},3284{"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT},3285{"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)",3286Mips::Val_GNU_MIPS_ABI_FP_OLD_64},3287{"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX},3288{"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64},3289{"Hard float compat (32-bit CPU, 64-bit FPU)",3290Mips::Val_GNU_MIPS_ABI_FP_64A}3291};3292
3293static const EnumEntry<unsigned> ElfMipsFlags1[] {3294{"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG},3295};3296
3297static int getMipsRegisterSize(uint8_t Flag) {3298switch (Flag) {3299case Mips::AFL_REG_NONE:3300return 0;3301case Mips::AFL_REG_32:3302return 32;3303case Mips::AFL_REG_64:3304return 64;3305case Mips::AFL_REG_128:3306return 128;3307default:3308return -1;3309}3310}
3311
3312template <class ELFT>3313static void printMipsReginfoData(ScopedPrinter &W,3314const Elf_Mips_RegInfo<ELFT> &Reginfo) {3315W.printHex("GP", Reginfo.ri_gp_value);3316W.printHex("General Mask", Reginfo.ri_gprmask);3317W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]);3318W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]);3319W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]);3320W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]);3321}
3322
3323template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {3324const Elf_Shdr *RegInfoSec = findSectionByName(".reginfo");3325if (!RegInfoSec) {3326W.startLine() << "There is no .reginfo section in the file.\n";3327return;3328}3329
3330Expected<ArrayRef<uint8_t>> ContentsOrErr =3331Obj.getSectionContents(*RegInfoSec);3332if (!ContentsOrErr) {3333this->reportUniqueWarning(3334"unable to read the content of the .reginfo section (" +3335describe(*RegInfoSec) + "): " + toString(ContentsOrErr.takeError()));3336return;3337}3338
3339if (ContentsOrErr->size() < sizeof(Elf_Mips_RegInfo<ELFT>)) {3340this->reportUniqueWarning("the .reginfo section has an invalid size (0x" +3341Twine::utohexstr(ContentsOrErr->size()) + ")");3342return;3343}3344
3345DictScope GS(W, "MIPS RegInfo");3346printMipsReginfoData(W, *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(3347ContentsOrErr->data()));3348}
3349
3350template <class ELFT>3351static Expected<const Elf_Mips_Options<ELFT> *>3352readMipsOptions(const uint8_t *SecBegin, ArrayRef<uint8_t> &SecData,3353bool &IsSupported) {3354if (SecData.size() < sizeof(Elf_Mips_Options<ELFT>))3355return createError("the .MIPS.options section has an invalid size (0x" +3356Twine::utohexstr(SecData.size()) + ")");3357
3358const Elf_Mips_Options<ELFT> *O =3359reinterpret_cast<const Elf_Mips_Options<ELFT> *>(SecData.data());3360const uint8_t Size = O->size;3361if (Size > SecData.size()) {3362const uint64_t Offset = SecData.data() - SecBegin;3363const uint64_t SecSize = Offset + SecData.size();3364return createError("a descriptor of size 0x" + Twine::utohexstr(Size) +3365" at offset 0x" + Twine::utohexstr(Offset) +3366" goes past the end of the .MIPS.options "3367"section of size 0x" +3368Twine::utohexstr(SecSize));3369}3370
3371IsSupported = O->kind == ODK_REGINFO;3372const size_t ExpectedSize =3373sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>);3374
3375if (IsSupported)3376if (Size < ExpectedSize)3377return createError(3378"a .MIPS.options entry of kind " +3379Twine(getElfMipsOptionsOdkType(O->kind)) +3380" has an invalid size (0x" + Twine::utohexstr(Size) +3381"), the expected size is 0x" + Twine::utohexstr(ExpectedSize));3382
3383SecData = SecData.drop_front(Size);3384return O;3385}
3386
3387template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {3388const Elf_Shdr *MipsOpts = findSectionByName(".MIPS.options");3389if (!MipsOpts) {3390W.startLine() << "There is no .MIPS.options section in the file.\n";3391return;3392}3393
3394DictScope GS(W, "MIPS Options");3395
3396ArrayRef<uint8_t> Data =3397unwrapOrError(ObjF.getFileName(), Obj.getSectionContents(*MipsOpts));3398const uint8_t *const SecBegin = Data.begin();3399while (!Data.empty()) {3400bool IsSupported;3401Expected<const Elf_Mips_Options<ELFT> *> OptsOrErr =3402readMipsOptions<ELFT>(SecBegin, Data, IsSupported);3403if (!OptsOrErr) {3404reportUniqueWarning(OptsOrErr.takeError());3405break;3406}3407
3408unsigned Kind = (*OptsOrErr)->kind;3409const char *Type = getElfMipsOptionsOdkType(Kind);3410if (!IsSupported) {3411W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind3412<< ")\n";3413continue;3414}3415
3416DictScope GS(W, Type);3417if (Kind == ODK_REGINFO)3418printMipsReginfoData(W, (*OptsOrErr)->getRegInfo());3419else3420llvm_unreachable("unexpected .MIPS.options section descriptor kind");3421}3422}
3423
3424template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {3425const Elf_Shdr *StackMapSection = findSectionByName(".llvm_stackmaps");3426if (!StackMapSection)3427return;3428
3429auto Warn = [&](Error &&E) {3430this->reportUniqueWarning("unable to read the stack map from " +3431describe(*StackMapSection) + ": " +3432toString(std::move(E)));3433};3434
3435Expected<ArrayRef<uint8_t>> ContentOrErr =3436Obj.getSectionContents(*StackMapSection);3437if (!ContentOrErr) {3438Warn(ContentOrErr.takeError());3439return;3440}3441
3442if (Error E =3443StackMapParser<ELFT::Endianness>::validateHeader(*ContentOrErr)) {3444Warn(std::move(E));3445return;3446}3447
3448prettyPrintStackMap(W, StackMapParser<ELFT::Endianness>(*ContentOrErr));3449}
3450
3451template <class ELFT>3452void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex,3453const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {3454Expected<RelSymbol<ELFT>> Target = getRelocationTarget(R, SymTab);3455if (!Target)3456reportUniqueWarning("unable to print relocation " + Twine(RelIndex) +3457" in " + describe(Sec) + ": " +3458toString(Target.takeError()));3459else3460printRelRelaReloc(R, *Target);3461}
3462
3463template <class ELFT>3464std::vector<EnumEntry<unsigned>>3465ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header,3466const Elf_Sym &Symbol) const {3467std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),3468std::end(ElfSymOtherFlags));3469if (Header.e_machine == EM_MIPS) {3470// Someone in their infinite wisdom decided to make STO_MIPS_MIPS163471// flag overlap with other ST_MIPS_xxx flags. So consider both3472// cases separately.3473if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)3474SymOtherFlags.insert(SymOtherFlags.end(),3475std::begin(ElfMips16SymOtherFlags),3476std::end(ElfMips16SymOtherFlags));3477else3478SymOtherFlags.insert(SymOtherFlags.end(),3479std::begin(ElfMipsSymOtherFlags),3480std::end(ElfMipsSymOtherFlags));3481} else if (Header.e_machine == EM_AARCH64) {3482SymOtherFlags.insert(SymOtherFlags.end(),3483std::begin(ElfAArch64SymOtherFlags),3484std::end(ElfAArch64SymOtherFlags));3485} else if (Header.e_machine == EM_RISCV) {3486SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags),3487std::end(ElfRISCVSymOtherFlags));3488}3489return SymOtherFlags;3490}
3491
3492static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,3493StringRef Str2) {3494OS.PadToColumn(2u);3495OS << Str1;3496OS.PadToColumn(37u);3497OS << Str2 << "\n";3498OS.flush();3499}
3500
3501template <class ELFT>3502static std::string getSectionHeadersNumString(const ELFFile<ELFT> &Obj,3503StringRef FileName) {3504const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();3505if (ElfHeader.e_shnum != 0)3506return to_string(ElfHeader.e_shnum);3507
3508Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();3509if (!ArrOrErr) {3510// In this case we can ignore an error, because we have already reported a3511// warning about the broken section header table earlier.3512consumeError(ArrOrErr.takeError());3513return "<?>";3514}3515
3516if (ArrOrErr->empty())3517return "0";3518return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")";3519}
3520
3521template <class ELFT>3522static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> &Obj,3523StringRef FileName) {3524const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();3525if (ElfHeader.e_shstrndx != SHN_XINDEX)3526return to_string(ElfHeader.e_shstrndx);3527
3528Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();3529if (!ArrOrErr) {3530// In this case we can ignore an error, because we have already reported a3531// warning about the broken section header table earlier.3532consumeError(ArrOrErr.takeError());3533return "<?>";3534}3535
3536if (ArrOrErr->empty())3537return "65535 (corrupt: out of range)";3538return to_string(ElfHeader.e_shstrndx) + " (" +3539to_string((*ArrOrErr)[0].sh_link) + ")";3540}
3541
3542static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) {3543auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) {3544return E.Value == Type;3545});3546if (It != ArrayRef(ElfObjectFileType).end())3547return It;3548return nullptr;3549}
3550
3551template <class ELFT>3552void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,3553ArrayRef<std::string> InputFilenames,3554const Archive *A) {3555if (InputFilenames.size() > 1 || A) {3556this->W.startLine() << "\n";3557this->W.printString("File", FileStr);3558}3559}
3560
3561template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() {3562const Elf_Ehdr &e = this->Obj.getHeader();3563OS << "ELF Header:\n";3564OS << " Magic: ";3565std::string Str;3566for (int i = 0; i < ELF::EI_NIDENT; i++)3567OS << format(" %02x", static_cast<int>(e.e_ident[i]));3568OS << "\n";3569Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));3570printFields(OS, "Class:", Str);3571Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding));3572printFields(OS, "Data:", Str);3573OS.PadToColumn(2u);3574OS << "Version:";3575OS.PadToColumn(37u);3576OS << utohexstr(e.e_ident[ELF::EI_VERSION]);3577if (e.e_version == ELF::EV_CURRENT)3578OS << " (current)";3579OS << "\n";3580auto OSABI = ArrayRef(ElfOSABI);3581if (e.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&3582e.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {3583switch (e.e_machine) {3584case ELF::EM_ARM:3585OSABI = ArrayRef(ARMElfOSABI);3586break;3587case ELF::EM_AMDGPU:3588OSABI = ArrayRef(AMDGPUElfOSABI);3589break;3590default:3591break;3592}3593}3594Str = enumToString(e.e_ident[ELF::EI_OSABI], OSABI);3595printFields(OS, "OS/ABI:", Str);3596printFields(OS,3597"ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION]));3598
3599if (const EnumEntry<unsigned> *E = getObjectFileEnumEntry(e.e_type)) {3600Str = E->AltName.str();3601} else {3602if (e.e_type >= ET_LOPROC)3603Str = "Processor Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";3604else if (e.e_type >= ET_LOOS)3605Str = "OS Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";3606else3607Str = "<unknown>: " + utohexstr(e.e_type, /*LowerCase=*/true);3608}3609printFields(OS, "Type:", Str);3610
3611Str = enumToString(e.e_machine, ArrayRef(ElfMachineType));3612printFields(OS, "Machine:", Str);3613Str = "0x" + utohexstr(e.e_version);3614printFields(OS, "Version:", Str);3615Str = "0x" + utohexstr(e.e_entry);3616printFields(OS, "Entry point address:", Str);3617Str = to_string(e.e_phoff) + " (bytes into file)";3618printFields(OS, "Start of program headers:", Str);3619Str = to_string(e.e_shoff) + " (bytes into file)";3620printFields(OS, "Start of section headers:", Str);3621std::string ElfFlags;3622if (e.e_machine == EM_MIPS)3623ElfFlags = printFlags(3624e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH),3625unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH));3626else if (e.e_machine == EM_RISCV)3627ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags));3628else if (e.e_machine == EM_AVR)3629ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags),3630unsigned(ELF::EF_AVR_ARCH_MASK));3631else if (e.e_machine == EM_LOONGARCH)3632ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags),3633unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),3634unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));3635else if (e.e_machine == EM_XTENSA)3636ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),3637unsigned(ELF::EF_XTENSA_MACH));3638else if (e.e_machine == EM_CUDA)3639ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags),3640unsigned(ELF::EF_CUDA_SM));3641else if (e.e_machine == EM_AMDGPU) {3642switch (e.e_ident[ELF::EI_ABIVERSION]) {3643default:3644break;3645case 0:3646// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.3647[[fallthrough]];3648case ELF::ELFABIVERSION_AMDGPU_HSA_V3:3649ElfFlags =3650printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),3651unsigned(ELF::EF_AMDGPU_MACH));3652break;3653case ELF::ELFABIVERSION_AMDGPU_HSA_V4:3654case ELF::ELFABIVERSION_AMDGPU_HSA_V5:3655ElfFlags =3656printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),3657unsigned(ELF::EF_AMDGPU_MACH),3658unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),3659unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));3660break;3661case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {3662ElfFlags =3663printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),3664unsigned(ELF::EF_AMDGPU_MACH),3665unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),3666unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));3667if (auto GenericV = e.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {3668ElfFlags +=3669", generic_v" +3670to_string(GenericV >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET);3671}3672} break;3673}3674}3675Str = "0x" + utohexstr(e.e_flags);3676if (!ElfFlags.empty())3677Str = Str + ", " + ElfFlags;3678printFields(OS, "Flags:", Str);3679Str = to_string(e.e_ehsize) + " (bytes)";3680printFields(OS, "Size of this header:", Str);3681Str = to_string(e.e_phentsize) + " (bytes)";3682printFields(OS, "Size of program headers:", Str);3683Str = to_string(e.e_phnum);3684printFields(OS, "Number of program headers:", Str);3685Str = to_string(e.e_shentsize) + " (bytes)";3686printFields(OS, "Size of section headers:", Str);3687Str = getSectionHeadersNumString(this->Obj, this->FileName);3688printFields(OS, "Number of section headers:", Str);3689Str = getSectionHeaderTableIndexString(this->Obj, this->FileName);3690printFields(OS, "Section header string table index:", Str);3691}
3692
3693template <class ELFT> std::vector<GroupSection> ELFDumper<ELFT>::getGroups() {3694auto GetSignature = [&](const Elf_Sym &Sym, unsigned SymNdx,3695const Elf_Shdr &Symtab) -> StringRef {3696Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab);3697if (!StrTableOrErr) {3698reportUniqueWarning("unable to get the string table for " +3699describe(Symtab) + ": " +3700toString(StrTableOrErr.takeError()));3701return "<?>";3702}3703
3704StringRef Strings = *StrTableOrErr;3705if (Sym.st_name >= Strings.size()) {3706reportUniqueWarning("unable to get the name of the symbol with index " +3707Twine(SymNdx) + ": st_name (0x" +3708Twine::utohexstr(Sym.st_name) +3709") is past the end of the string table of size 0x" +3710Twine::utohexstr(Strings.size()));3711return "<?>";3712}3713
3714return StrTableOrErr->data() + Sym.st_name;3715};3716
3717std::vector<GroupSection> Ret;3718uint64_t I = 0;3719for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {3720++I;3721if (Sec.sh_type != ELF::SHT_GROUP)3722continue;3723
3724StringRef Signature = "<?>";3725if (Expected<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Sec.sh_link)) {3726if (Expected<const Elf_Sym *> SymOrErr =3727Obj.template getEntry<Elf_Sym>(**SymtabOrErr, Sec.sh_info))3728Signature = GetSignature(**SymOrErr, Sec.sh_info, **SymtabOrErr);3729else3730reportUniqueWarning("unable to get the signature symbol for " +3731describe(Sec) + ": " +3732toString(SymOrErr.takeError()));3733} else {3734reportUniqueWarning("unable to get the symbol table for " +3735describe(Sec) + ": " +3736toString(SymtabOrErr.takeError()));3737}3738
3739ArrayRef<Elf_Word> Data;3740if (Expected<ArrayRef<Elf_Word>> ContentsOrErr =3741Obj.template getSectionContentsAsArray<Elf_Word>(Sec)) {3742if (ContentsOrErr->empty())3743reportUniqueWarning("unable to read the section group flag from the " +3744describe(Sec) + ": the section is empty");3745else3746Data = *ContentsOrErr;3747} else {3748reportUniqueWarning("unable to get the content of the " + describe(Sec) +3749": " + toString(ContentsOrErr.takeError()));3750}3751
3752Ret.push_back({getPrintableSectionName(Sec),3753maybeDemangle(Signature),3754Sec.sh_name,3755I - 1,3756Sec.sh_link,3757Sec.sh_info,3758Data.empty() ? Elf_Word(0) : Data[0],3759{}});3760
3761if (Data.empty())3762continue;3763
3764std::vector<GroupMember> &GM = Ret.back().Members;3765for (uint32_t Ndx : Data.slice(1)) {3766if (Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(Ndx)) {3767GM.push_back({getPrintableSectionName(**SecOrErr), Ndx});3768} else {3769reportUniqueWarning("unable to get the section with index " +3770Twine(Ndx) + " when dumping the " + describe(Sec) +3771": " + toString(SecOrErr.takeError()));3772GM.push_back({"<?>", Ndx});3773}3774}3775}3776return Ret;3777}
3778
3779static DenseMap<uint64_t, const GroupSection *>3780mapSectionsToGroups(ArrayRef<GroupSection> Groups) {3781DenseMap<uint64_t, const GroupSection *> Ret;3782for (const GroupSection &G : Groups)3783for (const GroupMember &GM : G.Members)3784Ret.insert({GM.Index, &G});3785return Ret;3786}
3787
3788template <class ELFT> void GNUELFDumper<ELFT>::printGroupSections() {3789std::vector<GroupSection> V = this->getGroups();3790DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);3791for (const GroupSection &G : V) {3792OS << "\n"3793<< getGroupType(G.Type) << " group section ["3794<< format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature3795<< "] contains " << G.Members.size() << " sections:\n"3796<< " [Index] Name\n";3797for (const GroupMember &GM : G.Members) {3798const GroupSection *MainGroup = Map[GM.Index];3799if (MainGroup != &G)3800this->reportUniqueWarning(3801"section with index " + Twine(GM.Index) +3802", included in the group section with index " +3803Twine(MainGroup->Index) +3804", was also found in the group section with index " +3805Twine(G.Index));3806OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n";3807}3808}3809
3810if (V.empty())3811OS << "There are no section groups in this file.\n";3812}
3813
3814template <class ELFT>3815void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,3816const RelSymbol<ELFT> &RelSym) {3817// First two fields are bit width dependent. The rest of them are fixed width.3818unsigned Bias = ELFT::Is64Bits ? 8 : 0;3819Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias};3820unsigned Width = ELFT::Is64Bits ? 16 : 8;3821
3822Fields[0].Str = to_string(format_hex_no_prefix(R.Offset, Width));3823Fields[1].Str = to_string(format_hex_no_prefix(R.Info, Width));3824
3825SmallString<32> RelocName;3826this->Obj.getRelocationTypeName(R.Type, RelocName);3827Fields[2].Str = RelocName.c_str();3828
3829if (RelSym.Sym)3830Fields[3].Str =3831to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width));3832if (RelSym.Sym && RelSym.Name.empty())3833Fields[4].Str = "<null>";3834else3835Fields[4].Str = std::string(RelSym.Name);3836
3837for (const Field &F : Fields)3838printField(F);3839
3840std::string Addend;3841if (std::optional<int64_t> A = R.Addend) {3842int64_t RelAddend = *A;3843if (!Fields[4].Str.empty()) {3844if (RelAddend < 0) {3845Addend = " - ";3846RelAddend = -static_cast<uint64_t>(RelAddend);3847} else {3848Addend = " + ";3849}3850}3851Addend += utohexstr(RelAddend, /*LowerCase=*/true);3852}3853OS << Addend << "\n";3854}
3855
3856template <class ELFT>3857static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType,3858const typename ELFT::Ehdr &EHeader,3859uint64_t CrelHdr = 0) {3860bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;3861if (ELFT::Is64Bits)3862OS << " Offset Info Type Symbol's "3863"Value Symbol's Name";3864else3865OS << " Offset Info Type Sym. Value Symbol's Name";3866if (IsRela || (SType == ELF::SHT_CREL && (CrelHdr & CREL_HDR_ADDEND)))3867OS << " + Addend";3868OS << "\n";3869}
3870
3871template <class ELFT>3872void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name,3873const DynRegionInfo &Reg) {3874uint64_t Offset = Reg.Addr - this->Obj.base();3875OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x"3876<< utohexstr(Offset, /*LowerCase=*/true);3877if (Type != ELF::SHT_CREL)3878OS << " contains " << Reg.Size << " bytes";3879OS << ":\n";3880printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader());3881}
3882
3883template <class ELFT>3884static bool isRelocationSec(const typename ELFT::Shdr &Sec,3885const typename ELFT::Ehdr &EHeader) {3886return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||3887Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_CREL ||3888Sec.sh_type == ELF::SHT_ANDROID_REL ||3889Sec.sh_type == ELF::SHT_ANDROID_RELA ||3890Sec.sh_type == ELF::SHT_ANDROID_RELR ||3891(EHeader.e_machine == EM_AARCH64 &&3892Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);3893}
3894
3895template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {3896auto PrintAsRelr = [&](const Elf_Shdr &Sec) {3897return Sec.sh_type == ELF::SHT_RELR ||3898Sec.sh_type == ELF::SHT_ANDROID_RELR ||3899(this->Obj.getHeader().e_machine == EM_AARCH64 &&3900Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);3901};3902auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> {3903// Android's packed relocation section needs to be unpacked first3904// to get the actual number of entries.3905if (Sec.sh_type == ELF::SHT_ANDROID_REL ||3906Sec.sh_type == ELF::SHT_ANDROID_RELA) {3907Expected<std::vector<typename ELFT::Rela>> RelasOrErr =3908this->Obj.android_relas(Sec);3909if (!RelasOrErr)3910return RelasOrErr.takeError();3911return RelasOrErr->size();3912}3913
3914if (Sec.sh_type == ELF::SHT_CREL) {3915Expected<ArrayRef<uint8_t>> ContentsOrErr =3916this->Obj.getSectionContents(Sec);3917if (!ContentsOrErr)3918return ContentsOrErr.takeError();3919auto NumOrErr = this->Obj.getCrelHeader(*ContentsOrErr);3920if (!NumOrErr)3921return NumOrErr.takeError();3922return *NumOrErr / 8;3923}3924
3925if (PrintAsRelr(Sec)) {3926Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);3927if (!RelrsOrErr)3928return RelrsOrErr.takeError();3929return this->Obj.decode_relrs(*RelrsOrErr).size();3930}3931
3932return Sec.getEntityCount();3933};3934
3935bool HasRelocSections = false;3936for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {3937if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))3938continue;3939HasRelocSections = true;3940
3941std::string EntriesNum = "<?>";3942if (Expected<size_t> NumOrErr = GetEntriesNum(Sec))3943EntriesNum = std::to_string(*NumOrErr);3944else3945this->reportUniqueWarning("unable to get the number of relocations in " +3946this->describe(Sec) + ": " +3947toString(NumOrErr.takeError()));3948
3949uintX_t Offset = Sec.sh_offset;3950StringRef Name = this->getPrintableSectionName(Sec);3951OS << "\nRelocation section '" << Name << "' at offset 0x"3952<< utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum3953<< " entries:\n";3954
3955if (PrintAsRelr(Sec)) {3956printRelr(Sec);3957} else {3958uint64_t CrelHdr = 0;3959// For CREL, read the header and call printRelocationsHelper only if3960// GetEntriesNum(Sec) succeeded.3961if (Sec.sh_type == ELF::SHT_CREL && EntriesNum != "<?>") {3962CrelHdr = cantFail(this->Obj.getCrelHeader(3963cantFail(this->Obj.getSectionContents(Sec))));3964}3965printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader(),3966CrelHdr);3967if (Sec.sh_type != ELF::SHT_CREL || EntriesNum != "<?>")3968this->printRelocationsHelper(Sec);3969}3970}3971if (!HasRelocSections)3972OS << "\nThere are no relocations in this file.\n";3973}
3974
3975template <class ELFT> void GNUELFDumper<ELFT>::printRelr(const Elf_Shdr &Sec) {3976Expected<Elf_Relr_Range> RangeOrErr = this->Obj.relrs(Sec);3977if (!RangeOrErr) {3978this->reportUniqueWarning("unable to read relocations from " +3979this->describe(Sec) + ": " +3980toString(RangeOrErr.takeError()));3981return;3982}3983if (ELFT::Is64Bits)3984OS << "Index: Entry Address Symbolic Address\n";3985else3986OS << "Index: Entry Address Symbolic Address\n";3987
3988// If .symtab is available, collect its defined symbols and sort them by3989// st_value.3990SmallVector<std::pair<uint64_t, std::string>, 0> Syms;3991if (this->DotSymtabSec) {3992Elf_Sym_Range Symtab;3993std::optional<StringRef> Strtab;3994std::tie(Symtab, Strtab) = this->getSymtabAndStrtab();3995if (Symtab.size() && Strtab) {3996for (auto [I, Sym] : enumerate(Symtab)) {3997if (!Sym.st_shndx)3998continue;3999Syms.emplace_back(Sym.st_value,4000this->getFullSymbolName(Sym, I, ArrayRef<Elf_Word>(),4001*Strtab, false));4002}4003}4004}4005llvm::stable_sort(Syms);4006
4007typename ELFT::uint Base = 0;4008size_t I = 0;4009auto Print = [&](uint64_t Where) {4010OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8);4011for (; I < Syms.size() && Syms[I].first <= Where; ++I)4012;4013// Try symbolizing the address. Find the nearest symbol before or at the4014// address and print the symbol and the address difference.4015if (I) {4016OS << " " << Syms[I - 1].second;4017if (Syms[I - 1].first < Where)4018OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first);4019}4020OS << '\n';4021};4022for (auto [Index, R] : enumerate(*RangeOrErr)) {4023typename ELFT::uint Entry = R;4024OS << formatv("{0:4}: ", Index)4025<< format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' ';4026if ((Entry & 1) == 0) {4027Print(Entry);4028Base = Entry + sizeof(typename ELFT::uint);4029} else {4030bool First = true;4031for (auto Where = Base; Entry >>= 1;4032Where += sizeof(typename ELFT::uint)) {4033if (Entry & 1) {4034if (First)4035First = false;4036else4037OS.indent(ELFT::Is64Bits ? 24 : 16);4038Print(Where);4039}4040}4041Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint);4042}4043}4044}
4045
4046// Print the offset of a particular section from anyone of the ranges:
4047// [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER].
4048// If 'Type' does not fall within any of those ranges, then a string is
4049// returned as '<unknown>' followed by the type value.
4050static std::string getSectionTypeOffsetString(unsigned Type) {4051if (Type >= SHT_LOOS && Type <= SHT_HIOS)4052return "LOOS+0x" + utohexstr(Type - SHT_LOOS);4053else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC)4054return "LOPROC+0x" + utohexstr(Type - SHT_LOPROC);4055else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER)4056return "LOUSER+0x" + utohexstr(Type - SHT_LOUSER);4057return "0x" + utohexstr(Type) + ": <unknown>";4058}
4059
4060static std::string getSectionTypeString(unsigned Machine, unsigned Type) {4061StringRef Name = getELFSectionTypeName(Machine, Type);4062
4063// Handle SHT_GNU_* type names.4064if (Name.consume_front("SHT_GNU_")) {4065if (Name == "HASH")4066return "GNU_HASH";4067// E.g. SHT_GNU_verneed -> VERNEED.4068return Name.upper();4069}4070
4071if (Name == "SHT_SYMTAB_SHNDX")4072return "SYMTAB SECTION INDICES";4073
4074if (Name.consume_front("SHT_"))4075return Name.str();4076return getSectionTypeOffsetString(Type);4077}
4078
4079static void printSectionDescription(formatted_raw_ostream &OS,4080unsigned EMachine) {4081OS << "Key to Flags:\n";4082OS << " W (write), A (alloc), X (execute), M (merge), S (strings), I "4083"(info),\n";4084OS << " L (link order), O (extra OS processing required), G (group), T "4085"(TLS),\n";4086OS << " C (compressed), x (unknown), o (OS specific), E (exclude),\n";4087OS << " R (retain)";4088
4089if (EMachine == EM_X86_64)4090OS << ", l (large)";4091else if (EMachine == EM_ARM)4092OS << ", y (purecode)";4093
4094OS << ", p (processor specific)\n";4095}
4096
4097template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {4098ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());4099if (Sections.empty()) {4100OS << "\nThere are no sections in this file.\n";4101Expected<StringRef> SecStrTableOrErr =4102this->Obj.getSectionStringTable(Sections, this->WarningHandler);4103if (!SecStrTableOrErr)4104this->reportUniqueWarning(SecStrTableOrErr.takeError());4105return;4106}4107unsigned Bias = ELFT::Is64Bits ? 0 : 8;4108OS << "There are " << to_string(Sections.size())4109<< " section headers, starting at offset "4110<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";4111OS << "Section Headers:\n";4112Field Fields[11] = {4113{"[Nr]", 2}, {"Name", 7}, {"Type", 25},4114{"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias},4115{"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias},4116{"Inf", 82 - Bias}, {"Al", 86 - Bias}};4117for (const Field &F : Fields)4118printField(F);4119OS << "\n";4120
4121StringRef SecStrTable;4122if (Expected<StringRef> SecStrTableOrErr =4123this->Obj.getSectionStringTable(Sections, this->WarningHandler))4124SecStrTable = *SecStrTableOrErr;4125else4126this->reportUniqueWarning(SecStrTableOrErr.takeError());4127
4128size_t SectionIndex = 0;4129for (const Elf_Shdr &Sec : Sections) {4130Fields[0].Str = to_string(SectionIndex);4131if (SecStrTable.empty())4132Fields[1].Str = "<no-strings>";4133else4134Fields[1].Str = std::string(unwrapOrError<StringRef>(4135this->FileName, this->Obj.getSectionName(Sec, SecStrTable)));4136Fields[2].Str =4137getSectionTypeString(this->Obj.getHeader().e_machine, Sec.sh_type);4138Fields[3].Str =4139to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8));4140Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6));4141Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6));4142Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2));4143Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI],4144this->Obj.getHeader().e_machine, Sec.sh_flags);4145Fields[8].Str = to_string(Sec.sh_link);4146Fields[9].Str = to_string(Sec.sh_info);4147Fields[10].Str = to_string(Sec.sh_addralign);4148
4149OS.PadToColumn(Fields[0].Column);4150OS << "[" << right_justify(Fields[0].Str, 2) << "]";4151for (int i = 1; i < 7; i++)4152printField(Fields[i]);4153OS.PadToColumn(Fields[7].Column);4154OS << right_justify(Fields[7].Str, 3);4155OS.PadToColumn(Fields[8].Column);4156OS << right_justify(Fields[8].Str, 2);4157OS.PadToColumn(Fields[9].Column);4158OS << right_justify(Fields[9].Str, 3);4159OS.PadToColumn(Fields[10].Column);4160OS << right_justify(Fields[10].Str, 2);4161OS << "\n";4162++SectionIndex;4163}4164printSectionDescription(OS, this->Obj.getHeader().e_machine);4165}
4166
4167template <class ELFT>4168void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,4169size_t Entries,4170bool NonVisibilityBitsUsed,4171bool ExtraSymInfo) const {4172StringRef Name;4173if (Symtab)4174Name = this->getPrintableSectionName(*Symtab);4175if (!Name.empty())4176OS << "\nSymbol table '" << Name << "'";4177else4178OS << "\nSymbol table for image";4179OS << " contains " << Entries << " entries:\n";4180
4181if (ELFT::Is64Bits) {4182OS << " Num: Value Size Type Bind Vis";4183if (ExtraSymInfo)4184OS << "+Other";4185} else {4186OS << " Num: Value Size Type Bind Vis";4187if (ExtraSymInfo)4188OS << "+Other";4189}4190
4191OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0));4192if (ExtraSymInfo)4193OS << "Ndx(SecName) Name [+ Version Info]\n";4194else4195OS << "Ndx Name\n";4196}
4197
4198template <class ELFT>4199std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(4200const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,4201bool ExtraSymInfo) const {4202unsigned SectionIndex = Symbol.st_shndx;4203switch (SectionIndex) {4204case ELF::SHN_UNDEF:4205return "UND";4206case ELF::SHN_ABS:4207return "ABS";4208case ELF::SHN_COMMON:4209return "COM";4210case ELF::SHN_XINDEX: {4211Expected<uint32_t> IndexOrErr =4212object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable);4213if (!IndexOrErr) {4214assert(Symbol.st_shndx == SHN_XINDEX &&4215"getExtendedSymbolTableIndex should only fail due to an invalid "4216"SHT_SYMTAB_SHNDX table/reference");4217this->reportUniqueWarning(IndexOrErr.takeError());4218return "RSV[0xffff]";4219}4220SectionIndex = *IndexOrErr;4221break;4222}4223default:4224// Find if:4225// Processor specific4226if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC)4227return std::string("PRC[0x") +4228to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4229// OS specific4230if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS)4231return std::string("OS[0x") +4232to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4233// Architecture reserved:4234if (SectionIndex >= ELF::SHN_LORESERVE &&4235SectionIndex <= ELF::SHN_HIRESERVE)4236return std::string("RSV[0x") +4237to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";4238break;4239}4240
4241std::string Extra;4242if (ExtraSymInfo) {4243auto Sec = this->Obj.getSection(SectionIndex);4244if (!Sec) {4245this->reportUniqueWarning(Sec.takeError());4246} else {4247auto SecName = this->Obj.getSectionName(**Sec);4248if (!SecName)4249this->reportUniqueWarning(SecName.takeError());4250else4251Extra = Twine(" (" + *SecName + ")").str();4252}4253}4254return to_string(format_decimal(SectionIndex, 3)) + Extra;4255}
4256
4257template <class ELFT>4258void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,4259DataRegion<Elf_Word> ShndxTable,4260std::optional<StringRef> StrTable,4261bool IsDynamic, bool NonVisibilityBitsUsed,4262bool ExtraSymInfo) const {4263unsigned Bias = ELFT::Is64Bits ? 8 : 0;4264Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,426531 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};4266Fields[0].Str = to_string(format_decimal(SymIndex, 6)) + ":";4267Fields[1].Str =4268to_string(format_hex_no_prefix(Symbol.st_value, ELFT::Is64Bits ? 16 : 8));4269Fields[2].Str = to_string(format_decimal(Symbol.st_size, 5));4270
4271unsigned char SymbolType = Symbol.getType();4272if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&4273SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)4274Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));4275else4276Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));4277
4278Fields[4].Str =4279enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings));4280Fields[5].Str =4281enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities));4282
4283if (Symbol.st_other & ~0x3) {4284if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) {4285uint8_t Other = Symbol.st_other & ~0x3;4286if (Other & STO_AARCH64_VARIANT_PCS) {4287Other &= ~STO_AARCH64_VARIANT_PCS;4288Fields[5].Str += " [VARIANT_PCS";4289if (Other != 0)4290Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));4291Fields[5].Str.append("]");4292}4293} else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) {4294uint8_t Other = Symbol.st_other & ~0x3;4295if (Other & STO_RISCV_VARIANT_CC) {4296Other &= ~STO_RISCV_VARIANT_CC;4297Fields[5].Str += " [VARIANT_CC";4298if (Other != 0)4299Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));4300Fields[5].Str.append("]");4301}4302} else {4303Fields[5].Str +=4304" [<other: " + to_string(format_hex(Symbol.st_other, 2)) + ">]";4305}4306}4307
4308Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;4309Fields[6].Str =4310getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo);4311
4312Fields[7].Column += ExtraSymInfo ? 10 : 0;4313Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,4314StrTable, IsDynamic);4315for (const Field &Entry : Fields)4316printField(Entry);4317OS << "\n";4318}
4319
4320template <class ELFT>4321void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,4322unsigned SymIndex,4323DataRegion<Elf_Word> ShndxTable,4324StringRef StrTable,4325uint32_t Bucket) {4326unsigned Bias = ELFT::Is64Bits ? 8 : 0;4327Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias,432834 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};4329Fields[0].Str = to_string(format_decimal(SymIndex, 5));4330Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":";4331
4332Fields[2].Str = to_string(4333format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));4334Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5));4335
4336unsigned char SymbolType = Symbol->getType();4337if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&4338SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)4339Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));4340else4341Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));4342
4343Fields[5].Str =4344enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings));4345Fields[6].Str =4346enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities));4347Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable);4348Fields[8].Str =4349this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true);4350
4351for (const Field &Entry : Fields)4352printField(Entry);4353OS << "\n";4354}
4355
4356template <class ELFT>4357void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols,4358bool PrintDynamicSymbols,4359bool ExtraSymInfo) {4360if (!PrintSymbols && !PrintDynamicSymbols)4361return;4362// GNU readelf prints both the .dynsym and .symtab with --symbols.4363this->printSymbolsHelper(true, ExtraSymInfo);4364if (PrintSymbols)4365this->printSymbolsHelper(false, ExtraSymInfo);4366}
4367
4368template <class ELFT>4369void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) {4370if (this->DynamicStringTable.empty())4371return;4372
4373if (ELFT::Is64Bits)4374OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4375else4376OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4377OS << "\n";4378
4379Elf_Sym_Range DynSyms = this->dynamic_symbols();4380const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];4381if (!FirstSym) {4382this->reportUniqueWarning(4383Twine("unable to print symbols for the .hash table: the "4384"dynamic symbol table ") +4385(this->DynSymRegion ? "is empty" : "was not found"));4386return;4387}4388
4389DataRegion<Elf_Word> ShndxTable(4390(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());4391auto Buckets = SysVHash.buckets();4392auto Chains = SysVHash.chains();4393for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) {4394if (Buckets[Buc] == ELF::STN_UNDEF)4395continue;4396BitVector Visited(SysVHash.nchain);4397for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) {4398if (Ch == ELF::STN_UNDEF)4399break;4400
4401if (Visited[Ch]) {4402this->reportUniqueWarning(".hash section is invalid: bucket " +4403Twine(Ch) +4404": a cycle was detected in the linked chain");4405break;4406}4407
4408printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable,4409Buc);4410Visited[Ch] = true;4411}4412}4413}
4414
4415template <class ELFT>4416void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) {4417if (this->DynamicStringTable.empty())4418return;4419
4420Elf_Sym_Range DynSyms = this->dynamic_symbols();4421const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];4422if (!FirstSym) {4423this->reportUniqueWarning(4424Twine("unable to print symbols for the .gnu.hash table: the "4425"dynamic symbol table ") +4426(this->DynSymRegion ? "is empty" : "was not found"));4427return;4428}4429
4430auto GetSymbol = [&](uint64_t SymIndex,4431uint64_t SymsTotal) -> const Elf_Sym * {4432if (SymIndex >= SymsTotal) {4433this->reportUniqueWarning(4434"unable to print hashed symbol with index " + Twine(SymIndex) +4435", which is greater than or equal to the number of dynamic symbols "4436"(" +4437Twine::utohexstr(SymsTotal) + ")");4438return nullptr;4439}4440return FirstSym + SymIndex;4441};4442
4443Expected<ArrayRef<Elf_Word>> ValuesOrErr =4444getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHash);4445ArrayRef<Elf_Word> Values;4446if (!ValuesOrErr)4447this->reportUniqueWarning("unable to get hash values for the SHT_GNU_HASH "4448"section: " +4449toString(ValuesOrErr.takeError()));4450else4451Values = *ValuesOrErr;4452
4453DataRegion<Elf_Word> ShndxTable(4454(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());4455ArrayRef<Elf_Word> Buckets = GnuHash.buckets();4456for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) {4457if (Buckets[Buc] == ELF::STN_UNDEF)4458continue;4459uint32_t Index = Buckets[Buc];4460// Print whole chain.4461while (true) {4462uint32_t SymIndex = Index++;4463if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size()))4464printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable,4465Buc);4466else4467break;4468
4469if (SymIndex < GnuHash.symndx) {4470this->reportUniqueWarning(4471"unable to read the hash value for symbol with index " +4472Twine(SymIndex) +4473", which is less than the index of the first hashed symbol (" +4474Twine(GnuHash.symndx) + ")");4475break;4476}4477
4478// Chain ends at symbol with stopper bit.4479if ((Values[SymIndex - GnuHash.symndx] & 1) == 1)4480break;4481}4482}4483}
4484
4485template <class ELFT> void GNUELFDumper<ELFT>::printHashSymbols() {4486if (this->HashTable) {4487OS << "\n Symbol table of .hash for image:\n";4488if (Error E = checkHashTable<ELFT>(*this, this->HashTable))4489this->reportUniqueWarning(std::move(E));4490else4491printHashTableSymbols(*this->HashTable);4492}4493
4494// Try printing the .gnu.hash table.4495if (this->GnuHashTable) {4496OS << "\n Symbol table of .gnu.hash for image:\n";4497if (ELFT::Is64Bits)4498OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4499else4500OS << " Num Buc: Value Size Type Bind Vis Ndx Name";4501OS << "\n";4502
4503if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))4504this->reportUniqueWarning(std::move(E));4505else4506printGnuHashTableSymbols(*this->GnuHashTable);4507}4508}
4509
4510template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() {4511ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());4512if (Sections.empty()) {4513OS << "\nThere are no sections in this file.\n";4514Expected<StringRef> SecStrTableOrErr =4515this->Obj.getSectionStringTable(Sections, this->WarningHandler);4516if (!SecStrTableOrErr)4517this->reportUniqueWarning(SecStrTableOrErr.takeError());4518return;4519}4520OS << "There are " << to_string(Sections.size())4521<< " section headers, starting at offset "4522<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";4523
4524OS << "Section Headers:\n";4525
4526auto PrintFields = [&](ArrayRef<Field> V) {4527for (const Field &F : V)4528printField(F);4529OS << "\n";4530};4531
4532PrintFields({{"[Nr]", 2}, {"Name", 7}});4533
4534constexpr bool Is64 = ELFT::Is64Bits;4535PrintFields({{"Type", 7},4536{Is64 ? "Address" : "Addr", 23},4537{"Off", Is64 ? 40 : 32},4538{"Size", Is64 ? 47 : 39},4539{"ES", Is64 ? 54 : 46},4540{"Lk", Is64 ? 59 : 51},4541{"Inf", Is64 ? 62 : 54},4542{"Al", Is64 ? 66 : 57}});4543PrintFields({{"Flags", 7}});4544
4545StringRef SecStrTable;4546if (Expected<StringRef> SecStrTableOrErr =4547this->Obj.getSectionStringTable(Sections, this->WarningHandler))4548SecStrTable = *SecStrTableOrErr;4549else4550this->reportUniqueWarning(SecStrTableOrErr.takeError());4551
4552size_t SectionIndex = 0;4553const unsigned AddrSize = Is64 ? 16 : 8;4554for (const Elf_Shdr &S : Sections) {4555StringRef Name = "<?>";4556if (Expected<StringRef> NameOrErr =4557this->Obj.getSectionName(S, SecStrTable))4558Name = *NameOrErr;4559else4560this->reportUniqueWarning(NameOrErr.takeError());4561
4562OS.PadToColumn(2);4563OS << "[" << right_justify(to_string(SectionIndex), 2) << "]";4564PrintFields({{Name, 7}});4565PrintFields(4566{{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7},4567{to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23},4568{to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32},4569{to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39},4570{to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46},4571{to_string(S.sh_link), Is64 ? 59 : 51},4572{to_string(S.sh_info), Is64 ? 63 : 55},4573{to_string(S.sh_addralign), Is64 ? 66 : 58}});4574
4575OS.PadToColumn(7);4576OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: ";4577
4578DenseMap<unsigned, StringRef> FlagToName = {4579{SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"},4580{SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"},4581{SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"},4582{SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"},4583{SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"},4584{SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}};4585
4586uint64_t Flags = S.sh_flags;4587uint64_t UnknownFlags = 0;4588ListSeparator LS;4589while (Flags) {4590// Take the least significant bit as a flag.4591uint64_t Flag = Flags & -Flags;4592Flags -= Flag;4593
4594auto It = FlagToName.find(Flag);4595if (It != FlagToName.end())4596OS << LS << It->second;4597else4598UnknownFlags |= Flag;4599}4600
4601auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) {4602uint64_t FlagsToPrint = UnknownFlags & Mask;4603if (!FlagsToPrint)4604return;4605
4606OS << LS << Name << " ("4607<< to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")";4608UnknownFlags &= ~Mask;4609};4610
4611PrintUnknownFlags(SHF_MASKOS, "OS");4612PrintUnknownFlags(SHF_MASKPROC, "PROC");4613PrintUnknownFlags(uint64_t(-1), "UNKNOWN");4614
4615OS << "\n";4616++SectionIndex;4617
4618if (!(S.sh_flags & SHF_COMPRESSED))4619continue;4620Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S);4621if (!Data || Data->size() < sizeof(Elf_Chdr)) {4622consumeError(Data.takeError());4623reportWarning(createError("SHF_COMPRESSED section '" + Name +4624"' does not have an Elf_Chdr header"),4625this->FileName);4626OS.indent(7);4627OS << "[<corrupt>]";4628} else {4629OS.indent(7);4630auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data());4631if (Chdr->ch_type == ELFCOMPRESS_ZLIB)4632OS << "ZLIB";4633else if (Chdr->ch_type == ELFCOMPRESS_ZSTD)4634OS << "ZSTD";4635else4636OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type));4637OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8)4638<< ", " << Chdr->ch_addralign;4639}4640OS << '\n';4641}4642}
4643
4644static inline std::string printPhdrFlags(unsigned Flag) {4645std::string Str;4646Str = (Flag & PF_R) ? "R" : " ";4647Str += (Flag & PF_W) ? "W" : " ";4648Str += (Flag & PF_X) ? "E" : " ";4649return Str;4650}
4651
4652template <class ELFT>4653static bool checkTLSSections(const typename ELFT::Phdr &Phdr,4654const typename ELFT::Shdr &Sec) {4655if (Sec.sh_flags & ELF::SHF_TLS) {4656// .tbss must only be shown in the PT_TLS segment.4657if (Sec.sh_type == ELF::SHT_NOBITS)4658return Phdr.p_type == ELF::PT_TLS;4659
4660// SHF_TLS sections are only shown in PT_TLS, PT_LOAD or PT_GNU_RELRO4661// segments.4662return (Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||4663(Phdr.p_type == ELF::PT_GNU_RELRO);4664}4665
4666// PT_TLS must only have SHF_TLS sections.4667return Phdr.p_type != ELF::PT_TLS;4668}
4669
4670template <class ELFT>4671static bool checkPTDynamic(const typename ELFT::Phdr &Phdr,4672const typename ELFT::Shdr &Sec) {4673if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0)4674return true;4675
4676// We get here when we have an empty section. Only non-empty sections can be4677// at the start or at the end of PT_DYNAMIC.4678// Is section within the phdr both based on offset and VMA?4679bool CheckOffset = (Sec.sh_type == ELF::SHT_NOBITS) ||4680(Sec.sh_offset > Phdr.p_offset &&4681Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz);4682bool CheckVA = !(Sec.sh_flags & ELF::SHF_ALLOC) ||4683(Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz);4684return CheckOffset && CheckVA;4685}
4686
4687template <class ELFT>4688void GNUELFDumper<ELFT>::printProgramHeaders(4689bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {4690const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE);4691// Exit early if no program header or section mapping details were requested.4692if (!PrintProgramHeaders && !ShouldPrintSectionMapping)4693return;4694
4695if (PrintProgramHeaders) {4696const Elf_Ehdr &Header = this->Obj.getHeader();4697if (Header.e_phnum == 0) {4698OS << "\nThere are no program headers in this file.\n";4699} else {4700printProgramHeaders();4701}4702}4703
4704if (ShouldPrintSectionMapping)4705printSectionMapping();4706}
4707
4708template <class ELFT> void GNUELFDumper<ELFT>::printProgramHeaders() {4709unsigned Bias = ELFT::Is64Bits ? 8 : 0;4710const Elf_Ehdr &Header = this->Obj.getHeader();4711Field Fields[8] = {2, 17, 26, 37 + Bias,471248 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};4713OS << "\nElf file type is "4714<< enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n"4715<< "Entry point " << format_hex(Header.e_entry, 3) << "\n"4716<< "There are " << Header.e_phnum << " program headers,"4717<< " starting at offset " << Header.e_phoff << "\n\n"4718<< "Program Headers:\n";4719if (ELFT::Is64Bits)4720OS << " Type Offset VirtAddr PhysAddr "4721<< " FileSiz MemSiz Flg Align\n";4722else4723OS << " Type Offset VirtAddr PhysAddr FileSiz "4724<< "MemSiz Flg Align\n";4725
4726unsigned Width = ELFT::Is64Bits ? 18 : 10;4727unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7;4728
4729Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();4730if (!PhdrsOrErr) {4731this->reportUniqueWarning("unable to dump program headers: " +4732toString(PhdrsOrErr.takeError()));4733return;4734}4735
4736for (const Elf_Phdr &Phdr : *PhdrsOrErr) {4737Fields[0].Str = getGNUPtType(Header.e_machine, Phdr.p_type);4738Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8));4739Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width));4740Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width));4741Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth));4742Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth));4743Fields[6].Str = printPhdrFlags(Phdr.p_flags);4744Fields[7].Str = to_string(format_hex(Phdr.p_align, 1));4745for (const Field &F : Fields)4746printField(F);4747if (Phdr.p_type == ELF::PT_INTERP) {4748OS << "\n";4749auto ReportBadInterp = [&](const Twine &Msg) {4750this->reportUniqueWarning(4751"unable to read program interpreter name at offset 0x" +4752Twine::utohexstr(Phdr.p_offset) + ": " + Msg);4753};4754
4755if (Phdr.p_offset >= this->Obj.getBufSize()) {4756ReportBadInterp("it goes past the end of the file (0x" +4757Twine::utohexstr(this->Obj.getBufSize()) + ")");4758continue;4759}4760
4761const char *Data =4762reinterpret_cast<const char *>(this->Obj.base()) + Phdr.p_offset;4763size_t MaxSize = this->Obj.getBufSize() - Phdr.p_offset;4764size_t Len = strnlen(Data, MaxSize);4765if (Len == MaxSize) {4766ReportBadInterp("it is not null-terminated");4767continue;4768}4769
4770OS << " [Requesting program interpreter: ";4771OS << StringRef(Data, Len) << "]";4772}4773OS << "\n";4774}4775}
4776
4777template <class ELFT> void GNUELFDumper<ELFT>::printSectionMapping() {4778OS << "\n Section to Segment mapping:\n Segment Sections...\n";4779DenseSet<const Elf_Shdr *> BelongsToSegment;4780int Phnum = 0;4781
4782Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();4783if (!PhdrsOrErr) {4784this->reportUniqueWarning(4785"can't read program headers to build section to segment mapping: " +4786toString(PhdrsOrErr.takeError()));4787return;4788}4789
4790for (const Elf_Phdr &Phdr : *PhdrsOrErr) {4791std::string Sections;4792OS << format(" %2.2d ", Phnum++);4793// Check if each section is in a segment and then print mapping.4794for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {4795if (Sec.sh_type == ELF::SHT_NULL)4796continue;4797
4798// readelf additionally makes sure it does not print zero sized sections4799// at end of segments and for PT_DYNAMIC both start and end of section4800// .tbss must only be shown in PT_TLS section.4801if (isSectionInSegment<ELFT>(Phdr, Sec) &&4802checkTLSSections<ELFT>(Phdr, Sec) &&4803checkPTDynamic<ELFT>(Phdr, Sec)) {4804Sections +=4805unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +4806" ";4807BelongsToSegment.insert(&Sec);4808}4809}4810OS << Sections << "\n";4811OS.flush();4812}4813
4814// Display sections that do not belong to a segment.4815std::string Sections;4816for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {4817if (BelongsToSegment.find(&Sec) == BelongsToSegment.end())4818Sections +=4819unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +4820' ';4821}4822if (!Sections.empty()) {4823OS << " None " << Sections << '\n';4824OS.flush();4825}4826}
4827
4828namespace {4829
4830template <class ELFT>4831RelSymbol<ELFT> getSymbolForReloc(const ELFDumper<ELFT> &Dumper,4832const Relocation<ELFT> &Reloc) {4833using Elf_Sym = typename ELFT::Sym;4834auto WarnAndReturn = [&](const Elf_Sym *Sym,4835const Twine &Reason) -> RelSymbol<ELFT> {4836Dumper.reportUniqueWarning(4837"unable to get name of the dynamic symbol with index " +4838Twine(Reloc.Symbol) + ": " + Reason);4839return {Sym, "<corrupt>"};4840};4841
4842ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols();4843const Elf_Sym *FirstSym = Symbols.begin();4844if (!FirstSym)4845return WarnAndReturn(nullptr, "no dynamic symbol table found");4846
4847// We might have an object without a section header. In this case the size of4848// Symbols is zero, because there is no way to know the size of the dynamic4849// table. We should allow this case and not print a warning.4850if (!Symbols.empty() && Reloc.Symbol >= Symbols.size())4851return WarnAndReturn(4852nullptr,4853"index is greater than or equal to the number of dynamic symbols (" +4854Twine(Symbols.size()) + ")");4855
4856const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();4857const uint64_t FileSize = Obj.getBufSize();4858const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) +4859(uint64_t)Reloc.Symbol * sizeof(Elf_Sym);4860if (SymOffset + sizeof(Elf_Sym) > FileSize)4861return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) +4862" goes past the end of the file (0x" +4863Twine::utohexstr(FileSize) + ")");4864
4865const Elf_Sym *Sym = FirstSym + Reloc.Symbol;4866Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable());4867if (!ErrOrName)4868return WarnAndReturn(Sym, toString(ErrOrName.takeError()));4869
4870return {Sym == FirstSym ? nullptr : Sym, maybeDemangle(*ErrOrName)};4871}
4872} // namespace4873
4874template <class ELFT>4875static size_t getMaxDynamicTagSize(const ELFFile<ELFT> &Obj,4876typename ELFT::DynRange Tags) {4877size_t Max = 0;4878for (const typename ELFT::Dyn &Dyn : Tags)4879Max = std::max(Max, Obj.getDynamicTagAsString(Dyn.d_tag).size());4880return Max;4881}
4882
4883template <class ELFT> void GNUELFDumper<ELFT>::printDynamicTable() {4884Elf_Dyn_Range Table = this->dynamic_table();4885if (Table.empty())4886return;4887
4888OS << "Dynamic section at offset "4889<< format_hex(reinterpret_cast<const uint8_t *>(this->DynamicTable.Addr) -4890this->Obj.base(),48911)4892<< " contains " << Table.size() << " entries:\n";4893
4894// The type name is surrounded with round brackets, hence add 2.4895size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table) + 2;4896// The "Name/Value" column should be indented from the "Type" column by N4897// spaces, where N = MaxTagSize - length of "Type" (4) + trailing4898// space (1) = 3.4899OS << " Tag" + std::string(ELFT::Is64Bits ? 16 : 8, ' ') + "Type"4900<< std::string(MaxTagSize - 3, ' ') << "Name/Value\n";4901
4902std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s ";4903for (auto Entry : Table) {4904uintX_t Tag = Entry.getTag();4905std::string Type =4906std::string("(") + this->Obj.getDynamicTagAsString(Tag) + ")";4907std::string Value = this->getDynamicEntry(Tag, Entry.getVal());4908OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10)4909<< format(ValueFmt.c_str(), Type.c_str()) << Value << "\n";4910}4911}
4912
4913template <class ELFT> void GNUELFDumper<ELFT>::printDynamicRelocations() {4914this->printDynamicRelocationsHelper();4915}
4916
4917template <class ELFT>4918void ELFDumper<ELFT>::printDynamicReloc(const Relocation<ELFT> &R) {4919printRelRelaReloc(R, getSymbolForReloc(*this, R));4920}
4921
4922template <class ELFT>4923void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) {4924this->forEachRelocationDo(4925Sec, [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec,4926const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); });4927}
4928
4929template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() {4930const bool IsMips64EL = this->Obj.isMips64EL();4931auto DumpCrelRegion = [&](DynRegionInfo &Region) {4932// While the size is unknown, a valid CREL has at least one byte. We can4933// check whether Addr is in bounds, and then decode CREL until the file4934// end.4935Region.Size = Region.EntSize = 1;4936if (!Region.template getAsArrayRef<uint8_t>().empty()) {4937const uint64_t Offset =4938Region.Addr - reinterpret_cast<const uint8_t *>(4939ObjF.getMemoryBufferRef().getBufferStart());4940const uint64_t ObjSize = ObjF.getMemoryBufferRef().getBufferSize();4941auto RelsOrRelas =4942Obj.decodeCrel(ArrayRef<uint8_t>(Region.Addr, ObjSize - Offset));4943if (!RelsOrRelas) {4944reportUniqueWarning(toString(RelsOrRelas.takeError()));4945} else {4946for (const Elf_Rel &R : RelsOrRelas->first)4947printDynamicReloc(Relocation<ELFT>(R, false));4948for (const Elf_Rela &R : RelsOrRelas->second)4949printDynamicReloc(Relocation<ELFT>(R, false));4950}4951}4952};4953
4954if (this->DynCrelRegion.Addr) {4955printDynamicRelocHeader(ELF::SHT_CREL, "CREL", this->DynCrelRegion);4956DumpCrelRegion(this->DynCrelRegion);4957}4958
4959if (this->DynRelaRegion.Size > 0) {4960printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion);4961for (const Elf_Rela &Rela :4962this->DynRelaRegion.template getAsArrayRef<Elf_Rela>())4963printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));4964}4965
4966if (this->DynRelRegion.Size > 0) {4967printDynamicRelocHeader(ELF::SHT_REL, "REL", this->DynRelRegion);4968for (const Elf_Rel &Rel :4969this->DynRelRegion.template getAsArrayRef<Elf_Rel>())4970printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4971}4972
4973if (this->DynRelrRegion.Size > 0) {4974printDynamicRelocHeader(ELF::SHT_REL, "RELR", this->DynRelrRegion);4975Elf_Relr_Range Relrs =4976this->DynRelrRegion.template getAsArrayRef<Elf_Relr>();4977for (const Elf_Rel &Rel : Obj.decode_relrs(Relrs))4978printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4979}4980
4981if (this->DynPLTRelRegion.Size) {4982if (this->DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {4983printDynamicRelocHeader(ELF::SHT_RELA, "PLT", this->DynPLTRelRegion);4984for (const Elf_Rela &Rela :4985this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>())4986printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));4987} else if (this->DynPLTRelRegion.EntSize == 1) {4988DumpCrelRegion(this->DynPLTRelRegion);4989} else {4990printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion);4991for (const Elf_Rel &Rel :4992this->DynPLTRelRegion.template getAsArrayRef<Elf_Rel>())4993printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));4994}4995}4996}
4997
4998template <class ELFT>4999void GNUELFDumper<ELFT>::printGNUVersionSectionProlog(5000const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) {5001// Don't inline the SecName, because it might report a warning to stderr and5002// corrupt the output.5003StringRef SecName = this->getPrintableSectionName(Sec);5004OS << Label << " section '" << SecName << "' "5005<< "contains " << EntriesNum << " entries:\n";5006
5007StringRef LinkedSecName = "<corrupt>";5008if (Expected<const typename ELFT::Shdr *> LinkedSecOrErr =5009this->Obj.getSection(Sec.sh_link))5010LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr);5011else5012this->reportUniqueWarning("invalid section linked to " +5013this->describe(Sec) + ": " +5014toString(LinkedSecOrErr.takeError()));5015
5016OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16)5017<< " Offset: " << format_hex(Sec.sh_offset, 8)5018<< " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n";5019}
5020
5021template <class ELFT>5022void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {5023if (!Sec)5024return;5025
5026printGNUVersionSectionProlog(*Sec, "Version symbols",5027Sec->sh_size / sizeof(Elf_Versym));5028Expected<ArrayRef<Elf_Versym>> VerTableOrErr =5029this->getVersionTable(*Sec, /*SymTab=*/nullptr,5030/*StrTab=*/nullptr, /*SymTabSec=*/nullptr);5031if (!VerTableOrErr) {5032this->reportUniqueWarning(VerTableOrErr.takeError());5033return;5034}5035
5036SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr;5037if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =5038this->getVersionMap())5039VersionMap = *MapOrErr;5040else5041this->reportUniqueWarning(MapOrErr.takeError());5042
5043ArrayRef<Elf_Versym> VerTable = *VerTableOrErr;5044std::vector<StringRef> Versions;5045for (size_t I = 0, E = VerTable.size(); I < E; ++I) {5046unsigned Ndx = VerTable[I].vs_index;5047if (Ndx == VER_NDX_LOCAL || Ndx == VER_NDX_GLOBAL) {5048Versions.emplace_back(Ndx == VER_NDX_LOCAL ? "*local*" : "*global*");5049continue;5050}5051
5052if (!VersionMap) {5053Versions.emplace_back("<corrupt>");5054continue;5055}5056
5057bool IsDefault;5058Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex(5059Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt);5060if (!NameOrErr) {5061this->reportUniqueWarning("unable to get a version for entry " +5062Twine(I) + " of " + this->describe(*Sec) +5063": " + toString(NameOrErr.takeError()));5064Versions.emplace_back("<corrupt>");5065continue;5066}5067Versions.emplace_back(*NameOrErr);5068}5069
5070// readelf prints 4 entries per line.5071uint64_t Entries = VerTable.size();5072for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {5073OS << " " << format_hex_no_prefix(VersymRow, 3) << ":";5074for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) {5075unsigned Ndx = VerTable[VersymRow + I].vs_index;5076OS << format("%4x%c", Ndx & VERSYM_VERSION,5077Ndx & VERSYM_HIDDEN ? 'h' : ' ');5078OS << left_justify("(" + std::string(Versions[VersymRow + I]) + ")", 13);5079}5080OS << '\n';5081}5082OS << '\n';5083}
5084
5085static std::string versionFlagToString(unsigned Flags) {5086if (Flags == 0)5087return "none";5088
5089std::string Ret;5090auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) {5091if (!(Flags & Flag))5092return;5093if (!Ret.empty())5094Ret += " | ";5095Ret += Name;5096Flags &= ~Flag;5097};5098
5099AddFlag(VER_FLG_BASE, "BASE");5100AddFlag(VER_FLG_WEAK, "WEAK");5101AddFlag(VER_FLG_INFO, "INFO");5102AddFlag(~0, "<unknown>");5103return Ret;5104}
5105
5106template <class ELFT>5107void GNUELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {5108if (!Sec)5109return;5110
5111printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info);5112
5113Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);5114if (!V) {5115this->reportUniqueWarning(V.takeError());5116return;5117}5118
5119for (const VerDef &Def : *V) {5120OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u Name: %s\n",5121Def.Offset, Def.Version,5122versionFlagToString(Def.Flags).c_str(), Def.Ndx, Def.Cnt,5123Def.Name.data());5124unsigned I = 0;5125for (const VerdAux &Aux : Def.AuxV)5126OS << format(" 0x%04x: Parent %u: %s\n", Aux.Offset, ++I,5127Aux.Name.data());5128}5129
5130OS << '\n';5131}
5132
5133template <class ELFT>5134void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {5135if (!Sec)5136return;5137
5138unsigned VerneedNum = Sec->sh_info;5139printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum);5140
5141Expected<std::vector<VerNeed>> V =5142this->Obj.getVersionDependencies(*Sec, this->WarningHandler);5143if (!V) {5144this->reportUniqueWarning(V.takeError());5145return;5146}5147
5148for (const VerNeed &VN : *V) {5149OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset,5150VN.Version, VN.File.data(), VN.Cnt);5151for (const VernAux &Aux : VN.AuxV)5152OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset,5153Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(),5154Aux.Other);5155}5156OS << '\n';5157}
5158
5159template <class ELFT>5160void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,5161size_t MaxChain,5162size_t TotalSyms,5163ArrayRef<size_t> Count,5164bool IsGnu) const {5165size_t CumulativeNonZero = 0;5166OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "")5167<< " bucket list length (total of " << NBucket << " buckets)\n"5168<< " Length Number % of total Coverage\n";5169for (size_t I = 0; I < MaxChain; ++I) {5170CumulativeNonZero += Count[I] * I;5171OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I],5172(Count[I] * 100.0) / NBucket,5173(CumulativeNonZero * 100.0) / TotalSyms);5174}5175}
5176
5177template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {5178OS << "GNUStyle::printCGProfile not implemented\n";5179}
5180
5181template <class ELFT>5182void GNUELFDumper<ELFT>::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) {5183OS << "GNUStyle::printBBAddrMaps not implemented\n";5184}
5185
5186static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {5187std::vector<uint64_t> Ret;5188const uint8_t *Cur = Data.begin();5189const uint8_t *End = Data.end();5190while (Cur != End) {5191unsigned Size;5192const char *Err = nullptr;5193Ret.push_back(decodeULEB128(Cur, &Size, End, &Err));5194if (Err)5195return createError(Err);5196Cur += Size;5197}5198return Ret;5199}
5200
5201template <class ELFT>5202static Expected<std::vector<uint64_t>>5203decodeAddrsigSection(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) {5204Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Sec);5205if (!ContentsOrErr)5206return ContentsOrErr.takeError();5207
5208if (Expected<std::vector<uint64_t>> SymsOrErr =5209toULEB128Array(*ContentsOrErr))5210return *SymsOrErr;5211else5212return createError("unable to decode " + describe(Obj, Sec) + ": " +5213toString(SymsOrErr.takeError()));5214}
5215
5216template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() {5217if (!this->DotAddrsigSec)5218return;5219
5220Expected<std::vector<uint64_t>> SymsOrErr =5221decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);5222if (!SymsOrErr) {5223this->reportUniqueWarning(SymsOrErr.takeError());5224return;5225}5226
5227StringRef Name = this->getPrintableSectionName(*this->DotAddrsigSec);5228OS << "\nAddress-significant symbols section '" << Name << "'"5229<< " contains " << SymsOrErr->size() << " entries:\n";5230OS << " Num: Name\n";5231
5232Field Fields[2] = {0, 8};5233size_t SymIndex = 0;5234for (uint64_t Sym : *SymsOrErr) {5235Fields[0].Str = to_string(format_decimal(++SymIndex, 6)) + ":";5236Fields[1].Str = this->getStaticSymbolName(Sym);5237for (const Field &Entry : Fields)5238printField(Entry);5239OS << "\n";5240}5241}
5242
5243template <class ELFT>5244static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,5245ArrayRef<uint8_t> Desc) {5246OS << " AArch64 PAuth ABI core info: ";5247// DataSize - size without padding, Desc.size() - size with padding5248if (DataSize != 16) {5249OS << format("<corrupted size: expected 16, got %d>", DataSize);5250return false;5251}5252
5253uint64_t Platform =5254support::endian::read64<ELFT::Endianness>(Desc.data() + 0);5255uint64_t Version = support::endian::read64<ELFT::Endianness>(Desc.data() + 8);5256
5257const char *PlatformDesc = [Platform]() {5258switch (Platform) {5259case AARCH64_PAUTH_PLATFORM_INVALID:5260return "invalid";5261case AARCH64_PAUTH_PLATFORM_BAREMETAL:5262return "baremetal";5263case AARCH64_PAUTH_PLATFORM_LLVM_LINUX:5264return "llvm_linux";5265default:5266return "unknown";5267}5268}();5269
5270std::string VersionDesc = [Platform, Version]() -> std::string {5271if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX)5272return "";5273if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1)))5274return "unknown";5275
5276std::array<StringRef, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1>5277Flags;5278Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS] = "Intrinsics";5279Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS] = "Calls";5280Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS] = "Returns";5281Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS] = "AuthTraps";5282Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR] =5283"VTPtrAddressDiscrimination";5284Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] =5285"VTPtrTypeDiscrimination";5286Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini";5287
5288static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI ==5289AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,5290"Update when new enum items are defined");5291
5292std::string Desc;5293for (uint32_t I = 0, End = Flags.size(); I < End; ++I) {5294if (!(Version & (1ULL << I)))5295Desc += '!';5296Desc +=5297Twine("PointerAuth" + Flags[I] + (I == End - 1 ? "" : ", ")).str();5298}5299return Desc;5300}();5301
5302OS << format("platform 0x%" PRIx64 " (%s), version 0x%" PRIx64, Platform,5303PlatformDesc, Version);5304if (!VersionDesc.empty())5305OS << format(" (%s)", VersionDesc.c_str());5306
5307return true;5308}
5309
5310template <typename ELFT>5311static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,5312ArrayRef<uint8_t> Data) {5313std::string str;5314raw_string_ostream OS(str);5315uint32_t PrData;5316auto DumpBit = [&](uint32_t Flag, StringRef Name) {5317if (PrData & Flag) {5318PrData &= ~Flag;5319OS << Name;5320if (PrData)5321OS << ", ";5322}5323};5324
5325switch (Type) {5326default:5327OS << format("<application-specific type 0x%x>", Type);5328return OS.str();5329case GNU_PROPERTY_STACK_SIZE: {5330OS << "stack size: ";5331if (DataSize == sizeof(typename ELFT::uint))5332OS << formatv("{0:x}",5333(uint64_t)(*(const typename ELFT::Addr *)Data.data()));5334else5335OS << format("<corrupt length: 0x%x>", DataSize);5336return OS.str();5337}5338case GNU_PROPERTY_NO_COPY_ON_PROTECTED:5339OS << "no copy on protected";5340if (DataSize)5341OS << format(" <corrupt length: 0x%x>", DataSize);5342return OS.str();5343case GNU_PROPERTY_AARCH64_FEATURE_1_AND:5344case GNU_PROPERTY_X86_FEATURE_1_AND:5345OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "5346: "x86 feature: ");5347if (DataSize != 4) {5348OS << format("<corrupt length: 0x%x>", DataSize);5349return OS.str();5350}5351PrData = endian::read32<ELFT::Endianness>(Data.data());5352if (PrData == 0) {5353OS << "<None>";5354return OS.str();5355}5356if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {5357DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");5358DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");5359DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");5360} else {5361DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");5362DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");5363}5364if (PrData)5365OS << format("<unknown flags: 0x%x>", PrData);5366return OS.str();5367case GNU_PROPERTY_AARCH64_FEATURE_PAUTH:5368printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data);5369return OS.str();5370case GNU_PROPERTY_X86_FEATURE_2_NEEDED:5371case GNU_PROPERTY_X86_FEATURE_2_USED:5372OS << "x86 feature "5373<< (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: ");5374if (DataSize != 4) {5375OS << format("<corrupt length: 0x%x>", DataSize);5376return OS.str();5377}5378PrData = endian::read32<ELFT::Endianness>(Data.data());5379if (PrData == 0) {5380OS << "<None>";5381return OS.str();5382}5383DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86");5384DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87");5385DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX");5386DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM");5387DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM");5388DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM");5389DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR");5390DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE");5391DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT");5392DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC");5393if (PrData)5394OS << format("<unknown flags: 0x%x>", PrData);5395return OS.str();5396case GNU_PROPERTY_X86_ISA_1_NEEDED:5397case GNU_PROPERTY_X86_ISA_1_USED:5398OS << "x86 ISA "5399<< (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");5400if (DataSize != 4) {5401OS << format("<corrupt length: 0x%x>", DataSize);5402return OS.str();5403}5404PrData = endian::read32<ELFT::Endianness>(Data.data());5405if (PrData == 0) {5406OS << "<None>";5407return OS.str();5408}5409DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline");5410DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2");5411DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3");5412DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4");5413if (PrData)5414OS << format("<unknown flags: 0x%x>", PrData);5415return OS.str();5416}5417}
5418
5419template <typename ELFT>5420static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {5421using Elf_Word = typename ELFT::Word;5422
5423SmallVector<std::string, 4> Properties;5424while (Arr.size() >= 8) {5425uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());5426uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);5427Arr = Arr.drop_front(8);5428
5429// Take padding size into account if present.5430uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));5431std::string str;5432raw_string_ostream OS(str);5433if (Arr.size() < PaddedSize) {5434OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize);5435Properties.push_back(OS.str());5436break;5437}5438Properties.push_back(5439getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));5440Arr = Arr.drop_front(PaddedSize);5441}5442
5443if (!Arr.empty())5444Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>");5445
5446return Properties;5447}
5448
5449struct GNUAbiTag {5450std::string OSName;5451std::string ABI;5452bool IsValid;5453};5454
5455template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) {5456typedef typename ELFT::Word Elf_Word;5457
5458ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()),5459reinterpret_cast<const Elf_Word *>(Desc.end()));5460
5461if (Words.size() < 4)5462return {"", "", /*IsValid=*/false};5463
5464static const char *OSNames[] = {5465"Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",5466};5467StringRef OSName = "Unknown";5468if (Words[0] < std::size(OSNames))5469OSName = OSNames[Words[0]];5470uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3];5471std::string str;5472raw_string_ostream ABI(str);5473ABI << Major << "." << Minor << "." << Patch;5474return {std::string(OSName), ABI.str(), /*IsValid=*/true};5475}
5476
5477static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) {5478std::string str;5479raw_string_ostream OS(str);5480for (uint8_t B : Desc)5481OS << format_hex_no_prefix(B, 2);5482return OS.str();5483}
5484
5485static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {5486return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());5487}
5488
5489template <typename ELFT>5490static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,5491ArrayRef<uint8_t> Desc) {5492// Return true if we were able to pretty-print the note, false otherwise.5493switch (NoteType) {5494default:5495return false;5496case ELF::NT_GNU_ABI_TAG: {5497const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);5498if (!AbiTag.IsValid)5499OS << " <corrupt GNU_ABI_TAG>";5500else5501OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI;5502break;5503}5504case ELF::NT_GNU_BUILD_ID: {5505OS << " Build ID: " << getGNUBuildId(Desc);5506break;5507}5508case ELF::NT_GNU_GOLD_VERSION:5509OS << " Version: " << getDescAsStringRef(Desc);5510break;5511case ELF::NT_GNU_PROPERTY_TYPE_0:5512OS << " Properties:";5513for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))5514OS << " " << Property << "\n";5515break;5516}5517OS << '\n';5518return true;5519}
5520
5521using AndroidNoteProperties = std::vector<std::pair<StringRef, std::string>>;5522static AndroidNoteProperties getAndroidNoteProperties(uint32_t NoteType,5523ArrayRef<uint8_t> Desc) {5524AndroidNoteProperties Props;5525switch (NoteType) {5526case ELF::NT_ANDROID_TYPE_MEMTAG:5527if (Desc.empty()) {5528Props.emplace_back("Invalid .note.android.memtag", "");5529return Props;5530}5531
5532switch (Desc[0] & NT_MEMTAG_LEVEL_MASK) {5533case NT_MEMTAG_LEVEL_NONE:5534Props.emplace_back("Tagging Mode", "NONE");5535break;5536case NT_MEMTAG_LEVEL_ASYNC:5537Props.emplace_back("Tagging Mode", "ASYNC");5538break;5539case NT_MEMTAG_LEVEL_SYNC:5540Props.emplace_back("Tagging Mode", "SYNC");5541break;5542default:5543Props.emplace_back(5544"Tagging Mode",5545("Unknown (" + Twine::utohexstr(Desc[0] & NT_MEMTAG_LEVEL_MASK) + ")")5546.str());5547break;5548}5549Props.emplace_back("Heap",5550(Desc[0] & NT_MEMTAG_HEAP) ? "Enabled" : "Disabled");5551Props.emplace_back("Stack",5552(Desc[0] & NT_MEMTAG_STACK) ? "Enabled" : "Disabled");5553break;5554default:5555return Props;5556}5557return Props;5558}
5559
5560static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,5561ArrayRef<uint8_t> Desc) {5562// Return true if we were able to pretty-print the note, false otherwise.5563AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);5564if (Props.empty())5565return false;5566for (const auto &KV : Props)5567OS << " " << KV.first << ": " << KV.second << '\n';5568return true;5569}
5570
5571template <class ELFT>5572void GNUELFDumper<ELFT>::printMemtag(5573const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,5574const ArrayRef<uint8_t> AndroidNoteDesc,5575const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {5576OS << "Memtag Dynamic Entries:\n";5577if (DynamicEntries.empty())5578OS << " < none found >\n";5579for (const auto &DynamicEntryKV : DynamicEntries)5580OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second5581<< "\n";5582
5583if (!AndroidNoteDesc.empty()) {5584OS << "Memtag Android Note:\n";5585printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc);5586}5587
5588if (Descriptors.empty())5589return;5590
5591OS << "Memtag Global Descriptors:\n";5592for (const auto &[Addr, BytesToTag] : Descriptors) {5593OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x"5594<< utohexstr(BytesToTag, /*LowerCase=*/true) << "\n";5595}5596}
5597
5598template <typename ELFT>5599static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType,5600ArrayRef<uint8_t> Desc) {5601switch (NoteType) {5602default:5603return false;5604case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:5605OS << " Version: " << getDescAsStringRef(Desc);5606break;5607case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:5608OS << " Producer: " << getDescAsStringRef(Desc);5609break;5610case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:5611OS << " Producer version: " << getDescAsStringRef(Desc);5612break;5613}5614OS << '\n';5615return true;5616}
5617
5618const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = {5619{"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE},5620{"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE},5621{"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE},5622{"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED},5623{"LA48", NT_FREEBSD_FCTL_LA48},5624{"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE},5625};5626
5627struct FreeBSDNote {5628std::string Type;5629std::string Value;5630};5631
5632template <typename ELFT>5633static std::optional<FreeBSDNote>5634getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) {5635if (IsCore)5636return std::nullopt; // No pretty-printing yet.5637switch (NoteType) {5638case ELF::NT_FREEBSD_ABI_TAG:5639if (Desc.size() != 4)5640return std::nullopt;5641return FreeBSDNote{"ABI tag",5642utostr(endian::read32<ELFT::Endianness>(Desc.data()))};5643case ELF::NT_FREEBSD_ARCH_TAG:5644return FreeBSDNote{"Arch tag", toStringRef(Desc).str()};5645case ELF::NT_FREEBSD_FEATURE_CTL: {5646if (Desc.size() != 4)5647return std::nullopt;5648unsigned Value = endian::read32<ELFT::Endianness>(Desc.data());5649std::string FlagsStr;5650raw_string_ostream OS(FlagsStr);5651printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS);5652if (OS.str().empty())5653OS << "0x" << utohexstr(Value);5654else5655OS << "(0x" << utohexstr(Value) << ")";5656return FreeBSDNote{"Feature flags", OS.str()};5657}5658default:5659return std::nullopt;5660}5661}
5662
5663struct AMDNote {5664std::string Type;5665std::string Value;5666};5667
5668template <typename ELFT>5669static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {5670switch (NoteType) {5671default:5672return {"", ""};5673case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: {5674struct CodeObjectVersion {5675support::aligned_ulittle32_t MajorVersion;5676support::aligned_ulittle32_t MinorVersion;5677};5678if (Desc.size() != sizeof(CodeObjectVersion))5679return {"AMD HSA Code Object Version",5680"Invalid AMD HSA Code Object Version"};5681std::string VersionString;5682raw_string_ostream StrOS(VersionString);5683auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data());5684StrOS << "[Major: " << Version->MajorVersion5685<< ", Minor: " << Version->MinorVersion << "]";5686return {"AMD HSA Code Object Version", VersionString};5687}5688case ELF::NT_AMD_HSA_HSAIL: {5689struct HSAILProperties {5690support::aligned_ulittle32_t HSAILMajorVersion;5691support::aligned_ulittle32_t HSAILMinorVersion;5692uint8_t Profile;5693uint8_t MachineModel;5694uint8_t DefaultFloatRound;5695};5696if (Desc.size() != sizeof(HSAILProperties))5697return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"};5698auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data());5699std::string HSAILPropetiesString;5700raw_string_ostream StrOS(HSAILPropetiesString);5701StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion5702<< ", HSAIL Minor: " << Properties->HSAILMinorVersion5703<< ", Profile: " << uint32_t(Properties->Profile)5704<< ", Machine Model: " << uint32_t(Properties->MachineModel)5705<< ", Default Float Round: "5706<< uint32_t(Properties->DefaultFloatRound) << "]";5707return {"AMD HSA HSAIL Properties", HSAILPropetiesString};5708}5709case ELF::NT_AMD_HSA_ISA_VERSION: {5710struct IsaVersion {5711support::aligned_ulittle16_t VendorNameSize;5712support::aligned_ulittle16_t ArchitectureNameSize;5713support::aligned_ulittle32_t Major;5714support::aligned_ulittle32_t Minor;5715support::aligned_ulittle32_t Stepping;5716};5717if (Desc.size() < sizeof(IsaVersion))5718return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};5719auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data());5720if (Desc.size() < sizeof(IsaVersion) +5721Isa->VendorNameSize + Isa->ArchitectureNameSize ||5722Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0)5723return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};5724std::string IsaString;5725raw_string_ostream StrOS(IsaString);5726StrOS << "[Vendor: "5727<< StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1)5728<< ", Architecture: "5729<< StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize,5730Isa->ArchitectureNameSize - 1)5731<< ", Major: " << Isa->Major << ", Minor: " << Isa->Minor5732<< ", Stepping: " << Isa->Stepping << "]";5733return {"AMD HSA ISA Version", IsaString};5734}5735case ELF::NT_AMD_HSA_METADATA: {5736if (Desc.size() == 0)5737return {"AMD HSA Metadata", ""};5738return {5739"AMD HSA Metadata",5740std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)};5741}5742case ELF::NT_AMD_HSA_ISA_NAME: {5743if (Desc.size() == 0)5744return {"AMD HSA ISA Name", ""};5745return {5746"AMD HSA ISA Name",5747std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};5748}5749case ELF::NT_AMD_PAL_METADATA: {5750struct PALMetadata {5751support::aligned_ulittle32_t Key;5752support::aligned_ulittle32_t Value;5753};5754if (Desc.size() % sizeof(PALMetadata) != 0)5755return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"};5756auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data());5757std::string MetadataString;5758raw_string_ostream StrOS(MetadataString);5759for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) {5760StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]";5761}5762return {"AMD PAL Metadata", MetadataString};5763}5764}5765}
5766
5767struct AMDGPUNote {5768std::string Type;5769std::string Value;5770};5771
5772template <typename ELFT>5773static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {5774switch (NoteType) {5775default:5776return {"", ""};5777case ELF::NT_AMDGPU_METADATA: {5778StringRef MsgPackString =5779StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());5780msgpack::Document MsgPackDoc;5781if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))5782return {"", ""};5783
5784std::string MetadataString;5785
5786// FIXME: Metadata Verifier only works with AMDHSA.5787// This is an ugly workaround to avoid the verifier for other MD5788// formats (e.g. amdpal)5789if (MsgPackString.contains("amdhsa.")) {5790AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);5791if (!Verifier.verify(MsgPackDoc.getRoot()))5792MetadataString = "Invalid AMDGPU Metadata\n";5793}5794
5795raw_string_ostream StrOS(MetadataString);5796if (MsgPackDoc.getRoot().isScalar()) {5797// TODO: passing a scalar root to toYAML() asserts:5798// (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar &&5799// "plain scalar documents are not supported")5800// To avoid this crash we print the raw data instead.5801return {"", ""};5802}5803MsgPackDoc.toYAML(StrOS);5804return {"AMDGPU Metadata", StrOS.str()};5805}5806}5807}
5808
5809struct CoreFileMapping {5810uint64_t Start, End, Offset;5811StringRef Filename;5812};5813
5814struct CoreNote {5815uint64_t PageSize;5816std::vector<CoreFileMapping> Mappings;5817};5818
5819static Expected<CoreNote> readCoreNote(DataExtractor Desc) {5820// Expected format of the NT_FILE note description:5821// 1. # of file mappings (call it N)5822// 2. Page size5823// 3. N (start, end, offset) triples5824// 4. N packed filenames (null delimited)5825// Each field is an Elf_Addr, except for filenames which are char* strings.5826
5827CoreNote Ret;5828const int Bytes = Desc.getAddressSize();5829
5830if (!Desc.isValidOffsetForAddress(2))5831return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) +5832" is too short, expected at least 0x" +5833Twine::utohexstr(Bytes * 2));5834if (Desc.getData().back() != 0)5835return createError("the note is not NUL terminated");5836
5837uint64_t DescOffset = 0;5838uint64_t FileCount = Desc.getAddress(&DescOffset);5839Ret.PageSize = Desc.getAddress(&DescOffset);5840
5841if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes))5842return createError("unable to read file mappings (found " +5843Twine(FileCount) + "): the note of size 0x" +5844Twine::utohexstr(Desc.size()) + " is too short");5845
5846uint64_t FilenamesOffset = 0;5847DataExtractor Filenames(5848Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes),5849Desc.isLittleEndian(), Desc.getAddressSize());5850
5851Ret.Mappings.resize(FileCount);5852size_t I = 0;5853for (CoreFileMapping &Mapping : Ret.Mappings) {5854++I;5855if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1))5856return createError(5857"unable to read the file name for the mapping with index " +5858Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) +5859" is truncated");5860Mapping.Start = Desc.getAddress(&DescOffset);5861Mapping.End = Desc.getAddress(&DescOffset);5862Mapping.Offset = Desc.getAddress(&DescOffset);5863Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset);5864}5865
5866return Ret;5867}
5868
5869template <typename ELFT>5870static void printCoreNote(raw_ostream &OS, const CoreNote &Note) {5871// Length of "0x<address>" string.5872const int FieldWidth = ELFT::Is64Bits ? 18 : 10;5873
5874OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n';5875OS << " " << right_justify("Start", FieldWidth) << " "5876<< right_justify("End", FieldWidth) << " "5877<< right_justify("Page Offset", FieldWidth) << '\n';5878for (const CoreFileMapping &Mapping : Note.Mappings) {5879OS << " " << format_hex(Mapping.Start, FieldWidth) << " "5880<< format_hex(Mapping.End, FieldWidth) << " "5881<< format_hex(Mapping.Offset, FieldWidth) << "\n "5882<< Mapping.Filename << '\n';5883}5884}
5885
5886const NoteType GenericNoteTypes[] = {5887{ELF::NT_VERSION, "NT_VERSION (version)"},5888{ELF::NT_ARCH, "NT_ARCH (architecture)"},5889{ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"},5890{ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"},5891};5892
5893const NoteType GNUNoteTypes[] = {5894{ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"},5895{ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},5896{ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},5897{ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},5898{ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},5899};5900
5901const NoteType FreeBSDCoreNoteTypes[] = {5902{ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},5903{ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},5904{ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"},5905{ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"},5906{ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"},5907{ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"},5908{ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"},5909{ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"},5910{ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS,5911"NT_PROCSTAT_PSSTRINGS (ps_strings data)"},5912{ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"},5913};5914
5915const NoteType FreeBSDNoteTypes[] = {5916{ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"},5917{ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"},5918{ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"},5919{ELF::NT_FREEBSD_FEATURE_CTL,5920"NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},5921};5922
5923const NoteType NetBSDCoreNoteTypes[] = {5924{ELF::NT_NETBSDCORE_PROCINFO,5925"NT_NETBSDCORE_PROCINFO (procinfo structure)"},5926{ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"},5927{ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"},5928};5929
5930const NoteType OpenBSDCoreNoteTypes[] = {5931{ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"},5932{ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"},5933{ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"},5934{ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"},5935{ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"},5936};5937
5938const NoteType AMDNoteTypes[] = {5939{ELF::NT_AMD_HSA_CODE_OBJECT_VERSION,5940"NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"},5941{ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"},5942{ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"},5943{ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"},5944{ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"},5945{ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"},5946};5947
5948const NoteType AMDGPUNoteTypes[] = {5949{ELF::NT_AMDGPU_METADATA, "NT_AMDGPU_METADATA (AMDGPU Metadata)"},5950};5951
5952const NoteType LLVMOMPOFFLOADNoteTypes[] = {5953{ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION,5954"NT_LLVM_OPENMP_OFFLOAD_VERSION (image format version)"},5955{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER,5956"NT_LLVM_OPENMP_OFFLOAD_PRODUCER (producing toolchain)"},5957{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION,5958"NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION (producing toolchain version)"},5959};5960
5961const NoteType AndroidNoteTypes[] = {5962{ELF::NT_ANDROID_TYPE_IDENT, "NT_ANDROID_TYPE_IDENT"},5963{ELF::NT_ANDROID_TYPE_KUSER, "NT_ANDROID_TYPE_KUSER"},5964{ELF::NT_ANDROID_TYPE_MEMTAG,5965"NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"},5966};5967
5968const NoteType CoreNoteTypes[] = {5969{ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},5970{ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},5971{ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"},5972{ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"},5973{ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"},5974{ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"},5975{ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"},5976{ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"},5977{ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"},5978{ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"},5979{ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"},5980
5981{ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"},5982{ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"},5983{ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"},5984{ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"},5985{ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"},5986{ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"},5987{ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"},5988{ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"},5989{ELF::NT_PPC_TM_CFPR,5990"NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"},5991{ELF::NT_PPC_TM_CVMX,5992"NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"},5993{ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"},5994{ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"},5995{ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"},5996{ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"},5997{ELF::NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"},5998
5999{ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"},6000{ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"},6001{ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"},6002
6003{ELF::NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS (s390 upper register halves)"},6004{ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"},6005{ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"},6006{ELF::NT_S390_TODPREG, "NT_S390_TODPREG (s390 TOD programmable register)"},6007{ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"},6008{ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"},6009{ELF::NT_S390_LAST_BREAK,6010"NT_S390_LAST_BREAK (s390 last breaking event address)"},6011{ELF::NT_S390_SYSTEM_CALL,6012"NT_S390_SYSTEM_CALL (s390 system call restart data)"},6013{ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"},6014{ELF::NT_S390_VXRS_LOW,6015"NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"},6016{ELF::NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"},6017{ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"},6018{ELF::NT_S390_GS_BC,6019"NT_S390_GS_BC (s390 guarded-storage broadcast control)"},6020
6021{ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"},6022{ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"},6023{ELF::NT_ARM_HW_BREAK,6024"NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"},6025{ELF::NT_ARM_HW_WATCH,6026"NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"},6027{ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"},6028{ELF::NT_ARM_PAC_MASK,6029"NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"},6030{ELF::NT_ARM_TAGGED_ADDR_CTRL,6031"NT_ARM_TAGGED_ADDR_CTRL (AArch64 Tagged Address Control)"},6032{ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"},6033{ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"},6034{ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"},6035
6036{ELF::NT_FILE, "NT_FILE (mapped files)"},6037{ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"},6038{ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"},6039};6040
6041template <class ELFT>6042StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {6043uint32_t Type = Note.getType();6044auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef {6045for (const NoteType &N : V)6046if (N.ID == Type)6047return N.Name;6048return "";6049};6050
6051StringRef Name = Note.getName();6052if (Name == "GNU")6053return FindNote(GNUNoteTypes);6054if (Name == "FreeBSD") {6055if (ELFType == ELF::ET_CORE) {6056// FreeBSD also places the generic core notes in the FreeBSD namespace.6057StringRef Result = FindNote(FreeBSDCoreNoteTypes);6058if (!Result.empty())6059return Result;6060return FindNote(CoreNoteTypes);6061} else {6062return FindNote(FreeBSDNoteTypes);6063}6064}6065if (ELFType == ELF::ET_CORE && Name.starts_with("NetBSD-CORE")) {6066StringRef Result = FindNote(NetBSDCoreNoteTypes);6067if (!Result.empty())6068return Result;6069return FindNote(CoreNoteTypes);6070}6071if (ELFType == ELF::ET_CORE && Name.starts_with("OpenBSD")) {6072// OpenBSD also places the generic core notes in the OpenBSD namespace.6073StringRef Result = FindNote(OpenBSDCoreNoteTypes);6074if (!Result.empty())6075return Result;6076return FindNote(CoreNoteTypes);6077}6078if (Name == "AMD")6079return FindNote(AMDNoteTypes);6080if (Name == "AMDGPU")6081return FindNote(AMDGPUNoteTypes);6082if (Name == "LLVMOMPOFFLOAD")6083return FindNote(LLVMOMPOFFLOADNoteTypes);6084if (Name == "Android")6085return FindNote(AndroidNoteTypes);6086
6087if (ELFType == ELF::ET_CORE)6088return FindNote(CoreNoteTypes);6089return FindNote(GenericNoteTypes);6090}
6091
6092template <class ELFT>6093static void processNotesHelper(6094const ELFDumper<ELFT> &Dumper,6095llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,6096typename ELFT::Addr, size_t)>6097StartNotesFn,6098llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,6099llvm::function_ref<void()> FinishNotesFn) {6100const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();6101bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE;6102
6103ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections());6104if (!IsCoreFile && !Sections.empty()) {6105for (const typename ELFT::Shdr &S : Sections) {6106if (S.sh_type != SHT_NOTE)6107continue;6108StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,6109S.sh_size, S.sh_addralign);6110Error Err = Error::success();6111size_t I = 0;6112for (const typename ELFT::Note Note : Obj.notes(S, Err)) {6113if (Error E = ProcessNoteFn(Note, IsCoreFile))6114Dumper.reportUniqueWarning(6115"unable to read note with index " + Twine(I) + " from the " +6116describe(Obj, S) + ": " + toString(std::move(E)));6117++I;6118}6119if (Err)6120Dumper.reportUniqueWarning("unable to read notes from the " +6121describe(Obj, S) + ": " +6122toString(std::move(Err)));6123FinishNotesFn();6124}6125return;6126}6127
6128Expected<ArrayRef<typename ELFT::Phdr>> PhdrsOrErr = Obj.program_headers();6129if (!PhdrsOrErr) {6130Dumper.reportUniqueWarning(6131"unable to read program headers to locate the PT_NOTE segment: " +6132toString(PhdrsOrErr.takeError()));6133return;6134}6135
6136for (size_t I = 0, E = (*PhdrsOrErr).size(); I != E; ++I) {6137const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];6138if (P.p_type != PT_NOTE)6139continue;6140StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align);6141Error Err = Error::success();6142size_t Index = 0;6143for (const typename ELFT::Note Note : Obj.notes(P, Err)) {6144if (Error E = ProcessNoteFn(Note, IsCoreFile))6145Dumper.reportUniqueWarning("unable to read note with index " +6146Twine(Index) +6147" from the PT_NOTE segment with index " +6148Twine(I) + ": " + toString(std::move(E)));6149++Index;6150}6151if (Err)6152Dumper.reportUniqueWarning(6153"unable to read notes from the PT_NOTE segment with index " +6154Twine(I) + ": " + toString(std::move(Err)));6155FinishNotesFn();6156}6157}
6158
6159template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {6160size_t Align = 0;6161bool IsFirstHeader = true;6162auto PrintHeader = [&](std::optional<StringRef> SecName,6163const typename ELFT::Off Offset,6164const typename ELFT::Addr Size, size_t Al) {6165Align = std::max<size_t>(Al, 4);6166// Print a newline between notes sections to match GNU readelf.6167if (!IsFirstHeader) {6168OS << '\n';6169} else {6170IsFirstHeader = false;6171}6172
6173OS << "Displaying notes found ";6174
6175if (SecName)6176OS << "in: " << *SecName << "\n";6177else6178OS << "at file offset " << format_hex(Offset, 10) << " with length "6179<< format_hex(Size, 10) << ":\n";6180
6181OS << " Owner Data size \tDescription\n";6182};6183
6184auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {6185StringRef Name = Note.getName();6186ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);6187Elf_Word Type = Note.getType();6188
6189// Print the note owner/type.6190OS << " " << left_justify(Name, 20) << ' '6191<< format_hex(Descriptor.size(), 10) << '\t';6192
6193StringRef NoteType =6194getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);6195if (!NoteType.empty())6196OS << NoteType << '\n';6197else6198OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";6199
6200// Print the description, or fallback to printing raw bytes for unknown6201// owners/if we fail to pretty-print the contents.6202if (Name == "GNU") {6203if (printGNUNote<ELFT>(OS, Type, Descriptor))6204return Error::success();6205} else if (Name == "FreeBSD") {6206if (std::optional<FreeBSDNote> N =6207getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {6208OS << " " << N->Type << ": " << N->Value << '\n';6209return Error::success();6210}6211} else if (Name == "AMD") {6212const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);6213if (!N.Type.empty()) {6214OS << " " << N.Type << ":\n " << N.Value << '\n';6215return Error::success();6216}6217} else if (Name == "AMDGPU") {6218const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);6219if (!N.Type.empty()) {6220OS << " " << N.Type << ":\n " << N.Value << '\n';6221return Error::success();6222}6223} else if (Name == "LLVMOMPOFFLOAD") {6224if (printLLVMOMPOFFLOADNote<ELFT>(OS, Type, Descriptor))6225return Error::success();6226} else if (Name == "CORE") {6227if (Type == ELF::NT_FILE) {6228DataExtractor DescExtractor(6229Descriptor, ELFT::Endianness == llvm::endianness::little,6230sizeof(Elf_Addr));6231if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {6232printCoreNote<ELFT>(OS, *NoteOrErr);6233return Error::success();6234} else {6235return NoteOrErr.takeError();6236}6237}6238} else if (Name == "Android") {6239if (printAndroidNote(OS, Type, Descriptor))6240return Error::success();6241}6242if (!Descriptor.empty()) {6243OS << " description data:";6244for (uint8_t B : Descriptor)6245OS << " " << format("%02x", B);6246OS << '\n';6247}6248return Error::success();6249};6250
6251processNotesHelper(*this, /*StartNotesFn=*/PrintHeader,6252/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {});6253}
6254
6255template <class ELFT>6256ArrayRef<uint8_t>6257ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) {6258for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) {6259if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC)6260continue;6261if (Sec.sh_addr != ExpectedAddr) {6262reportUniqueWarning(6263"SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" +6264Twine::utohexstr(Sec.sh_addr) +6265", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" +6266Twine::utohexstr(ExpectedAddr));6267return ArrayRef<uint8_t>();6268}6269Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec);6270if (auto E = Contents.takeError()) {6271reportUniqueWarning(6272"couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " +6273toString(std::move(E)));6274return ArrayRef<uint8_t>();6275}6276return Contents.get();6277}6278return ArrayRef<uint8_t>();6279}
6280
6281// Reserve the lower three bits of the first byte of the step distance when
6282// encoding the memtag descriptors. Found to be the best overall size tradeoff
6283// when compiling Android T with full MTE globals enabled.
6284constexpr uint64_t MemtagStepVarintReservedBits = 3;6285constexpr uint64_t MemtagGranuleSize = 16;6286
6287template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {6288if (Obj.getHeader().e_machine != EM_AARCH64) return;6289std::vector<std::pair<std::string, std::string>> DynamicEntries;6290uint64_t MemtagGlobalsSz = 0;6291uint64_t MemtagGlobals = 0;6292for (const typename ELFT::Dyn &Entry : dynamic_table()) {6293uintX_t Tag = Entry.getTag();6294switch (Tag) {6295case DT_AARCH64_MEMTAG_GLOBALSSZ:6296MemtagGlobalsSz = Entry.getVal();6297DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6298getDynamicEntry(Tag, Entry.getVal()));6299break;6300case DT_AARCH64_MEMTAG_GLOBALS:6301MemtagGlobals = Entry.getVal();6302DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6303getDynamicEntry(Tag, Entry.getVal()));6304break;6305case DT_AARCH64_MEMTAG_MODE:6306case DT_AARCH64_MEMTAG_HEAP:6307case DT_AARCH64_MEMTAG_STACK:6308DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),6309getDynamicEntry(Tag, Entry.getVal()));6310break;6311}6312}6313
6314ArrayRef<uint8_t> AndroidNoteDesc;6315auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error {6316if (Note.getName() == "Android" &&6317Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG)6318AndroidNoteDesc = Note.getDesc(4);6319return Error::success();6320};6321
6322processNotesHelper(6323*this,6324/*StartNotesFn=*/6325[](std::optional<StringRef>, const typename ELFT::Off,6326const typename ELFT::Addr, size_t) {},6327/*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {});6328
6329ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals);6330if (Contents.size() != MemtagGlobalsSz) {6331reportUniqueWarning(6332"mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" +6333Twine::utohexstr(MemtagGlobalsSz) +6334") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" +6335Twine::utohexstr(Contents.size()) + ")");6336Contents = ArrayRef<uint8_t>();6337}6338
6339std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors;6340uint64_t Address = 0;6341// See the AArch64 MemtagABI document for a description of encoding scheme:6342// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic6343for (size_t I = 0; I < Contents.size();) {6344const char *Error = nullptr;6345unsigned DecodedBytes = 0;6346uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes,6347Contents.end(), &Error);6348I += DecodedBytes;6349if (Error) {6350reportUniqueWarning(6351"error decoding distance uleb, " + Twine(DecodedBytes) +6352" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));6353GlobalDescriptors.clear();6354break;6355}6356uint64_t Distance = Value >> MemtagStepVarintReservedBits;6357uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1);6358if (GranulesToTag == 0) {6359GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes,6360Contents.end(), &Error) +63611;6362I += DecodedBytes;6363if (Error) {6364reportUniqueWarning(6365"error decoding size-only uleb, " + Twine(DecodedBytes) +6366" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));6367GlobalDescriptors.clear();6368break;6369}6370}6371Address += Distance * MemtagGranuleSize;6372GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize);6373Address += GranulesToTag * MemtagGranuleSize;6374}6375
6376printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors);6377}
6378
6379template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() {6380OS << "printELFLinkerOptions not implemented!\n";6381}
6382
6383template <class ELFT>6384void ELFDumper<ELFT>::printDependentLibsHelper(6385function_ref<void(const Elf_Shdr &)> OnSectionStart,6386function_ref<void(StringRef, uint64_t)> OnLibEntry) {6387auto Warn = [this](unsigned SecNdx, StringRef Msg) {6388this->reportUniqueWarning("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +6389Twine(SecNdx) + " is broken: " + Msg);6390};6391
6392unsigned I = -1;6393for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {6394++I;6395if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)6396continue;6397
6398OnSectionStart(Shdr);6399
6400Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Shdr);6401if (!ContentsOrErr) {6402Warn(I, toString(ContentsOrErr.takeError()));6403continue;6404}6405
6406ArrayRef<uint8_t> Contents = *ContentsOrErr;6407if (!Contents.empty() && Contents.back() != 0) {6408Warn(I, "the content is not null-terminated");6409continue;6410}6411
6412for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {6413StringRef Lib((const char *)I);6414OnLibEntry(Lib, I - Contents.begin());6415I += Lib.size() + 1;6416}6417}6418}
6419
6420template <class ELFT>6421void ELFDumper<ELFT>::forEachRelocationDo(6422const Elf_Shdr &Sec,6423llvm::function_ref<void(const Relocation<ELFT> &, unsigned,6424const Elf_Shdr &, const Elf_Shdr *)>6425RelRelaFn) {6426auto Warn = [&](Error &&E,6427const Twine &Prefix = "unable to read relocations from") {6428this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " +6429toString(std::move(E)));6430};6431
6432// SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an6433// associated symbol table. For them we should not treat the value of the6434// sh_link field as an index of a symbol table.6435const Elf_Shdr *SymTab;6436if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&6437!(Obj.getHeader().e_machine == EM_AARCH64 &&6438Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {6439Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);6440if (!SymTabOrErr) {6441Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");6442return;6443}6444SymTab = *SymTabOrErr;6445}6446
6447unsigned RelNdx = 0;6448const bool IsMips64EL = this->Obj.isMips64EL();6449switch (Sec.sh_type) {6450case ELF::SHT_REL:6451if (Expected<Elf_Rel_Range> RangeOrErr = Obj.rels(Sec)) {6452for (const Elf_Rel &R : *RangeOrErr)6453RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6454} else {6455Warn(RangeOrErr.takeError());6456}6457break;6458case ELF::SHT_RELA:6459if (Expected<Elf_Rela_Range> RangeOrErr = Obj.relas(Sec)) {6460for (const Elf_Rela &R : *RangeOrErr)6461RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6462} else {6463Warn(RangeOrErr.takeError());6464}6465break;6466case ELF::SHT_AARCH64_AUTH_RELR:6467if (Obj.getHeader().e_machine != EM_AARCH64)6468break;6469[[fallthrough]];6470case ELF::SHT_RELR:6471case ELF::SHT_ANDROID_RELR: {6472Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);6473if (!RangeOrErr) {6474Warn(RangeOrErr.takeError());6475break;6476}6477
6478for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr))6479RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec,6480/*SymTab=*/nullptr);6481break;6482}6483case ELF::SHT_CREL: {6484if (auto RelsOrRelas = Obj.crels(Sec)) {6485for (const Elf_Rel &R : RelsOrRelas->first)6486RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);6487for (const Elf_Rela &R : RelsOrRelas->second)6488RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);6489} else {6490Warn(RelsOrRelas.takeError());6491}6492break;6493}6494case ELF::SHT_ANDROID_REL:6495case ELF::SHT_ANDROID_RELA:6496if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) {6497for (const Elf_Rela &R : *RelasOrErr)6498RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);6499} else {6500Warn(RelasOrErr.takeError());6501}6502break;6503}6504}
6505
6506template <class ELFT>6507StringRef ELFDumper<ELFT>::getPrintableSectionName(const Elf_Shdr &Sec) const {6508StringRef Name = "<?>";6509if (Expected<StringRef> SecNameOrErr =6510Obj.getSectionName(Sec, this->WarningHandler))6511Name = *SecNameOrErr;6512else6513this->reportUniqueWarning("unable to get the name of " + describe(Sec) +6514": " + toString(SecNameOrErr.takeError()));6515return Name;6516}
6517
6518template <class ELFT> void GNUELFDumper<ELFT>::printDependentLibs() {6519bool SectionStarted = false;6520struct NameOffset {6521StringRef Name;6522uint64_t Offset;6523};6524std::vector<NameOffset> SecEntries;6525NameOffset Current;6526auto PrintSection = [&]() {6527OS << "Dependent libraries section " << Current.Name << " at offset "6528<< format_hex(Current.Offset, 1) << " contains " << SecEntries.size()6529<< " entries:\n";6530for (NameOffset Entry : SecEntries)6531OS << " [" << format("%6" PRIx64, Entry.Offset) << "] " << Entry.Name6532<< "\n";6533OS << "\n";6534SecEntries.clear();6535};6536
6537auto OnSectionStart = [&](const Elf_Shdr &Shdr) {6538if (SectionStarted)6539PrintSection();6540SectionStarted = true;6541Current.Offset = Shdr.sh_offset;6542Current.Name = this->getPrintableSectionName(Shdr);6543};6544auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {6545SecEntries.push_back(NameOffset{Lib, Offset});6546};6547
6548this->printDependentLibsHelper(OnSectionStart, OnLibEntry);6549if (SectionStarted)6550PrintSection();6551}
6552
6553template <class ELFT>6554SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress(6555uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) {6556SmallVector<uint32_t> SymbolIndexes;6557if (!this->AddressToIndexMap) {6558// Populate the address to index map upon the first invocation of this6559// function.6560this->AddressToIndexMap.emplace();6561if (this->DotSymtabSec) {6562if (Expected<Elf_Sym_Range> SymsOrError =6563Obj.symbols(this->DotSymtabSec)) {6564uint32_t Index = (uint32_t)-1;6565for (const Elf_Sym &Sym : *SymsOrError) {6566++Index;6567
6568if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC)6569continue;6570
6571Expected<uint64_t> SymAddrOrErr =6572ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress();6573if (!SymAddrOrErr) {6574std::string Name = this->getStaticSymbolName(Index);6575reportUniqueWarning("unable to get address of symbol '" + Name +6576"': " + toString(SymAddrOrErr.takeError()));6577return SymbolIndexes;6578}6579
6580(*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index);6581}6582} else {6583reportUniqueWarning("unable to read the symbol table: " +6584toString(SymsOrError.takeError()));6585}6586}6587}6588
6589auto Symbols = this->AddressToIndexMap->find(SymValue);6590if (Symbols == this->AddressToIndexMap->end())6591return SymbolIndexes;6592
6593for (uint32_t Index : Symbols->second) {6594// Check if the symbol is in the right section. FunctionSec == None6595// means "any section".6596if (FunctionSec) {6597const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index));6598if (Expected<const Elf_Shdr *> SecOrErr =6599Obj.getSection(Sym, this->DotSymtabSec,6600this->getShndxTable(this->DotSymtabSec))) {6601if (*FunctionSec != *SecOrErr)6602continue;6603} else {6604std::string Name = this->getStaticSymbolName(Index);6605// Note: it is impossible to trigger this error currently, it is6606// untested.6607reportUniqueWarning("unable to get section of symbol '" + Name +6608"': " + toString(SecOrErr.takeError()));6609return SymbolIndexes;6610}6611}6612
6613SymbolIndexes.push_back(Index);6614}6615
6616return SymbolIndexes;6617}
6618
6619template <class ELFT>6620bool ELFDumper<ELFT>::printFunctionStackSize(6621uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec,6622const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {6623SmallVector<uint32_t> FuncSymIndexes =6624this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec);6625if (FuncSymIndexes.empty())6626reportUniqueWarning(6627"could not identify function symbol for stack size entry in " +6628describe(StackSizeSec));6629
6630// Extract the size. The expectation is that Offset is pointing to the right6631// place, i.e. past the function address.6632Error Err = Error::success();6633uint64_t StackSize = Data.getULEB128(Offset, &Err);6634if (Err) {6635reportUniqueWarning("could not extract a valid stack size from " +6636describe(StackSizeSec) + ": " +6637toString(std::move(Err)));6638return false;6639}6640
6641if (FuncSymIndexes.empty()) {6642printStackSizeEntry(StackSize, {"?"});6643} else {6644SmallVector<std::string> FuncSymNames;6645for (uint32_t Index : FuncSymIndexes)6646FuncSymNames.push_back(this->getStaticSymbolName(Index));6647printStackSizeEntry(StackSize, FuncSymNames);6648}6649
6650return true;6651}
6652
6653template <class ELFT>6654void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,6655ArrayRef<std::string> FuncNames) {6656OS.PadToColumn(2);6657OS << format_decimal(Size, 11);6658OS.PadToColumn(18);6659
6660OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n";6661}
6662
6663template <class ELFT>6664void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R,6665const Elf_Shdr &RelocSec, unsigned Ndx,6666const Elf_Shdr *SymTab,6667const Elf_Shdr *FunctionSec,6668const Elf_Shdr &StackSizeSec,6669const RelocationResolver &Resolver,6670DataExtractor Data) {6671// This function ignores potentially erroneous input, unless it is directly6672// related to stack size reporting.6673const Elf_Sym *Sym = nullptr;6674Expected<RelSymbol<ELFT>> TargetOrErr = this->getRelocationTarget(R, SymTab);6675if (!TargetOrErr)6676reportUniqueWarning("unable to get the target of relocation with index " +6677Twine(Ndx) + " in " + describe(RelocSec) + ": " +6678toString(TargetOrErr.takeError()));6679else6680Sym = TargetOrErr->Sym;6681
6682uint64_t RelocSymValue = 0;6683if (Sym) {6684Expected<const Elf_Shdr *> SectionOrErr =6685this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab));6686if (!SectionOrErr) {6687reportUniqueWarning(6688"cannot identify the section for relocation symbol '" +6689(*TargetOrErr).Name + "': " + toString(SectionOrErr.takeError()));6690} else if (*SectionOrErr != FunctionSec) {6691reportUniqueWarning("relocation symbol '" + (*TargetOrErr).Name +6692"' is not in the expected section");6693// Pretend that the symbol is in the correct section and report its6694// stack size anyway.6695FunctionSec = *SectionOrErr;6696}6697
6698RelocSymValue = Sym->st_value;6699}6700
6701uint64_t Offset = R.Offset;6702if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {6703reportUniqueWarning("found invalid relocation offset (0x" +6704Twine::utohexstr(Offset) + ") into " +6705describe(StackSizeSec) +6706" while trying to extract a stack size entry");6707return;6708}6709
6710uint64_t SymValue = Resolver(R.Type, Offset, RelocSymValue,6711Data.getAddress(&Offset), R.Addend.value_or(0));6712this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data,6713&Offset);6714}
6715
6716template <class ELFT>6717void ELFDumper<ELFT>::printNonRelocatableStackSizes(6718std::function<void()> PrintHeader) {6719// This function ignores potentially erroneous input, unless it is directly6720// related to stack size reporting.6721for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {6722if (this->getPrintableSectionName(Sec) != ".stack_sizes")6723continue;6724PrintHeader();6725ArrayRef<uint8_t> Contents =6726unwrapOrError(this->FileName, Obj.getSectionContents(Sec));6727DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));6728uint64_t Offset = 0;6729while (Offset < Contents.size()) {6730// The function address is followed by a ULEB representing the stack6731// size. Check for an extra byte before we try to process the entry.6732if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {6733reportUniqueWarning(6734describe(Sec) +6735" ended while trying to extract a stack size entry");6736break;6737}6738uint64_t SymValue = Data.getAddress(&Offset);6739if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec,6740Data, &Offset))6741break;6742}6743}6744}
6745
6746template <class ELFT>6747void ELFDumper<ELFT>::printRelocatableStackSizes(6748std::function<void()> PrintHeader) {6749// Build a map between stack size sections and their corresponding relocation6750// sections.6751auto IsMatch = [&](const Elf_Shdr &Sec) -> bool {6752StringRef SectionName;6753if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))6754SectionName = *NameOrErr;6755else6756consumeError(NameOrErr.takeError());6757
6758return SectionName == ".stack_sizes";6759};6760
6761Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>>6762StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch);6763if (!StackSizeRelocMapOrErr) {6764reportUniqueWarning("unable to get stack size map section(s): " +6765toString(StackSizeRelocMapOrErr.takeError()));6766return;6767}6768
6769for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) {6770PrintHeader();6771const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first;6772const Elf_Shdr *RelocSec = StackSizeMapEntry.second;6773
6774// Warn about stack size sections without a relocation section.6775if (!RelocSec) {6776reportWarning(createError(".stack_sizes (" + describe(*StackSizesELFSec) +6777") does not have a corresponding "6778"relocation section"),6779FileName);6780continue;6781}6782
6783// A .stack_sizes section header's sh_link field is supposed to point6784// to the section that contains the functions whose stack sizes are6785// described in it.6786const Elf_Shdr *FunctionSec = unwrapOrError(6787this->FileName, Obj.getSection(StackSizesELFSec->sh_link));6788
6789SupportsRelocation IsSupportedFn;6790RelocationResolver Resolver;6791std::tie(IsSupportedFn, Resolver) = getRelocationResolver(this->ObjF);6792ArrayRef<uint8_t> Contents =6793unwrapOrError(this->FileName, Obj.getSectionContents(*StackSizesELFSec));6794DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));6795
6796forEachRelocationDo(6797*RelocSec, [&](const Relocation<ELFT> &R, unsigned Ndx,6798const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {6799if (!IsSupportedFn || !IsSupportedFn(R.Type)) {6800reportUniqueWarning(6801describe(*RelocSec) +6802" contains an unsupported relocation with index " + Twine(Ndx) +6803": " + Obj.getRelocationTypeName(R.Type));6804return;6805}6806
6807this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec,6808*StackSizesELFSec, Resolver, Data);6809});6810}6811}
6812
6813template <class ELFT>6814void GNUELFDumper<ELFT>::printStackSizes() {6815bool HeaderHasBeenPrinted = false;6816auto PrintHeader = [&]() {6817if (HeaderHasBeenPrinted)6818return;6819OS << "\nStack Sizes:\n";6820OS.PadToColumn(9);6821OS << "Size";6822OS.PadToColumn(18);6823OS << "Functions\n";6824HeaderHasBeenPrinted = true;6825};6826
6827// For non-relocatable objects, look directly for sections whose name starts6828// with .stack_sizes and process the contents.6829if (this->Obj.getHeader().e_type == ELF::ET_REL)6830this->printRelocatableStackSizes(PrintHeader);6831else6832this->printNonRelocatableStackSizes(PrintHeader);6833}
6834
6835template <class ELFT>6836void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {6837size_t Bias = ELFT::Is64Bits ? 8 : 0;6838auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {6839OS.PadToColumn(2);6840OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);6841OS.PadToColumn(11 + Bias);6842OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";6843OS.PadToColumn(22 + Bias);6844OS << format_hex_no_prefix(*E, 8 + Bias);6845OS.PadToColumn(31 + 2 * Bias);6846OS << Purpose << "\n";6847};6848
6849OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");6850OS << " Canonical gp value: "6851<< format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";6852
6853OS << " Reserved entries:\n";6854if (ELFT::Is64Bits)6855OS << " Address Access Initial Purpose\n";6856else6857OS << " Address Access Initial Purpose\n";6858PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");6859if (Parser.getGotModulePointer())6860PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");6861
6862if (!Parser.getLocalEntries().empty()) {6863OS << "\n";6864OS << " Local entries:\n";6865if (ELFT::Is64Bits)6866OS << " Address Access Initial\n";6867else6868OS << " Address Access Initial\n";6869for (auto &E : Parser.getLocalEntries())6870PrintEntry(&E, "");6871}6872
6873if (Parser.IsStatic)6874return;6875
6876if (!Parser.getGlobalEntries().empty()) {6877OS << "\n";6878OS << " Global entries:\n";6879if (ELFT::Is64Bits)6880OS << " Address Access Initial Sym.Val."6881<< " Type Ndx Name\n";6882else6883OS << " Address Access Initial Sym.Val. Type Ndx Name\n";6884
6885DataRegion<Elf_Word> ShndxTable(6886(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());6887for (auto &E : Parser.getGlobalEntries()) {6888const Elf_Sym &Sym = *Parser.getGotSym(&E);6889const Elf_Sym &FirstSym = this->dynamic_symbols()[0];6890std::string SymName = this->getFullSymbolName(6891Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);6892
6893OS.PadToColumn(2);6894OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));6895OS.PadToColumn(11 + Bias);6896OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";6897OS.PadToColumn(22 + Bias);6898OS << to_string(format_hex_no_prefix(E, 8 + Bias));6899OS.PadToColumn(31 + 2 * Bias);6900OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));6901OS.PadToColumn(40 + 3 * Bias);6902OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));6903OS.PadToColumn(48 + 3 * Bias);6904OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),6905ShndxTable);6906OS.PadToColumn(52 + 3 * Bias);6907OS << SymName << "\n";6908}6909}6910
6911if (!Parser.getOtherEntries().empty())6912OS << "\n Number of TLS and multi-GOT entries "6913<< Parser.getOtherEntries().size() << "\n";6914}
6915
6916template <class ELFT>6917void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {6918size_t Bias = ELFT::Is64Bits ? 8 : 0;6919auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {6920OS.PadToColumn(2);6921OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias);6922OS.PadToColumn(11 + Bias);6923OS << format_hex_no_prefix(*E, 8 + Bias);6924OS.PadToColumn(20 + 2 * Bias);6925OS << Purpose << "\n";6926};6927
6928OS << "PLT GOT:\n\n";6929
6930OS << " Reserved entries:\n";6931OS << " Address Initial Purpose\n";6932PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");6933if (Parser.getPltModulePointer())6934PrintEntry(Parser.getPltModulePointer(), "Module pointer");6935
6936if (!Parser.getPltEntries().empty()) {6937OS << "\n";6938OS << " Entries:\n";6939OS << " Address Initial Sym.Val. Type Ndx Name\n";6940DataRegion<Elf_Word> ShndxTable(6941(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());6942for (auto &E : Parser.getPltEntries()) {6943const Elf_Sym &Sym = *Parser.getPltSym(&E);6944const Elf_Sym &FirstSym = *cantFail(6945this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));6946std::string SymName = this->getFullSymbolName(6947Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);6948
6949OS.PadToColumn(2);6950OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias));6951OS.PadToColumn(11 + Bias);6952OS << to_string(format_hex_no_prefix(E, 8 + Bias));6953OS.PadToColumn(20 + 2 * Bias);6954OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));6955OS.PadToColumn(29 + 3 * Bias);6956OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));6957OS.PadToColumn(37 + 3 * Bias);6958OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),6959ShndxTable);6960OS.PadToColumn(41 + 3 * Bias);6961OS << SymName << "\n";6962}6963}6964}
6965
6966template <class ELFT>6967Expected<const Elf_Mips_ABIFlags<ELFT> *>6968getMipsAbiFlagsSection(const ELFDumper<ELFT> &Dumper) {6969const typename ELFT::Shdr *Sec = Dumper.findSectionByName(".MIPS.abiflags");6970if (Sec == nullptr)6971return nullptr;6972
6973constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: ";6974Expected<ArrayRef<uint8_t>> DataOrErr =6975Dumper.getElfObject().getELFFile().getSectionContents(*Sec);6976if (!DataOrErr)6977return createError(ErrPrefix + toString(DataOrErr.takeError()));6978
6979if (DataOrErr->size() != sizeof(Elf_Mips_ABIFlags<ELFT>))6980return createError(ErrPrefix + "it has a wrong size (" +6981Twine(DataOrErr->size()) + ")");6982return reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(DataOrErr->data());6983}
6984
6985template <class ELFT> void GNUELFDumper<ELFT>::printMipsABIFlags() {6986const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;6987if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =6988getMipsAbiFlagsSection(*this))6989Flags = *SecOrErr;6990else6991this->reportUniqueWarning(SecOrErr.takeError());6992if (!Flags)6993return;6994
6995OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n";6996OS << "ISA: MIPS" << int(Flags->isa_level);6997if (Flags->isa_rev > 1)6998OS << "r" << int(Flags->isa_rev);6999OS << "\n";7000OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n";7001OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n";7002OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n";7003OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType))7004<< "\n";7005OS << "ISA Extension: "7006<< enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n";7007if (Flags->ases == 0)7008OS << "ASEs: None\n";7009else7010// FIXME: Print each flag on a separate line.7011OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags))7012<< "\n";7013OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n";7014OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n";7015OS << "\n";7016}
7017
7018template <class ELFT> void LLVMELFDumper<ELFT>::printFileHeaders() {7019const Elf_Ehdr &E = this->Obj.getHeader();7020{7021DictScope D(W, "ElfHeader");7022{7023DictScope D(W, "Ident");7024W.printBinary("Magic",7025ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4));7026W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));7027W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA],7028ArrayRef(ElfDataEncoding));7029W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]);7030
7031auto OSABI = ArrayRef(ElfOSABI);7032if (E.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&7033E.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {7034switch (E.e_machine) {7035case ELF::EM_AMDGPU:7036OSABI = ArrayRef(AMDGPUElfOSABI);7037break;7038case ELF::EM_ARM:7039OSABI = ArrayRef(ARMElfOSABI);7040break;7041case ELF::EM_TI_C6000:7042OSABI = ArrayRef(C6000ElfOSABI);7043break;7044}7045}7046W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI);7047W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]);7048W.printBinary("Unused",7049ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD));7050}7051
7052std::string TypeStr;7053if (const EnumEntry<unsigned> *Ent = getObjectFileEnumEntry(E.e_type)) {7054TypeStr = Ent->Name.str();7055} else {7056if (E.e_type >= ET_LOPROC)7057TypeStr = "Processor Specific";7058else if (E.e_type >= ET_LOOS)7059TypeStr = "OS Specific";7060else7061TypeStr = "Unknown";7062}7063W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")");7064
7065W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType));7066W.printNumber("Version", E.e_version);7067W.printHex("Entry", E.e_entry);7068W.printHex("ProgramHeaderOffset", E.e_phoff);7069W.printHex("SectionHeaderOffset", E.e_shoff);7070if (E.e_machine == EM_MIPS)7071W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags),7072unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),7073unsigned(ELF::EF_MIPS_MACH));7074else if (E.e_machine == EM_AMDGPU) {7075switch (E.e_ident[ELF::EI_ABIVERSION]) {7076default:7077W.printHex("Flags", E.e_flags);7078break;7079case 0:7080// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.7081[[fallthrough]];7082case ELF::ELFABIVERSION_AMDGPU_HSA_V3:7083W.printFlags("Flags", E.e_flags,7084ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),7085unsigned(ELF::EF_AMDGPU_MACH));7086break;7087case ELF::ELFABIVERSION_AMDGPU_HSA_V4:7088case ELF::ELFABIVERSION_AMDGPU_HSA_V5:7089W.printFlags("Flags", E.e_flags,7090ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),7091unsigned(ELF::EF_AMDGPU_MACH),7092unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),7093unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));7094break;7095case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {7096std::optional<FlagEntry> VerFlagEntry;7097// The string needs to remain alive from the moment we create a7098// FlagEntry until printFlags is done.7099std::string FlagStr;7100if (auto VersionFlag = E.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {7101unsigned Version =7102VersionFlag >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET;7103FlagStr = "EF_AMDGPU_GENERIC_VERSION_V" + std::to_string(Version);7104VerFlagEntry = FlagEntry(FlagStr, VersionFlag);7105}7106W.printFlags(7107"Flags", E.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),7108unsigned(ELF::EF_AMDGPU_MACH),7109unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),7110unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4),7111VerFlagEntry ? ArrayRef(*VerFlagEntry) : ArrayRef<FlagEntry>());7112break;7113}7114}7115} else if (E.e_machine == EM_RISCV)7116W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags));7117else if (E.e_machine == EM_AVR)7118W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags),7119unsigned(ELF::EF_AVR_ARCH_MASK));7120else if (E.e_machine == EM_LOONGARCH)7121W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags),7122unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),7123unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));7124else if (E.e_machine == EM_XTENSA)7125W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags),7126unsigned(ELF::EF_XTENSA_MACH));7127else if (E.e_machine == EM_CUDA)7128W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderNVPTXFlags),7129unsigned(ELF::EF_CUDA_SM));7130else7131W.printFlags("Flags", E.e_flags);7132W.printNumber("HeaderSize", E.e_ehsize);7133W.printNumber("ProgramHeaderEntrySize", E.e_phentsize);7134W.printNumber("ProgramHeaderCount", E.e_phnum);7135W.printNumber("SectionHeaderEntrySize", E.e_shentsize);7136W.printString("SectionHeaderCount",7137getSectionHeadersNumString(this->Obj, this->FileName));7138W.printString("StringTableSectionIndex",7139getSectionHeaderTableIndexString(this->Obj, this->FileName));7140}7141}
7142
7143template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() {7144DictScope Lists(W, "Groups");7145std::vector<GroupSection> V = this->getGroups();7146DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);7147for (const GroupSection &G : V) {7148DictScope D(W, "Group");7149W.printNumber("Name", G.Name, G.ShName);7150W.printNumber("Index", G.Index);7151W.printNumber("Link", G.Link);7152W.printNumber("Info", G.Info);7153W.printHex("Type", getGroupType(G.Type), G.Type);7154W.printString("Signature", G.Signature);7155
7156ListScope L(W, getGroupSectionHeaderName());7157for (const GroupMember &GM : G.Members) {7158const GroupSection *MainGroup = Map[GM.Index];7159if (MainGroup != &G)7160this->reportUniqueWarning(7161"section with index " + Twine(GM.Index) +7162", included in the group section with index " +7163Twine(MainGroup->Index) +7164", was also found in the group section with index " +7165Twine(G.Index));7166printSectionGroupMembers(GM.Name, GM.Index);7167}7168}7169
7170if (V.empty())7171printEmptyGroupMessage();7172}
7173
7174template <class ELFT>7175std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const {7176return "Section(s) in group";7177}
7178
7179template <class ELFT>7180void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,7181uint64_t Idx) const {7182W.startLine() << Name << " (" << Idx << ")\n";7183}
7184
7185template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {7186ListScope D(W, "Relocations");7187
7188for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {7189if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))7190continue;7191
7192StringRef Name = this->getPrintableSectionName(Sec);7193unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front();7194printRelocationSectionInfo(Sec, Name, SecNdx);7195}7196}
7197
7198template <class ELFT>7199void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R,7200StringRef SymbolName,7201StringRef RelocName) {7202DictScope Group(W, "Relocation");7203W.printHex("Offset", R.Offset);7204W.printNumber("Type", RelocName, R.Type);7205W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol);7206if (R.Addend)7207W.printHex("Addend", (uintX_t)*R.Addend);7208}
7209
7210template <class ELFT>7211void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,7212StringRef SymbolName,7213StringRef RelocName) {7214raw_ostream &OS = W.startLine();7215OS << W.hex(R.Offset) << " " << RelocName << " "7216<< (!SymbolName.empty() ? SymbolName : "-");7217if (R.Addend)7218OS << " " << W.hex((uintX_t)*R.Addend);7219OS << "\n";7220}
7221
7222template <class ELFT>7223void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,7224StringRef Name,7225const unsigned SecNdx) {7226DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str());7227this->printRelocationsHelper(Sec);7228}
7229
7230template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const {7231W.startLine() << "There are no group sections in the file.\n";7232}
7233
7234template <class ELFT>7235void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,7236const RelSymbol<ELFT> &RelSym) {7237StringRef SymbolName = RelSym.Name;7238if (RelSym.Sym && RelSym.Name.empty())7239SymbolName = "<null>";7240SmallString<32> RelocName;7241this->Obj.getRelocationTypeName(R.Type, RelocName);7242
7243if (opts::ExpandRelocs) {7244printExpandedRelRelaReloc(R, SymbolName, RelocName);7245} else {7246printDefaultRelRelaReloc(R, SymbolName, RelocName);7247}7248}
7249
7250template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {7251ListScope SectionsD(W, "Sections");7252
7253int SectionIndex = -1;7254std::vector<EnumEntry<unsigned>> FlagsList =7255getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI],7256this->Obj.getHeader().e_machine);7257for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {7258DictScope SectionD(W, "Section");7259W.printNumber("Index", ++SectionIndex);7260W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name);7261W.printHex("Type",7262object::getELFSectionTypeName(this->Obj.getHeader().e_machine,7263Sec.sh_type),7264Sec.sh_type);7265W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList));7266W.printHex("Address", Sec.sh_addr);7267W.printHex("Offset", Sec.sh_offset);7268W.printNumber("Size", Sec.sh_size);7269W.printNumber("Link", Sec.sh_link);7270W.printNumber("Info", Sec.sh_info);7271W.printNumber("AddressAlignment", Sec.sh_addralign);7272W.printNumber("EntrySize", Sec.sh_entsize);7273
7274if (opts::SectionRelocations) {7275ListScope D(W, "Relocations");7276this->printRelocationsHelper(Sec);7277}7278
7279if (opts::SectionSymbols) {7280ListScope D(W, "Symbols");7281if (this->DotSymtabSec) {7282StringRef StrTable = unwrapOrError(7283this->FileName,7284this->Obj.getStringTableForSymtab(*this->DotSymtabSec));7285ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec);7286
7287typename ELFT::SymRange Symbols = unwrapOrError(7288this->FileName, this->Obj.symbols(this->DotSymtabSec));7289for (const Elf_Sym &Sym : Symbols) {7290const Elf_Shdr *SymSec = unwrapOrError(7291this->FileName,7292this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));7293if (SymSec == &Sec)7294printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,7295/*NonVisibilityBitsUsed=*/false,7296/*ExtraSymInfo=*/false);7297}7298}7299}7300
7301if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) {7302ArrayRef<uint8_t> Data =7303unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec));7304W.printBinaryBlock(7305"SectionData",7306StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()));7307}7308}7309}
7310
7311template <class ELFT>7312void LLVMELFDumper<ELFT>::printSymbolSection(7313const Elf_Sym &Symbol, unsigned SymIndex,7314DataRegion<Elf_Word> ShndxTable) const {7315auto GetSectionSpecialType = [&]() -> std::optional<StringRef> {7316if (Symbol.isUndefined())7317return StringRef("Undefined");7318if (Symbol.isProcessorSpecific())7319return StringRef("Processor Specific");7320if (Symbol.isOSSpecific())7321return StringRef("Operating System Specific");7322if (Symbol.isAbsolute())7323return StringRef("Absolute");7324if (Symbol.isCommon())7325return StringRef("Common");7326if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX)7327return StringRef("Reserved");7328return std::nullopt;7329};7330
7331if (std::optional<StringRef> Type = GetSectionSpecialType()) {7332W.printHex("Section", *Type, Symbol.st_shndx);7333return;7334}7335
7336Expected<unsigned> SectionIndex =7337this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);7338if (!SectionIndex) {7339assert(Symbol.st_shndx == SHN_XINDEX &&7340"getSymbolSectionIndex should only fail due to an invalid "7341"SHT_SYMTAB_SHNDX table/reference");7342this->reportUniqueWarning(SectionIndex.takeError());7343W.printHex("Section", "Reserved", SHN_XINDEX);7344return;7345}7346
7347Expected<StringRef> SectionName =7348this->getSymbolSectionName(Symbol, *SectionIndex);7349if (!SectionName) {7350// Don't report an invalid section name if the section headers are missing.7351// In such situations, all sections will be "invalid".7352if (!this->ObjF.sections().empty())7353this->reportUniqueWarning(SectionName.takeError());7354else7355consumeError(SectionName.takeError());7356W.printHex("Section", "<?>", *SectionIndex);7357} else {7358W.printHex("Section", *SectionName, *SectionIndex);7359}7360}
7361
7362template <class ELFT>7363void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const {7364std::vector<EnumEntry<unsigned>> SymOtherFlags =7365this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol);7366W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);7367}
7368
7369template <class ELFT>7370void LLVMELFDumper<ELFT>::printZeroSymbolOtherField(7371const Elf_Sym &Symbol) const {7372assert(Symbol.st_other == 0 && "non-zero Other Field");7373// Usually st_other flag is zero. Do not pollute the output7374// by flags enumeration in that case.7375W.printNumber("Other", 0);7376}
7377
7378template <class ELFT>7379void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,7380DataRegion<Elf_Word> ShndxTable,7381std::optional<StringRef> StrTable,7382bool IsDynamic,7383bool /*NonVisibilityBitsUsed*/,7384bool /*ExtraSymInfo*/) const {7385std::string FullSymbolName = this->getFullSymbolName(7386Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);7387unsigned char SymbolType = Symbol.getType();7388
7389DictScope D(W, "Symbol");7390W.printNumber("Name", FullSymbolName, Symbol.st_name);7391W.printHex("Value", Symbol.st_value);7392W.printNumber("Size", Symbol.st_size);7393W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings));7394if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&7395SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)7396W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes));7397else7398W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes));7399if (Symbol.st_other == 0)7400printZeroSymbolOtherField(Symbol);7401else7402printSymbolOtherField(Symbol);7403printSymbolSection(Symbol, SymIndex, ShndxTable);7404}
7405
7406template <class ELFT>7407void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols,7408bool PrintDynamicSymbols,7409bool ExtraSymInfo) {7410if (PrintSymbols) {7411ListScope Group(W, "Symbols");7412this->printSymbolsHelper(false, ExtraSymInfo);7413}7414if (PrintDynamicSymbols) {7415ListScope Group(W, "DynamicSymbols");7416this->printSymbolsHelper(true, ExtraSymInfo);7417}7418}
7419
7420template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() {7421Elf_Dyn_Range Table = this->dynamic_table();7422if (Table.empty())7423return;7424
7425W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";7426
7427size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table);7428// The "Name/Value" column should be indented from the "Type" column by N7429// spaces, where N = MaxTagSize - length of "Type" (4) + trailing7430// space (1) = -3.7431W.startLine() << " Tag" << std::string(ELFT::Is64Bits ? 16 : 8, ' ')7432<< "Type" << std::string(MaxTagSize - 3, ' ') << "Name/Value\n";7433
7434std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s ";7435for (auto Entry : Table) {7436uintX_t Tag = Entry.getTag();7437std::string Value = this->getDynamicEntry(Tag, Entry.getVal());7438W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true)7439<< " "7440<< format(ValueFmt.c_str(),7441this->Obj.getDynamicTagAsString(Tag).c_str())7442<< Value << "\n";7443}7444W.startLine() << "]\n";7445}
7446
7447template <class ELFT>7448void JSONELFDumper<ELFT>::printAuxillaryDynamicTableEntryInfo(7449const Elf_Dyn &Entry) {7450auto FormatFlags = [this, Value = Entry.getVal()](auto Flags) {7451ListScope L(this->W, "Flags");7452for (const auto &Flag : Flags) {7453if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)7454this->W.printString(Flag.Name);7455}7456};7457switch (Entry.getTag()) {7458case DT_SONAME:7459this->W.printString("Name", this->getDynamicString(Entry.getVal()));7460break;7461case DT_AUXILIARY:7462case DT_FILTER:7463case DT_NEEDED:7464this->W.printString("Library", this->getDynamicString(Entry.getVal()));7465break;7466case DT_USED:7467this->W.printString("Object", this->getDynamicString(Entry.getVal()));7468break;7469case DT_RPATH:7470case DT_RUNPATH: {7471StringRef Value = this->getDynamicString(Entry.getVal());7472ListScope L(this->W, "Path");7473while (!Value.empty()) {7474auto [Front, Back] = Value.split(':');7475this->W.printString(Front);7476Value = Back;7477}7478break;7479}7480case DT_FLAGS:7481FormatFlags(ArrayRef(ElfDynamicDTFlags));7482break;7483case DT_FLAGS_1:7484FormatFlags(ArrayRef(ElfDynamicDTFlags1));7485break;7486default:7487return;7488}7489}
7490
7491template <class ELFT> void JSONELFDumper<ELFT>::printDynamicTable() {7492Elf_Dyn_Range Table = this->dynamic_table();7493ListScope L(this->W, "DynamicSection");7494for (const auto &Entry : Table) {7495DictScope D(this->W);7496uintX_t Tag = Entry.getTag();7497this->W.printHex("Tag", Tag);7498this->W.printString("Type", this->Obj.getDynamicTagAsString(Tag));7499this->W.printHex("Value", Entry.getVal());7500this->printAuxillaryDynamicTableEntryInfo(Entry);7501}7502}
7503
7504template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() {7505W.startLine() << "Dynamic Relocations {\n";7506W.indent();7507this->printDynamicRelocationsHelper();7508W.unindent();7509W.startLine() << "}\n";7510}
7511
7512template <class ELFT>7513void LLVMELFDumper<ELFT>::printProgramHeaders(7514bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {7515if (PrintProgramHeaders)7516printProgramHeaders();7517if (PrintSectionMapping == cl::BOU_TRUE)7518printSectionMapping();7519}
7520
7521template <class ELFT> void LLVMELFDumper<ELFT>::printProgramHeaders() {7522ListScope L(W, "ProgramHeaders");7523
7524Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();7525if (!PhdrsOrErr) {7526this->reportUniqueWarning("unable to dump program headers: " +7527toString(PhdrsOrErr.takeError()));7528return;7529}7530
7531for (const Elf_Phdr &Phdr : *PhdrsOrErr) {7532DictScope P(W, "ProgramHeader");7533StringRef Type =7534segmentTypeToString(this->Obj.getHeader().e_machine, Phdr.p_type);7535
7536W.printHex("Type", Type.empty() ? "Unknown" : Type, Phdr.p_type);7537W.printHex("Offset", Phdr.p_offset);7538W.printHex("VirtualAddress", Phdr.p_vaddr);7539W.printHex("PhysicalAddress", Phdr.p_paddr);7540W.printNumber("FileSize", Phdr.p_filesz);7541W.printNumber("MemSize", Phdr.p_memsz);7542W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags));7543W.printNumber("Alignment", Phdr.p_align);7544}7545}
7546
7547template <class ELFT>7548void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {7549ListScope SS(W, "VersionSymbols");7550if (!Sec)7551return;7552
7553StringRef StrTable;7554ArrayRef<Elf_Sym> Syms;7555const Elf_Shdr *SymTabSec;7556Expected<ArrayRef<Elf_Versym>> VerTableOrErr =7557this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec);7558if (!VerTableOrErr) {7559this->reportUniqueWarning(VerTableOrErr.takeError());7560return;7561}7562
7563if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size())7564return;7565
7566ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec);7567for (size_t I = 0, E = Syms.size(); I < E; ++I) {7568DictScope S(W, "Symbol");7569W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION);7570W.printString("Name",7571this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable,7572/*IsDynamic=*/true));7573}7574}
7575
7576const EnumEntry<unsigned> SymVersionFlags[] = {7577{"Base", "BASE", VER_FLG_BASE},7578{"Weak", "WEAK", VER_FLG_WEAK},7579{"Info", "INFO", VER_FLG_INFO}};7580
7581template <class ELFT>7582void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {7583ListScope SD(W, "VersionDefinitions");7584if (!Sec)7585return;7586
7587Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);7588if (!V) {7589this->reportUniqueWarning(V.takeError());7590return;7591}7592
7593for (const VerDef &D : *V) {7594DictScope Def(W, "Definition");7595W.printNumber("Version", D.Version);7596W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags));7597W.printNumber("Index", D.Ndx);7598W.printNumber("Hash", D.Hash);7599W.printString("Name", D.Name.c_str());7600W.printList(7601"Predecessors", D.AuxV,7602[](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); });7603}7604}
7605
7606template <class ELFT>7607void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {7608ListScope SD(W, "VersionRequirements");7609if (!Sec)7610return;7611
7612Expected<std::vector<VerNeed>> V =7613this->Obj.getVersionDependencies(*Sec, this->WarningHandler);7614if (!V) {7615this->reportUniqueWarning(V.takeError());7616return;7617}7618
7619for (const VerNeed &VN : *V) {7620DictScope Entry(W, "Dependency");7621W.printNumber("Version", VN.Version);7622W.printNumber("Count", VN.Cnt);7623W.printString("FileName", VN.File.c_str());7624
7625ListScope L(W, "Entries");7626for (const VernAux &Aux : VN.AuxV) {7627DictScope Entry(W, "Entry");7628W.printNumber("Hash", Aux.Hash);7629W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags));7630W.printNumber("Index", Aux.Other);7631W.printString("Name", Aux.Name.c_str());7632}7633}7634}
7635
7636template <class ELFT>7637void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,7638size_t MaxChain,7639size_t TotalSyms,7640ArrayRef<size_t> Count,7641bool IsGnu) const {7642StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram";7643StringRef BucketName = IsGnu ? "Bucket" : "Chain";7644StringRef ListName = IsGnu ? "Buckets" : "Chains";7645DictScope Outer(W, HistName);7646W.printNumber("TotalBuckets", NBucket);7647ListScope Buckets(W, ListName);7648size_t CumulativeNonZero = 0;7649for (size_t I = 0; I < MaxChain; ++I) {7650CumulativeNonZero += Count[I] * I;7651DictScope Bucket(W, BucketName);7652W.printNumber("Length", I);7653W.printNumber("Count", Count[I]);7654W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket);7655W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms);7656}7657}
7658
7659// Returns true if rel/rela section exists, and populates SymbolIndices.
7660// Otherwise returns false.
7661template <class ELFT>7662static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,7663const ELFFile<ELFT> &Obj,7664const LLVMELFDumper<ELFT> *Dumper,7665SmallVector<uint32_t, 128> &SymbolIndices) {7666if (!CGRelSection) {7667Dumper->reportUniqueWarning(7668"relocation section for a call graph section doesn't exist");7669return false;7670}7671
7672if (CGRelSection->sh_type == SHT_REL) {7673typename ELFT::RelRange CGProfileRel;7674Expected<typename ELFT::RelRange> CGProfileRelOrError =7675Obj.rels(*CGRelSection);7676if (!CGProfileRelOrError) {7677Dumper->reportUniqueWarning("unable to load relocations for "7678"SHT_LLVM_CALL_GRAPH_PROFILE section: " +7679toString(CGProfileRelOrError.takeError()));7680return false;7681}7682
7683CGProfileRel = *CGProfileRelOrError;7684for (const typename ELFT::Rel &Rel : CGProfileRel)7685SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL()));7686} else {7687// MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert7688// the format to SHT_RELA7689// (https://sourceware.org/bugzilla/show_bug.cgi?id=28035)7690typename ELFT::RelaRange CGProfileRela;7691Expected<typename ELFT::RelaRange> CGProfileRelaOrError =7692Obj.relas(*CGRelSection);7693if (!CGProfileRelaOrError) {7694Dumper->reportUniqueWarning("unable to load relocations for "7695"SHT_LLVM_CALL_GRAPH_PROFILE section: " +7696toString(CGProfileRelaOrError.takeError()));7697return false;7698}7699
7700CGProfileRela = *CGProfileRelaOrError;7701for (const typename ELFT::Rela &Rela : CGProfileRela)7702SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL()));7703}7704
7705return true;7706}
7707
7708template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {7709auto IsMatch = [](const Elf_Shdr &Sec) -> bool {7710return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE;7711};7712
7713Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =7714this->Obj.getSectionAndRelocations(IsMatch);7715if (!SecToRelocMapOrErr) {7716this->reportUniqueWarning("unable to get CG Profile section(s): " +7717toString(SecToRelocMapOrErr.takeError()));7718return;7719}7720
7721for (const auto &CGMapEntry : *SecToRelocMapOrErr) {7722const Elf_Shdr *CGSection = CGMapEntry.first;7723const Elf_Shdr *CGRelSection = CGMapEntry.second;7724
7725Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr =7726this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection);7727if (!CGProfileOrErr) {7728this->reportUniqueWarning(7729"unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " +7730toString(CGProfileOrErr.takeError()));7731return;7732}7733
7734SmallVector<uint32_t, 128> SymbolIndices;7735bool UseReloc =7736getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices);7737if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) {7738this->reportUniqueWarning(7739"number of from/to pairs does not match number of frequencies");7740UseReloc = false;7741}7742
7743ListScope L(W, "CGProfile");7744for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) {7745const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I];7746DictScope D(W, "CGProfileEntry");7747if (UseReloc) {7748uint32_t From = SymbolIndices[I * 2];7749uint32_t To = SymbolIndices[I * 2 + 1];7750W.printNumber("From", this->getStaticSymbolName(From), From);7751W.printNumber("To", this->getStaticSymbolName(To), To);7752}7753W.printNumber("Weight", CGPE.cgp_weight);7754}7755}7756}
7757
7758template <class ELFT>7759void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {7760bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;7761using Elf_Shdr = typename ELFT::Shdr;7762auto IsMatch = [](const Elf_Shdr &Sec) -> bool {7763return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP;7764};7765Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr =7766this->Obj.getSectionAndRelocations(IsMatch);7767if (!SecRelocMapOrErr) {7768this->reportUniqueWarning(7769"failed to get SHT_LLVM_BB_ADDR_MAP section(s): " +7770toString(SecRelocMapOrErr.takeError()));7771return;7772}7773for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) {7774std::optional<const Elf_Shdr *> FunctionSec;7775if (IsRelocatable)7776FunctionSec =7777unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link));7778ListScope L(W, "BBAddrMap");7779if (IsRelocatable && !RelocSec) {7780this->reportUniqueWarning("unable to get relocation section for " +7781this->describe(*Sec));7782continue;7783}7784std::vector<PGOAnalysisMap> PGOAnalyses;7785Expected<std::vector<BBAddrMap>> BBAddrMapOrErr =7786this->Obj.decodeBBAddrMap(*Sec, RelocSec, &PGOAnalyses);7787if (!BBAddrMapOrErr) {7788this->reportUniqueWarning("unable to dump " + this->describe(*Sec) +7789": " + toString(BBAddrMapOrErr.takeError()));7790continue;7791}7792for (const auto &[AM, PAM] : zip_equal(*BBAddrMapOrErr, PGOAnalyses)) {7793DictScope D(W, "Function");7794W.printHex("At", AM.getFunctionAddress());7795SmallVector<uint32_t> FuncSymIndex =7796this->getSymbolIndexesForFunctionAddress(AM.getFunctionAddress(),7797FunctionSec);7798std::string FuncName = "<?>";7799if (FuncSymIndex.empty())7800this->reportUniqueWarning(7801"could not identify function symbol for address (0x" +7802Twine::utohexstr(AM.getFunctionAddress()) + ") in " +7803this->describe(*Sec));7804else7805FuncName = this->getStaticSymbolName(FuncSymIndex.front());7806W.printString("Name", FuncName);7807{7808ListScope BBRL(W, "BB Ranges");7809for (const BBAddrMap::BBRangeEntry &BBR : AM.BBRanges) {7810DictScope BBRD(W);7811W.printHex("Base Address", BBR.BaseAddress);7812ListScope BBEL(W, "BB Entries");7813for (const BBAddrMap::BBEntry &BBE : BBR.BBEntries) {7814DictScope BBED(W);7815W.printNumber("ID", BBE.ID);7816W.printHex("Offset", BBE.Offset);7817W.printHex("Size", BBE.Size);7818W.printBoolean("HasReturn", BBE.hasReturn());7819W.printBoolean("HasTailCall", BBE.hasTailCall());7820W.printBoolean("IsEHPad", BBE.isEHPad());7821W.printBoolean("CanFallThrough", BBE.canFallThrough());7822W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch());7823}7824}7825}7826
7827if (PAM.FeatEnable.hasPGOAnalysis()) {7828DictScope PD(W, "PGO analyses");7829
7830if (PAM.FeatEnable.FuncEntryCount)7831W.printNumber("FuncEntryCount", PAM.FuncEntryCount);7832
7833if (PAM.FeatEnable.hasPGOAnalysisBBData()) {7834ListScope L(W, "PGO BB entries");7835for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) {7836DictScope L(W);7837
7838if (PAM.FeatEnable.BBFreq) {7839if (PrettyPGOAnalysis) {7840std::string BlockFreqStr;7841raw_string_ostream SS(BlockFreqStr);7842printRelativeBlockFreq(SS, PAM.BBEntries.front().BlockFreq,7843PBBE.BlockFreq);7844W.printString("Frequency", BlockFreqStr);7845} else {7846W.printNumber("Frequency", PBBE.BlockFreq.getFrequency());7847}7848}7849
7850if (PAM.FeatEnable.BrProb) {7851ListScope L(W, "Successors");7852for (const auto &Succ : PBBE.Successors) {7853DictScope L(W);7854W.printNumber("ID", Succ.ID);7855if (PrettyPGOAnalysis) {7856W.printObject("Probability", Succ.Prob);7857} else {7858W.printHex("Probability", Succ.Prob.getNumerator());7859}7860}7861}7862}7863}7864}7865}7866}7867}
7868
7869template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {7870ListScope L(W, "Addrsig");7871if (!this->DotAddrsigSec)7872return;7873
7874Expected<std::vector<uint64_t>> SymsOrErr =7875decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);7876if (!SymsOrErr) {7877this->reportUniqueWarning(SymsOrErr.takeError());7878return;7879}7880
7881for (uint64_t Sym : *SymsOrErr)7882W.printNumber("Sym", this->getStaticSymbolName(Sym), Sym);7883}
7884
7885template <typename ELFT>7886static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,7887ScopedPrinter &W) {7888// Return true if we were able to pretty-print the note, false otherwise.7889switch (NoteType) {7890default:7891return false;7892case ELF::NT_GNU_ABI_TAG: {7893const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);7894if (!AbiTag.IsValid) {7895W.printString("ABI", "<corrupt GNU_ABI_TAG>");7896return false;7897} else {7898W.printString("OS", AbiTag.OSName);7899W.printString("ABI", AbiTag.ABI);7900}7901break;7902}7903case ELF::NT_GNU_BUILD_ID: {7904W.printString("Build ID", getGNUBuildId(Desc));7905break;7906}7907case ELF::NT_GNU_GOLD_VERSION:7908W.printString("Version", getDescAsStringRef(Desc));7909break;7910case ELF::NT_GNU_PROPERTY_TYPE_0:7911ListScope D(W, "Property");7912for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))7913W.printString(Property);7914break;7915}7916return true;7917}
7918
7919static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,7920ScopedPrinter &W) {7921// Return true if we were able to pretty-print the note, false otherwise.7922AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);7923if (Props.empty())7924return false;7925for (const auto &KV : Props)7926W.printString(KV.first, KV.second);7927return true;7928}
7929
7930template <class ELFT>7931void LLVMELFDumper<ELFT>::printMemtag(7932const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,7933const ArrayRef<uint8_t> AndroidNoteDesc,7934const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {7935{7936ListScope L(W, "Memtag Dynamic Entries:");7937if (DynamicEntries.empty())7938W.printString("< none found >");7939for (const auto &DynamicEntryKV : DynamicEntries)7940W.printString(DynamicEntryKV.first, DynamicEntryKV.second);7941}7942
7943if (!AndroidNoteDesc.empty()) {7944ListScope L(W, "Memtag Android Note:");7945printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W);7946}7947
7948if (Descriptors.empty())7949return;7950
7951{7952ListScope L(W, "Memtag Global Descriptors:");7953for (const auto &[Addr, BytesToTag] : Descriptors) {7954W.printHex("0x" + utohexstr(Addr), BytesToTag);7955}7956}7957}
7958
7959template <typename ELFT>7960static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType,7961ArrayRef<uint8_t> Desc,7962ScopedPrinter &W) {7963switch (NoteType) {7964default:7965return false;7966case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:7967W.printString("Version", getDescAsStringRef(Desc));7968break;7969case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:7970W.printString("Producer", getDescAsStringRef(Desc));7971break;7972case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:7973W.printString("Producer version", getDescAsStringRef(Desc));7974break;7975}7976return true;7977}
7978
7979static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {7980W.printNumber("Page Size", Note.PageSize);7981ListScope D(W, "Mappings");7982for (const CoreFileMapping &Mapping : Note.Mappings) {7983DictScope D(W);7984W.printHex("Start", Mapping.Start);7985W.printHex("End", Mapping.End);7986W.printHex("Offset", Mapping.Offset);7987W.printString("Filename", Mapping.Filename);7988}7989}
7990
7991template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {7992ListScope L(W, "NoteSections");7993
7994std::unique_ptr<DictScope> NoteSectionScope;7995std::unique_ptr<ListScope> NotesScope;7996size_t Align = 0;7997auto StartNotes = [&](std::optional<StringRef> SecName,7998const typename ELFT::Off Offset,7999const typename ELFT::Addr Size, size_t Al) {8000Align = std::max<size_t>(Al, 4);8001NoteSectionScope = std::make_unique<DictScope>(W, "NoteSection");8002W.printString("Name", SecName ? *SecName : "<?>");8003W.printHex("Offset", Offset);8004W.printHex("Size", Size);8005NotesScope = std::make_unique<ListScope>(W, "Notes");8006};8007
8008auto EndNotes = [&] {8009NotesScope.reset();8010NoteSectionScope.reset();8011};8012
8013auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {8014DictScope D2(W);8015StringRef Name = Note.getName();8016ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);8017Elf_Word Type = Note.getType();8018
8019// Print the note owner/type.8020W.printString("Owner", Name);8021W.printHex("Data size", Descriptor.size());8022
8023StringRef NoteType =8024getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);8025if (!NoteType.empty())8026W.printString("Type", NoteType);8027else8028W.printString("Type",8029"Unknown (" + to_string(format_hex(Type, 10)) + ")");8030
8031// Print the description, or fallback to printing raw bytes for unknown8032// owners/if we fail to pretty-print the contents.8033if (Name == "GNU") {8034if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))8035return Error::success();8036} else if (Name == "FreeBSD") {8037if (std::optional<FreeBSDNote> N =8038getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {8039W.printString(N->Type, N->Value);8040return Error::success();8041}8042} else if (Name == "AMD") {8043const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);8044if (!N.Type.empty()) {8045W.printString(N.Type, N.Value);8046return Error::success();8047}8048} else if (Name == "AMDGPU") {8049const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);8050if (!N.Type.empty()) {8051W.printString(N.Type, N.Value);8052return Error::success();8053}8054} else if (Name == "LLVMOMPOFFLOAD") {8055if (printLLVMOMPOFFLOADNoteLLVMStyle<ELFT>(Type, Descriptor, W))8056return Error::success();8057} else if (Name == "CORE") {8058if (Type == ELF::NT_FILE) {8059DataExtractor DescExtractor(8060Descriptor, ELFT::Endianness == llvm::endianness::little,8061sizeof(Elf_Addr));8062if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {8063printCoreNoteLLVMStyle(*N, W);8064return Error::success();8065} else {8066return N.takeError();8067}8068}8069} else if (Name == "Android") {8070if (printAndroidNoteLLVMStyle(Type, Descriptor, W))8071return Error::success();8072}8073if (!Descriptor.empty()) {8074W.printBinaryBlock("Description data", Descriptor);8075}8076return Error::success();8077};8078
8079processNotesHelper(*this, /*StartNotesFn=*/StartNotes,8080/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes);8081}
8082
8083template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() {8084ListScope L(W, "LinkerOptions");8085
8086unsigned I = -1;8087for (const Elf_Shdr &Shdr : cantFail(this->Obj.sections())) {8088++I;8089if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)8090continue;8091
8092Expected<ArrayRef<uint8_t>> ContentsOrErr =8093this->Obj.getSectionContents(Shdr);8094if (!ContentsOrErr) {8095this->reportUniqueWarning("unable to read the content of the "8096"SHT_LLVM_LINKER_OPTIONS section: " +8097toString(ContentsOrErr.takeError()));8098continue;8099}8100if (ContentsOrErr->empty())8101continue;8102
8103if (ContentsOrErr->back() != 0) {8104this->reportUniqueWarning("SHT_LLVM_LINKER_OPTIONS section at index " +8105Twine(I) +8106" is broken: the "8107"content is not null-terminated");8108continue;8109}8110
8111SmallVector<StringRef, 16> Strings;8112toStringRef(ContentsOrErr->drop_back()).split(Strings, '\0');8113if (Strings.size() % 2 != 0) {8114this->reportUniqueWarning(8115"SHT_LLVM_LINKER_OPTIONS section at index " + Twine(I) +8116" is broken: an incomplete "8117"key-value pair was found. The last possible key was: \"" +8118Strings.back() + "\"");8119continue;8120}8121
8122for (size_t I = 0; I < Strings.size(); I += 2)8123W.printString(Strings[I], Strings[I + 1]);8124}8125}
8126
8127template <class ELFT> void LLVMELFDumper<ELFT>::printDependentLibs() {8128ListScope L(W, "DependentLibs");8129this->printDependentLibsHelper(8130[](const Elf_Shdr &) {},8131[this](StringRef Lib, uint64_t) { W.printString(Lib); });8132}
8133
8134template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() {8135ListScope L(W, "StackSizes");8136if (this->Obj.getHeader().e_type == ELF::ET_REL)8137this->printRelocatableStackSizes([]() {});8138else8139this->printNonRelocatableStackSizes([]() {});8140}
8141
8142template <class ELFT>8143void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,8144ArrayRef<std::string> FuncNames) {8145DictScope D(W, "Entry");8146W.printList("Functions", FuncNames);8147W.printHex("Size", Size);8148}
8149
8150template <class ELFT>8151void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {8152auto PrintEntry = [&](const Elf_Addr *E) {8153W.printHex("Address", Parser.getGotAddress(E));8154W.printNumber("Access", Parser.getGotOffset(E));8155W.printHex("Initial", *E);8156};8157
8158DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");8159
8160W.printHex("Canonical gp value", Parser.getGp());8161{8162ListScope RS(W, "Reserved entries");8163{8164DictScope D(W, "Entry");8165PrintEntry(Parser.getGotLazyResolver());8166W.printString("Purpose", StringRef("Lazy resolver"));8167}8168
8169if (Parser.getGotModulePointer()) {8170DictScope D(W, "Entry");8171PrintEntry(Parser.getGotModulePointer());8172W.printString("Purpose", StringRef("Module pointer (GNU extension)"));8173}8174}8175{8176ListScope LS(W, "Local entries");8177for (auto &E : Parser.getLocalEntries()) {8178DictScope D(W, "Entry");8179PrintEntry(&E);8180}8181}8182
8183if (Parser.IsStatic)8184return;8185
8186{8187ListScope GS(W, "Global entries");8188for (auto &E : Parser.getGlobalEntries()) {8189DictScope D(W, "Entry");8190
8191PrintEntry(&E);8192
8193const Elf_Sym &Sym = *Parser.getGotSym(&E);8194W.printHex("Value", Sym.st_value);8195W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));8196
8197const unsigned SymIndex = &Sym - this->dynamic_symbols().begin();8198DataRegion<Elf_Word> ShndxTable(8199(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());8200printSymbolSection(Sym, SymIndex, ShndxTable);8201
8202std::string SymName = this->getFullSymbolName(8203Sym, SymIndex, ShndxTable, this->DynamicStringTable, true);8204W.printNumber("Name", SymName, Sym.st_name);8205}8206}8207
8208W.printNumber("Number of TLS and multi-GOT entries",8209uint64_t(Parser.getOtherEntries().size()));8210}
8211
8212template <class ELFT>8213void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {8214auto PrintEntry = [&](const Elf_Addr *E) {8215W.printHex("Address", Parser.getPltAddress(E));8216W.printHex("Initial", *E);8217};8218
8219DictScope GS(W, "PLT GOT");8220
8221{8222ListScope RS(W, "Reserved entries");8223{8224DictScope D(W, "Entry");8225PrintEntry(Parser.getPltLazyResolver());8226W.printString("Purpose", StringRef("PLT lazy resolver"));8227}8228
8229if (auto E = Parser.getPltModulePointer()) {8230DictScope D(W, "Entry");8231PrintEntry(E);8232W.printString("Purpose", StringRef("Module pointer"));8233}8234}8235{8236ListScope LS(W, "Entries");8237DataRegion<Elf_Word> ShndxTable(8238(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());8239for (auto &E : Parser.getPltEntries()) {8240DictScope D(W, "Entry");8241PrintEntry(&E);8242
8243const Elf_Sym &Sym = *Parser.getPltSym(&E);8244W.printHex("Value", Sym.st_value);8245W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));8246printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(),8247ShndxTable);8248
8249const Elf_Sym *FirstSym = cantFail(8250this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));8251std::string SymName = this->getFullSymbolName(8252Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true);8253W.printNumber("Name", SymName, Sym.st_name);8254}8255}8256}
8257
8258template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() {8259const Elf_Mips_ABIFlags<ELFT> *Flags;8260if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =8261getMipsAbiFlagsSection(*this)) {8262Flags = *SecOrErr;8263if (!Flags) {8264W.startLine() << "There is no .MIPS.abiflags section in the file.\n";8265return;8266}8267} else {8268this->reportUniqueWarning(SecOrErr.takeError());8269return;8270}8271
8272raw_ostream &OS = W.getOStream();8273DictScope GS(W, "MIPS ABI Flags");8274
8275W.printNumber("Version", Flags->version);8276W.startLine() << "ISA: ";8277if (Flags->isa_rev <= 1)8278OS << format("MIPS%u", Flags->isa_level);8279else8280OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);8281OS << "\n";8282W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType));8283W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags));8284W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType));8285W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));8286W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));8287W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));8288W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1));8289W.printHex("Flags 2", Flags->flags2);8290}
8291
8292template <class ELFT>8293void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,8294ArrayRef<std::string> InputFilenames,8295const Archive *A) {8296FileScope = std::make_unique<DictScope>(this->W);8297DictScope D(this->W, "FileSummary");8298this->W.printString("File", FileStr);8299this->W.printString("Format", Obj.getFileFormatName());8300this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));8301this->W.printString(8302"AddressSize",8303std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));8304this->printLoadName();8305}
8306
8307template <class ELFT>8308void JSONELFDumper<ELFT>::printZeroSymbolOtherField(8309const Elf_Sym &Symbol) const {8310// We want the JSON format to be uniform, since it is machine readable, so8311// always print the `Other` field the same way.8312this->printSymbolOtherField(Symbol);8313}
8314
8315template <class ELFT>8316void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,8317StringRef SymbolName,8318StringRef RelocName) {8319this->printExpandedRelRelaReloc(R, SymbolName, RelocName);8320}
8321
8322template <class ELFT>8323void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,8324StringRef Name,8325const unsigned SecNdx) {8326DictScope Group(this->W);8327this->W.printNumber("SectionIndex", SecNdx);8328ListScope D(this->W, "Relocs");8329this->printRelocationsHelper(Sec);8330}
8331
8332template <class ELFT>8333std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const {8334return "GroupSections";8335}
8336
8337template <class ELFT>8338void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,8339uint64_t Idx) const {8340DictScope Grp(this->W);8341this->W.printString("Name", Name);8342this->W.printNumber("Index", Idx);8343}
8344
8345template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const {8346// JSON output does not need to print anything for empty groups8347}
8348