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