10b57cec5SDimitry Andric //===- ELFDumper.cpp - ELF-specific dumper --------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements the ELF-specific dumper for llvm-readobj.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "ARMEHABIPrinter.h"
150b57cec5SDimitry Andric #include "DwarfCFIEHPrinter.h"
160b57cec5SDimitry Andric #include "Error.h"
170b57cec5SDimitry Andric #include "ObjDumper.h"
180b57cec5SDimitry Andric #include "StackMapPrinter.h"
190b57cec5SDimitry Andric #include "llvm-readobj.h"
200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
220b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
230b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
240b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
250b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
260b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
270b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
280b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
290b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
300b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
310b57cec5SDimitry Andric #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
320b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
330b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h"
340b57cec5SDimitry Andric #include "llvm/Object/ELF.h"
350b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
360b57cec5SDimitry Andric #include "llvm/Object/ELFTypes.h"
370b57cec5SDimitry Andric #include "llvm/Object/Error.h"
380b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
390b57cec5SDimitry Andric #include "llvm/Object/StackMapParser.h"
400b57cec5SDimitry Andric #include "llvm/Support/AMDGPUMetadata.h"
410b57cec5SDimitry Andric #include "llvm/Support/ARMAttributeParser.h"
420b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
430b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
440b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
450b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
460b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
470b57cec5SDimitry Andric #include "llvm/Support/Format.h"
480b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
490b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
500b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
510b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
520b57cec5SDimitry Andric #include "llvm/Support/MipsABIFlags.h"
530b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
540b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
550b57cec5SDimitry Andric #include <algorithm>
560b57cec5SDimitry Andric #include <cinttypes>
570b57cec5SDimitry Andric #include <cstddef>
580b57cec5SDimitry Andric #include <cstdint>
590b57cec5SDimitry Andric #include <cstdlib>
600b57cec5SDimitry Andric #include <iterator>
610b57cec5SDimitry Andric #include <memory>
620b57cec5SDimitry Andric #include <string>
630b57cec5SDimitry Andric #include <system_error>
640b57cec5SDimitry Andric #include <vector>
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric using namespace llvm;
670b57cec5SDimitry Andric using namespace llvm::object;
680b57cec5SDimitry Andric using namespace ELF;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric #define LLVM_READOBJ_ENUM_CASE(ns, enum)                                       \
710b57cec5SDimitry Andric   case ns::enum:                                                               \
720b57cec5SDimitry Andric     return #enum;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric #define ENUM_ENT(enum, altName)                                                \
750b57cec5SDimitry Andric   { #enum, altName, ELF::enum }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric #define ENUM_ENT_1(enum)                                                       \
780b57cec5SDimitry Andric   { #enum, #enum, ELF::enum }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric #define LLVM_READOBJ_PHDR_ENUM(ns, enum)                                       \
810b57cec5SDimitry Andric   case ns::enum:                                                               \
820b57cec5SDimitry Andric     return std::string(#enum).substr(3);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric #define TYPEDEF_ELF_TYPES(ELFT)                                                \
850b57cec5SDimitry Andric   using ELFO = ELFFile<ELFT>;                                                  \
860b57cec5SDimitry Andric   using Elf_Addr = typename ELFT::Addr;                                        \
870b57cec5SDimitry Andric   using Elf_Shdr = typename ELFT::Shdr;                                        \
880b57cec5SDimitry Andric   using Elf_Sym = typename ELFT::Sym;                                          \
890b57cec5SDimitry Andric   using Elf_Dyn = typename ELFT::Dyn;                                          \
900b57cec5SDimitry Andric   using Elf_Dyn_Range = typename ELFT::DynRange;                               \
910b57cec5SDimitry Andric   using Elf_Rel = typename ELFT::Rel;                                          \
920b57cec5SDimitry Andric   using Elf_Rela = typename ELFT::Rela;                                        \
930b57cec5SDimitry Andric   using Elf_Relr = typename ELFT::Relr;                                        \
940b57cec5SDimitry Andric   using Elf_Rel_Range = typename ELFT::RelRange;                               \
950b57cec5SDimitry Andric   using Elf_Rela_Range = typename ELFT::RelaRange;                             \
960b57cec5SDimitry Andric   using Elf_Relr_Range = typename ELFT::RelrRange;                             \
970b57cec5SDimitry Andric   using Elf_Phdr = typename ELFT::Phdr;                                        \
980b57cec5SDimitry Andric   using Elf_Half = typename ELFT::Half;                                        \
990b57cec5SDimitry Andric   using Elf_Ehdr = typename ELFT::Ehdr;                                        \
1000b57cec5SDimitry Andric   using Elf_Word = typename ELFT::Word;                                        \
1010b57cec5SDimitry Andric   using Elf_Hash = typename ELFT::Hash;                                        \
1020b57cec5SDimitry Andric   using Elf_GnuHash = typename ELFT::GnuHash;                                  \
1030b57cec5SDimitry Andric   using Elf_Note  = typename ELFT::Note;                                       \
1040b57cec5SDimitry Andric   using Elf_Sym_Range = typename ELFT::SymRange;                               \
1050b57cec5SDimitry Andric   using Elf_Versym = typename ELFT::Versym;                                    \
1060b57cec5SDimitry Andric   using Elf_Verneed = typename ELFT::Verneed;                                  \
1070b57cec5SDimitry Andric   using Elf_Vernaux = typename ELFT::Vernaux;                                  \
1080b57cec5SDimitry Andric   using Elf_Verdef = typename ELFT::Verdef;                                    \
1090b57cec5SDimitry Andric   using Elf_Verdaux = typename ELFT::Verdaux;                                  \
1100b57cec5SDimitry Andric   using Elf_CGProfile = typename ELFT::CGProfile;                              \
1110b57cec5SDimitry Andric   using uintX_t = typename ELFT::uint;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric namespace {
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric template <class ELFT> class DumpStyle;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric /// Represents a contiguous uniform range in the file. We cannot just create a
1180b57cec5SDimitry Andric /// range directly because when creating one of these from the .dynamic table
1190b57cec5SDimitry Andric /// the size, entity size and virtual address are different entries in arbitrary
1200b57cec5SDimitry Andric /// order (DT_REL, DT_RELSZ, DT_RELENT for example).
1210b57cec5SDimitry Andric struct DynRegionInfo {
1220b57cec5SDimitry Andric   DynRegionInfo() = default;
1230b57cec5SDimitry Andric   DynRegionInfo(const void *A, uint64_t S, uint64_t ES)
1240b57cec5SDimitry Andric       : Addr(A), Size(S), EntSize(ES) {}
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   /// Address in current address space.
1270b57cec5SDimitry Andric   const void *Addr = nullptr;
1280b57cec5SDimitry Andric   /// Size in bytes of the region.
1290b57cec5SDimitry Andric   uint64_t Size = 0;
1300b57cec5SDimitry Andric   /// Size of each entity in the region.
1310b57cec5SDimitry Andric   uint64_t EntSize = 0;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   template <typename Type> ArrayRef<Type> getAsArrayRef() const {
1340b57cec5SDimitry Andric     const Type *Start = reinterpret_cast<const Type *>(Addr);
1350b57cec5SDimitry Andric     if (!Start)
1360b57cec5SDimitry Andric       return {Start, Start};
1370b57cec5SDimitry Andric     if (EntSize != sizeof(Type) || Size % EntSize) {
1380b57cec5SDimitry Andric       // TODO: Add a section index to this warning.
1390b57cec5SDimitry Andric       reportWarning("invalid section size (" + Twine(Size) +
1400b57cec5SDimitry Andric                     ") or entity size (" + Twine(EntSize) + ")");
1410b57cec5SDimitry Andric       return {Start, Start};
1420b57cec5SDimitry Andric     }
1430b57cec5SDimitry Andric     return {Start, Start + (Size / EntSize)};
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric };
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric template <typename ELFT> class ELFDumper : public ObjDumper {
1480b57cec5SDimitry Andric public:
1490b57cec5SDimitry Andric   ELFDumper(const object::ELFObjectFile<ELFT> *ObjF, ScopedPrinter &Writer);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   void printFileHeaders() override;
1520b57cec5SDimitry Andric   void printSectionHeaders() override;
1530b57cec5SDimitry Andric   void printRelocations() override;
1540b57cec5SDimitry Andric   void printDynamicRelocations() override;
1550b57cec5SDimitry Andric   void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
1560b57cec5SDimitry Andric   void printHashSymbols() override;
1570b57cec5SDimitry Andric   void printUnwindInfo() override;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   void printDynamicTable() override;
1600b57cec5SDimitry Andric   void printNeededLibraries() override;
1610b57cec5SDimitry Andric   void printProgramHeaders(bool PrintProgramHeaders,
1620b57cec5SDimitry Andric                            cl::boolOrDefault PrintSectionMapping) override;
1630b57cec5SDimitry Andric   void printHashTable() override;
1640b57cec5SDimitry Andric   void printGnuHashTable() override;
1650b57cec5SDimitry Andric   void printLoadName() override;
1660b57cec5SDimitry Andric   void printVersionInfo() override;
1670b57cec5SDimitry Andric   void printGroupSections() override;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   void printAttributes() override;
1700b57cec5SDimitry Andric   void printMipsPLTGOT() override;
1710b57cec5SDimitry Andric   void printMipsABIFlags() override;
1720b57cec5SDimitry Andric   void printMipsReginfo() override;
1730b57cec5SDimitry Andric   void printMipsOptions() override;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   void printStackMap() const override;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   void printHashHistogram() override;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   void printCGProfile() override;
1800b57cec5SDimitry Andric   void printAddrsig() override;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   void printNotes() override;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   void printELFLinkerOptions() override;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   const object::ELFObjectFile<ELFT> *getElfObject() const { return ObjF; };
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric private:
1890b57cec5SDimitry Andric   std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   TYPEDEF_ELF_TYPES(ELFT)
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   DynRegionInfo checkDRI(DynRegionInfo DRI) {
1940b57cec5SDimitry Andric     const ELFFile<ELFT> *Obj = ObjF->getELFFile();
1950b57cec5SDimitry Andric     if (DRI.Addr < Obj->base() ||
1960b57cec5SDimitry Andric         reinterpret_cast<const uint8_t *>(DRI.Addr) + DRI.Size >
1970b57cec5SDimitry Andric             Obj->base() + Obj->getBufSize())
1980b57cec5SDimitry Andric       error(llvm::object::object_error::parse_failed);
1990b57cec5SDimitry Andric     return DRI;
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) {
2030b57cec5SDimitry Andric     return checkDRI(
2040b57cec5SDimitry Andric         {ObjF->getELFFile()->base() + P->p_offset, P->p_filesz, EntSize});
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   DynRegionInfo createDRIFrom(const Elf_Shdr *S) {
2080b57cec5SDimitry Andric     return checkDRI(
2090b57cec5SDimitry Andric         {ObjF->getELFFile()->base() + S->sh_offset, S->sh_size, S->sh_entsize});
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   void loadDynamicTable(const ELFFile<ELFT> *Obj);
2130b57cec5SDimitry Andric   void parseDynamicTable();
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
2160b57cec5SDimitry Andric                              bool &IsDefault) const;
2170b57cec5SDimitry Andric   void LoadVersionMap() const;
2180b57cec5SDimitry Andric   void LoadVersionNeeds(const Elf_Shdr *ec) const;
2190b57cec5SDimitry Andric   void LoadVersionDefs(const Elf_Shdr *sec) const;
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   const object::ELFObjectFile<ELFT> *ObjF;
2220b57cec5SDimitry Andric   DynRegionInfo DynRelRegion;
2230b57cec5SDimitry Andric   DynRegionInfo DynRelaRegion;
2240b57cec5SDimitry Andric   DynRegionInfo DynRelrRegion;
2250b57cec5SDimitry Andric   DynRegionInfo DynPLTRelRegion;
2260b57cec5SDimitry Andric   DynRegionInfo DynSymRegion;
2270b57cec5SDimitry Andric   DynRegionInfo DynamicTable;
2280b57cec5SDimitry Andric   StringRef DynamicStringTable;
2290b57cec5SDimitry Andric   StringRef SOName = "<Not found>";
2300b57cec5SDimitry Andric   const Elf_Hash *HashTable = nullptr;
2310b57cec5SDimitry Andric   const Elf_GnuHash *GnuHashTable = nullptr;
2320b57cec5SDimitry Andric   const Elf_Shdr *DotSymtabSec = nullptr;
2330b57cec5SDimitry Andric   const Elf_Shdr *DotCGProfileSec = nullptr;
2340b57cec5SDimitry Andric   const Elf_Shdr *DotAddrsigSec = nullptr;
2350b57cec5SDimitry Andric   StringRef DynSymtabName;
2360b57cec5SDimitry Andric   ArrayRef<Elf_Word> ShndxTable;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   const Elf_Shdr *SymbolVersionSection = nullptr;   // .gnu.version
2390b57cec5SDimitry Andric   const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r
2400b57cec5SDimitry Andric   const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   // Records for each version index the corresponding Verdef or Vernaux entry.
2430b57cec5SDimitry Andric   // This is filled the first time LoadVersionMap() is called.
2440b57cec5SDimitry Andric   class VersionMapEntry : public PointerIntPair<const void *, 1> {
2450b57cec5SDimitry Andric   public:
2460b57cec5SDimitry Andric     // If the integer is 0, this is an Elf_Verdef*.
2470b57cec5SDimitry Andric     // If the integer is 1, this is an Elf_Vernaux*.
2480b57cec5SDimitry Andric     VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {}
2490b57cec5SDimitry Andric     VersionMapEntry(const Elf_Verdef *verdef)
2500b57cec5SDimitry Andric         : PointerIntPair<const void *, 1>(verdef, 0) {}
2510b57cec5SDimitry Andric     VersionMapEntry(const Elf_Vernaux *vernaux)
2520b57cec5SDimitry Andric         : PointerIntPair<const void *, 1>(vernaux, 1) {}
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric     bool isNull() const { return getPointer() == nullptr; }
2550b57cec5SDimitry Andric     bool isVerdef() const { return !isNull() && getInt() == 0; }
2560b57cec5SDimitry Andric     bool isVernaux() const { return !isNull() && getInt() == 1; }
2570b57cec5SDimitry Andric     const Elf_Verdef *getVerdef() const {
2580b57cec5SDimitry Andric       return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr;
2590b57cec5SDimitry Andric     }
2600b57cec5SDimitry Andric     const Elf_Vernaux *getVernaux() const {
2610b57cec5SDimitry Andric       return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr;
2620b57cec5SDimitry Andric     }
2630b57cec5SDimitry Andric   };
2640b57cec5SDimitry Andric   mutable SmallVector<VersionMapEntry, 16> VersionMap;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric public:
2670b57cec5SDimitry Andric   Elf_Dyn_Range dynamic_table() const {
2680b57cec5SDimitry Andric     // A valid .dynamic section contains an array of entries terminated
2690b57cec5SDimitry Andric     // with a DT_NULL entry. However, sometimes the section content may
2700b57cec5SDimitry Andric     // continue past the DT_NULL entry, so to dump the section correctly,
2710b57cec5SDimitry Andric     // we first find the end of the entries by iterating over them.
2720b57cec5SDimitry Andric     Elf_Dyn_Range Table = DynamicTable.getAsArrayRef<Elf_Dyn>();
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric     size_t Size = 0;
2750b57cec5SDimitry Andric     while (Size < Table.size())
2760b57cec5SDimitry Andric       if (Table[Size++].getTag() == DT_NULL)
2770b57cec5SDimitry Andric         break;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric     return Table.slice(0, Size);
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   Elf_Sym_Range dynamic_symbols() const {
2830b57cec5SDimitry Andric     return DynSymRegion.getAsArrayRef<Elf_Sym>();
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   Elf_Rel_Range dyn_rels() const;
2870b57cec5SDimitry Andric   Elf_Rela_Range dyn_relas() const;
2880b57cec5SDimitry Andric   Elf_Relr_Range dyn_relrs() const;
2890b57cec5SDimitry Andric   std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
2900b57cec5SDimitry Andric                                 bool IsDynamic) const;
2910b57cec5SDimitry Andric   void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
2920b57cec5SDimitry Andric                            StringRef &SectionName,
2930b57cec5SDimitry Andric                            unsigned &SectionIndex) const;
2940b57cec5SDimitry Andric   std::string getStaticSymbolName(uint32_t Index) const;
2950b57cec5SDimitry Andric   StringRef getSymbolVersionByIndex(StringRef StrTab,
2960b57cec5SDimitry Andric                                     uint32_t VersionSymbolIndex,
2970b57cec5SDimitry Andric                                     bool &IsDefault) const;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   void printSymbolsHelper(bool IsDynamic) const;
3000b57cec5SDimitry Andric   void printDynamicEntry(raw_ostream &OS, uint64_t Type, uint64_t Value) const;
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
3030b57cec5SDimitry Andric   const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; }
3040b57cec5SDimitry Andric   const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; }
3050b57cec5SDimitry Andric   ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; }
3060b57cec5SDimitry Andric   StringRef getDynamicStringTable() const { return DynamicStringTable; }
3070b57cec5SDimitry Andric   const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; }
3080b57cec5SDimitry Andric   const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; }
3090b57cec5SDimitry Andric   const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; }
3100b57cec5SDimitry Andric   const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; }
3110b57cec5SDimitry Andric   const DynRegionInfo &getDynamicTableRegion() const { return DynamicTable; }
3120b57cec5SDimitry Andric   const Elf_Hash *getHashTable() const { return HashTable; }
3130b57cec5SDimitry Andric   const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; }
3140b57cec5SDimitry Andric };
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric template <class ELFT>
3170b57cec5SDimitry Andric void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
3180b57cec5SDimitry Andric   StringRef StrTable, SymtabName;
3190b57cec5SDimitry Andric   size_t Entries = 0;
3200b57cec5SDimitry Andric   Elf_Sym_Range Syms(nullptr, nullptr);
3210b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
3220b57cec5SDimitry Andric   if (IsDynamic) {
3230b57cec5SDimitry Andric     StrTable = DynamicStringTable;
3240b57cec5SDimitry Andric     Syms = dynamic_symbols();
3250b57cec5SDimitry Andric     SymtabName = DynSymtabName;
3260b57cec5SDimitry Andric     if (DynSymRegion.Addr)
3270b57cec5SDimitry Andric       Entries = DynSymRegion.Size / DynSymRegion.EntSize;
3280b57cec5SDimitry Andric   } else {
3290b57cec5SDimitry Andric     if (!DotSymtabSec)
3300b57cec5SDimitry Andric       return;
3310b57cec5SDimitry Andric     StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
3320b57cec5SDimitry Andric     Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
3330b57cec5SDimitry Andric     SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec));
3340b57cec5SDimitry Andric     Entries = DotSymtabSec->getEntityCount();
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric   if (Syms.begin() == Syms.end())
3370b57cec5SDimitry Andric     return;
3380b57cec5SDimitry Andric   ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries);
3390b57cec5SDimitry Andric   for (const auto &Sym : Syms)
3400b57cec5SDimitry Andric     ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric template <typename ELFT> class DumpStyle {
3460b57cec5SDimitry Andric public:
3470b57cec5SDimitry Andric   using Elf_Shdr = typename ELFT::Shdr;
3480b57cec5SDimitry Andric   using Elf_Sym = typename ELFT::Sym;
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {}
3510b57cec5SDimitry Andric   virtual ~DumpStyle() = default;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0;
3540b57cec5SDimitry Andric   virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0;
3550b57cec5SDimitry Andric   virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0;
3560b57cec5SDimitry Andric   virtual void printSectionHeaders(const ELFFile<ELFT> *Obj) = 0;
3570b57cec5SDimitry Andric   virtual void printSymbols(const ELFFile<ELFT> *Obj, bool PrintSymbols,
3580b57cec5SDimitry Andric                             bool PrintDynamicSymbols) = 0;
3590b57cec5SDimitry Andric   virtual void printHashSymbols(const ELFFile<ELFT> *Obj) {}
3600b57cec5SDimitry Andric   virtual void printDynamic(const ELFFile<ELFT> *Obj) {}
3610b57cec5SDimitry Andric   virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
3620b57cec5SDimitry Andric   virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
3630b57cec5SDimitry Andric                                   size_t Offset) {}
3640b57cec5SDimitry Andric   virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol,
3650b57cec5SDimitry Andric                            const Elf_Sym *FirstSym, StringRef StrTable,
3660b57cec5SDimitry Andric                            bool IsDynamic) = 0;
3670b57cec5SDimitry Andric   virtual void printProgramHeaders(const ELFFile<ELFT> *Obj,
3680b57cec5SDimitry Andric                                    bool PrintProgramHeaders,
3690b57cec5SDimitry Andric                                    cl::boolOrDefault PrintSectionMapping) = 0;
3700b57cec5SDimitry Andric   virtual void printVersionSymbolSection(const ELFFile<ELFT> *Obj,
3710b57cec5SDimitry Andric                                          const Elf_Shdr *Sec) = 0;
3720b57cec5SDimitry Andric   virtual void printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
3730b57cec5SDimitry Andric                                              const Elf_Shdr *Sec) = 0;
3740b57cec5SDimitry Andric   virtual void printVersionDependencySection(const ELFFile<ELFT> *Obj,
3750b57cec5SDimitry Andric                                              const Elf_Shdr *Sec) = 0;
3760b57cec5SDimitry Andric   virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;
3770b57cec5SDimitry Andric   virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0;
3780b57cec5SDimitry Andric   virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0;
3790b57cec5SDimitry Andric   virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
3800b57cec5SDimitry Andric   virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0;
3810b57cec5SDimitry Andric   virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
3820b57cec5SDimitry Andric   virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
3830b57cec5SDimitry Andric   const ELFDumper<ELFT> *dumper() const { return Dumper; }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric private:
3860b57cec5SDimitry Andric   const ELFDumper<ELFT> *Dumper;
3870b57cec5SDimitry Andric };
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> {
3900b57cec5SDimitry Andric   formatted_raw_ostream &OS;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric public:
3930b57cec5SDimitry Andric   TYPEDEF_ELF_TYPES(ELFT)
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper)
3960b57cec5SDimitry Andric       : DumpStyle<ELFT>(Dumper),
3970b57cec5SDimitry Andric         OS(static_cast<formatted_raw_ostream&>(W.getOStream())) {
3980b57cec5SDimitry Andric     assert (&W.getOStream() == &llvm::fouts());
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   void printFileHeaders(const ELFO *Obj) override;
4020b57cec5SDimitry Andric   void printGroupSections(const ELFFile<ELFT> *Obj) override;
4030b57cec5SDimitry Andric   void printRelocations(const ELFO *Obj) override;
4040b57cec5SDimitry Andric   void printSectionHeaders(const ELFO *Obj) override;
4050b57cec5SDimitry Andric   void printSymbols(const ELFO *Obj, bool PrintSymbols,
4060b57cec5SDimitry Andric                     bool PrintDynamicSymbols) override;
4070b57cec5SDimitry Andric   void printHashSymbols(const ELFO *Obj) override;
4080b57cec5SDimitry Andric   void printDynamic(const ELFFile<ELFT> *Obj) override;
4090b57cec5SDimitry Andric   void printDynamicRelocations(const ELFO *Obj) override;
4100b57cec5SDimitry Andric   void printSymtabMessage(const ELFO *Obj, StringRef Name,
4110b57cec5SDimitry Andric                           size_t Offset) override;
4120b57cec5SDimitry Andric   void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders,
4130b57cec5SDimitry Andric                            cl::boolOrDefault PrintSectionMapping) override;
4140b57cec5SDimitry Andric   void printVersionSymbolSection(const ELFFile<ELFT> *Obj,
4150b57cec5SDimitry Andric                                  const Elf_Shdr *Sec) override;
4160b57cec5SDimitry Andric   void printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
4170b57cec5SDimitry Andric                                      const Elf_Shdr *Sec) override;
4180b57cec5SDimitry Andric   void printVersionDependencySection(const ELFFile<ELFT> *Obj,
4190b57cec5SDimitry Andric                                      const Elf_Shdr *Sec) override;
4200b57cec5SDimitry Andric   void printHashHistogram(const ELFFile<ELFT> *Obj) override;
4210b57cec5SDimitry Andric   void printCGProfile(const ELFFile<ELFT> *Obj) override;
4220b57cec5SDimitry Andric   void printAddrsig(const ELFFile<ELFT> *Obj) override;
4230b57cec5SDimitry Andric   void printNotes(const ELFFile<ELFT> *Obj) override;
4240b57cec5SDimitry Andric   void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
4250b57cec5SDimitry Andric   void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
4260b57cec5SDimitry Andric   void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric private:
4290b57cec5SDimitry Andric   struct Field {
4300b57cec5SDimitry Andric     std::string Str;
4310b57cec5SDimitry Andric     unsigned Column;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     Field(StringRef S, unsigned Col) : Str(S), Column(Col) {}
4340b57cec5SDimitry Andric     Field(unsigned Col) : Column(Col) {}
4350b57cec5SDimitry Andric   };
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   template <typename T, typename TEnum>
4380b57cec5SDimitry Andric   std::string printEnum(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) {
4390b57cec5SDimitry Andric     for (const auto &EnumItem : EnumValues)
4400b57cec5SDimitry Andric       if (EnumItem.Value == Value)
4410b57cec5SDimitry Andric         return EnumItem.AltName;
4420b57cec5SDimitry Andric     return to_hexString(Value, false);
4430b57cec5SDimitry Andric   }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   template <typename T, typename TEnum>
4460b57cec5SDimitry Andric   std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues,
4470b57cec5SDimitry Andric                          TEnum EnumMask1 = {}, TEnum EnumMask2 = {},
4480b57cec5SDimitry Andric                          TEnum EnumMask3 = {}) {
4490b57cec5SDimitry Andric     std::string Str;
4500b57cec5SDimitry Andric     for (const auto &Flag : EnumValues) {
4510b57cec5SDimitry Andric       if (Flag.Value == 0)
4520b57cec5SDimitry Andric         continue;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric       TEnum EnumMask{};
4550b57cec5SDimitry Andric       if (Flag.Value & EnumMask1)
4560b57cec5SDimitry Andric         EnumMask = EnumMask1;
4570b57cec5SDimitry Andric       else if (Flag.Value & EnumMask2)
4580b57cec5SDimitry Andric         EnumMask = EnumMask2;
4590b57cec5SDimitry Andric       else if (Flag.Value & EnumMask3)
4600b57cec5SDimitry Andric         EnumMask = EnumMask3;
4610b57cec5SDimitry Andric       bool IsEnum = (Flag.Value & EnumMask) != 0;
4620b57cec5SDimitry Andric       if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
4630b57cec5SDimitry Andric           (IsEnum && (Value & EnumMask) == Flag.Value)) {
4640b57cec5SDimitry Andric         if (!Str.empty())
4650b57cec5SDimitry Andric           Str += ", ";
4660b57cec5SDimitry Andric         Str += Flag.AltName;
4670b57cec5SDimitry Andric       }
4680b57cec5SDimitry Andric     }
4690b57cec5SDimitry Andric     return Str;
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   formatted_raw_ostream &printField(struct Field F) {
4730b57cec5SDimitry Andric     if (F.Column != 0)
4740b57cec5SDimitry Andric       OS.PadToColumn(F.Column);
4750b57cec5SDimitry Andric     OS << F.Str;
4760b57cec5SDimitry Andric     OS.flush();
4770b57cec5SDimitry Andric     return OS;
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric   void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym,
4800b57cec5SDimitry Andric                          StringRef StrTable, uint32_t Bucket);
4810b57cec5SDimitry Andric   void printRelocHeader(unsigned SType);
4820b57cec5SDimitry Andric   void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
4830b57cec5SDimitry Andric                        const Elf_Rela &R, bool IsRela);
4840b57cec5SDimitry Andric   void printRelocation(const ELFO *Obj, const Elf_Sym *Sym,
4850b57cec5SDimitry Andric                        StringRef SymbolName, const Elf_Rela &R, bool IsRela);
4860b57cec5SDimitry Andric   void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
4870b57cec5SDimitry Andric                    StringRef StrTable, bool IsDynamic) override;
4880b57cec5SDimitry Andric   std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
4890b57cec5SDimitry Andric                                   const Elf_Sym *FirstSym);
4900b57cec5SDimitry Andric   void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela);
4910b57cec5SDimitry Andric   bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
4920b57cec5SDimitry Andric   bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
4930b57cec5SDimitry Andric   bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
4940b57cec5SDimitry Andric   bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
4950b57cec5SDimitry Andric   void printProgramHeaders(const ELFO *Obj);
4960b57cec5SDimitry Andric   void printSectionMapping(const ELFO *Obj);
4970b57cec5SDimitry Andric };
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> {
5000b57cec5SDimitry Andric public:
5010b57cec5SDimitry Andric   TYPEDEF_ELF_TYPES(ELFT)
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   LLVMStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper)
5040b57cec5SDimitry Andric       : DumpStyle<ELFT>(Dumper), W(W) {}
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   void printFileHeaders(const ELFO *Obj) override;
5070b57cec5SDimitry Andric   void printGroupSections(const ELFFile<ELFT> *Obj) override;
5080b57cec5SDimitry Andric   void printRelocations(const ELFO *Obj) override;
5090b57cec5SDimitry Andric   void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj);
5100b57cec5SDimitry Andric   void printSectionHeaders(const ELFO *Obj) override;
5110b57cec5SDimitry Andric   void printSymbols(const ELFO *Obj, bool PrintSymbols,
5120b57cec5SDimitry Andric                     bool PrintDynamicSymbols) override;
5130b57cec5SDimitry Andric   void printDynamic(const ELFFile<ELFT> *Obj) override;
5140b57cec5SDimitry Andric   void printDynamicRelocations(const ELFO *Obj) override;
5150b57cec5SDimitry Andric   void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders,
5160b57cec5SDimitry Andric                            cl::boolOrDefault PrintSectionMapping) override;
5170b57cec5SDimitry Andric   void printVersionSymbolSection(const ELFFile<ELFT> *Obj,
5180b57cec5SDimitry Andric                                  const Elf_Shdr *Sec) override;
5190b57cec5SDimitry Andric   void printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
5200b57cec5SDimitry Andric                                      const Elf_Shdr *Sec) override;
5210b57cec5SDimitry Andric   void printVersionDependencySection(const ELFFile<ELFT> *Obj,
5220b57cec5SDimitry Andric                                      const Elf_Shdr *Sec) override;
5230b57cec5SDimitry Andric   void printHashHistogram(const ELFFile<ELFT> *Obj) override;
5240b57cec5SDimitry Andric   void printCGProfile(const ELFFile<ELFT> *Obj) override;
5250b57cec5SDimitry Andric   void printAddrsig(const ELFFile<ELFT> *Obj) override;
5260b57cec5SDimitry Andric   void printNotes(const ELFFile<ELFT> *Obj) override;
5270b57cec5SDimitry Andric   void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
5280b57cec5SDimitry Andric   void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
5290b57cec5SDimitry Andric   void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric private:
5320b57cec5SDimitry Andric   void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
5330b57cec5SDimitry Andric   void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel);
5340b57cec5SDimitry Andric   void printSymbols(const ELFO *Obj);
5350b57cec5SDimitry Andric   void printDynamicSymbols(const ELFO *Obj);
5360b57cec5SDimitry Andric   void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
5370b57cec5SDimitry Andric                    StringRef StrTable, bool IsDynamic) override;
5380b57cec5SDimitry Andric   void printProgramHeaders(const ELFO *Obj);
5390b57cec5SDimitry Andric   void printSectionMapping(const ELFO *Obj) {}
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   ScopedPrinter &W;
5420b57cec5SDimitry Andric };
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric } // end anonymous namespace
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric namespace llvm {
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric template <class ELFT>
5490b57cec5SDimitry Andric static std::error_code createELFDumper(const ELFObjectFile<ELFT> *Obj,
5500b57cec5SDimitry Andric                                        ScopedPrinter &Writer,
5510b57cec5SDimitry Andric                                        std::unique_ptr<ObjDumper> &Result) {
5520b57cec5SDimitry Andric   Result.reset(new ELFDumper<ELFT>(Obj, Writer));
5530b57cec5SDimitry Andric   return readobj_error::success;
5540b57cec5SDimitry Andric }
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric std::error_code createELFDumper(const object::ObjectFile *Obj,
5570b57cec5SDimitry Andric                                 ScopedPrinter &Writer,
5580b57cec5SDimitry Andric                                 std::unique_ptr<ObjDumper> &Result) {
5590b57cec5SDimitry Andric   // Little-endian 32-bit
5600b57cec5SDimitry Andric   if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
5610b57cec5SDimitry Andric     return createELFDumper(ELFObj, Writer, Result);
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   // Big-endian 32-bit
5640b57cec5SDimitry Andric   if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
5650b57cec5SDimitry Andric     return createELFDumper(ELFObj, Writer, Result);
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   // Little-endian 64-bit
5680b57cec5SDimitry Andric   if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
5690b57cec5SDimitry Andric     return createELFDumper(ELFObj, Writer, Result);
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   // Big-endian 64-bit
5720b57cec5SDimitry Andric   if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
5730b57cec5SDimitry Andric     return createELFDumper(ELFObj, Writer, Result);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   return readobj_error::unsupported_obj_file_format;
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric } // end namespace llvm
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric // Iterate through the versions needed section, and place each Elf_Vernaux
5810b57cec5SDimitry Andric // in the VersionMap according to its index.
5820b57cec5SDimitry Andric template <class ELFT>
5830b57cec5SDimitry Andric void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *Sec) const {
5840b57cec5SDimitry Andric   unsigned VerneedSize = Sec->sh_size;    // Size of section in bytes
5850b57cec5SDimitry Andric   unsigned VerneedEntries = Sec->sh_info; // Number of Verneed entries
5860b57cec5SDimitry Andric   const uint8_t *VerneedStart = reinterpret_cast<const uint8_t *>(
5870b57cec5SDimitry Andric       ObjF->getELFFile()->base() + Sec->sh_offset);
5880b57cec5SDimitry Andric   const uint8_t *VerneedEnd = VerneedStart + VerneedSize;
5890b57cec5SDimitry Andric   // The first Verneed entry is at the start of the section.
5900b57cec5SDimitry Andric   const uint8_t *VerneedBuf = VerneedStart;
5910b57cec5SDimitry Andric   for (unsigned VerneedIndex = 0; VerneedIndex < VerneedEntries;
5920b57cec5SDimitry Andric        ++VerneedIndex) {
5930b57cec5SDimitry Andric     if (VerneedBuf + sizeof(Elf_Verneed) > VerneedEnd)
5940b57cec5SDimitry Andric       report_fatal_error("Section ended unexpectedly while scanning "
5950b57cec5SDimitry Andric                          "version needed records.");
5960b57cec5SDimitry Andric     const Elf_Verneed *Verneed =
5970b57cec5SDimitry Andric         reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
5980b57cec5SDimitry Andric     if (Verneed->vn_version != ELF::VER_NEED_CURRENT)
5990b57cec5SDimitry Andric       report_fatal_error("Unexpected verneed version");
6000b57cec5SDimitry Andric     // Iterate through the Vernaux entries
6010b57cec5SDimitry Andric     const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
6020b57cec5SDimitry Andric     for (unsigned VernauxIndex = 0; VernauxIndex < Verneed->vn_cnt;
6030b57cec5SDimitry Andric          ++VernauxIndex) {
6040b57cec5SDimitry Andric       if (VernauxBuf + sizeof(Elf_Vernaux) > VerneedEnd)
6050b57cec5SDimitry Andric         report_fatal_error("Section ended unexpected while scanning auxiliary "
6060b57cec5SDimitry Andric                            "version needed records.");
6070b57cec5SDimitry Andric       const Elf_Vernaux *Vernaux =
6080b57cec5SDimitry Andric           reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
6090b57cec5SDimitry Andric       size_t Index = Vernaux->vna_other & ELF::VERSYM_VERSION;
6100b57cec5SDimitry Andric       if (Index >= VersionMap.size())
6110b57cec5SDimitry Andric         VersionMap.resize(Index + 1);
6120b57cec5SDimitry Andric       VersionMap[Index] = VersionMapEntry(Vernaux);
6130b57cec5SDimitry Andric       VernauxBuf += Vernaux->vna_next;
6140b57cec5SDimitry Andric     }
6150b57cec5SDimitry Andric     VerneedBuf += Verneed->vn_next;
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric // Iterate through the version definitions, and place each Elf_Verdef
6200b57cec5SDimitry Andric // in the VersionMap according to its index.
6210b57cec5SDimitry Andric template <class ELFT>
6220b57cec5SDimitry Andric void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *Sec) const {
6230b57cec5SDimitry Andric   unsigned VerdefSize = Sec->sh_size;    // Size of section in bytes
6240b57cec5SDimitry Andric   unsigned VerdefEntries = Sec->sh_info; // Number of Verdef entries
6250b57cec5SDimitry Andric   const uint8_t *VerdefStart = reinterpret_cast<const uint8_t *>(
6260b57cec5SDimitry Andric       ObjF->getELFFile()->base() + Sec->sh_offset);
6270b57cec5SDimitry Andric   const uint8_t *VerdefEnd = VerdefStart + VerdefSize;
6280b57cec5SDimitry Andric   // The first Verdef entry is at the start of the section.
6290b57cec5SDimitry Andric   const uint8_t *VerdefBuf = VerdefStart;
6300b57cec5SDimitry Andric   for (unsigned VerdefIndex = 0; VerdefIndex < VerdefEntries; ++VerdefIndex) {
6310b57cec5SDimitry Andric     if (VerdefBuf + sizeof(Elf_Verdef) > VerdefEnd)
6320b57cec5SDimitry Andric       report_fatal_error("Section ended unexpectedly while scanning "
6330b57cec5SDimitry Andric                          "version definitions.");
6340b57cec5SDimitry Andric     const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf);
6350b57cec5SDimitry Andric     if (Verdef->vd_version != ELF::VER_DEF_CURRENT)
6360b57cec5SDimitry Andric       report_fatal_error("Unexpected verdef version");
6370b57cec5SDimitry Andric     size_t Index = Verdef->vd_ndx & ELF::VERSYM_VERSION;
6380b57cec5SDimitry Andric     if (Index >= VersionMap.size())
6390b57cec5SDimitry Andric       VersionMap.resize(Index + 1);
6400b57cec5SDimitry Andric     VersionMap[Index] = VersionMapEntry(Verdef);
6410b57cec5SDimitry Andric     VerdefBuf += Verdef->vd_next;
6420b57cec5SDimitry Andric   }
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() const {
6460b57cec5SDimitry Andric   // If there is no dynamic symtab or version table, there is nothing to do.
6470b57cec5SDimitry Andric   if (!DynSymRegion.Addr || !SymbolVersionSection)
6480b57cec5SDimitry Andric     return;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   // Has the VersionMap already been loaded?
6510b57cec5SDimitry Andric   if (!VersionMap.empty())
6520b57cec5SDimitry Andric     return;
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   // The first two version indexes are reserved.
6550b57cec5SDimitry Andric   // Index 0 is LOCAL, index 1 is GLOBAL.
6560b57cec5SDimitry Andric   VersionMap.push_back(VersionMapEntry());
6570b57cec5SDimitry Andric   VersionMap.push_back(VersionMapEntry());
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   if (SymbolVersionDefSection)
6600b57cec5SDimitry Andric     LoadVersionDefs(SymbolVersionDefSection);
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   if (SymbolVersionNeedSection)
6630b57cec5SDimitry Andric     LoadVersionNeeds(SymbolVersionNeedSection);
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric template <typename ELFT>
6670b57cec5SDimitry Andric StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
6680b57cec5SDimitry Andric                                             const Elf_Sym *Sym,
6690b57cec5SDimitry Andric                                             bool &IsDefault) const {
6700b57cec5SDimitry Andric   // This is a dynamic symbol. Look in the GNU symbol version table.
6710b57cec5SDimitry Andric   if (!SymbolVersionSection) {
6720b57cec5SDimitry Andric     // No version table.
6730b57cec5SDimitry Andric     IsDefault = false;
6740b57cec5SDimitry Andric     return "";
6750b57cec5SDimitry Andric   }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   // Determine the position in the symbol table of this entry.
6780b57cec5SDimitry Andric   size_t EntryIndex = (reinterpret_cast<uintptr_t>(Sym) -
6790b57cec5SDimitry Andric                         reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) /
6800b57cec5SDimitry Andric                        sizeof(Elf_Sym);
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Get the corresponding version index entry.
6830b57cec5SDimitry Andric   const Elf_Versym *Versym =
6840b57cec5SDimitry Andric       unwrapOrError(ObjF->getELFFile()->template getEntry<Elf_Versym>(
6850b57cec5SDimitry Andric           SymbolVersionSection, EntryIndex));
6860b57cec5SDimitry Andric   return this->getSymbolVersionByIndex(StrTab, Versym->vs_index, IsDefault);
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric static std::string maybeDemangle(StringRef Name) {
6900b57cec5SDimitry Andric   return opts::Demangle ? demangle(Name) : Name.str();
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric template <typename ELFT>
6940b57cec5SDimitry Andric std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
6950b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
6960b57cec5SDimitry Andric   StringRef StrTable =
6970b57cec5SDimitry Andric       unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
6980b57cec5SDimitry Andric   Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
6990b57cec5SDimitry Andric   if (Index >= Syms.size())
7000b57cec5SDimitry Andric     reportError("Invalid symbol index");
7010b57cec5SDimitry Andric   const Elf_Sym *Sym = &Syms[Index];
7020b57cec5SDimitry Andric   return maybeDemangle(unwrapOrError(Sym->getName(StrTable)));
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric template <typename ELFT>
7060b57cec5SDimitry Andric StringRef ELFDumper<ELFT>::getSymbolVersionByIndex(StringRef StrTab,
7070b57cec5SDimitry Andric                                                    uint32_t SymbolVersionIndex,
7080b57cec5SDimitry Andric                                                    bool &IsDefault) const {
7090b57cec5SDimitry Andric   size_t VersionIndex = SymbolVersionIndex & VERSYM_VERSION;
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   // Special markers for unversioned symbols.
7120b57cec5SDimitry Andric   if (VersionIndex == VER_NDX_LOCAL || VersionIndex == VER_NDX_GLOBAL) {
7130b57cec5SDimitry Andric     IsDefault = false;
7140b57cec5SDimitry Andric     return "";
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   // Lookup this symbol in the version table.
7180b57cec5SDimitry Andric   LoadVersionMap();
7190b57cec5SDimitry Andric   if (VersionIndex >= VersionMap.size() || VersionMap[VersionIndex].isNull())
7200b57cec5SDimitry Andric     reportError("Invalid version entry");
7210b57cec5SDimitry Andric   const VersionMapEntry &Entry = VersionMap[VersionIndex];
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric   // Get the version name string.
7240b57cec5SDimitry Andric   size_t NameOffset;
7250b57cec5SDimitry Andric   if (Entry.isVerdef()) {
7260b57cec5SDimitry Andric     // The first Verdaux entry holds the name.
7270b57cec5SDimitry Andric     NameOffset = Entry.getVerdef()->getAux()->vda_name;
7280b57cec5SDimitry Andric     IsDefault = !(SymbolVersionIndex & VERSYM_HIDDEN);
7290b57cec5SDimitry Andric   } else {
7300b57cec5SDimitry Andric     NameOffset = Entry.getVernaux()->vna_name;
7310b57cec5SDimitry Andric     IsDefault = false;
7320b57cec5SDimitry Andric   }
7330b57cec5SDimitry Andric   if (NameOffset >= StrTab.size())
7340b57cec5SDimitry Andric     reportError("Invalid string offset");
7350b57cec5SDimitry Andric   return StrTab.data() + NameOffset;
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric template <typename ELFT>
7390b57cec5SDimitry Andric std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
7400b57cec5SDimitry Andric                                                StringRef StrTable,
7410b57cec5SDimitry Andric                                                bool IsDynamic) const {
7420b57cec5SDimitry Andric   std::string SymbolName =
7430b57cec5SDimitry Andric       maybeDemangle(unwrapOrError(Symbol->getName(StrTable)));
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) {
7460b57cec5SDimitry Andric     unsigned SectionIndex;
7470b57cec5SDimitry Andric     StringRef SectionName;
7480b57cec5SDimitry Andric     Elf_Sym_Range Syms =
7490b57cec5SDimitry Andric         unwrapOrError(ObjF->getELFFile()->symbols(DotSymtabSec));
7500b57cec5SDimitry Andric     getSectionNameIndex(Symbol, Syms.begin(), SectionName, SectionIndex);
7510b57cec5SDimitry Andric     return SectionName;
7520b57cec5SDimitry Andric   }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   if (!IsDynamic)
7550b57cec5SDimitry Andric     return SymbolName;
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   bool IsDefault;
7580b57cec5SDimitry Andric   StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault);
7590b57cec5SDimitry Andric   if (!Version.empty()) {
7600b57cec5SDimitry Andric     SymbolName += (IsDefault ? "@@" : "@");
7610b57cec5SDimitry Andric     SymbolName += Version;
7620b57cec5SDimitry Andric   }
7630b57cec5SDimitry Andric   return SymbolName;
7640b57cec5SDimitry Andric }
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric template <typename ELFT>
7670b57cec5SDimitry Andric void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol,
7680b57cec5SDimitry Andric                                           const Elf_Sym *FirstSym,
7690b57cec5SDimitry Andric                                           StringRef &SectionName,
7700b57cec5SDimitry Andric                                           unsigned &SectionIndex) const {
7710b57cec5SDimitry Andric   SectionIndex = Symbol->st_shndx;
7720b57cec5SDimitry Andric   if (Symbol->isUndefined())
7730b57cec5SDimitry Andric     SectionName = "Undefined";
7740b57cec5SDimitry Andric   else if (Symbol->isProcessorSpecific())
7750b57cec5SDimitry Andric     SectionName = "Processor Specific";
7760b57cec5SDimitry Andric   else if (Symbol->isOSSpecific())
7770b57cec5SDimitry Andric     SectionName = "Operating System Specific";
7780b57cec5SDimitry Andric   else if (Symbol->isAbsolute())
7790b57cec5SDimitry Andric     SectionName = "Absolute";
7800b57cec5SDimitry Andric   else if (Symbol->isCommon())
7810b57cec5SDimitry Andric     SectionName = "Common";
7820b57cec5SDimitry Andric   else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX)
7830b57cec5SDimitry Andric     SectionName = "Reserved";
7840b57cec5SDimitry Andric   else {
7850b57cec5SDimitry Andric     if (SectionIndex == SHN_XINDEX)
7860b57cec5SDimitry Andric       SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(
7870b57cec5SDimitry Andric           Symbol, FirstSym, ShndxTable));
7880b57cec5SDimitry Andric     const ELFFile<ELFT> *Obj = ObjF->getELFFile();
7890b57cec5SDimitry Andric     const typename ELFT::Shdr *Sec =
7900b57cec5SDimitry Andric         unwrapOrError(Obj->getSection(SectionIndex));
7910b57cec5SDimitry Andric     SectionName = unwrapOrError(Obj->getSectionName(Sec));
7920b57cec5SDimitry Andric   }
7930b57cec5SDimitry Andric }
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric template <class ELFO>
7960b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr *
7970b57cec5SDimitry Andric findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) {
7980b57cec5SDimitry Andric   for (const auto &Shdr : unwrapOrError(Obj->sections()))
7990b57cec5SDimitry Andric     if (Shdr.sh_addr == Addr && Shdr.sh_size > 0)
8000b57cec5SDimitry Andric       return &Shdr;
8010b57cec5SDimitry Andric   return nullptr;
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric template <class ELFO>
8050b57cec5SDimitry Andric static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj,
8060b57cec5SDimitry Andric                                                         StringRef Name) {
8070b57cec5SDimitry Andric   for (const auto &Shdr : unwrapOrError(Obj.sections())) {
8080b57cec5SDimitry Andric     if (Name == unwrapOrError(Obj.getSectionName(&Shdr)))
8090b57cec5SDimitry Andric       return &Shdr;
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric   return nullptr;
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfClass[] = {
8150b57cec5SDimitry Andric   {"None",   "none",   ELF::ELFCLASSNONE},
8160b57cec5SDimitry Andric   {"32-bit", "ELF32",  ELF::ELFCLASS32},
8170b57cec5SDimitry Andric   {"64-bit", "ELF64",  ELF::ELFCLASS64},
8180b57cec5SDimitry Andric };
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDataEncoding[] = {
8210b57cec5SDimitry Andric   {"None",         "none",                          ELF::ELFDATANONE},
8220b57cec5SDimitry Andric   {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB},
8230b57cec5SDimitry Andric   {"BigEndian",    "2's complement, big endian",    ELF::ELFDATA2MSB},
8240b57cec5SDimitry Andric };
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfObjectFileType[] = {
8270b57cec5SDimitry Andric   {"None",         "NONE (none)",              ELF::ET_NONE},
8280b57cec5SDimitry Andric   {"Relocatable",  "REL (Relocatable file)",   ELF::ET_REL},
8290b57cec5SDimitry Andric   {"Executable",   "EXEC (Executable file)",   ELF::ET_EXEC},
8300b57cec5SDimitry Andric   {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN},
8310b57cec5SDimitry Andric   {"Core",         "CORE (Core file)",         ELF::ET_CORE},
8320b57cec5SDimitry Andric };
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfOSABI[] = {
8350b57cec5SDimitry Andric   {"SystemV",      "UNIX - System V",      ELF::ELFOSABI_NONE},
8360b57cec5SDimitry Andric   {"HPUX",         "UNIX - HP-UX",         ELF::ELFOSABI_HPUX},
8370b57cec5SDimitry Andric   {"NetBSD",       "UNIX - NetBSD",        ELF::ELFOSABI_NETBSD},
8380b57cec5SDimitry Andric   {"GNU/Linux",    "UNIX - GNU",           ELF::ELFOSABI_LINUX},
8390b57cec5SDimitry Andric   {"GNU/Hurd",     "GNU/Hurd",             ELF::ELFOSABI_HURD},
8400b57cec5SDimitry Andric   {"Solaris",      "UNIX - Solaris",       ELF::ELFOSABI_SOLARIS},
8410b57cec5SDimitry Andric   {"AIX",          "UNIX - AIX",           ELF::ELFOSABI_AIX},
8420b57cec5SDimitry Andric   {"IRIX",         "UNIX - IRIX",          ELF::ELFOSABI_IRIX},
8430b57cec5SDimitry Andric   {"FreeBSD",      "UNIX - FreeBSD",       ELF::ELFOSABI_FREEBSD},
8440b57cec5SDimitry Andric   {"TRU64",        "UNIX - TRU64",         ELF::ELFOSABI_TRU64},
8450b57cec5SDimitry Andric   {"Modesto",      "Novell - Modesto",     ELF::ELFOSABI_MODESTO},
8460b57cec5SDimitry Andric   {"OpenBSD",      "UNIX - OpenBSD",       ELF::ELFOSABI_OPENBSD},
8470b57cec5SDimitry Andric   {"OpenVMS",      "VMS - OpenVMS",        ELF::ELFOSABI_OPENVMS},
8480b57cec5SDimitry Andric   {"NSK",          "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},
8490b57cec5SDimitry Andric   {"AROS",         "AROS",                 ELF::ELFOSABI_AROS},
8500b57cec5SDimitry Andric   {"FenixOS",      "FenixOS",              ELF::ELFOSABI_FENIXOS},
8510b57cec5SDimitry Andric   {"CloudABI",     "CloudABI",             ELF::ELFOSABI_CLOUDABI},
8520b57cec5SDimitry Andric   {"Standalone",   "Standalone App",       ELF::ELFOSABI_STANDALONE}
8530b57cec5SDimitry Andric };
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric static const EnumEntry<unsigned> SymVersionFlags[] = {
8560b57cec5SDimitry Andric     {"Base", "BASE", VER_FLG_BASE},
8570b57cec5SDimitry Andric     {"Weak", "WEAK", VER_FLG_WEAK},
8580b57cec5SDimitry Andric     {"Info", "INFO", VER_FLG_INFO}};
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric static const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
8610b57cec5SDimitry Andric   {"AMDGPU_HSA",    "AMDGPU - HSA",    ELF::ELFOSABI_AMDGPU_HSA},
8620b57cec5SDimitry Andric   {"AMDGPU_PAL",    "AMDGPU - PAL",    ELF::ELFOSABI_AMDGPU_PAL},
8630b57cec5SDimitry Andric   {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}
8640b57cec5SDimitry Andric };
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric static const EnumEntry<unsigned> ARMElfOSABI[] = {
8670b57cec5SDimitry Andric   {"ARM", "ARM", ELF::ELFOSABI_ARM}
8680b57cec5SDimitry Andric };
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric static const EnumEntry<unsigned> C6000ElfOSABI[] = {
8710b57cec5SDimitry Andric   {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
8720b57cec5SDimitry Andric   {"C6000_LINUX",  "Linux C6000",      ELF::ELFOSABI_C6000_LINUX}
8730b57cec5SDimitry Andric };
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMachineType[] = {
8760b57cec5SDimitry Andric   ENUM_ENT(EM_NONE,          "None"),
8770b57cec5SDimitry Andric   ENUM_ENT(EM_M32,           "WE32100"),
8780b57cec5SDimitry Andric   ENUM_ENT(EM_SPARC,         "Sparc"),
8790b57cec5SDimitry Andric   ENUM_ENT(EM_386,           "Intel 80386"),
8800b57cec5SDimitry Andric   ENUM_ENT(EM_68K,           "MC68000"),
8810b57cec5SDimitry Andric   ENUM_ENT(EM_88K,           "MC88000"),
8820b57cec5SDimitry Andric   ENUM_ENT(EM_IAMCU,         "EM_IAMCU"),
8830b57cec5SDimitry Andric   ENUM_ENT(EM_860,           "Intel 80860"),
8840b57cec5SDimitry Andric   ENUM_ENT(EM_MIPS,          "MIPS R3000"),
8850b57cec5SDimitry Andric   ENUM_ENT(EM_S370,          "IBM System/370"),
8860b57cec5SDimitry Andric   ENUM_ENT(EM_MIPS_RS3_LE,   "MIPS R3000 little-endian"),
8870b57cec5SDimitry Andric   ENUM_ENT(EM_PARISC,        "HPPA"),
8880b57cec5SDimitry Andric   ENUM_ENT(EM_VPP500,        "Fujitsu VPP500"),
8890b57cec5SDimitry Andric   ENUM_ENT(EM_SPARC32PLUS,   "Sparc v8+"),
8900b57cec5SDimitry Andric   ENUM_ENT(EM_960,           "Intel 80960"),
8910b57cec5SDimitry Andric   ENUM_ENT(EM_PPC,           "PowerPC"),
8920b57cec5SDimitry Andric   ENUM_ENT(EM_PPC64,         "PowerPC64"),
8930b57cec5SDimitry Andric   ENUM_ENT(EM_S390,          "IBM S/390"),
8940b57cec5SDimitry Andric   ENUM_ENT(EM_SPU,           "SPU"),
8950b57cec5SDimitry Andric   ENUM_ENT(EM_V800,          "NEC V800 series"),
8960b57cec5SDimitry Andric   ENUM_ENT(EM_FR20,          "Fujistsu FR20"),
8970b57cec5SDimitry Andric   ENUM_ENT(EM_RH32,          "TRW RH-32"),
8980b57cec5SDimitry Andric   ENUM_ENT(EM_RCE,           "Motorola RCE"),
8990b57cec5SDimitry Andric   ENUM_ENT(EM_ARM,           "ARM"),
9000b57cec5SDimitry Andric   ENUM_ENT(EM_ALPHA,         "EM_ALPHA"),
9010b57cec5SDimitry Andric   ENUM_ENT(EM_SH,            "Hitachi SH"),
9020b57cec5SDimitry Andric   ENUM_ENT(EM_SPARCV9,       "Sparc v9"),
9030b57cec5SDimitry Andric   ENUM_ENT(EM_TRICORE,       "Siemens Tricore"),
9040b57cec5SDimitry Andric   ENUM_ENT(EM_ARC,           "ARC"),
9050b57cec5SDimitry Andric   ENUM_ENT(EM_H8_300,        "Hitachi H8/300"),
9060b57cec5SDimitry Andric   ENUM_ENT(EM_H8_300H,       "Hitachi H8/300H"),
9070b57cec5SDimitry Andric   ENUM_ENT(EM_H8S,           "Hitachi H8S"),
9080b57cec5SDimitry Andric   ENUM_ENT(EM_H8_500,        "Hitachi H8/500"),
9090b57cec5SDimitry Andric   ENUM_ENT(EM_IA_64,         "Intel IA-64"),
9100b57cec5SDimitry Andric   ENUM_ENT(EM_MIPS_X,        "Stanford MIPS-X"),
9110b57cec5SDimitry Andric   ENUM_ENT(EM_COLDFIRE,      "Motorola Coldfire"),
9120b57cec5SDimitry Andric   ENUM_ENT(EM_68HC12,        "Motorola MC68HC12 Microcontroller"),
9130b57cec5SDimitry Andric   ENUM_ENT(EM_MMA,           "Fujitsu Multimedia Accelerator"),
9140b57cec5SDimitry Andric   ENUM_ENT(EM_PCP,           "Siemens PCP"),
9150b57cec5SDimitry Andric   ENUM_ENT(EM_NCPU,          "Sony nCPU embedded RISC processor"),
9160b57cec5SDimitry Andric   ENUM_ENT(EM_NDR1,          "Denso NDR1 microprocesspr"),
9170b57cec5SDimitry Andric   ENUM_ENT(EM_STARCORE,      "Motorola Star*Core processor"),
9180b57cec5SDimitry Andric   ENUM_ENT(EM_ME16,          "Toyota ME16 processor"),
9190b57cec5SDimitry Andric   ENUM_ENT(EM_ST100,         "STMicroelectronics ST100 processor"),
9200b57cec5SDimitry Andric   ENUM_ENT(EM_TINYJ,         "Advanced Logic Corp. TinyJ embedded processor"),
9210b57cec5SDimitry Andric   ENUM_ENT(EM_X86_64,        "Advanced Micro Devices X86-64"),
9220b57cec5SDimitry Andric   ENUM_ENT(EM_PDSP,          "Sony DSP processor"),
9230b57cec5SDimitry Andric   ENUM_ENT(EM_PDP10,         "Digital Equipment Corp. PDP-10"),
9240b57cec5SDimitry Andric   ENUM_ENT(EM_PDP11,         "Digital Equipment Corp. PDP-11"),
9250b57cec5SDimitry Andric   ENUM_ENT(EM_FX66,          "Siemens FX66 microcontroller"),
9260b57cec5SDimitry Andric   ENUM_ENT(EM_ST9PLUS,       "STMicroelectronics ST9+ 8/16 bit microcontroller"),
9270b57cec5SDimitry Andric   ENUM_ENT(EM_ST7,           "STMicroelectronics ST7 8-bit microcontroller"),
9280b57cec5SDimitry Andric   ENUM_ENT(EM_68HC16,        "Motorola MC68HC16 Microcontroller"),
9290b57cec5SDimitry Andric   ENUM_ENT(EM_68HC11,        "Motorola MC68HC11 Microcontroller"),
9300b57cec5SDimitry Andric   ENUM_ENT(EM_68HC08,        "Motorola MC68HC08 Microcontroller"),
9310b57cec5SDimitry Andric   ENUM_ENT(EM_68HC05,        "Motorola MC68HC05 Microcontroller"),
9320b57cec5SDimitry Andric   ENUM_ENT(EM_SVX,           "Silicon Graphics SVx"),
9330b57cec5SDimitry Andric   ENUM_ENT(EM_ST19,          "STMicroelectronics ST19 8-bit microcontroller"),
9340b57cec5SDimitry Andric   ENUM_ENT(EM_VAX,           "Digital VAX"),
9350b57cec5SDimitry Andric   ENUM_ENT(EM_CRIS,          "Axis Communications 32-bit embedded processor"),
9360b57cec5SDimitry Andric   ENUM_ENT(EM_JAVELIN,       "Infineon Technologies 32-bit embedded cpu"),
9370b57cec5SDimitry Andric   ENUM_ENT(EM_FIREPATH,      "Element 14 64-bit DSP processor"),
9380b57cec5SDimitry Andric   ENUM_ENT(EM_ZSP,           "LSI Logic's 16-bit DSP processor"),
9390b57cec5SDimitry Andric   ENUM_ENT(EM_MMIX,          "Donald Knuth's educational 64-bit processor"),
9400b57cec5SDimitry Andric   ENUM_ENT(EM_HUANY,         "Harvard Universitys's machine-independent object format"),
9410b57cec5SDimitry Andric   ENUM_ENT(EM_PRISM,         "Vitesse Prism"),
9420b57cec5SDimitry Andric   ENUM_ENT(EM_AVR,           "Atmel AVR 8-bit microcontroller"),
9430b57cec5SDimitry Andric   ENUM_ENT(EM_FR30,          "Fujitsu FR30"),
9440b57cec5SDimitry Andric   ENUM_ENT(EM_D10V,          "Mitsubishi D10V"),
9450b57cec5SDimitry Andric   ENUM_ENT(EM_D30V,          "Mitsubishi D30V"),
9460b57cec5SDimitry Andric   ENUM_ENT(EM_V850,          "NEC v850"),
9470b57cec5SDimitry Andric   ENUM_ENT(EM_M32R,          "Renesas M32R (formerly Mitsubishi M32r)"),
9480b57cec5SDimitry Andric   ENUM_ENT(EM_MN10300,       "Matsushita MN10300"),
9490b57cec5SDimitry Andric   ENUM_ENT(EM_MN10200,       "Matsushita MN10200"),
9500b57cec5SDimitry Andric   ENUM_ENT(EM_PJ,            "picoJava"),
9510b57cec5SDimitry Andric   ENUM_ENT(EM_OPENRISC,      "OpenRISC 32-bit embedded processor"),
9520b57cec5SDimitry Andric   ENUM_ENT(EM_ARC_COMPACT,   "EM_ARC_COMPACT"),
9530b57cec5SDimitry Andric   ENUM_ENT(EM_XTENSA,        "Tensilica Xtensa Processor"),
9540b57cec5SDimitry Andric   ENUM_ENT(EM_VIDEOCORE,     "Alphamosaic VideoCore processor"),
9550b57cec5SDimitry Andric   ENUM_ENT(EM_TMM_GPP,       "Thompson Multimedia General Purpose Processor"),
9560b57cec5SDimitry Andric   ENUM_ENT(EM_NS32K,         "National Semiconductor 32000 series"),
9570b57cec5SDimitry Andric   ENUM_ENT(EM_TPC,           "Tenor Network TPC processor"),
9580b57cec5SDimitry Andric   ENUM_ENT(EM_SNP1K,         "EM_SNP1K"),
9590b57cec5SDimitry Andric   ENUM_ENT(EM_ST200,         "STMicroelectronics ST200 microcontroller"),
9600b57cec5SDimitry Andric   ENUM_ENT(EM_IP2K,          "Ubicom IP2xxx 8-bit microcontrollers"),
9610b57cec5SDimitry Andric   ENUM_ENT(EM_MAX,           "MAX Processor"),
9620b57cec5SDimitry Andric   ENUM_ENT(EM_CR,            "National Semiconductor CompactRISC"),
9630b57cec5SDimitry Andric   ENUM_ENT(EM_F2MC16,        "Fujitsu F2MC16"),
9640b57cec5SDimitry Andric   ENUM_ENT(EM_MSP430,        "Texas Instruments msp430 microcontroller"),
9650b57cec5SDimitry Andric   ENUM_ENT(EM_BLACKFIN,      "Analog Devices Blackfin"),
9660b57cec5SDimitry Andric   ENUM_ENT(EM_SE_C33,        "S1C33 Family of Seiko Epson processors"),
9670b57cec5SDimitry Andric   ENUM_ENT(EM_SEP,           "Sharp embedded microprocessor"),
9680b57cec5SDimitry Andric   ENUM_ENT(EM_ARCA,          "Arca RISC microprocessor"),
9690b57cec5SDimitry Andric   ENUM_ENT(EM_UNICORE,       "Unicore"),
9700b57cec5SDimitry Andric   ENUM_ENT(EM_EXCESS,        "eXcess 16/32/64-bit configurable embedded CPU"),
9710b57cec5SDimitry Andric   ENUM_ENT(EM_DXP,           "Icera Semiconductor Inc. Deep Execution Processor"),
9720b57cec5SDimitry Andric   ENUM_ENT(EM_ALTERA_NIOS2,  "Altera Nios"),
9730b57cec5SDimitry Andric   ENUM_ENT(EM_CRX,           "National Semiconductor CRX microprocessor"),
9740b57cec5SDimitry Andric   ENUM_ENT(EM_XGATE,         "Motorola XGATE embedded processor"),
9750b57cec5SDimitry Andric   ENUM_ENT(EM_C166,          "Infineon Technologies xc16x"),
9760b57cec5SDimitry Andric   ENUM_ENT(EM_M16C,          "Renesas M16C"),
9770b57cec5SDimitry Andric   ENUM_ENT(EM_DSPIC30F,      "Microchip Technology dsPIC30F Digital Signal Controller"),
9780b57cec5SDimitry Andric   ENUM_ENT(EM_CE,            "Freescale Communication Engine RISC core"),
9790b57cec5SDimitry Andric   ENUM_ENT(EM_M32C,          "Renesas M32C"),
9800b57cec5SDimitry Andric   ENUM_ENT(EM_TSK3000,       "Altium TSK3000 core"),
9810b57cec5SDimitry Andric   ENUM_ENT(EM_RS08,          "Freescale RS08 embedded processor"),
9820b57cec5SDimitry Andric   ENUM_ENT(EM_SHARC,         "EM_SHARC"),
9830b57cec5SDimitry Andric   ENUM_ENT(EM_ECOG2,         "Cyan Technology eCOG2 microprocessor"),
9840b57cec5SDimitry Andric   ENUM_ENT(EM_SCORE7,        "SUNPLUS S+Core"),
9850b57cec5SDimitry Andric   ENUM_ENT(EM_DSP24,         "New Japan Radio (NJR) 24-bit DSP Processor"),
9860b57cec5SDimitry Andric   ENUM_ENT(EM_VIDEOCORE3,    "Broadcom VideoCore III processor"),
9870b57cec5SDimitry Andric   ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"),
9880b57cec5SDimitry Andric   ENUM_ENT(EM_SE_C17,        "Seiko Epson C17 family"),
9890b57cec5SDimitry Andric   ENUM_ENT(EM_TI_C6000,      "Texas Instruments TMS320C6000 DSP family"),
9900b57cec5SDimitry Andric   ENUM_ENT(EM_TI_C2000,      "Texas Instruments TMS320C2000 DSP family"),
9910b57cec5SDimitry Andric   ENUM_ENT(EM_TI_C5500,      "Texas Instruments TMS320C55x DSP family"),
9920b57cec5SDimitry Andric   ENUM_ENT(EM_MMDSP_PLUS,    "STMicroelectronics 64bit VLIW Data Signal Processor"),
9930b57cec5SDimitry Andric   ENUM_ENT(EM_CYPRESS_M8C,   "Cypress M8C microprocessor"),
9940b57cec5SDimitry Andric   ENUM_ENT(EM_R32C,          "Renesas R32C series microprocessors"),
9950b57cec5SDimitry Andric   ENUM_ENT(EM_TRIMEDIA,      "NXP Semiconductors TriMedia architecture family"),
9960b57cec5SDimitry Andric   ENUM_ENT(EM_HEXAGON,       "Qualcomm Hexagon"),
9970b57cec5SDimitry Andric   ENUM_ENT(EM_8051,          "Intel 8051 and variants"),
9980b57cec5SDimitry Andric   ENUM_ENT(EM_STXP7X,        "STMicroelectronics STxP7x family"),
9990b57cec5SDimitry Andric   ENUM_ENT(EM_NDS32,         "Andes Technology compact code size embedded RISC processor family"),
10000b57cec5SDimitry Andric   ENUM_ENT(EM_ECOG1,         "Cyan Technology eCOG1 microprocessor"),
10010b57cec5SDimitry Andric   ENUM_ENT(EM_ECOG1X,        "Cyan Technology eCOG1X family"),
10020b57cec5SDimitry Andric   ENUM_ENT(EM_MAXQ30,        "Dallas Semiconductor MAXQ30 Core microcontrollers"),
10030b57cec5SDimitry Andric   ENUM_ENT(EM_XIMO16,        "New Japan Radio (NJR) 16-bit DSP Processor"),
10040b57cec5SDimitry Andric   ENUM_ENT(EM_MANIK,         "M2000 Reconfigurable RISC Microprocessor"),
10050b57cec5SDimitry Andric   ENUM_ENT(EM_CRAYNV2,       "Cray Inc. NV2 vector architecture"),
10060b57cec5SDimitry Andric   ENUM_ENT(EM_RX,            "Renesas RX"),
10070b57cec5SDimitry Andric   ENUM_ENT(EM_METAG,         "Imagination Technologies Meta processor architecture"),
10080b57cec5SDimitry Andric   ENUM_ENT(EM_MCST_ELBRUS,   "MCST Elbrus general purpose hardware architecture"),
10090b57cec5SDimitry Andric   ENUM_ENT(EM_ECOG16,        "Cyan Technology eCOG16 family"),
10100b57cec5SDimitry Andric   ENUM_ENT(EM_CR16,          "Xilinx MicroBlaze"),
10110b57cec5SDimitry Andric   ENUM_ENT(EM_ETPU,          "Freescale Extended Time Processing Unit"),
10120b57cec5SDimitry Andric   ENUM_ENT(EM_SLE9X,         "Infineon Technologies SLE9X core"),
10130b57cec5SDimitry Andric   ENUM_ENT(EM_L10M,          "EM_L10M"),
10140b57cec5SDimitry Andric   ENUM_ENT(EM_K10M,          "EM_K10M"),
10150b57cec5SDimitry Andric   ENUM_ENT(EM_AARCH64,       "AArch64"),
10160b57cec5SDimitry Andric   ENUM_ENT(EM_AVR32,         "Atmel Corporation 32-bit microprocessor family"),
10170b57cec5SDimitry Andric   ENUM_ENT(EM_STM8,          "STMicroeletronics STM8 8-bit microcontroller"),
10180b57cec5SDimitry Andric   ENUM_ENT(EM_TILE64,        "Tilera TILE64 multicore architecture family"),
10190b57cec5SDimitry Andric   ENUM_ENT(EM_TILEPRO,       "Tilera TILEPro multicore architecture family"),
10200b57cec5SDimitry Andric   ENUM_ENT(EM_CUDA,          "NVIDIA CUDA architecture"),
10210b57cec5SDimitry Andric   ENUM_ENT(EM_TILEGX,        "Tilera TILE-Gx multicore architecture family"),
10220b57cec5SDimitry Andric   ENUM_ENT(EM_CLOUDSHIELD,   "EM_CLOUDSHIELD"),
10230b57cec5SDimitry Andric   ENUM_ENT(EM_COREA_1ST,     "EM_COREA_1ST"),
10240b57cec5SDimitry Andric   ENUM_ENT(EM_COREA_2ND,     "EM_COREA_2ND"),
10250b57cec5SDimitry Andric   ENUM_ENT(EM_ARC_COMPACT2,  "EM_ARC_COMPACT2"),
10260b57cec5SDimitry Andric   ENUM_ENT(EM_OPEN8,         "EM_OPEN8"),
10270b57cec5SDimitry Andric   ENUM_ENT(EM_RL78,          "Renesas RL78"),
10280b57cec5SDimitry Andric   ENUM_ENT(EM_VIDEOCORE5,    "Broadcom VideoCore V processor"),
10290b57cec5SDimitry Andric   ENUM_ENT(EM_78KOR,         "EM_78KOR"),
10300b57cec5SDimitry Andric   ENUM_ENT(EM_56800EX,       "EM_56800EX"),
10310b57cec5SDimitry Andric   ENUM_ENT(EM_AMDGPU,        "EM_AMDGPU"),
10320b57cec5SDimitry Andric   ENUM_ENT(EM_RISCV,         "RISC-V"),
10330b57cec5SDimitry Andric   ENUM_ENT(EM_LANAI,         "EM_LANAI"),
10340b57cec5SDimitry Andric   ENUM_ENT(EM_BPF,           "EM_BPF"),
10350b57cec5SDimitry Andric };
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymbolBindings[] = {
10380b57cec5SDimitry Andric     {"Local",  "LOCAL",  ELF::STB_LOCAL},
10390b57cec5SDimitry Andric     {"Global", "GLOBAL", ELF::STB_GLOBAL},
10400b57cec5SDimitry Andric     {"Weak",   "WEAK",   ELF::STB_WEAK},
10410b57cec5SDimitry Andric     {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}};
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymbolVisibilities[] = {
10440b57cec5SDimitry Andric     {"DEFAULT",   "DEFAULT",   ELF::STV_DEFAULT},
10450b57cec5SDimitry Andric     {"INTERNAL",  "INTERNAL",  ELF::STV_INTERNAL},
10460b57cec5SDimitry Andric     {"HIDDEN",    "HIDDEN",    ELF::STV_HIDDEN},
10470b57cec5SDimitry Andric     {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};
10480b57cec5SDimitry Andric 
10490b57cec5SDimitry Andric static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {
10500b57cec5SDimitry Andric   { "AMDGPU_HSA_KERNEL",            ELF::STT_AMDGPU_HSA_KERNEL }
10510b57cec5SDimitry Andric };
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric static const char *getGroupType(uint32_t Flag) {
10540b57cec5SDimitry Andric   if (Flag & ELF::GRP_COMDAT)
10550b57cec5SDimitry Andric     return "COMDAT";
10560b57cec5SDimitry Andric   else
10570b57cec5SDimitry Andric     return "(unknown)";
10580b57cec5SDimitry Andric }
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSectionFlags[] = {
10610b57cec5SDimitry Andric   ENUM_ENT(SHF_WRITE,            "W"),
10620b57cec5SDimitry Andric   ENUM_ENT(SHF_ALLOC,            "A"),
10630b57cec5SDimitry Andric   ENUM_ENT(SHF_EXCLUDE,          "E"),
10640b57cec5SDimitry Andric   ENUM_ENT(SHF_EXECINSTR,        "X"),
10650b57cec5SDimitry Andric   ENUM_ENT(SHF_MERGE,            "M"),
10660b57cec5SDimitry Andric   ENUM_ENT(SHF_STRINGS,          "S"),
10670b57cec5SDimitry Andric   ENUM_ENT(SHF_INFO_LINK,        "I"),
10680b57cec5SDimitry Andric   ENUM_ENT(SHF_LINK_ORDER,       "L"),
10690b57cec5SDimitry Andric   ENUM_ENT(SHF_OS_NONCONFORMING, "o"),
10700b57cec5SDimitry Andric   ENUM_ENT(SHF_GROUP,            "G"),
10710b57cec5SDimitry Andric   ENUM_ENT(SHF_TLS,              "T"),
10720b57cec5SDimitry Andric   ENUM_ENT(SHF_MASKOS,           "o"),
10730b57cec5SDimitry Andric   ENUM_ENT(SHF_MASKPROC,         "p"),
10740b57cec5SDimitry Andric   ENUM_ENT_1(SHF_COMPRESSED),
10750b57cec5SDimitry Andric };
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
10780b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION),
10790b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION)
10800b57cec5SDimitry Andric };
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfARMSectionFlags[] = {
10830b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE)
10840b57cec5SDimitry Andric };
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = {
10870b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL)
10880b57cec5SDimitry Andric };
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsSectionFlags[] = {
10910b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NODUPES),
10920b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NAMES  ),
10930b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_LOCAL  ),
10940b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP),
10950b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_GPREL  ),
10960b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_MERGE  ),
10970b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_ADDR   ),
10980b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_STRING )
10990b57cec5SDimitry Andric };
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {
11020b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, SHF_X86_64_LARGE)
11030b57cec5SDimitry Andric };
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric static std::string getGNUFlags(uint64_t Flags) {
11060b57cec5SDimitry Andric   std::string Str;
11070b57cec5SDimitry Andric   for (auto Entry : ElfSectionFlags) {
11080b57cec5SDimitry Andric     uint64_t Flag = Entry.Value & Flags;
11090b57cec5SDimitry Andric     Flags &= ~Entry.Value;
11100b57cec5SDimitry Andric     switch (Flag) {
11110b57cec5SDimitry Andric     case ELF::SHF_WRITE:
11120b57cec5SDimitry Andric     case ELF::SHF_ALLOC:
11130b57cec5SDimitry Andric     case ELF::SHF_EXECINSTR:
11140b57cec5SDimitry Andric     case ELF::SHF_MERGE:
11150b57cec5SDimitry Andric     case ELF::SHF_STRINGS:
11160b57cec5SDimitry Andric     case ELF::SHF_INFO_LINK:
11170b57cec5SDimitry Andric     case ELF::SHF_LINK_ORDER:
11180b57cec5SDimitry Andric     case ELF::SHF_OS_NONCONFORMING:
11190b57cec5SDimitry Andric     case ELF::SHF_GROUP:
11200b57cec5SDimitry Andric     case ELF::SHF_TLS:
11210b57cec5SDimitry Andric     case ELF::SHF_EXCLUDE:
11220b57cec5SDimitry Andric       Str += Entry.AltName;
11230b57cec5SDimitry Andric       break;
11240b57cec5SDimitry Andric     default:
11250b57cec5SDimitry Andric       if (Flag & ELF::SHF_MASKOS)
11260b57cec5SDimitry Andric         Str += "o";
11270b57cec5SDimitry Andric       else if (Flag & ELF::SHF_MASKPROC)
11280b57cec5SDimitry Andric         Str += "p";
11290b57cec5SDimitry Andric       else if (Flag)
11300b57cec5SDimitry Andric         Str += "x";
11310b57cec5SDimitry Andric     }
11320b57cec5SDimitry Andric   }
11330b57cec5SDimitry Andric   return Str;
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric static const char *getElfSegmentType(unsigned Arch, unsigned Type) {
11370b57cec5SDimitry Andric   // Check potentially overlapped processor-specific
11380b57cec5SDimitry Andric   // program header type.
11390b57cec5SDimitry Andric   switch (Arch) {
11400b57cec5SDimitry Andric   case ELF::EM_ARM:
11410b57cec5SDimitry Andric     switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); }
11420b57cec5SDimitry Andric     break;
11430b57cec5SDimitry Andric   case ELF::EM_MIPS:
11440b57cec5SDimitry Andric   case ELF::EM_MIPS_RS3_LE:
11450b57cec5SDimitry Andric     switch (Type) {
11460b57cec5SDimitry Andric       LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);
11470b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);
11480b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);
11490b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS);
11500b57cec5SDimitry Andric     }
11510b57cec5SDimitry Andric     break;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   switch (Type) {
11550b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL   );
11560b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD   );
11570b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC);
11580b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP );
11590b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE   );
11600b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB  );
11610b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR   );
11620b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS    );
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME);
11650b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND);
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK);
11680b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);
11710b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);
11720b57cec5SDimitry Andric     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   default:
11750b57cec5SDimitry Andric     return "";
11760b57cec5SDimitry Andric   }
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric static std::string getElfPtType(unsigned Arch, unsigned Type) {
11800b57cec5SDimitry Andric   switch (Type) {
11810b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_NULL)
11820b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_LOAD)
11830b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_DYNAMIC)
11840b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_INTERP)
11850b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_NOTE)
11860b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_SHLIB)
11870b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_PHDR)
11880b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_TLS)
11890b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_EH_FRAME)
11900b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_SUNW_UNWIND)
11910b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_STACK)
11920b57cec5SDimitry Andric     LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_RELRO)
11930b57cec5SDimitry Andric   default:
11940b57cec5SDimitry Andric     // All machine specific PT_* types
11950b57cec5SDimitry Andric     switch (Arch) {
11960b57cec5SDimitry Andric     case ELF::EM_ARM:
11970b57cec5SDimitry Andric       if (Type == ELF::PT_ARM_EXIDX)
11980b57cec5SDimitry Andric         return "EXIDX";
11990b57cec5SDimitry Andric       break;
12000b57cec5SDimitry Andric     case ELF::EM_MIPS:
12010b57cec5SDimitry Andric     case ELF::EM_MIPS_RS3_LE:
12020b57cec5SDimitry Andric       switch (Type) {
12030b57cec5SDimitry Andric       case PT_MIPS_REGINFO:
12040b57cec5SDimitry Andric         return "REGINFO";
12050b57cec5SDimitry Andric       case PT_MIPS_RTPROC:
12060b57cec5SDimitry Andric         return "RTPROC";
12070b57cec5SDimitry Andric       case PT_MIPS_OPTIONS:
12080b57cec5SDimitry Andric         return "OPTIONS";
12090b57cec5SDimitry Andric       case PT_MIPS_ABIFLAGS:
12100b57cec5SDimitry Andric         return "ABIFLAGS";
12110b57cec5SDimitry Andric       }
12120b57cec5SDimitry Andric       break;
12130b57cec5SDimitry Andric     }
12140b57cec5SDimitry Andric   }
12150b57cec5SDimitry Andric   return std::string("<unknown>: ") + to_string(format_hex(Type, 1));
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSegmentFlags[] = {
12190b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, PF_X),
12200b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, PF_W),
12210b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, PF_R)
12220b57cec5SDimitry Andric };
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
12250b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"),
12260b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_PIC, "pic"),
12270b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_CPIC, "cpic"),
12280b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ABI2, "abi2"),
12290b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"),
12300b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_FP64, "fp64"),
12310b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_NAN2008, "nan2008"),
12320b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ABI_O32, "o32"),
12330b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ABI_O64, "o64"),
12340b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"),
12350b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"),
12360b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_3900, "3900"),
12370b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_4010, "4010"),
12380b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_4100, "4100"),
12390b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_4650, "4650"),
12400b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_4120, "4120"),
12410b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_4111, "4111"),
12420b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"),
12430b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"),
12440b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"),
12450b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"),
12460b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"),
12470b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_5400, "5400"),
12480b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_5900, "5900"),
12490b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_5500, "5500"),
12500b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_9000, "9000"),
12510b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"),
12520b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"),
12530b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"),
12540b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"),
12550b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"),
12560b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"),
12570b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_1, "mips1"),
12580b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_2, "mips2"),
12590b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_3, "mips3"),
12600b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_4, "mips4"),
12610b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_5, "mips5"),
12620b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_32, "mips32"),
12630b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_64, "mips64"),
12640b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"),
12650b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"),
12660b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"),
12670b57cec5SDimitry Andric   ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6")
12680b57cec5SDimitry Andric };
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = {
12710b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
12720b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
12730b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
12740b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880),
12750b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670),
12760b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710),
12770b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730),
12780b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770),
12790b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR),
12800b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS),
12810b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER),
12820b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD),
12830b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO),
12840b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS),
12850b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS),
12860b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN),
12870b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS),
12880b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600),
12890b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601),
12900b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700),
12910b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701),
12920b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702),
12930b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703),
12940b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704),
12950b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801),
12960b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802),
12970b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803),
12980b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810),
12990b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900),
13000b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902),
13010b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904),
13020b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
13030b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908),
13040b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909),
13050b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
13060b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
13070b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
13080b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK),
13090b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_SRAM_ECC)
13100b57cec5SDimitry Andric };
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
13130b57cec5SDimitry Andric   ENUM_ENT(EF_RISCV_RVC, "RVC"),
13140b57cec5SDimitry Andric   ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"),
13150b57cec5SDimitry Andric   ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"),
13160b57cec5SDimitry Andric   ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"),
13170b57cec5SDimitry Andric   ENUM_ENT(EF_RISCV_RVE, "RVE")
13180b57cec5SDimitry Andric };
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfSymOtherFlags[] = {
13210b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
13220b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),
13230b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED)
13240b57cec5SDimitry Andric };
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = {
13270b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),
13280b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),
13290b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC),
13300b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS)
13310b57cec5SDimitry Andric };
13320b57cec5SDimitry Andric 
13330b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = {
13340b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),
13350b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),
13360b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16)
13370b57cec5SDimitry Andric };
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric static const char *getElfMipsOptionsOdkType(unsigned Odk) {
13400b57cec5SDimitry Andric   switch (Odk) {
13410b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL);
13420b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO);
13430b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS);
13440b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD);
13450b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH);
13460b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL);
13470b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS);
13480b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND);
13490b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR);
13500b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP);
13510b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT);
13520b57cec5SDimitry Andric   LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE);
13530b57cec5SDimitry Andric   default:
13540b57cec5SDimitry Andric     return "Unknown";
13550b57cec5SDimitry Andric   }
13560b57cec5SDimitry Andric }
13570b57cec5SDimitry Andric 
13580b57cec5SDimitry Andric template <typename ELFT>
13590b57cec5SDimitry Andric void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
13600b57cec5SDimitry Andric   // Try to locate the PT_DYNAMIC header.
13610b57cec5SDimitry Andric   const Elf_Phdr *DynamicPhdr = nullptr;
13620b57cec5SDimitry Andric   for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
13630b57cec5SDimitry Andric     if (Phdr.p_type != ELF::PT_DYNAMIC)
13640b57cec5SDimitry Andric       continue;
13650b57cec5SDimitry Andric     DynamicPhdr = &Phdr;
13660b57cec5SDimitry Andric     break;
13670b57cec5SDimitry Andric   }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   // Try to locate the .dynamic section in the sections header table.
13700b57cec5SDimitry Andric   const Elf_Shdr *DynamicSec = nullptr;
13710b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
13720b57cec5SDimitry Andric     if (Sec.sh_type != ELF::SHT_DYNAMIC)
13730b57cec5SDimitry Andric       continue;
13740b57cec5SDimitry Andric     DynamicSec = &Sec;
13750b57cec5SDimitry Andric     break;
13760b57cec5SDimitry Andric   }
13770b57cec5SDimitry Andric 
13780b57cec5SDimitry Andric   // Information in the section header has priority over the information
13790b57cec5SDimitry Andric   // in a PT_DYNAMIC header.
13800b57cec5SDimitry Andric   // Ignore sh_entsize and use the expected value for entry size explicitly.
13810b57cec5SDimitry Andric   // This allows us to dump the dynamic sections with a broken sh_entsize
13820b57cec5SDimitry Andric   // field.
13830b57cec5SDimitry Andric   if (DynamicSec) {
13840b57cec5SDimitry Andric     DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
13850b57cec5SDimitry Andric                              DynamicSec->sh_size, sizeof(Elf_Dyn)});
13860b57cec5SDimitry Andric     parseDynamicTable();
13870b57cec5SDimitry Andric   }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   // If we have a PT_DYNAMIC header, we will either check the found dynamic
13900b57cec5SDimitry Andric   // section or take the dynamic table data directly from the header.
13910b57cec5SDimitry Andric   if (!DynamicPhdr)
13920b57cec5SDimitry Andric     return;
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric   if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
13950b57cec5SDimitry Andric       ObjF->getMemoryBufferRef().getBufferSize())
13960b57cec5SDimitry Andric     reportError(
13970b57cec5SDimitry Andric         "PT_DYNAMIC segment offset + size exceeds the size of the file");
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric   if (!DynamicSec) {
14000b57cec5SDimitry Andric     DynamicTable = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn));
14010b57cec5SDimitry Andric     parseDynamicTable();
14020b57cec5SDimitry Andric     return;
14030b57cec5SDimitry Andric   }
14040b57cec5SDimitry Andric 
14050b57cec5SDimitry Andric   StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec));
14060b57cec5SDimitry Andric   if (DynamicSec->sh_addr + DynamicSec->sh_size >
14070b57cec5SDimitry Andric           DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
14080b57cec5SDimitry Andric       DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
14090b57cec5SDimitry Andric     reportWarning("The SHT_DYNAMIC section '" + Name +
14100b57cec5SDimitry Andric                   "' is not contained within the "
14110b57cec5SDimitry Andric                   "PT_DYNAMIC segment");
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric   if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
14140b57cec5SDimitry Andric     reportWarning("The SHT_DYNAMIC section '" + Name +
14150b57cec5SDimitry Andric                   "' is not at the start of "
14160b57cec5SDimitry Andric                   "PT_DYNAMIC segment");
14170b57cec5SDimitry Andric }
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric template <typename ELFT>
14200b57cec5SDimitry Andric ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
14210b57cec5SDimitry Andric     ScopedPrinter &Writer)
14220b57cec5SDimitry Andric     : ObjDumper(Writer), ObjF(ObjF) {
14230b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
14260b57cec5SDimitry Andric     switch (Sec.sh_type) {
14270b57cec5SDimitry Andric     case ELF::SHT_SYMTAB:
14280b57cec5SDimitry Andric       if (!DotSymtabSec)
14290b57cec5SDimitry Andric         DotSymtabSec = &Sec;
14300b57cec5SDimitry Andric       break;
14310b57cec5SDimitry Andric     case ELF::SHT_DYNSYM:
14320b57cec5SDimitry Andric       if (!DynSymRegion.Size) {
14330b57cec5SDimitry Andric         DynSymRegion = createDRIFrom(&Sec);
14340b57cec5SDimitry Andric         // This is only used (if Elf_Shdr present)for naming section in GNU
14350b57cec5SDimitry Andric         // style
14360b57cec5SDimitry Andric         DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric         if (Expected<StringRef> E = Obj->getStringTableForSymtab(Sec))
14390b57cec5SDimitry Andric           DynamicStringTable = *E;
14400b57cec5SDimitry Andric         else
14410b57cec5SDimitry Andric           warn(E.takeError());
14420b57cec5SDimitry Andric       }
14430b57cec5SDimitry Andric       break;
14440b57cec5SDimitry Andric     case ELF::SHT_SYMTAB_SHNDX:
14450b57cec5SDimitry Andric       ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
14460b57cec5SDimitry Andric       break;
14470b57cec5SDimitry Andric     case ELF::SHT_GNU_versym:
14480b57cec5SDimitry Andric       if (!SymbolVersionSection)
14490b57cec5SDimitry Andric         SymbolVersionSection = &Sec;
14500b57cec5SDimitry Andric       break;
14510b57cec5SDimitry Andric     case ELF::SHT_GNU_verdef:
14520b57cec5SDimitry Andric       if (!SymbolVersionDefSection)
14530b57cec5SDimitry Andric         SymbolVersionDefSection = &Sec;
14540b57cec5SDimitry Andric       break;
14550b57cec5SDimitry Andric     case ELF::SHT_GNU_verneed:
14560b57cec5SDimitry Andric       if (!SymbolVersionNeedSection)
14570b57cec5SDimitry Andric         SymbolVersionNeedSection = &Sec;
14580b57cec5SDimitry Andric       break;
14590b57cec5SDimitry Andric     case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
14600b57cec5SDimitry Andric       if (!DotCGProfileSec)
14610b57cec5SDimitry Andric         DotCGProfileSec = &Sec;
14620b57cec5SDimitry Andric       break;
14630b57cec5SDimitry Andric     case ELF::SHT_LLVM_ADDRSIG:
14640b57cec5SDimitry Andric       if (!DotAddrsigSec)
14650b57cec5SDimitry Andric         DotAddrsigSec = &Sec;
14660b57cec5SDimitry Andric       break;
14670b57cec5SDimitry Andric     }
14680b57cec5SDimitry Andric   }
14690b57cec5SDimitry Andric 
14700b57cec5SDimitry Andric   loadDynamicTable(Obj);
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric   if (opts::Output == opts::GNU)
14730b57cec5SDimitry Andric     ELFDumperStyle.reset(new GNUStyle<ELFT>(Writer, this));
14740b57cec5SDimitry Andric   else
14750b57cec5SDimitry Andric     ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, this));
14760b57cec5SDimitry Andric }
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric static const char *getTypeString(unsigned Arch, uint64_t Type) {
14790b57cec5SDimitry Andric #define DYNAMIC_TAG(n, v)
14800b57cec5SDimitry Andric   switch (Arch) {
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric   case EM_AARCH64:
14830b57cec5SDimitry Andric     switch (Type) {
14840b57cec5SDimitry Andric #define AARCH64_DYNAMIC_TAG(name, value)                                       \
14850b57cec5SDimitry Andric     case DT_##name:                                                            \
14860b57cec5SDimitry Andric       return #name;
14870b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def"
14880b57cec5SDimitry Andric #undef AARCH64_DYNAMIC_TAG
14890b57cec5SDimitry Andric     }
14900b57cec5SDimitry Andric     break;
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric   case EM_HEXAGON:
14930b57cec5SDimitry Andric     switch (Type) {
14940b57cec5SDimitry Andric #define HEXAGON_DYNAMIC_TAG(name, value)                                       \
14950b57cec5SDimitry Andric   case DT_##name:                                                              \
14960b57cec5SDimitry Andric     return #name;
14970b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def"
14980b57cec5SDimitry Andric #undef HEXAGON_DYNAMIC_TAG
14990b57cec5SDimitry Andric     }
15000b57cec5SDimitry Andric     break;
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric   case EM_MIPS:
15030b57cec5SDimitry Andric     switch (Type) {
15040b57cec5SDimitry Andric #define MIPS_DYNAMIC_TAG(name, value)                                          \
15050b57cec5SDimitry Andric   case DT_##name:                                                              \
15060b57cec5SDimitry Andric     return #name;
15070b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def"
15080b57cec5SDimitry Andric #undef MIPS_DYNAMIC_TAG
15090b57cec5SDimitry Andric     }
15100b57cec5SDimitry Andric     break;
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric   case EM_PPC64:
15130b57cec5SDimitry Andric     switch (Type) {
15140b57cec5SDimitry Andric #define PPC64_DYNAMIC_TAG(name, value)                                         \
15150b57cec5SDimitry Andric   case DT_##name:                                                              \
15160b57cec5SDimitry Andric     return #name;
15170b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def"
15180b57cec5SDimitry Andric #undef PPC64_DYNAMIC_TAG
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric     break;
15210b57cec5SDimitry Andric   }
15220b57cec5SDimitry Andric #undef DYNAMIC_TAG
15230b57cec5SDimitry Andric   switch (Type) {
15240b57cec5SDimitry Andric // Now handle all dynamic tags except the architecture specific ones
15250b57cec5SDimitry Andric #define AARCH64_DYNAMIC_TAG(name, value)
15260b57cec5SDimitry Andric #define MIPS_DYNAMIC_TAG(name, value)
15270b57cec5SDimitry Andric #define HEXAGON_DYNAMIC_TAG(name, value)
15280b57cec5SDimitry Andric #define PPC64_DYNAMIC_TAG(name, value)
15290b57cec5SDimitry Andric // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
15300b57cec5SDimitry Andric #define DYNAMIC_TAG_MARKER(name, value)
15310b57cec5SDimitry Andric #define DYNAMIC_TAG(name, value)                                               \
15320b57cec5SDimitry Andric   case DT_##name:                                                              \
15330b57cec5SDimitry Andric     return #name;
15340b57cec5SDimitry Andric #include "llvm/BinaryFormat/DynamicTags.def"
15350b57cec5SDimitry Andric #undef DYNAMIC_TAG
15360b57cec5SDimitry Andric #undef AARCH64_DYNAMIC_TAG
15370b57cec5SDimitry Andric #undef MIPS_DYNAMIC_TAG
15380b57cec5SDimitry Andric #undef HEXAGON_DYNAMIC_TAG
15390b57cec5SDimitry Andric #undef PPC64_DYNAMIC_TAG
15400b57cec5SDimitry Andric #undef DYNAMIC_TAG_MARKER
15410b57cec5SDimitry Andric   default:
15420b57cec5SDimitry Andric     return "unknown";
15430b57cec5SDimitry Andric   }
15440b57cec5SDimitry Andric }
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
15470b57cec5SDimitry Andric   auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {
15480b57cec5SDimitry Andric     auto MappedAddrOrError = ObjF->getELFFile()->toMappedAddr(VAddr);
15490b57cec5SDimitry Andric     if (!MappedAddrOrError) {
15500b57cec5SDimitry Andric       reportWarning("Unable to parse DT_" +
15510b57cec5SDimitry Andric                     Twine(getTypeString(
15520b57cec5SDimitry Andric                         ObjF->getELFFile()->getHeader()->e_machine, Tag)) +
15530b57cec5SDimitry Andric                     ": " + llvm::toString(MappedAddrOrError.takeError()));
15540b57cec5SDimitry Andric       return nullptr;
15550b57cec5SDimitry Andric     }
15560b57cec5SDimitry Andric     return MappedAddrOrError.get();
15570b57cec5SDimitry Andric   };
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   uint64_t SONameOffset = 0;
15600b57cec5SDimitry Andric   const char *StringTableBegin = nullptr;
15610b57cec5SDimitry Andric   uint64_t StringTableSize = 0;
15620b57cec5SDimitry Andric   for (const Elf_Dyn &Dyn : dynamic_table()) {
15630b57cec5SDimitry Andric     switch (Dyn.d_tag) {
15640b57cec5SDimitry Andric     case ELF::DT_HASH:
15650b57cec5SDimitry Andric       HashTable = reinterpret_cast<const Elf_Hash *>(
15660b57cec5SDimitry Andric           toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
15670b57cec5SDimitry Andric       break;
15680b57cec5SDimitry Andric     case ELF::DT_GNU_HASH:
15690b57cec5SDimitry Andric       GnuHashTable = reinterpret_cast<const Elf_GnuHash *>(
15700b57cec5SDimitry Andric           toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
15710b57cec5SDimitry Andric       break;
15720b57cec5SDimitry Andric     case ELF::DT_STRTAB:
15730b57cec5SDimitry Andric       StringTableBegin = reinterpret_cast<const char *>(
15740b57cec5SDimitry Andric           toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
15750b57cec5SDimitry Andric       break;
15760b57cec5SDimitry Andric     case ELF::DT_STRSZ:
15770b57cec5SDimitry Andric       StringTableSize = Dyn.getVal();
15780b57cec5SDimitry Andric       break;
15790b57cec5SDimitry Andric     case ELF::DT_SYMTAB:
15800b57cec5SDimitry Andric       DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
15810b57cec5SDimitry Andric       DynSymRegion.EntSize = sizeof(Elf_Sym);
15820b57cec5SDimitry Andric       break;
15830b57cec5SDimitry Andric     case ELF::DT_RELA:
15840b57cec5SDimitry Andric       DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
15850b57cec5SDimitry Andric       break;
15860b57cec5SDimitry Andric     case ELF::DT_RELASZ:
15870b57cec5SDimitry Andric       DynRelaRegion.Size = Dyn.getVal();
15880b57cec5SDimitry Andric       break;
15890b57cec5SDimitry Andric     case ELF::DT_RELAENT:
15900b57cec5SDimitry Andric       DynRelaRegion.EntSize = Dyn.getVal();
15910b57cec5SDimitry Andric       break;
15920b57cec5SDimitry Andric     case ELF::DT_SONAME:
15930b57cec5SDimitry Andric       SONameOffset = Dyn.getVal();
15940b57cec5SDimitry Andric       break;
15950b57cec5SDimitry Andric     case ELF::DT_REL:
15960b57cec5SDimitry Andric       DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
15970b57cec5SDimitry Andric       break;
15980b57cec5SDimitry Andric     case ELF::DT_RELSZ:
15990b57cec5SDimitry Andric       DynRelRegion.Size = Dyn.getVal();
16000b57cec5SDimitry Andric       break;
16010b57cec5SDimitry Andric     case ELF::DT_RELENT:
16020b57cec5SDimitry Andric       DynRelRegion.EntSize = Dyn.getVal();
16030b57cec5SDimitry Andric       break;
16040b57cec5SDimitry Andric     case ELF::DT_RELR:
16050b57cec5SDimitry Andric     case ELF::DT_ANDROID_RELR:
16060b57cec5SDimitry Andric       DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
16070b57cec5SDimitry Andric       break;
16080b57cec5SDimitry Andric     case ELF::DT_RELRSZ:
16090b57cec5SDimitry Andric     case ELF::DT_ANDROID_RELRSZ:
16100b57cec5SDimitry Andric       DynRelrRegion.Size = Dyn.getVal();
16110b57cec5SDimitry Andric       break;
16120b57cec5SDimitry Andric     case ELF::DT_RELRENT:
16130b57cec5SDimitry Andric     case ELF::DT_ANDROID_RELRENT:
16140b57cec5SDimitry Andric       DynRelrRegion.EntSize = Dyn.getVal();
16150b57cec5SDimitry Andric       break;
16160b57cec5SDimitry Andric     case ELF::DT_PLTREL:
16170b57cec5SDimitry Andric       if (Dyn.getVal() == DT_REL)
16180b57cec5SDimitry Andric         DynPLTRelRegion.EntSize = sizeof(Elf_Rel);
16190b57cec5SDimitry Andric       else if (Dyn.getVal() == DT_RELA)
16200b57cec5SDimitry Andric         DynPLTRelRegion.EntSize = sizeof(Elf_Rela);
16210b57cec5SDimitry Andric       else
16220b57cec5SDimitry Andric         reportError(Twine("unknown DT_PLTREL value of ") +
16230b57cec5SDimitry Andric                     Twine((uint64_t)Dyn.getVal()));
16240b57cec5SDimitry Andric       break;
16250b57cec5SDimitry Andric     case ELF::DT_JMPREL:
16260b57cec5SDimitry Andric       DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
16270b57cec5SDimitry Andric       break;
16280b57cec5SDimitry Andric     case ELF::DT_PLTRELSZ:
16290b57cec5SDimitry Andric       DynPLTRelRegion.Size = Dyn.getVal();
16300b57cec5SDimitry Andric       break;
16310b57cec5SDimitry Andric     }
16320b57cec5SDimitry Andric   }
16330b57cec5SDimitry Andric   if (StringTableBegin)
16340b57cec5SDimitry Andric     DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
16350b57cec5SDimitry Andric   if (SONameOffset && SONameOffset < DynamicStringTable.size())
16360b57cec5SDimitry Andric     SOName = DynamicStringTable.data() + SONameOffset;
16370b57cec5SDimitry Andric }
16380b57cec5SDimitry Andric 
16390b57cec5SDimitry Andric template <typename ELFT>
16400b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const {
16410b57cec5SDimitry Andric   return DynRelRegion.getAsArrayRef<Elf_Rel>();
16420b57cec5SDimitry Andric }
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric template <typename ELFT>
16450b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
16460b57cec5SDimitry Andric   return DynRelaRegion.getAsArrayRef<Elf_Rela>();
16470b57cec5SDimitry Andric }
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric template <typename ELFT>
16500b57cec5SDimitry Andric typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const {
16510b57cec5SDimitry Andric   return DynRelrRegion.getAsArrayRef<Elf_Relr>();
16520b57cec5SDimitry Andric }
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printFileHeaders() {
16550b57cec5SDimitry Andric   ELFDumperStyle->printFileHeaders(ObjF->getELFFile());
16560b57cec5SDimitry Andric }
16570b57cec5SDimitry Andric 
16580b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printSectionHeaders() {
16590b57cec5SDimitry Andric   ELFDumperStyle->printSectionHeaders(ObjF->getELFFile());
16600b57cec5SDimitry Andric }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printRelocations() {
16630b57cec5SDimitry Andric   ELFDumperStyle->printRelocations(ObjF->getELFFile());
16640b57cec5SDimitry Andric }
16650b57cec5SDimitry Andric 
16660b57cec5SDimitry Andric template <class ELFT>
16670b57cec5SDimitry Andric void ELFDumper<ELFT>::printProgramHeaders(
16680b57cec5SDimitry Andric     bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {
16690b57cec5SDimitry Andric   ELFDumperStyle->printProgramHeaders(ObjF->getELFFile(), PrintProgramHeaders,
16700b57cec5SDimitry Andric                                       PrintSectionMapping);
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {
16740b57cec5SDimitry Andric   // Dump version symbol section.
16750b57cec5SDimitry Andric   ELFDumperStyle->printVersionSymbolSection(ObjF->getELFFile(),
16760b57cec5SDimitry Andric                                             SymbolVersionSection);
16770b57cec5SDimitry Andric 
16780b57cec5SDimitry Andric   // Dump version definition section.
16790b57cec5SDimitry Andric   ELFDumperStyle->printVersionDefinitionSection(ObjF->getELFFile(),
16800b57cec5SDimitry Andric                                                 SymbolVersionDefSection);
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric   // Dump version dependency section.
16830b57cec5SDimitry Andric   ELFDumperStyle->printVersionDependencySection(ObjF->getELFFile(),
16840b57cec5SDimitry Andric                                                 SymbolVersionNeedSection);
16850b57cec5SDimitry Andric }
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
16880b57cec5SDimitry Andric   ELFDumperStyle->printDynamicRelocations(ObjF->getELFFile());
16890b57cec5SDimitry Andric }
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric template <class ELFT>
16920b57cec5SDimitry Andric void ELFDumper<ELFT>::printSymbols(bool PrintSymbols,
16930b57cec5SDimitry Andric                                    bool PrintDynamicSymbols) {
16940b57cec5SDimitry Andric   ELFDumperStyle->printSymbols(ObjF->getELFFile(), PrintSymbols,
16950b57cec5SDimitry Andric                                PrintDynamicSymbols);
16960b57cec5SDimitry Andric }
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printHashSymbols() {
16990b57cec5SDimitry Andric   ELFDumperStyle->printHashSymbols(ObjF->getELFFile());
17000b57cec5SDimitry Andric }
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() {
17030b57cec5SDimitry Andric   ELFDumperStyle->printHashHistogram(ObjF->getELFFile());
17040b57cec5SDimitry Andric }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printCGProfile() {
17070b57cec5SDimitry Andric   ELFDumperStyle->printCGProfile(ObjF->getELFFile());
17080b57cec5SDimitry Andric }
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNotes() {
17110b57cec5SDimitry Andric   ELFDumperStyle->printNotes(ObjF->getELFFile());
17120b57cec5SDimitry Andric }
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() {
17150b57cec5SDimitry Andric   ELFDumperStyle->printELFLinkerOptions(ObjF->getELFFile());
17160b57cec5SDimitry Andric }
17170b57cec5SDimitry Andric 
17180b57cec5SDimitry Andric #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum)                                 \
17190b57cec5SDimitry Andric   { #enum, prefix##_##enum }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTFlags[] = {
17220b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),
17230b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),
17240b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),
17250b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),
17260b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)
17270b57cec5SDimitry Andric };
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = {
17300b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW),
17310b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL),
17320b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP),
17330b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE),
17340b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR),
17350b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST),
17360b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN),
17370b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN),
17380b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT),
17390b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS),
17400b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE),
17410b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB),
17420b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP),
17430b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT),
17440b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE),
17450b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE),
17460b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND),
17470b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT),
17480b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF),
17490b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS),
17500b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR),
17510b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED),
17520b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC),
17530b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE),
17540b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT),
17550b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON)
17560b57cec5SDimitry Andric };
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {
17590b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),
17600b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),
17610b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),
17620b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),
17630b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),
17640b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),
17650b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),
17660b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),
17670b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),
17680b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),
17690b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),
17700b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),
17710b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),
17720b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),
17730b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),
17740b57cec5SDimitry Andric   LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)
17750b57cec5SDimitry Andric };
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric #undef LLVM_READOBJ_DT_FLAG_ENT
17780b57cec5SDimitry Andric 
17790b57cec5SDimitry Andric template <typename T, typename TFlag>
17800b57cec5SDimitry Andric void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
17810b57cec5SDimitry Andric   using FlagEntry = EnumEntry<TFlag>;
17820b57cec5SDimitry Andric   using FlagVector = SmallVector<FlagEntry, 10>;
17830b57cec5SDimitry Andric   FlagVector SetFlags;
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric   for (const auto &Flag : Flags) {
17860b57cec5SDimitry Andric     if (Flag.Value == 0)
17870b57cec5SDimitry Andric       continue;
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric     if ((Value & Flag.Value) == Flag.Value)
17900b57cec5SDimitry Andric       SetFlags.push_back(Flag);
17910b57cec5SDimitry Andric   }
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric   for (const auto &Flag : SetFlags) {
17940b57cec5SDimitry Andric     OS << Flag.Name << " ";
17950b57cec5SDimitry Andric   }
17960b57cec5SDimitry Andric }
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric template <class ELFT>
17990b57cec5SDimitry Andric void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
18000b57cec5SDimitry Andric                                         uint64_t Value) const {
18010b57cec5SDimitry Andric   const char *ConvChar =
18020b57cec5SDimitry Andric       (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
18030b57cec5SDimitry Andric 
18040b57cec5SDimitry Andric   // Handle custom printing of architecture specific tags
18050b57cec5SDimitry Andric   switch (ObjF->getELFFile()->getHeader()->e_machine) {
18060b57cec5SDimitry Andric   case EM_AARCH64:
18070b57cec5SDimitry Andric     switch (Type) {
18080b57cec5SDimitry Andric     case DT_AARCH64_BTI_PLT:
18090b57cec5SDimitry Andric     case DT_AARCH64_PAC_PLT:
18100b57cec5SDimitry Andric       OS << Value;
18110b57cec5SDimitry Andric       return;
18120b57cec5SDimitry Andric     default:
18130b57cec5SDimitry Andric       break;
18140b57cec5SDimitry Andric     }
18150b57cec5SDimitry Andric     break;
18160b57cec5SDimitry Andric   case EM_HEXAGON:
18170b57cec5SDimitry Andric     switch (Type) {
18180b57cec5SDimitry Andric     case DT_HEXAGON_VER:
18190b57cec5SDimitry Andric       OS << Value;
18200b57cec5SDimitry Andric       return;
18210b57cec5SDimitry Andric     case DT_HEXAGON_SYMSZ:
18220b57cec5SDimitry Andric     case DT_HEXAGON_PLT:
18230b57cec5SDimitry Andric       OS << format(ConvChar, Value);
18240b57cec5SDimitry Andric       return;
18250b57cec5SDimitry Andric     default:
18260b57cec5SDimitry Andric       break;
18270b57cec5SDimitry Andric     }
18280b57cec5SDimitry Andric     break;
18290b57cec5SDimitry Andric   case EM_MIPS:
18300b57cec5SDimitry Andric     switch (Type) {
18310b57cec5SDimitry Andric     case DT_MIPS_RLD_VERSION:
18320b57cec5SDimitry Andric     case DT_MIPS_LOCAL_GOTNO:
18330b57cec5SDimitry Andric     case DT_MIPS_SYMTABNO:
18340b57cec5SDimitry Andric     case DT_MIPS_UNREFEXTNO:
18350b57cec5SDimitry Andric       OS << Value;
18360b57cec5SDimitry Andric       return;
18370b57cec5SDimitry Andric     case DT_MIPS_TIME_STAMP:
18380b57cec5SDimitry Andric     case DT_MIPS_ICHECKSUM:
18390b57cec5SDimitry Andric     case DT_MIPS_IVERSION:
18400b57cec5SDimitry Andric     case DT_MIPS_BASE_ADDRESS:
18410b57cec5SDimitry Andric     case DT_MIPS_MSYM:
18420b57cec5SDimitry Andric     case DT_MIPS_CONFLICT:
18430b57cec5SDimitry Andric     case DT_MIPS_LIBLIST:
18440b57cec5SDimitry Andric     case DT_MIPS_CONFLICTNO:
18450b57cec5SDimitry Andric     case DT_MIPS_LIBLISTNO:
18460b57cec5SDimitry Andric     case DT_MIPS_GOTSYM:
18470b57cec5SDimitry Andric     case DT_MIPS_HIPAGENO:
18480b57cec5SDimitry Andric     case DT_MIPS_RLD_MAP:
18490b57cec5SDimitry Andric     case DT_MIPS_DELTA_CLASS:
18500b57cec5SDimitry Andric     case DT_MIPS_DELTA_CLASS_NO:
18510b57cec5SDimitry Andric     case DT_MIPS_DELTA_INSTANCE:
18520b57cec5SDimitry Andric     case DT_MIPS_DELTA_RELOC:
18530b57cec5SDimitry Andric     case DT_MIPS_DELTA_RELOC_NO:
18540b57cec5SDimitry Andric     case DT_MIPS_DELTA_SYM:
18550b57cec5SDimitry Andric     case DT_MIPS_DELTA_SYM_NO:
18560b57cec5SDimitry Andric     case DT_MIPS_DELTA_CLASSSYM:
18570b57cec5SDimitry Andric     case DT_MIPS_DELTA_CLASSSYM_NO:
18580b57cec5SDimitry Andric     case DT_MIPS_CXX_FLAGS:
18590b57cec5SDimitry Andric     case DT_MIPS_PIXIE_INIT:
18600b57cec5SDimitry Andric     case DT_MIPS_SYMBOL_LIB:
18610b57cec5SDimitry Andric     case DT_MIPS_LOCALPAGE_GOTIDX:
18620b57cec5SDimitry Andric     case DT_MIPS_LOCAL_GOTIDX:
18630b57cec5SDimitry Andric     case DT_MIPS_HIDDEN_GOTIDX:
18640b57cec5SDimitry Andric     case DT_MIPS_PROTECTED_GOTIDX:
18650b57cec5SDimitry Andric     case DT_MIPS_OPTIONS:
18660b57cec5SDimitry Andric     case DT_MIPS_INTERFACE:
18670b57cec5SDimitry Andric     case DT_MIPS_DYNSTR_ALIGN:
18680b57cec5SDimitry Andric     case DT_MIPS_INTERFACE_SIZE:
18690b57cec5SDimitry Andric     case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
18700b57cec5SDimitry Andric     case DT_MIPS_PERF_SUFFIX:
18710b57cec5SDimitry Andric     case DT_MIPS_COMPACT_SIZE:
18720b57cec5SDimitry Andric     case DT_MIPS_GP_VALUE:
18730b57cec5SDimitry Andric     case DT_MIPS_AUX_DYNAMIC:
18740b57cec5SDimitry Andric     case DT_MIPS_PLTGOT:
18750b57cec5SDimitry Andric     case DT_MIPS_RWPLT:
18760b57cec5SDimitry Andric     case DT_MIPS_RLD_MAP_REL:
18770b57cec5SDimitry Andric       OS << format(ConvChar, Value);
18780b57cec5SDimitry Andric       return;
18790b57cec5SDimitry Andric     case DT_MIPS_FLAGS:
18800b57cec5SDimitry Andric       printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
18810b57cec5SDimitry Andric       return;
18820b57cec5SDimitry Andric     default:
18830b57cec5SDimitry Andric       break;
18840b57cec5SDimitry Andric     }
18850b57cec5SDimitry Andric     break;
18860b57cec5SDimitry Andric   default:
18870b57cec5SDimitry Andric     break;
18880b57cec5SDimitry Andric   }
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric   switch (Type) {
18910b57cec5SDimitry Andric   case DT_PLTREL:
18920b57cec5SDimitry Andric     if (Value == DT_REL) {
18930b57cec5SDimitry Andric       OS << "REL";
18940b57cec5SDimitry Andric       break;
18950b57cec5SDimitry Andric     } else if (Value == DT_RELA) {
18960b57cec5SDimitry Andric       OS << "RELA";
18970b57cec5SDimitry Andric       break;
18980b57cec5SDimitry Andric     }
18990b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
19000b57cec5SDimitry Andric   case DT_PLTGOT:
19010b57cec5SDimitry Andric   case DT_HASH:
19020b57cec5SDimitry Andric   case DT_STRTAB:
19030b57cec5SDimitry Andric   case DT_SYMTAB:
19040b57cec5SDimitry Andric   case DT_RELA:
19050b57cec5SDimitry Andric   case DT_INIT:
19060b57cec5SDimitry Andric   case DT_FINI:
19070b57cec5SDimitry Andric   case DT_REL:
19080b57cec5SDimitry Andric   case DT_JMPREL:
19090b57cec5SDimitry Andric   case DT_INIT_ARRAY:
19100b57cec5SDimitry Andric   case DT_FINI_ARRAY:
19110b57cec5SDimitry Andric   case DT_PREINIT_ARRAY:
19120b57cec5SDimitry Andric   case DT_DEBUG:
19130b57cec5SDimitry Andric   case DT_VERDEF:
19140b57cec5SDimitry Andric   case DT_VERNEED:
19150b57cec5SDimitry Andric   case DT_VERSYM:
19160b57cec5SDimitry Andric   case DT_GNU_HASH:
19170b57cec5SDimitry Andric   case DT_NULL:
19180b57cec5SDimitry Andric     OS << format(ConvChar, Value);
19190b57cec5SDimitry Andric     break;
19200b57cec5SDimitry Andric   case DT_RELACOUNT:
19210b57cec5SDimitry Andric   case DT_RELCOUNT:
19220b57cec5SDimitry Andric   case DT_VERDEFNUM:
19230b57cec5SDimitry Andric   case DT_VERNEEDNUM:
19240b57cec5SDimitry Andric     OS << Value;
19250b57cec5SDimitry Andric     break;
19260b57cec5SDimitry Andric   case DT_PLTRELSZ:
19270b57cec5SDimitry Andric   case DT_RELASZ:
19280b57cec5SDimitry Andric   case DT_RELAENT:
19290b57cec5SDimitry Andric   case DT_STRSZ:
19300b57cec5SDimitry Andric   case DT_SYMENT:
19310b57cec5SDimitry Andric   case DT_RELSZ:
19320b57cec5SDimitry Andric   case DT_RELENT:
19330b57cec5SDimitry Andric   case DT_INIT_ARRAYSZ:
19340b57cec5SDimitry Andric   case DT_FINI_ARRAYSZ:
19350b57cec5SDimitry Andric   case DT_PREINIT_ARRAYSZ:
19360b57cec5SDimitry Andric   case DT_ANDROID_RELSZ:
19370b57cec5SDimitry Andric   case DT_ANDROID_RELASZ:
19380b57cec5SDimitry Andric     OS << Value << " (bytes)";
19390b57cec5SDimitry Andric     break;
19400b57cec5SDimitry Andric   case DT_NEEDED:
19410b57cec5SDimitry Andric   case DT_SONAME:
19420b57cec5SDimitry Andric   case DT_AUXILIARY:
19430b57cec5SDimitry Andric   case DT_USED:
19440b57cec5SDimitry Andric   case DT_FILTER:
19450b57cec5SDimitry Andric   case DT_RPATH:
19460b57cec5SDimitry Andric   case DT_RUNPATH: {
19470b57cec5SDimitry Andric     const std::map<uint64_t, const char*> TagNames = {
19480b57cec5SDimitry Andric       {DT_NEEDED,    "Shared library"},
19490b57cec5SDimitry Andric       {DT_SONAME,    "Library soname"},
19500b57cec5SDimitry Andric       {DT_AUXILIARY, "Auxiliary library"},
19510b57cec5SDimitry Andric       {DT_USED,      "Not needed object"},
19520b57cec5SDimitry Andric       {DT_FILTER,    "Filter library"},
19530b57cec5SDimitry Andric       {DT_RPATH,     "Library rpath"},
19540b57cec5SDimitry Andric       {DT_RUNPATH,   "Library runpath"},
19550b57cec5SDimitry Andric     };
19560b57cec5SDimitry Andric     OS << TagNames.at(Type) << ": ";
19570b57cec5SDimitry Andric     if (DynamicStringTable.empty())
19580b57cec5SDimitry Andric       OS << "<String table is empty or was not found> ";
19590b57cec5SDimitry Andric     else if (Value < DynamicStringTable.size())
19600b57cec5SDimitry Andric       OS << "[" << StringRef(DynamicStringTable.data() + Value) << "]";
19610b57cec5SDimitry Andric     else
19620b57cec5SDimitry Andric       OS << "<Invalid offset 0x" << utohexstr(Value) << ">";
19630b57cec5SDimitry Andric     break;
19640b57cec5SDimitry Andric   }
19650b57cec5SDimitry Andric   case DT_FLAGS:
19660b57cec5SDimitry Andric     printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
19670b57cec5SDimitry Andric     break;
19680b57cec5SDimitry Andric   case DT_FLAGS_1:
19690b57cec5SDimitry Andric     printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
19700b57cec5SDimitry Andric     break;
19710b57cec5SDimitry Andric   default:
19720b57cec5SDimitry Andric     OS << format(ConvChar, Value);
19730b57cec5SDimitry Andric     break;
19740b57cec5SDimitry Andric   }
19750b57cec5SDimitry Andric }
19760b57cec5SDimitry Andric 
19770b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {
19780b57cec5SDimitry Andric   DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF);
19790b57cec5SDimitry Andric   Ctx.printUnwindInformation();
19800b57cec5SDimitry Andric }
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric namespace {
19830b57cec5SDimitry Andric 
19840b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printUnwindInfo() {
19850b57cec5SDimitry Andric   const ELFFile<ELF32LE> *Obj = ObjF->getELFFile();
19860b57cec5SDimitry Andric   const unsigned Machine = Obj->getHeader()->e_machine;
19870b57cec5SDimitry Andric   if (Machine == EM_ARM) {
19880b57cec5SDimitry Andric     ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec);
19890b57cec5SDimitry Andric     Ctx.PrintUnwindInformation();
19900b57cec5SDimitry Andric   }
19910b57cec5SDimitry Andric   DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF);
19920b57cec5SDimitry Andric   Ctx.printUnwindInformation();
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric } // end anonymous namespace
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printDynamicTable() {
19980b57cec5SDimitry Andric   ELFDumperStyle->printDynamic(ObjF->getELFFile());
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
20020b57cec5SDimitry Andric   ListScope D(W, "NeededLibraries");
20030b57cec5SDimitry Andric 
20040b57cec5SDimitry Andric   using LibsTy = std::vector<StringRef>;
20050b57cec5SDimitry Andric   LibsTy Libs;
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric   for (const auto &Entry : dynamic_table())
20080b57cec5SDimitry Andric     if (Entry.d_tag == ELF::DT_NEEDED) {
20090b57cec5SDimitry Andric       uint64_t Value = Entry.d_un.d_val;
20100b57cec5SDimitry Andric       if (Value < DynamicStringTable.size())
20110b57cec5SDimitry Andric         Libs.push_back(StringRef(DynamicStringTable.data() + Value));
20120b57cec5SDimitry Andric       else
20130b57cec5SDimitry Andric         Libs.push_back("<Library name index out of range>");
20140b57cec5SDimitry Andric     }
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric   llvm::stable_sort(Libs);
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric   for (const auto &L : Libs)
20190b57cec5SDimitry Andric     W.startLine() << L << "\n";
20200b57cec5SDimitry Andric }
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printHashTable() {
20230b57cec5SDimitry Andric   DictScope D(W, "HashTable");
20240b57cec5SDimitry Andric   if (!HashTable)
20250b57cec5SDimitry Andric     return;
20260b57cec5SDimitry Andric   W.printNumber("Num Buckets", HashTable->nbucket);
20270b57cec5SDimitry Andric   W.printNumber("Num Chains", HashTable->nchain);
20280b57cec5SDimitry Andric   W.printList("Buckets", HashTable->buckets());
20290b57cec5SDimitry Andric   W.printList("Chains", HashTable->chains());
20300b57cec5SDimitry Andric }
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printGnuHashTable() {
20330b57cec5SDimitry Andric   DictScope D(W, "GnuHashTable");
20340b57cec5SDimitry Andric   if (!GnuHashTable)
20350b57cec5SDimitry Andric     return;
20360b57cec5SDimitry Andric   W.printNumber("Num Buckets", GnuHashTable->nbuckets);
20370b57cec5SDimitry Andric   W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);
20380b57cec5SDimitry Andric   W.printNumber("Num Mask Words", GnuHashTable->maskwords);
20390b57cec5SDimitry Andric   W.printNumber("Shift Count", GnuHashTable->shift2);
20400b57cec5SDimitry Andric   W.printHexList("Bloom Filter", GnuHashTable->filter());
20410b57cec5SDimitry Andric   W.printList("Buckets", GnuHashTable->buckets());
20420b57cec5SDimitry Andric   Elf_Sym_Range Syms = dynamic_symbols();
20430b57cec5SDimitry Andric   unsigned NumSyms = std::distance(Syms.begin(), Syms.end());
20440b57cec5SDimitry Andric   if (!NumSyms)
20450b57cec5SDimitry Andric     reportError("No dynamic symbol section");
20460b57cec5SDimitry Andric   W.printHexList("Values", GnuHashTable->values(NumSyms));
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric 
20490b57cec5SDimitry Andric template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
20500b57cec5SDimitry Andric   W.printString("LoadName", SOName);
20510b57cec5SDimitry Andric }
20520b57cec5SDimitry Andric 
20530b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
20540b57cec5SDimitry Andric   W.startLine() << "Attributes not implemented.\n";
20550b57cec5SDimitry Andric }
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric namespace {
20580b57cec5SDimitry Andric 
20590b57cec5SDimitry Andric template <> void ELFDumper<ELF32LE>::printAttributes() {
20600b57cec5SDimitry Andric   const ELFFile<ELF32LE> *Obj = ObjF->getELFFile();
20610b57cec5SDimitry Andric   if (Obj->getHeader()->e_machine != EM_ARM) {
20620b57cec5SDimitry Andric     W.startLine() << "Attributes not implemented.\n";
20630b57cec5SDimitry Andric     return;
20640b57cec5SDimitry Andric   }
20650b57cec5SDimitry Andric 
20660b57cec5SDimitry Andric   DictScope BA(W, "BuildAttributes");
20670b57cec5SDimitry Andric   for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
20680b57cec5SDimitry Andric     if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES)
20690b57cec5SDimitry Andric       continue;
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric     ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec));
20720b57cec5SDimitry Andric     if (Contents[0] != ARMBuildAttrs::Format_Version) {
20730b57cec5SDimitry Andric       errs() << "unrecognised FormatVersion: 0x"
20740b57cec5SDimitry Andric              << Twine::utohexstr(Contents[0]) << '\n';
20750b57cec5SDimitry Andric       continue;
20760b57cec5SDimitry Andric     }
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric     W.printHex("FormatVersion", Contents[0]);
20790b57cec5SDimitry Andric     if (Contents.size() == 1)
20800b57cec5SDimitry Andric       continue;
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric     ARMAttributeParser(&W).Parse(Contents, true);
20830b57cec5SDimitry Andric   }
20840b57cec5SDimitry Andric }
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric template <class ELFT> class MipsGOTParser {
20870b57cec5SDimitry Andric public:
20880b57cec5SDimitry Andric   TYPEDEF_ELF_TYPES(ELFT)
20890b57cec5SDimitry Andric   using Entry = typename ELFO::Elf_Addr;
20900b57cec5SDimitry Andric   using Entries = ArrayRef<Entry>;
20910b57cec5SDimitry Andric 
20920b57cec5SDimitry Andric   const bool IsStatic;
20930b57cec5SDimitry Andric   const ELFO * const Obj;
20940b57cec5SDimitry Andric 
20950b57cec5SDimitry Andric   MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   bool hasGot() const { return !GotEntries.empty(); }
20980b57cec5SDimitry Andric   bool hasPlt() const { return !PltEntries.empty(); }
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric   uint64_t getGp() const;
21010b57cec5SDimitry Andric 
21020b57cec5SDimitry Andric   const Entry *getGotLazyResolver() const;
21030b57cec5SDimitry Andric   const Entry *getGotModulePointer() const;
21040b57cec5SDimitry Andric   const Entry *getPltLazyResolver() const;
21050b57cec5SDimitry Andric   const Entry *getPltModulePointer() const;
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   Entries getLocalEntries() const;
21080b57cec5SDimitry Andric   Entries getGlobalEntries() const;
21090b57cec5SDimitry Andric   Entries getOtherEntries() const;
21100b57cec5SDimitry Andric   Entries getPltEntries() const;
21110b57cec5SDimitry Andric 
21120b57cec5SDimitry Andric   uint64_t getGotAddress(const Entry * E) const;
21130b57cec5SDimitry Andric   int64_t getGotOffset(const Entry * E) const;
21140b57cec5SDimitry Andric   const Elf_Sym *getGotSym(const Entry *E) const;
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric   uint64_t getPltAddress(const Entry * E) const;
21170b57cec5SDimitry Andric   const Elf_Sym *getPltSym(const Entry *E) const;
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric   StringRef getPltStrTable() const { return PltStrTable; }
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric private:
21220b57cec5SDimitry Andric   const Elf_Shdr *GotSec;
21230b57cec5SDimitry Andric   size_t LocalNum;
21240b57cec5SDimitry Andric   size_t GlobalNum;
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   const Elf_Shdr *PltSec;
21270b57cec5SDimitry Andric   const Elf_Shdr *PltRelSec;
21280b57cec5SDimitry Andric   const Elf_Shdr *PltSymTable;
21290b57cec5SDimitry Andric   Elf_Sym_Range GotDynSyms;
21300b57cec5SDimitry Andric   StringRef PltStrTable;
21310b57cec5SDimitry Andric 
21320b57cec5SDimitry Andric   Entries GotEntries;
21330b57cec5SDimitry Andric   Entries PltEntries;
21340b57cec5SDimitry Andric };
21350b57cec5SDimitry Andric 
21360b57cec5SDimitry Andric } // end anonymous namespace
21370b57cec5SDimitry Andric 
21380b57cec5SDimitry Andric template <class ELFT>
21390b57cec5SDimitry Andric MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
21400b57cec5SDimitry Andric                                    Elf_Sym_Range DynSyms)
21410b57cec5SDimitry Andric     : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0),
21420b57cec5SDimitry Andric       GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) {
21430b57cec5SDimitry Andric   // See "Global Offset Table" in Chapter 5 in the following document
21440b57cec5SDimitry Andric   // for detailed GOT description.
21450b57cec5SDimitry Andric   // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
21460b57cec5SDimitry Andric 
21470b57cec5SDimitry Andric   // Find static GOT secton.
21480b57cec5SDimitry Andric   if (IsStatic) {
21490b57cec5SDimitry Andric     GotSec = findSectionByName(*Obj, ".got");
21500b57cec5SDimitry Andric     if (!GotSec)
21510b57cec5SDimitry Andric       reportError("Cannot find .got section");
21520b57cec5SDimitry Andric 
21530b57cec5SDimitry Andric     ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
21540b57cec5SDimitry Andric     GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
21550b57cec5SDimitry Andric                          Content.size() / sizeof(Entry));
21560b57cec5SDimitry Andric     LocalNum = GotEntries.size();
21570b57cec5SDimitry Andric     return;
21580b57cec5SDimitry Andric   }
21590b57cec5SDimitry Andric 
21600b57cec5SDimitry Andric   // Lookup dynamic table tags which define GOT/PLT layouts.
21610b57cec5SDimitry Andric   Optional<uint64_t> DtPltGot;
21620b57cec5SDimitry Andric   Optional<uint64_t> DtLocalGotNum;
21630b57cec5SDimitry Andric   Optional<uint64_t> DtGotSym;
21640b57cec5SDimitry Andric   Optional<uint64_t> DtMipsPltGot;
21650b57cec5SDimitry Andric   Optional<uint64_t> DtJmpRel;
21660b57cec5SDimitry Andric   for (const auto &Entry : DynTable) {
21670b57cec5SDimitry Andric     switch (Entry.getTag()) {
21680b57cec5SDimitry Andric     case ELF::DT_PLTGOT:
21690b57cec5SDimitry Andric       DtPltGot = Entry.getVal();
21700b57cec5SDimitry Andric       break;
21710b57cec5SDimitry Andric     case ELF::DT_MIPS_LOCAL_GOTNO:
21720b57cec5SDimitry Andric       DtLocalGotNum = Entry.getVal();
21730b57cec5SDimitry Andric       break;
21740b57cec5SDimitry Andric     case ELF::DT_MIPS_GOTSYM:
21750b57cec5SDimitry Andric       DtGotSym = Entry.getVal();
21760b57cec5SDimitry Andric       break;
21770b57cec5SDimitry Andric     case ELF::DT_MIPS_PLTGOT:
21780b57cec5SDimitry Andric       DtMipsPltGot = Entry.getVal();
21790b57cec5SDimitry Andric       break;
21800b57cec5SDimitry Andric     case ELF::DT_JMPREL:
21810b57cec5SDimitry Andric       DtJmpRel = Entry.getVal();
21820b57cec5SDimitry Andric       break;
21830b57cec5SDimitry Andric     }
21840b57cec5SDimitry Andric   }
21850b57cec5SDimitry Andric 
21860b57cec5SDimitry Andric   // Find dynamic GOT section.
21870b57cec5SDimitry Andric   if (DtPltGot || DtLocalGotNum || DtGotSym) {
21880b57cec5SDimitry Andric     if (!DtPltGot)
21890b57cec5SDimitry Andric       report_fatal_error("Cannot find PLTGOT dynamic table tag.");
21900b57cec5SDimitry Andric     if (!DtLocalGotNum)
21910b57cec5SDimitry Andric       report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag.");
21920b57cec5SDimitry Andric     if (!DtGotSym)
21930b57cec5SDimitry Andric       report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag.");
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric     size_t DynSymTotal = DynSyms.size();
21960b57cec5SDimitry Andric     if (*DtGotSym > DynSymTotal)
21970b57cec5SDimitry Andric       reportError("MIPS_GOTSYM exceeds a number of dynamic symbols");
21980b57cec5SDimitry Andric 
21990b57cec5SDimitry Andric     GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot);
22000b57cec5SDimitry Andric     if (!GotSec)
22010b57cec5SDimitry Andric       reportError("There is no not empty GOT section at 0x" +
22020b57cec5SDimitry Andric                   Twine::utohexstr(*DtPltGot));
22030b57cec5SDimitry Andric 
22040b57cec5SDimitry Andric     LocalNum = *DtLocalGotNum;
22050b57cec5SDimitry Andric     GlobalNum = DynSymTotal - *DtGotSym;
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric     ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
22080b57cec5SDimitry Andric     GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
22090b57cec5SDimitry Andric                          Content.size() / sizeof(Entry));
22100b57cec5SDimitry Andric     GotDynSyms = DynSyms.drop_front(*DtGotSym);
22110b57cec5SDimitry Andric   }
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric   // Find PLT section.
22140b57cec5SDimitry Andric   if (DtMipsPltGot || DtJmpRel) {
22150b57cec5SDimitry Andric     if (!DtMipsPltGot)
22160b57cec5SDimitry Andric       report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag.");
22170b57cec5SDimitry Andric     if (!DtJmpRel)
22180b57cec5SDimitry Andric       report_fatal_error("Cannot find JMPREL dynamic table tag.");
22190b57cec5SDimitry Andric 
22200b57cec5SDimitry Andric     PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
22210b57cec5SDimitry Andric     if (!PltSec)
22220b57cec5SDimitry Andric       report_fatal_error("There is no not empty PLTGOT section at 0x " +
22230b57cec5SDimitry Andric                          Twine::utohexstr(*DtMipsPltGot));
22240b57cec5SDimitry Andric 
22250b57cec5SDimitry Andric     PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel);
22260b57cec5SDimitry Andric     if (!PltRelSec)
22270b57cec5SDimitry Andric       report_fatal_error("There is no not empty RELPLT section at 0x" +
22280b57cec5SDimitry Andric                          Twine::utohexstr(*DtJmpRel));
22290b57cec5SDimitry Andric 
22300b57cec5SDimitry Andric     ArrayRef<uint8_t> PltContent =
22310b57cec5SDimitry Andric         unwrapOrError(Obj->getSectionContents(PltSec));
22320b57cec5SDimitry Andric     PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()),
22330b57cec5SDimitry Andric                          PltContent.size() / sizeof(Entry));
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric     PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link));
22360b57cec5SDimitry Andric     PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable));
22370b57cec5SDimitry Andric   }
22380b57cec5SDimitry Andric }
22390b57cec5SDimitry Andric 
22400b57cec5SDimitry Andric template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const {
22410b57cec5SDimitry Andric   return GotSec->sh_addr + 0x7ff0;
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric template <class ELFT>
22450b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry *
22460b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotLazyResolver() const {
22470b57cec5SDimitry Andric   return LocalNum > 0 ? &GotEntries[0] : nullptr;
22480b57cec5SDimitry Andric }
22490b57cec5SDimitry Andric 
22500b57cec5SDimitry Andric template <class ELFT>
22510b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry *
22520b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotModulePointer() const {
22530b57cec5SDimitry Andric   if (LocalNum < 2)
22540b57cec5SDimitry Andric     return nullptr;
22550b57cec5SDimitry Andric   const Entry &E = GotEntries[1];
22560b57cec5SDimitry Andric   if ((E >> (sizeof(Entry) * 8 - 1)) == 0)
22570b57cec5SDimitry Andric     return nullptr;
22580b57cec5SDimitry Andric   return &E;
22590b57cec5SDimitry Andric }
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric template <class ELFT>
22620b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries
22630b57cec5SDimitry Andric MipsGOTParser<ELFT>::getLocalEntries() const {
22640b57cec5SDimitry Andric   size_t Skip = getGotModulePointer() ? 2 : 1;
22650b57cec5SDimitry Andric   if (LocalNum - Skip <= 0)
22660b57cec5SDimitry Andric     return Entries();
22670b57cec5SDimitry Andric   return GotEntries.slice(Skip, LocalNum - Skip);
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric 
22700b57cec5SDimitry Andric template <class ELFT>
22710b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries
22720b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGlobalEntries() const {
22730b57cec5SDimitry Andric   if (GlobalNum == 0)
22740b57cec5SDimitry Andric     return Entries();
22750b57cec5SDimitry Andric   return GotEntries.slice(LocalNum, GlobalNum);
22760b57cec5SDimitry Andric }
22770b57cec5SDimitry Andric 
22780b57cec5SDimitry Andric template <class ELFT>
22790b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries
22800b57cec5SDimitry Andric MipsGOTParser<ELFT>::getOtherEntries() const {
22810b57cec5SDimitry Andric   size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;
22820b57cec5SDimitry Andric   if (OtherNum == 0)
22830b57cec5SDimitry Andric     return Entries();
22840b57cec5SDimitry Andric   return GotEntries.slice(LocalNum + GlobalNum, OtherNum);
22850b57cec5SDimitry Andric }
22860b57cec5SDimitry Andric 
22870b57cec5SDimitry Andric template <class ELFT>
22880b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const {
22890b57cec5SDimitry Andric   int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
22900b57cec5SDimitry Andric   return GotSec->sh_addr + Offset;
22910b57cec5SDimitry Andric }
22920b57cec5SDimitry Andric 
22930b57cec5SDimitry Andric template <class ELFT>
22940b57cec5SDimitry Andric int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const {
22950b57cec5SDimitry Andric   int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
22960b57cec5SDimitry Andric   return Offset - 0x7ff0;
22970b57cec5SDimitry Andric }
22980b57cec5SDimitry Andric 
22990b57cec5SDimitry Andric template <class ELFT>
23000b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym *
23010b57cec5SDimitry Andric MipsGOTParser<ELFT>::getGotSym(const Entry *E) const {
23020b57cec5SDimitry Andric   int64_t Offset = std::distance(GotEntries.data(), E);
23030b57cec5SDimitry Andric   return &GotDynSyms[Offset - LocalNum];
23040b57cec5SDimitry Andric }
23050b57cec5SDimitry Andric 
23060b57cec5SDimitry Andric template <class ELFT>
23070b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry *
23080b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltLazyResolver() const {
23090b57cec5SDimitry Andric   return PltEntries.empty() ? nullptr : &PltEntries[0];
23100b57cec5SDimitry Andric }
23110b57cec5SDimitry Andric 
23120b57cec5SDimitry Andric template <class ELFT>
23130b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Entry *
23140b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltModulePointer() const {
23150b57cec5SDimitry Andric   return PltEntries.size() < 2 ? nullptr : &PltEntries[1];
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric template <class ELFT>
23190b57cec5SDimitry Andric typename MipsGOTParser<ELFT>::Entries
23200b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltEntries() const {
23210b57cec5SDimitry Andric   if (PltEntries.size() <= 2)
23220b57cec5SDimitry Andric     return Entries();
23230b57cec5SDimitry Andric   return PltEntries.slice(2, PltEntries.size() - 2);
23240b57cec5SDimitry Andric }
23250b57cec5SDimitry Andric 
23260b57cec5SDimitry Andric template <class ELFT>
23270b57cec5SDimitry Andric uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const {
23280b57cec5SDimitry Andric   int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);
23290b57cec5SDimitry Andric   return PltSec->sh_addr + Offset;
23300b57cec5SDimitry Andric }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric template <class ELFT>
23330b57cec5SDimitry Andric const typename MipsGOTParser<ELFT>::Elf_Sym *
23340b57cec5SDimitry Andric MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {
23350b57cec5SDimitry Andric   int64_t Offset = std::distance(getPltEntries().data(), E);
23360b57cec5SDimitry Andric   if (PltRelSec->sh_type == ELF::SHT_REL) {
23370b57cec5SDimitry Andric     Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec));
23380b57cec5SDimitry Andric     return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
23390b57cec5SDimitry Andric   } else {
23400b57cec5SDimitry Andric     Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec));
23410b57cec5SDimitry Andric     return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
23420b57cec5SDimitry Andric   }
23430b57cec5SDimitry Andric }
23440b57cec5SDimitry Andric 
23450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
23460b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
23470b57cec5SDimitry Andric   if (Obj->getHeader()->e_machine != EM_MIPS)
23480b57cec5SDimitry Andric     reportError("MIPS PLT GOT is available for MIPS targets only");
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric   MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols());
23510b57cec5SDimitry Andric   if (Parser.hasGot())
23520b57cec5SDimitry Andric     ELFDumperStyle->printMipsGOT(Parser);
23530b57cec5SDimitry Andric   if (Parser.hasPlt())
23540b57cec5SDimitry Andric     ELFDumperStyle->printMipsPLT(Parser);
23550b57cec5SDimitry Andric }
23560b57cec5SDimitry Andric 
23570b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
23580b57cec5SDimitry Andric   {"None",                    Mips::AFL_EXT_NONE},
23590b57cec5SDimitry Andric   {"Broadcom SB-1",           Mips::AFL_EXT_SB1},
23600b57cec5SDimitry Andric   {"Cavium Networks Octeon",  Mips::AFL_EXT_OCTEON},
23610b57cec5SDimitry Andric   {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2},
23620b57cec5SDimitry Andric   {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP},
23630b57cec5SDimitry Andric   {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3},
23640b57cec5SDimitry Andric   {"LSI R4010",               Mips::AFL_EXT_4010},
23650b57cec5SDimitry Andric   {"Loongson 2E",             Mips::AFL_EXT_LOONGSON_2E},
23660b57cec5SDimitry Andric   {"Loongson 2F",             Mips::AFL_EXT_LOONGSON_2F},
23670b57cec5SDimitry Andric   {"Loongson 3A",             Mips::AFL_EXT_LOONGSON_3A},
23680b57cec5SDimitry Andric   {"MIPS R4650",              Mips::AFL_EXT_4650},
23690b57cec5SDimitry Andric   {"MIPS R5900",              Mips::AFL_EXT_5900},
23700b57cec5SDimitry Andric   {"MIPS R10000",             Mips::AFL_EXT_10000},
23710b57cec5SDimitry Andric   {"NEC VR4100",              Mips::AFL_EXT_4100},
23720b57cec5SDimitry Andric   {"NEC VR4111/VR4181",       Mips::AFL_EXT_4111},
23730b57cec5SDimitry Andric   {"NEC VR4120",              Mips::AFL_EXT_4120},
23740b57cec5SDimitry Andric   {"NEC VR5400",              Mips::AFL_EXT_5400},
23750b57cec5SDimitry Andric   {"NEC VR5500",              Mips::AFL_EXT_5500},
23760b57cec5SDimitry Andric   {"RMI Xlr",                 Mips::AFL_EXT_XLR},
23770b57cec5SDimitry Andric   {"Toshiba R3900",           Mips::AFL_EXT_3900}
23780b57cec5SDimitry Andric };
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsASEFlags[] = {
23810b57cec5SDimitry Andric   {"DSP",                Mips::AFL_ASE_DSP},
23820b57cec5SDimitry Andric   {"DSPR2",              Mips::AFL_ASE_DSPR2},
23830b57cec5SDimitry Andric   {"Enhanced VA Scheme", Mips::AFL_ASE_EVA},
23840b57cec5SDimitry Andric   {"MCU",                Mips::AFL_ASE_MCU},
23850b57cec5SDimitry Andric   {"MDMX",               Mips::AFL_ASE_MDMX},
23860b57cec5SDimitry Andric   {"MIPS-3D",            Mips::AFL_ASE_MIPS3D},
23870b57cec5SDimitry Andric   {"MT",                 Mips::AFL_ASE_MT},
23880b57cec5SDimitry Andric   {"SmartMIPS",          Mips::AFL_ASE_SMARTMIPS},
23890b57cec5SDimitry Andric   {"VZ",                 Mips::AFL_ASE_VIRT},
23900b57cec5SDimitry Andric   {"MSA",                Mips::AFL_ASE_MSA},
23910b57cec5SDimitry Andric   {"MIPS16",             Mips::AFL_ASE_MIPS16},
23920b57cec5SDimitry Andric   {"microMIPS",          Mips::AFL_ASE_MICROMIPS},
23930b57cec5SDimitry Andric   {"XPA",                Mips::AFL_ASE_XPA},
23940b57cec5SDimitry Andric   {"CRC",                Mips::AFL_ASE_CRC},
23950b57cec5SDimitry Andric   {"GINV",               Mips::AFL_ASE_GINV},
23960b57cec5SDimitry Andric };
23970b57cec5SDimitry Andric 
23980b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFpABIType[] = {
23990b57cec5SDimitry Andric   {"Hard or soft float",                  Mips::Val_GNU_MIPS_ABI_FP_ANY},
24000b57cec5SDimitry Andric   {"Hard float (double precision)",       Mips::Val_GNU_MIPS_ABI_FP_DOUBLE},
24010b57cec5SDimitry Andric   {"Hard float (single precision)",       Mips::Val_GNU_MIPS_ABI_FP_SINGLE},
24020b57cec5SDimitry Andric   {"Soft float",                          Mips::Val_GNU_MIPS_ABI_FP_SOFT},
24030b57cec5SDimitry Andric   {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)",
24040b57cec5SDimitry Andric    Mips::Val_GNU_MIPS_ABI_FP_OLD_64},
24050b57cec5SDimitry Andric   {"Hard float (32-bit CPU, Any FPU)",    Mips::Val_GNU_MIPS_ABI_FP_XX},
24060b57cec5SDimitry Andric   {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64},
24070b57cec5SDimitry Andric   {"Hard float compat (32-bit CPU, 64-bit FPU)",
24080b57cec5SDimitry Andric    Mips::Val_GNU_MIPS_ABI_FP_64A}
24090b57cec5SDimitry Andric };
24100b57cec5SDimitry Andric 
24110b57cec5SDimitry Andric static const EnumEntry<unsigned> ElfMipsFlags1[] {
24120b57cec5SDimitry Andric   {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG},
24130b57cec5SDimitry Andric };
24140b57cec5SDimitry Andric 
24150b57cec5SDimitry Andric static int getMipsRegisterSize(uint8_t Flag) {
24160b57cec5SDimitry Andric   switch (Flag) {
24170b57cec5SDimitry Andric   case Mips::AFL_REG_NONE:
24180b57cec5SDimitry Andric     return 0;
24190b57cec5SDimitry Andric   case Mips::AFL_REG_32:
24200b57cec5SDimitry Andric     return 32;
24210b57cec5SDimitry Andric   case Mips::AFL_REG_64:
24220b57cec5SDimitry Andric     return 64;
24230b57cec5SDimitry Andric   case Mips::AFL_REG_128:
24240b57cec5SDimitry Andric     return 128;
24250b57cec5SDimitry Andric   default:
24260b57cec5SDimitry Andric     return -1;
24270b57cec5SDimitry Andric   }
24280b57cec5SDimitry Andric }
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() {
24310b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
24320b57cec5SDimitry Andric   const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags");
24330b57cec5SDimitry Andric   if (!Shdr) {
24340b57cec5SDimitry Andric     W.startLine() << "There is no .MIPS.abiflags section in the file.\n";
24350b57cec5SDimitry Andric     return;
24360b57cec5SDimitry Andric   }
24370b57cec5SDimitry Andric   ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
24380b57cec5SDimitry Andric   if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
24390b57cec5SDimitry Andric     W.startLine() << "The .MIPS.abiflags section has a wrong size.\n";
24400b57cec5SDimitry Andric     return;
24410b57cec5SDimitry Andric   }
24420b57cec5SDimitry Andric 
24430b57cec5SDimitry Andric   auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data());
24440b57cec5SDimitry Andric 
24450b57cec5SDimitry Andric   raw_ostream &OS = W.getOStream();
24460b57cec5SDimitry Andric   DictScope GS(W, "MIPS ABI Flags");
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric   W.printNumber("Version", Flags->version);
24490b57cec5SDimitry Andric   W.startLine() << "ISA: ";
24500b57cec5SDimitry Andric   if (Flags->isa_rev <= 1)
24510b57cec5SDimitry Andric     OS << format("MIPS%u", Flags->isa_level);
24520b57cec5SDimitry Andric   else
24530b57cec5SDimitry Andric     OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
24540b57cec5SDimitry Andric   OS << "\n";
24550b57cec5SDimitry Andric   W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType));
24560b57cec5SDimitry Andric   W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags));
24570b57cec5SDimitry Andric   W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType));
24580b57cec5SDimitry Andric   W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
24590b57cec5SDimitry Andric   W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
24600b57cec5SDimitry Andric   W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
24610b57cec5SDimitry Andric   W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
24620b57cec5SDimitry Andric   W.printHex("Flags 2", Flags->flags2);
24630b57cec5SDimitry Andric }
24640b57cec5SDimitry Andric 
24650b57cec5SDimitry Andric template <class ELFT>
24660b57cec5SDimitry Andric static void printMipsReginfoData(ScopedPrinter &W,
24670b57cec5SDimitry Andric                                  const Elf_Mips_RegInfo<ELFT> &Reginfo) {
24680b57cec5SDimitry Andric   W.printHex("GP", Reginfo.ri_gp_value);
24690b57cec5SDimitry Andric   W.printHex("General Mask", Reginfo.ri_gprmask);
24700b57cec5SDimitry Andric   W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]);
24710b57cec5SDimitry Andric   W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]);
24720b57cec5SDimitry Andric   W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]);
24730b57cec5SDimitry Andric   W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]);
24740b57cec5SDimitry Andric }
24750b57cec5SDimitry Andric 
24760b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
24770b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
24780b57cec5SDimitry Andric   const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo");
24790b57cec5SDimitry Andric   if (!Shdr) {
24800b57cec5SDimitry Andric     W.startLine() << "There is no .reginfo section in the file.\n";
24810b57cec5SDimitry Andric     return;
24820b57cec5SDimitry Andric   }
24830b57cec5SDimitry Andric   ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
24840b57cec5SDimitry Andric   if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
24850b57cec5SDimitry Andric     W.startLine() << "The .reginfo section has a wrong size.\n";
24860b57cec5SDimitry Andric     return;
24870b57cec5SDimitry Andric   }
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric   DictScope GS(W, "MIPS RegInfo");
24900b57cec5SDimitry Andric   auto *Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Sec.data());
24910b57cec5SDimitry Andric   printMipsReginfoData(W, *Reginfo);
24920b57cec5SDimitry Andric }
24930b57cec5SDimitry Andric 
24940b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
24950b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
24960b57cec5SDimitry Andric   const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.options");
24970b57cec5SDimitry Andric   if (!Shdr) {
24980b57cec5SDimitry Andric     W.startLine() << "There is no .MIPS.options section in the file.\n";
24990b57cec5SDimitry Andric     return;
25000b57cec5SDimitry Andric   }
25010b57cec5SDimitry Andric 
25020b57cec5SDimitry Andric   DictScope GS(W, "MIPS Options");
25030b57cec5SDimitry Andric 
25040b57cec5SDimitry Andric   ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
25050b57cec5SDimitry Andric   while (!Sec.empty()) {
25060b57cec5SDimitry Andric     if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) {
25070b57cec5SDimitry Andric       W.startLine() << "The .MIPS.options section has a wrong size.\n";
25080b57cec5SDimitry Andric       return;
25090b57cec5SDimitry Andric     }
25100b57cec5SDimitry Andric     auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(Sec.data());
25110b57cec5SDimitry Andric     DictScope GS(W, getElfMipsOptionsOdkType(O->kind));
25120b57cec5SDimitry Andric     switch (O->kind) {
25130b57cec5SDimitry Andric     case ODK_REGINFO:
25140b57cec5SDimitry Andric       printMipsReginfoData(W, O->getRegInfo());
25150b57cec5SDimitry Andric       break;
25160b57cec5SDimitry Andric     default:
25170b57cec5SDimitry Andric       W.startLine() << "Unsupported MIPS options tag.\n";
25180b57cec5SDimitry Andric       break;
25190b57cec5SDimitry Andric     }
25200b57cec5SDimitry Andric     Sec = Sec.slice(O->size);
25210b57cec5SDimitry Andric   }
25220b57cec5SDimitry Andric }
25230b57cec5SDimitry Andric 
25240b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
25250b57cec5SDimitry Andric   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
25260b57cec5SDimitry Andric   const Elf_Shdr *StackMapSection = nullptr;
25270b57cec5SDimitry Andric   for (const auto &Sec : unwrapOrError(Obj->sections())) {
25280b57cec5SDimitry Andric     StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
25290b57cec5SDimitry Andric     if (Name == ".llvm_stackmaps") {
25300b57cec5SDimitry Andric       StackMapSection = &Sec;
25310b57cec5SDimitry Andric       break;
25320b57cec5SDimitry Andric     }
25330b57cec5SDimitry Andric   }
25340b57cec5SDimitry Andric 
25350b57cec5SDimitry Andric   if (!StackMapSection)
25360b57cec5SDimitry Andric     return;
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   ArrayRef<uint8_t> StackMapContentsArray =
25390b57cec5SDimitry Andric       unwrapOrError(Obj->getSectionContents(StackMapSection));
25400b57cec5SDimitry Andric 
25410b57cec5SDimitry Andric   prettyPrintStackMap(
25420b57cec5SDimitry Andric       W, StackMapParser<ELFT::TargetEndianness>(StackMapContentsArray));
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric 
25450b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printGroupSections() {
25460b57cec5SDimitry Andric   ELFDumperStyle->printGroupSections(ObjF->getELFFile());
25470b57cec5SDimitry Andric }
25480b57cec5SDimitry Andric 
25490b57cec5SDimitry Andric template <class ELFT> void ELFDumper<ELFT>::printAddrsig() {
25500b57cec5SDimitry Andric   ELFDumperStyle->printAddrsig(ObjF->getELFFile());
25510b57cec5SDimitry Andric }
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
25540b57cec5SDimitry Andric                                StringRef Str2) {
25550b57cec5SDimitry Andric   OS.PadToColumn(2u);
25560b57cec5SDimitry Andric   OS << Str1;
25570b57cec5SDimitry Andric   OS.PadToColumn(37u);
25580b57cec5SDimitry Andric   OS << Str2 << "\n";
25590b57cec5SDimitry Andric   OS.flush();
25600b57cec5SDimitry Andric }
25610b57cec5SDimitry Andric 
25620b57cec5SDimitry Andric template <class ELFT>
25630b57cec5SDimitry Andric static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) {
25640b57cec5SDimitry Andric   const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
25650b57cec5SDimitry Andric   if (ElfHeader->e_shnum != 0)
25660b57cec5SDimitry Andric     return to_string(ElfHeader->e_shnum);
25670b57cec5SDimitry Andric 
25680b57cec5SDimitry Andric   ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
25690b57cec5SDimitry Andric   if (Arr.empty())
25700b57cec5SDimitry Andric     return "0";
25710b57cec5SDimitry Andric   return "0 (" + to_string(Arr[0].sh_size) + ")";
25720b57cec5SDimitry Andric }
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric template <class ELFT>
25750b57cec5SDimitry Andric static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) {
25760b57cec5SDimitry Andric   const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
25770b57cec5SDimitry Andric   if (ElfHeader->e_shstrndx != SHN_XINDEX)
25780b57cec5SDimitry Andric     return to_string(ElfHeader->e_shstrndx);
25790b57cec5SDimitry Andric 
25800b57cec5SDimitry Andric   ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
25810b57cec5SDimitry Andric   if (Arr.empty())
25820b57cec5SDimitry Andric     return "65535 (corrupt: out of range)";
25830b57cec5SDimitry Andric   return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) +
25840b57cec5SDimitry Andric          ")";
25850b57cec5SDimitry Andric }
25860b57cec5SDimitry Andric 
25870b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
25880b57cec5SDimitry Andric   const Elf_Ehdr *e = Obj->getHeader();
25890b57cec5SDimitry Andric   OS << "ELF Header:\n";
25900b57cec5SDimitry Andric   OS << "  Magic:  ";
25910b57cec5SDimitry Andric   std::string Str;
25920b57cec5SDimitry Andric   for (int i = 0; i < ELF::EI_NIDENT; i++)
25930b57cec5SDimitry Andric     OS << format(" %02x", static_cast<int>(e->e_ident[i]));
25940b57cec5SDimitry Andric   OS << "\n";
25950b57cec5SDimitry Andric   Str = printEnum(e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass));
25960b57cec5SDimitry Andric   printFields(OS, "Class:", Str);
25970b57cec5SDimitry Andric   Str = printEnum(e->e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding));
25980b57cec5SDimitry Andric   printFields(OS, "Data:", Str);
25990b57cec5SDimitry Andric   OS.PadToColumn(2u);
26000b57cec5SDimitry Andric   OS << "Version:";
26010b57cec5SDimitry Andric   OS.PadToColumn(37u);
26020b57cec5SDimitry Andric   OS << to_hexString(e->e_ident[ELF::EI_VERSION]);
26030b57cec5SDimitry Andric   if (e->e_version == ELF::EV_CURRENT)
26040b57cec5SDimitry Andric     OS << " (current)";
26050b57cec5SDimitry Andric   OS << "\n";
26060b57cec5SDimitry Andric   Str = printEnum(e->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI));
26070b57cec5SDimitry Andric   printFields(OS, "OS/ABI:", Str);
26080b57cec5SDimitry Andric   Str = "0x" + to_hexString(e->e_ident[ELF::EI_ABIVERSION]);
26090b57cec5SDimitry Andric   printFields(OS, "ABI Version:", Str);
26100b57cec5SDimitry Andric   Str = printEnum(e->e_type, makeArrayRef(ElfObjectFileType));
26110b57cec5SDimitry Andric   printFields(OS, "Type:", Str);
26120b57cec5SDimitry Andric   Str = printEnum(e->e_machine, makeArrayRef(ElfMachineType));
26130b57cec5SDimitry Andric   printFields(OS, "Machine:", Str);
26140b57cec5SDimitry Andric   Str = "0x" + to_hexString(e->e_version);
26150b57cec5SDimitry Andric   printFields(OS, "Version:", Str);
26160b57cec5SDimitry Andric   Str = "0x" + to_hexString(e->e_entry);
26170b57cec5SDimitry Andric   printFields(OS, "Entry point address:", Str);
26180b57cec5SDimitry Andric   Str = to_string(e->e_phoff) + " (bytes into file)";
26190b57cec5SDimitry Andric   printFields(OS, "Start of program headers:", Str);
26200b57cec5SDimitry Andric   Str = to_string(e->e_shoff) + " (bytes into file)";
26210b57cec5SDimitry Andric   printFields(OS, "Start of section headers:", Str);
26220b57cec5SDimitry Andric   std::string ElfFlags;
26230b57cec5SDimitry Andric   if (e->e_machine == EM_MIPS)
26240b57cec5SDimitry Andric     ElfFlags =
26250b57cec5SDimitry Andric         printFlags(e->e_flags, makeArrayRef(ElfHeaderMipsFlags),
26260b57cec5SDimitry Andric                    unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
26270b57cec5SDimitry Andric                    unsigned(ELF::EF_MIPS_MACH));
26280b57cec5SDimitry Andric   else if (e->e_machine == EM_RISCV)
26290b57cec5SDimitry Andric     ElfFlags = printFlags(e->e_flags, makeArrayRef(ElfHeaderRISCVFlags));
26300b57cec5SDimitry Andric   Str = "0x" + to_hexString(e->e_flags);
26310b57cec5SDimitry Andric   if (!ElfFlags.empty())
26320b57cec5SDimitry Andric     Str = Str + ", " + ElfFlags;
26330b57cec5SDimitry Andric   printFields(OS, "Flags:", Str);
26340b57cec5SDimitry Andric   Str = to_string(e->e_ehsize) + " (bytes)";
26350b57cec5SDimitry Andric   printFields(OS, "Size of this header:", Str);
26360b57cec5SDimitry Andric   Str = to_string(e->e_phentsize) + " (bytes)";
26370b57cec5SDimitry Andric   printFields(OS, "Size of program headers:", Str);
26380b57cec5SDimitry Andric   Str = to_string(e->e_phnum);
26390b57cec5SDimitry Andric   printFields(OS, "Number of program headers:", Str);
26400b57cec5SDimitry Andric   Str = to_string(e->e_shentsize) + " (bytes)";
26410b57cec5SDimitry Andric   printFields(OS, "Size of section headers:", Str);
26420b57cec5SDimitry Andric   Str = getSectionHeadersNumString(Obj);
26430b57cec5SDimitry Andric   printFields(OS, "Number of section headers:", Str);
26440b57cec5SDimitry Andric   Str = getSectionHeaderTableIndexString(Obj);
26450b57cec5SDimitry Andric   printFields(OS, "Section header string table index:", Str);
26460b57cec5SDimitry Andric }
26470b57cec5SDimitry Andric 
26480b57cec5SDimitry Andric namespace {
26490b57cec5SDimitry Andric struct GroupMember {
26500b57cec5SDimitry Andric   StringRef Name;
26510b57cec5SDimitry Andric   uint64_t Index;
26520b57cec5SDimitry Andric };
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric struct GroupSection {
26550b57cec5SDimitry Andric   StringRef Name;
26560b57cec5SDimitry Andric   std::string Signature;
26570b57cec5SDimitry Andric   uint64_t ShName;
26580b57cec5SDimitry Andric   uint64_t Index;
26590b57cec5SDimitry Andric   uint32_t Link;
26600b57cec5SDimitry Andric   uint32_t Info;
26610b57cec5SDimitry Andric   uint32_t Type;
26620b57cec5SDimitry Andric   std::vector<GroupMember> Members;
26630b57cec5SDimitry Andric };
26640b57cec5SDimitry Andric 
26650b57cec5SDimitry Andric template <class ELFT>
26660b57cec5SDimitry Andric std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
26670b57cec5SDimitry Andric   using Elf_Shdr = typename ELFT::Shdr;
26680b57cec5SDimitry Andric   using Elf_Sym = typename ELFT::Sym;
26690b57cec5SDimitry Andric   using Elf_Word = typename ELFT::Word;
26700b57cec5SDimitry Andric 
26710b57cec5SDimitry Andric   std::vector<GroupSection> Ret;
26720b57cec5SDimitry Andric   uint64_t I = 0;
26730b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
26740b57cec5SDimitry Andric     ++I;
26750b57cec5SDimitry Andric     if (Sec.sh_type != ELF::SHT_GROUP)
26760b57cec5SDimitry Andric       continue;
26770b57cec5SDimitry Andric 
26780b57cec5SDimitry Andric     const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
26790b57cec5SDimitry Andric     StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
26800b57cec5SDimitry Andric     const Elf_Sym *Sym =
26810b57cec5SDimitry Andric         unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
26820b57cec5SDimitry Andric     auto Data =
26830b57cec5SDimitry Andric         unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
26840b57cec5SDimitry Andric 
26850b57cec5SDimitry Andric     StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
26860b57cec5SDimitry Andric     StringRef Signature = StrTable.data() + Sym->st_name;
26870b57cec5SDimitry Andric     Ret.push_back({Name,
26880b57cec5SDimitry Andric                    maybeDemangle(Signature),
26890b57cec5SDimitry Andric                    Sec.sh_name,
26900b57cec5SDimitry Andric                    I - 1,
26910b57cec5SDimitry Andric                    Sec.sh_link,
26920b57cec5SDimitry Andric                    Sec.sh_info,
26930b57cec5SDimitry Andric                    Data[0],
26940b57cec5SDimitry Andric                    {}});
26950b57cec5SDimitry Andric 
26960b57cec5SDimitry Andric     std::vector<GroupMember> &GM = Ret.back().Members;
26970b57cec5SDimitry Andric     for (uint32_t Ndx : Data.slice(1)) {
26980b57cec5SDimitry Andric       auto Sec = unwrapOrError(Obj->getSection(Ndx));
26990b57cec5SDimitry Andric       const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
27000b57cec5SDimitry Andric       GM.push_back({Name, Ndx});
27010b57cec5SDimitry Andric     }
27020b57cec5SDimitry Andric   }
27030b57cec5SDimitry Andric   return Ret;
27040b57cec5SDimitry Andric }
27050b57cec5SDimitry Andric 
27060b57cec5SDimitry Andric DenseMap<uint64_t, const GroupSection *>
27070b57cec5SDimitry Andric mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
27080b57cec5SDimitry Andric   DenseMap<uint64_t, const GroupSection *> Ret;
27090b57cec5SDimitry Andric   for (const GroupSection &G : Groups)
27100b57cec5SDimitry Andric     for (const GroupMember &GM : G.Members)
27110b57cec5SDimitry Andric       Ret.insert({GM.Index, &G});
27120b57cec5SDimitry Andric   return Ret;
27130b57cec5SDimitry Andric }
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric } // namespace
27160b57cec5SDimitry Andric 
27170b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
27180b57cec5SDimitry Andric   std::vector<GroupSection> V = getGroups<ELFT>(Obj);
27190b57cec5SDimitry Andric   DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
27200b57cec5SDimitry Andric   for (const GroupSection &G : V) {
27210b57cec5SDimitry Andric     OS << "\n"
27220b57cec5SDimitry Andric        << getGroupType(G.Type) << " group section ["
27230b57cec5SDimitry Andric        << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature
27240b57cec5SDimitry Andric        << "] contains " << G.Members.size() << " sections:\n"
27250b57cec5SDimitry Andric        << "   [Index]    Name\n";
27260b57cec5SDimitry Andric     for (const GroupMember &GM : G.Members) {
27270b57cec5SDimitry Andric       const GroupSection *MainGroup = Map[GM.Index];
27280b57cec5SDimitry Andric       if (MainGroup != &G) {
27290b57cec5SDimitry Andric         OS.flush();
27300b57cec5SDimitry Andric         errs() << "Error: section [" << format_decimal(GM.Index, 5)
27310b57cec5SDimitry Andric                << "] in group section [" << format_decimal(G.Index, 5)
27320b57cec5SDimitry Andric                << "] already in group section ["
27330b57cec5SDimitry Andric                << format_decimal(MainGroup->Index, 5) << "]";
27340b57cec5SDimitry Andric         errs().flush();
27350b57cec5SDimitry Andric         continue;
27360b57cec5SDimitry Andric       }
27370b57cec5SDimitry Andric       OS << "   [" << format_decimal(GM.Index, 5) << "]   " << GM.Name << "\n";
27380b57cec5SDimitry Andric     }
27390b57cec5SDimitry Andric   }
27400b57cec5SDimitry Andric 
27410b57cec5SDimitry Andric   if (V.empty())
27420b57cec5SDimitry Andric     OS << "There are no section groups in this file.\n";
27430b57cec5SDimitry Andric }
27440b57cec5SDimitry Andric 
27450b57cec5SDimitry Andric template <class ELFT>
27460b57cec5SDimitry Andric void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
27470b57cec5SDimitry Andric                                      const Elf_Rela &R, bool IsRela) {
27480b57cec5SDimitry Andric   const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab));
27490b57cec5SDimitry Andric   std::string TargetName;
27500b57cec5SDimitry Andric   if (Sym && Sym->getType() == ELF::STT_SECTION) {
27510b57cec5SDimitry Andric     const Elf_Shdr *Sec = unwrapOrError(
27520b57cec5SDimitry Andric         Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
27530b57cec5SDimitry Andric     TargetName = unwrapOrError(Obj->getSectionName(Sec));
27540b57cec5SDimitry Andric   } else if (Sym) {
27550b57cec5SDimitry Andric     StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
27560b57cec5SDimitry Andric     TargetName = this->dumper()->getFullSymbolName(
27570b57cec5SDimitry Andric         Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */);
27580b57cec5SDimitry Andric   }
27590b57cec5SDimitry Andric   printRelocation(Obj, Sym, TargetName, R, IsRela);
27600b57cec5SDimitry Andric }
27610b57cec5SDimitry Andric 
27620b57cec5SDimitry Andric template <class ELFT>
27630b57cec5SDimitry Andric void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Sym *Sym,
27640b57cec5SDimitry Andric                                      StringRef SymbolName, const Elf_Rela &R,
27650b57cec5SDimitry Andric                                      bool IsRela) {
27660b57cec5SDimitry Andric   // First two fields are bit width dependent. The rest of them are fixed width.
27670b57cec5SDimitry Andric   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
27680b57cec5SDimitry Andric   Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias};
27690b57cec5SDimitry Andric   unsigned Width = ELFT::Is64Bits ? 16 : 8;
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric   Fields[0].Str = to_string(format_hex_no_prefix(R.r_offset, Width));
27720b57cec5SDimitry Andric   Fields[1].Str = to_string(format_hex_no_prefix(R.r_info, Width));
27730b57cec5SDimitry Andric 
27740b57cec5SDimitry Andric   SmallString<32> RelocName;
27750b57cec5SDimitry Andric   Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName);
27760b57cec5SDimitry Andric   Fields[2].Str = RelocName.c_str();
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric   if (Sym && (!SymbolName.empty() || Sym->getValue() != 0))
27790b57cec5SDimitry Andric     Fields[3].Str = to_string(format_hex_no_prefix(Sym->getValue(), Width));
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric   Fields[4].Str = SymbolName;
27820b57cec5SDimitry Andric   for (const Field &F : Fields)
27830b57cec5SDimitry Andric     printField(F);
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric   std::string Addend;
27860b57cec5SDimitry Andric   if (IsRela) {
27870b57cec5SDimitry Andric     int64_t RelAddend = R.r_addend;
27880b57cec5SDimitry Andric     if (!SymbolName.empty()) {
27890b57cec5SDimitry Andric       if (R.r_addend < 0) {
27900b57cec5SDimitry Andric         Addend = " - ";
27910b57cec5SDimitry Andric         RelAddend = std::abs(RelAddend);
27920b57cec5SDimitry Andric       } else
27930b57cec5SDimitry Andric         Addend = " + ";
27940b57cec5SDimitry Andric     }
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric     Addend += to_hexString(RelAddend, false);
27970b57cec5SDimitry Andric   }
27980b57cec5SDimitry Andric   OS << Addend << "\n";
27990b57cec5SDimitry Andric }
28000b57cec5SDimitry Andric 
28010b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) {
28020b57cec5SDimitry Andric   bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
28030b57cec5SDimitry Andric   bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR;
28040b57cec5SDimitry Andric   if (ELFT::Is64Bits)
28050b57cec5SDimitry Andric     OS << "    ";
28060b57cec5SDimitry Andric   else
28070b57cec5SDimitry Andric     OS << " ";
28080b57cec5SDimitry Andric   if (IsRelr && opts::RawRelr)
28090b57cec5SDimitry Andric     OS << "Data  ";
28100b57cec5SDimitry Andric   else
28110b57cec5SDimitry Andric     OS << "Offset";
28120b57cec5SDimitry Andric   if (ELFT::Is64Bits)
28130b57cec5SDimitry Andric     OS << "             Info             Type"
28140b57cec5SDimitry Andric        << "               Symbol's Value  Symbol's Name";
28150b57cec5SDimitry Andric   else
28160b57cec5SDimitry Andric     OS << "     Info    Type                Sym. Value  Symbol's Name";
28170b57cec5SDimitry Andric   if (IsRela)
28180b57cec5SDimitry Andric     OS << " + Addend";
28190b57cec5SDimitry Andric   OS << "\n";
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
28230b57cec5SDimitry Andric   bool HasRelocSections = false;
28240b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
28250b57cec5SDimitry Andric     if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
28260b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL &&
28270b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_ANDROID_RELA &&
28280b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_ANDROID_RELR)
28290b57cec5SDimitry Andric       continue;
28300b57cec5SDimitry Andric     HasRelocSections = true;
28310b57cec5SDimitry Andric     StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
28320b57cec5SDimitry Andric     unsigned Entries = Sec.getEntityCount();
28330b57cec5SDimitry Andric     std::vector<Elf_Rela> AndroidRelas;
28340b57cec5SDimitry Andric     if (Sec.sh_type == ELF::SHT_ANDROID_REL ||
28350b57cec5SDimitry Andric         Sec.sh_type == ELF::SHT_ANDROID_RELA) {
28360b57cec5SDimitry Andric       // Android's packed relocation section needs to be unpacked first
28370b57cec5SDimitry Andric       // to get the actual number of entries.
28380b57cec5SDimitry Andric       AndroidRelas = unwrapOrError(Obj->android_relas(&Sec));
28390b57cec5SDimitry Andric       Entries = AndroidRelas.size();
28400b57cec5SDimitry Andric     }
28410b57cec5SDimitry Andric     std::vector<Elf_Rela> RelrRelas;
28420b57cec5SDimitry Andric     if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
28430b57cec5SDimitry Andric                            Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
28440b57cec5SDimitry Andric       // .relr.dyn relative relocation section needs to be unpacked first
28450b57cec5SDimitry Andric       // to get the actual number of entries.
28460b57cec5SDimitry Andric       Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec));
28470b57cec5SDimitry Andric       RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
28480b57cec5SDimitry Andric       Entries = RelrRelas.size();
28490b57cec5SDimitry Andric     }
28500b57cec5SDimitry Andric     uintX_t Offset = Sec.sh_offset;
28510b57cec5SDimitry Andric     OS << "\nRelocation section '" << Name << "' at offset 0x"
28520b57cec5SDimitry Andric        << to_hexString(Offset, false) << " contains " << Entries
28530b57cec5SDimitry Andric        << " entries:\n";
28540b57cec5SDimitry Andric     printRelocHeader(Sec.sh_type);
28550b57cec5SDimitry Andric     const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
28560b57cec5SDimitry Andric     switch (Sec.sh_type) {
28570b57cec5SDimitry Andric     case ELF::SHT_REL:
28580b57cec5SDimitry Andric       for (const auto &R : unwrapOrError(Obj->rels(&Sec))) {
28590b57cec5SDimitry Andric         Elf_Rela Rela;
28600b57cec5SDimitry Andric         Rela.r_offset = R.r_offset;
28610b57cec5SDimitry Andric         Rela.r_info = R.r_info;
28620b57cec5SDimitry Andric         Rela.r_addend = 0;
28630b57cec5SDimitry Andric         printRelocation(Obj, SymTab, Rela, false);
28640b57cec5SDimitry Andric       }
28650b57cec5SDimitry Andric       break;
28660b57cec5SDimitry Andric     case ELF::SHT_RELA:
28670b57cec5SDimitry Andric       for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
28680b57cec5SDimitry Andric         printRelocation(Obj, SymTab, R, true);
28690b57cec5SDimitry Andric       break;
28700b57cec5SDimitry Andric     case ELF::SHT_RELR:
28710b57cec5SDimitry Andric     case ELF::SHT_ANDROID_RELR:
28720b57cec5SDimitry Andric       if (opts::RawRelr)
28730b57cec5SDimitry Andric         for (const auto &R : unwrapOrError(Obj->relrs(&Sec)))
28740b57cec5SDimitry Andric           OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8))
28750b57cec5SDimitry Andric              << "\n";
28760b57cec5SDimitry Andric       else
28770b57cec5SDimitry Andric         for (const auto &R : RelrRelas)
28780b57cec5SDimitry Andric           printRelocation(Obj, SymTab, R, false);
28790b57cec5SDimitry Andric       break;
28800b57cec5SDimitry Andric     case ELF::SHT_ANDROID_REL:
28810b57cec5SDimitry Andric     case ELF::SHT_ANDROID_RELA:
28820b57cec5SDimitry Andric       for (const auto &R : AndroidRelas)
28830b57cec5SDimitry Andric         printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA);
28840b57cec5SDimitry Andric       break;
28850b57cec5SDimitry Andric     }
28860b57cec5SDimitry Andric   }
28870b57cec5SDimitry Andric   if (!HasRelocSections)
28880b57cec5SDimitry Andric     OS << "\nThere are no relocations in this file.\n";
28890b57cec5SDimitry Andric }
28900b57cec5SDimitry Andric 
28910b57cec5SDimitry Andric // Print the offset of a particular section from anyone of the ranges:
28920b57cec5SDimitry Andric // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER].
28930b57cec5SDimitry Andric // If 'Type' does not fall within any of those ranges, then a string is
28940b57cec5SDimitry Andric // returned as '<unknown>' followed by the type value.
28950b57cec5SDimitry Andric static std::string getSectionTypeOffsetString(unsigned Type) {
28960b57cec5SDimitry Andric   if (Type >= SHT_LOOS && Type <= SHT_HIOS)
28970b57cec5SDimitry Andric     return "LOOS+0x" + to_hexString(Type - SHT_LOOS);
28980b57cec5SDimitry Andric   else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC)
28990b57cec5SDimitry Andric     return "LOPROC+0x" + to_hexString(Type - SHT_LOPROC);
29000b57cec5SDimitry Andric   else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER)
29010b57cec5SDimitry Andric     return "LOUSER+0x" + to_hexString(Type - SHT_LOUSER);
29020b57cec5SDimitry Andric   return "0x" + to_hexString(Type) + ": <unknown>";
29030b57cec5SDimitry Andric }
29040b57cec5SDimitry Andric 
29050b57cec5SDimitry Andric static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
29060b57cec5SDimitry Andric   using namespace ELF;
29070b57cec5SDimitry Andric 
29080b57cec5SDimitry Andric   switch (Arch) {
29090b57cec5SDimitry Andric   case EM_ARM:
29100b57cec5SDimitry Andric     switch (Type) {
29110b57cec5SDimitry Andric     case SHT_ARM_EXIDX:
29120b57cec5SDimitry Andric       return "ARM_EXIDX";
29130b57cec5SDimitry Andric     case SHT_ARM_PREEMPTMAP:
29140b57cec5SDimitry Andric       return "ARM_PREEMPTMAP";
29150b57cec5SDimitry Andric     case SHT_ARM_ATTRIBUTES:
29160b57cec5SDimitry Andric       return "ARM_ATTRIBUTES";
29170b57cec5SDimitry Andric     case SHT_ARM_DEBUGOVERLAY:
29180b57cec5SDimitry Andric       return "ARM_DEBUGOVERLAY";
29190b57cec5SDimitry Andric     case SHT_ARM_OVERLAYSECTION:
29200b57cec5SDimitry Andric       return "ARM_OVERLAYSECTION";
29210b57cec5SDimitry Andric     }
29220b57cec5SDimitry Andric     break;
29230b57cec5SDimitry Andric   case EM_X86_64:
29240b57cec5SDimitry Andric     switch (Type) {
29250b57cec5SDimitry Andric     case SHT_X86_64_UNWIND:
29260b57cec5SDimitry Andric       return "X86_64_UNWIND";
29270b57cec5SDimitry Andric     }
29280b57cec5SDimitry Andric     break;
29290b57cec5SDimitry Andric   case EM_MIPS:
29300b57cec5SDimitry Andric   case EM_MIPS_RS3_LE:
29310b57cec5SDimitry Andric     switch (Type) {
29320b57cec5SDimitry Andric     case SHT_MIPS_REGINFO:
29330b57cec5SDimitry Andric       return "MIPS_REGINFO";
29340b57cec5SDimitry Andric     case SHT_MIPS_OPTIONS:
29350b57cec5SDimitry Andric       return "MIPS_OPTIONS";
29360b57cec5SDimitry Andric     case SHT_MIPS_DWARF:
29370b57cec5SDimitry Andric       return "MIPS_DWARF";
29380b57cec5SDimitry Andric     case SHT_MIPS_ABIFLAGS:
29390b57cec5SDimitry Andric       return "MIPS_ABIFLAGS";
29400b57cec5SDimitry Andric     }
29410b57cec5SDimitry Andric     break;
29420b57cec5SDimitry Andric   }
29430b57cec5SDimitry Andric   switch (Type) {
29440b57cec5SDimitry Andric   case SHT_NULL:
29450b57cec5SDimitry Andric     return "NULL";
29460b57cec5SDimitry Andric   case SHT_PROGBITS:
29470b57cec5SDimitry Andric     return "PROGBITS";
29480b57cec5SDimitry Andric   case SHT_SYMTAB:
29490b57cec5SDimitry Andric     return "SYMTAB";
29500b57cec5SDimitry Andric   case SHT_STRTAB:
29510b57cec5SDimitry Andric     return "STRTAB";
29520b57cec5SDimitry Andric   case SHT_RELA:
29530b57cec5SDimitry Andric     return "RELA";
29540b57cec5SDimitry Andric   case SHT_HASH:
29550b57cec5SDimitry Andric     return "HASH";
29560b57cec5SDimitry Andric   case SHT_DYNAMIC:
29570b57cec5SDimitry Andric     return "DYNAMIC";
29580b57cec5SDimitry Andric   case SHT_NOTE:
29590b57cec5SDimitry Andric     return "NOTE";
29600b57cec5SDimitry Andric   case SHT_NOBITS:
29610b57cec5SDimitry Andric     return "NOBITS";
29620b57cec5SDimitry Andric   case SHT_REL:
29630b57cec5SDimitry Andric     return "REL";
29640b57cec5SDimitry Andric   case SHT_SHLIB:
29650b57cec5SDimitry Andric     return "SHLIB";
29660b57cec5SDimitry Andric   case SHT_DYNSYM:
29670b57cec5SDimitry Andric     return "DYNSYM";
29680b57cec5SDimitry Andric   case SHT_INIT_ARRAY:
29690b57cec5SDimitry Andric     return "INIT_ARRAY";
29700b57cec5SDimitry Andric   case SHT_FINI_ARRAY:
29710b57cec5SDimitry Andric     return "FINI_ARRAY";
29720b57cec5SDimitry Andric   case SHT_PREINIT_ARRAY:
29730b57cec5SDimitry Andric     return "PREINIT_ARRAY";
29740b57cec5SDimitry Andric   case SHT_GROUP:
29750b57cec5SDimitry Andric     return "GROUP";
29760b57cec5SDimitry Andric   case SHT_SYMTAB_SHNDX:
29770b57cec5SDimitry Andric     return "SYMTAB SECTION INDICES";
29780b57cec5SDimitry Andric   case SHT_ANDROID_REL:
29790b57cec5SDimitry Andric     return "ANDROID_REL";
29800b57cec5SDimitry Andric   case SHT_ANDROID_RELA:
29810b57cec5SDimitry Andric     return "ANDROID_RELA";
29820b57cec5SDimitry Andric   case SHT_RELR:
29830b57cec5SDimitry Andric   case SHT_ANDROID_RELR:
29840b57cec5SDimitry Andric     return "RELR";
29850b57cec5SDimitry Andric   case SHT_LLVM_ODRTAB:
29860b57cec5SDimitry Andric     return "LLVM_ODRTAB";
29870b57cec5SDimitry Andric   case SHT_LLVM_LINKER_OPTIONS:
29880b57cec5SDimitry Andric     return "LLVM_LINKER_OPTIONS";
29890b57cec5SDimitry Andric   case SHT_LLVM_CALL_GRAPH_PROFILE:
29900b57cec5SDimitry Andric     return "LLVM_CALL_GRAPH_PROFILE";
29910b57cec5SDimitry Andric   case SHT_LLVM_ADDRSIG:
29920b57cec5SDimitry Andric     return "LLVM_ADDRSIG";
29930b57cec5SDimitry Andric   case SHT_LLVM_DEPENDENT_LIBRARIES:
29940b57cec5SDimitry Andric     return "LLVM_DEPENDENT_LIBRARIES";
29950b57cec5SDimitry Andric   // FIXME: Parse processor specific GNU attributes
29960b57cec5SDimitry Andric   case SHT_GNU_ATTRIBUTES:
29970b57cec5SDimitry Andric     return "ATTRIBUTES";
29980b57cec5SDimitry Andric   case SHT_GNU_HASH:
29990b57cec5SDimitry Andric     return "GNU_HASH";
30000b57cec5SDimitry Andric   case SHT_GNU_verdef:
30010b57cec5SDimitry Andric     return "VERDEF";
30020b57cec5SDimitry Andric   case SHT_GNU_verneed:
30030b57cec5SDimitry Andric     return "VERNEED";
30040b57cec5SDimitry Andric   case SHT_GNU_versym:
30050b57cec5SDimitry Andric     return "VERSYM";
30060b57cec5SDimitry Andric   default:
30070b57cec5SDimitry Andric     return getSectionTypeOffsetString(Type);
30080b57cec5SDimitry Andric   }
30090b57cec5SDimitry Andric   return "";
30100b57cec5SDimitry Andric }
30110b57cec5SDimitry Andric 
30120b57cec5SDimitry Andric template <class ELFT>
30130b57cec5SDimitry Andric static StringRef getSectionName(const typename ELFT::Shdr &Sec,
30140b57cec5SDimitry Andric                                 const ELFObjectFile<ELFT> &ElfObj,
30150b57cec5SDimitry Andric                                 ArrayRef<typename ELFT::Shdr> Sections) {
30160b57cec5SDimitry Andric   const ELFFile<ELFT> &Obj = *ElfObj.getELFFile();
30170b57cec5SDimitry Andric   uint32_t Index = Obj.getHeader()->e_shstrndx;
30180b57cec5SDimitry Andric   if (Index == ELF::SHN_XINDEX)
30190b57cec5SDimitry Andric     Index = Sections[0].sh_link;
30200b57cec5SDimitry Andric   if (!Index) // no section string table.
30210b57cec5SDimitry Andric     return "";
30220b57cec5SDimitry Andric   // TODO: Test a case when the sh_link of the section with index 0 is broken.
30230b57cec5SDimitry Andric   if (Index >= Sections.size())
30240b57cec5SDimitry Andric     reportError(ElfObj.getFileName(),
30250b57cec5SDimitry Andric                 createError("section header string table index " +
30260b57cec5SDimitry Andric                             Twine(Index) + " does not exist"));
30270b57cec5SDimitry Andric   StringRef Data = toStringRef(unwrapOrError(
30280b57cec5SDimitry Andric       Obj.template getSectionContentsAsArray<uint8_t>(&Sections[Index])));
30290b57cec5SDimitry Andric   return unwrapOrError(Obj.getSectionName(&Sec, Data));
30300b57cec5SDimitry Andric }
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric template <class ELFT>
30330b57cec5SDimitry Andric void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
30340b57cec5SDimitry Andric   unsigned Bias = ELFT::Is64Bits ? 0 : 8;
30350b57cec5SDimitry Andric   ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
30360b57cec5SDimitry Andric   OS << "There are " << to_string(Sections.size())
30370b57cec5SDimitry Andric      << " section headers, starting at offset "
30380b57cec5SDimitry Andric      << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n";
30390b57cec5SDimitry Andric   OS << "Section Headers:\n";
30400b57cec5SDimitry Andric   Field Fields[11] = {
30410b57cec5SDimitry Andric       {"[Nr]", 2},        {"Name", 7},        {"Type", 25},
30420b57cec5SDimitry Andric       {"Address", 41},    {"Off", 58 - Bias}, {"Size", 65 - Bias},
30430b57cec5SDimitry Andric       {"ES", 72 - Bias},  {"Flg", 75 - Bias}, {"Lk", 79 - Bias},
30440b57cec5SDimitry Andric       {"Inf", 82 - Bias}, {"Al", 86 - Bias}};
30450b57cec5SDimitry Andric   for (auto &F : Fields)
30460b57cec5SDimitry Andric     printField(F);
30470b57cec5SDimitry Andric   OS << "\n";
30480b57cec5SDimitry Andric 
30490b57cec5SDimitry Andric   const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject();
30500b57cec5SDimitry Andric   size_t SectionIndex = 0;
30510b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : Sections) {
30520b57cec5SDimitry Andric     Fields[0].Str = to_string(SectionIndex);
30530b57cec5SDimitry Andric     Fields[1].Str = getSectionName(Sec, *ElfObj, Sections);
30540b57cec5SDimitry Andric     Fields[2].Str =
30550b57cec5SDimitry Andric         getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type);
30560b57cec5SDimitry Andric     Fields[3].Str =
30570b57cec5SDimitry Andric         to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8));
30580b57cec5SDimitry Andric     Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6));
30590b57cec5SDimitry Andric     Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6));
30600b57cec5SDimitry Andric     Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2));
30610b57cec5SDimitry Andric     Fields[7].Str = getGNUFlags(Sec.sh_flags);
30620b57cec5SDimitry Andric     Fields[8].Str = to_string(Sec.sh_link);
30630b57cec5SDimitry Andric     Fields[9].Str = to_string(Sec.sh_info);
30640b57cec5SDimitry Andric     Fields[10].Str = to_string(Sec.sh_addralign);
30650b57cec5SDimitry Andric 
30660b57cec5SDimitry Andric     OS.PadToColumn(Fields[0].Column);
30670b57cec5SDimitry Andric     OS << "[" << right_justify(Fields[0].Str, 2) << "]";
30680b57cec5SDimitry Andric     for (int i = 1; i < 7; i++)
30690b57cec5SDimitry Andric       printField(Fields[i]);
30700b57cec5SDimitry Andric     OS.PadToColumn(Fields[7].Column);
30710b57cec5SDimitry Andric     OS << right_justify(Fields[7].Str, 3);
30720b57cec5SDimitry Andric     OS.PadToColumn(Fields[8].Column);
30730b57cec5SDimitry Andric     OS << right_justify(Fields[8].Str, 2);
30740b57cec5SDimitry Andric     OS.PadToColumn(Fields[9].Column);
30750b57cec5SDimitry Andric     OS << right_justify(Fields[9].Str, 3);
30760b57cec5SDimitry Andric     OS.PadToColumn(Fields[10].Column);
30770b57cec5SDimitry Andric     OS << right_justify(Fields[10].Str, 2);
30780b57cec5SDimitry Andric     OS << "\n";
30790b57cec5SDimitry Andric     ++SectionIndex;
30800b57cec5SDimitry Andric   }
30810b57cec5SDimitry Andric   OS << "Key to Flags:\n"
30820b57cec5SDimitry Andric      << "  W (write), A (alloc), X (execute), M (merge), S (strings), l "
30830b57cec5SDimitry Andric         "(large)\n"
30840b57cec5SDimitry Andric      << "  I (info), L (link order), G (group), T (TLS), E (exclude),\
30850b57cec5SDimitry Andric  x (unknown)\n"
30860b57cec5SDimitry Andric      << "  O (extra OS processing required) o (OS specific),\
30870b57cec5SDimitry Andric  p (processor specific)\n";
30880b57cec5SDimitry Andric }
30890b57cec5SDimitry Andric 
30900b57cec5SDimitry Andric template <class ELFT>
30910b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name,
30920b57cec5SDimitry Andric                                         size_t Entries) {
30930b57cec5SDimitry Andric   if (!Name.empty())
30940b57cec5SDimitry Andric     OS << "\nSymbol table '" << Name << "' contains " << Entries
30950b57cec5SDimitry Andric        << " entries:\n";
30960b57cec5SDimitry Andric   else
30970b57cec5SDimitry Andric     OS << "\n Symbol table for image:\n";
30980b57cec5SDimitry Andric 
30990b57cec5SDimitry Andric   if (ELFT::Is64Bits)
31000b57cec5SDimitry Andric     OS << "   Num:    Value          Size Type    Bind   Vis      Ndx Name\n";
31010b57cec5SDimitry Andric   else
31020b57cec5SDimitry Andric     OS << "   Num:    Value  Size Type    Bind   Vis      Ndx Name\n";
31030b57cec5SDimitry Andric }
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric template <class ELFT>
31060b57cec5SDimitry Andric std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj,
31070b57cec5SDimitry Andric                                                 const Elf_Sym *Symbol,
31080b57cec5SDimitry Andric                                                 const Elf_Sym *FirstSym) {
31090b57cec5SDimitry Andric   unsigned SectionIndex = Symbol->st_shndx;
31100b57cec5SDimitry Andric   switch (SectionIndex) {
31110b57cec5SDimitry Andric   case ELF::SHN_UNDEF:
31120b57cec5SDimitry Andric     return "UND";
31130b57cec5SDimitry Andric   case ELF::SHN_ABS:
31140b57cec5SDimitry Andric     return "ABS";
31150b57cec5SDimitry Andric   case ELF::SHN_COMMON:
31160b57cec5SDimitry Andric     return "COM";
31170b57cec5SDimitry Andric   case ELF::SHN_XINDEX:
31180b57cec5SDimitry Andric     return to_string(
31190b57cec5SDimitry Andric         format_decimal(unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(
31200b57cec5SDimitry Andric                            Symbol, FirstSym, this->dumper()->getShndxTable())),
31210b57cec5SDimitry Andric                        3));
31220b57cec5SDimitry Andric   default:
31230b57cec5SDimitry Andric     // Find if:
31240b57cec5SDimitry Andric     // Processor specific
31250b57cec5SDimitry Andric     if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC)
31260b57cec5SDimitry Andric       return std::string("PRC[0x") +
31270b57cec5SDimitry Andric              to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
31280b57cec5SDimitry Andric     // OS specific
31290b57cec5SDimitry Andric     if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS)
31300b57cec5SDimitry Andric       return std::string("OS[0x") +
31310b57cec5SDimitry Andric              to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
31320b57cec5SDimitry Andric     // Architecture reserved:
31330b57cec5SDimitry Andric     if (SectionIndex >= ELF::SHN_LORESERVE &&
31340b57cec5SDimitry Andric         SectionIndex <= ELF::SHN_HIRESERVE)
31350b57cec5SDimitry Andric       return std::string("RSV[0x") +
31360b57cec5SDimitry Andric              to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
31370b57cec5SDimitry Andric     // A normal section with an index
31380b57cec5SDimitry Andric     return to_string(format_decimal(SectionIndex, 3));
31390b57cec5SDimitry Andric   }
31400b57cec5SDimitry Andric }
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric template <class ELFT>
31430b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
31440b57cec5SDimitry Andric                                  const Elf_Sym *FirstSym, StringRef StrTable,
31450b57cec5SDimitry Andric                                  bool IsDynamic) {
31460b57cec5SDimitry Andric   static int Idx = 0;
31470b57cec5SDimitry Andric   static bool Dynamic = true;
31480b57cec5SDimitry Andric 
31490b57cec5SDimitry Andric   // If this function was called with a different value from IsDynamic
31500b57cec5SDimitry Andric   // from last call, happens when we move from dynamic to static symbol
31510b57cec5SDimitry Andric   // table, "Num" field should be reset.
31520b57cec5SDimitry Andric   if (!Dynamic != !IsDynamic) {
31530b57cec5SDimitry Andric     Idx = 0;
31540b57cec5SDimitry Andric     Dynamic = false;
31550b57cec5SDimitry Andric   }
31560b57cec5SDimitry Andric 
31570b57cec5SDimitry Andric   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
31580b57cec5SDimitry Andric   Field Fields[8] = {0,         8,         17 + Bias, 23 + Bias,
31590b57cec5SDimitry Andric                      31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias};
31600b57cec5SDimitry Andric   Fields[0].Str = to_string(format_decimal(Idx++, 6)) + ":";
31610b57cec5SDimitry Andric   Fields[1].Str = to_string(
31620b57cec5SDimitry Andric       format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));
31630b57cec5SDimitry Andric   Fields[2].Str = to_string(format_decimal(Symbol->st_size, 5));
31640b57cec5SDimitry Andric 
31650b57cec5SDimitry Andric   unsigned char SymbolType = Symbol->getType();
31660b57cec5SDimitry Andric   if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
31670b57cec5SDimitry Andric       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
31680b57cec5SDimitry Andric     Fields[3].Str = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
31690b57cec5SDimitry Andric   else
31700b57cec5SDimitry Andric     Fields[3].Str = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes));
31710b57cec5SDimitry Andric 
31720b57cec5SDimitry Andric   Fields[4].Str =
31730b57cec5SDimitry Andric       printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
31740b57cec5SDimitry Andric   Fields[5].Str =
31750b57cec5SDimitry Andric       printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities));
31760b57cec5SDimitry Andric   Fields[6].Str = getSymbolSectionNdx(Obj, Symbol, FirstSym);
31770b57cec5SDimitry Andric   Fields[7].Str =
31780b57cec5SDimitry Andric       this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);
31790b57cec5SDimitry Andric   for (auto &Entry : Fields)
31800b57cec5SDimitry Andric     printField(Entry);
31810b57cec5SDimitry Andric   OS << "\n";
31820b57cec5SDimitry Andric }
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric template <class ELFT>
31850b57cec5SDimitry Andric void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym,
31860b57cec5SDimitry Andric                                        uint32_t Sym, StringRef StrTable,
31870b57cec5SDimitry Andric                                        uint32_t Bucket) {
31880b57cec5SDimitry Andric   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
31890b57cec5SDimitry Andric   Field Fields[9] = {0,         6,         11,        20 + Bias, 25 + Bias,
31900b57cec5SDimitry Andric                      34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};
31910b57cec5SDimitry Andric   Fields[0].Str = to_string(format_decimal(Sym, 5));
31920b57cec5SDimitry Andric   Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":";
31930b57cec5SDimitry Andric 
31940b57cec5SDimitry Andric   const auto Symbol = FirstSym + Sym;
31950b57cec5SDimitry Andric   Fields[2].Str = to_string(
31960b57cec5SDimitry Andric       format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 18 : 8));
31970b57cec5SDimitry Andric   Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5));
31980b57cec5SDimitry Andric 
31990b57cec5SDimitry Andric   unsigned char SymbolType = Symbol->getType();
32000b57cec5SDimitry Andric   if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
32010b57cec5SDimitry Andric       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
32020b57cec5SDimitry Andric     Fields[4].Str = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
32030b57cec5SDimitry Andric   else
32040b57cec5SDimitry Andric     Fields[4].Str = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes));
32050b57cec5SDimitry Andric 
32060b57cec5SDimitry Andric   Fields[5].Str =
32070b57cec5SDimitry Andric       printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
32080b57cec5SDimitry Andric   Fields[6].Str =
32090b57cec5SDimitry Andric       printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities));
32100b57cec5SDimitry Andric   Fields[7].Str = getSymbolSectionNdx(Obj, Symbol, FirstSym);
32110b57cec5SDimitry Andric   Fields[8].Str = this->dumper()->getFullSymbolName(Symbol, StrTable, true);
32120b57cec5SDimitry Andric 
32130b57cec5SDimitry Andric   for (auto &Entry : Fields)
32140b57cec5SDimitry Andric     printField(Entry);
32150b57cec5SDimitry Andric   OS << "\n";
32160b57cec5SDimitry Andric }
32170b57cec5SDimitry Andric 
32180b57cec5SDimitry Andric template <class ELFT>
32190b57cec5SDimitry Andric void GNUStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols,
32200b57cec5SDimitry Andric                                   bool PrintDynamicSymbols) {
32210b57cec5SDimitry Andric   if (!PrintSymbols && !PrintDynamicSymbols)
32220b57cec5SDimitry Andric     return;
32230b57cec5SDimitry Andric   // GNU readelf prints both the .dynsym and .symtab with --symbols.
32240b57cec5SDimitry Andric   this->dumper()->printSymbolsHelper(true);
32250b57cec5SDimitry Andric   if (PrintSymbols)
32260b57cec5SDimitry Andric     this->dumper()->printSymbolsHelper(false);
32270b57cec5SDimitry Andric }
32280b57cec5SDimitry Andric 
32290b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
32300b57cec5SDimitry Andric   if (this->dumper()->getDynamicStringTable().empty())
32310b57cec5SDimitry Andric     return;
32320b57cec5SDimitry Andric   auto StringTable = this->dumper()->getDynamicStringTable();
32330b57cec5SDimitry Andric   auto DynSyms = this->dumper()->dynamic_symbols();
32340b57cec5SDimitry Andric 
32350b57cec5SDimitry Andric   // Try printing .hash
32360b57cec5SDimitry Andric   if (auto SysVHash = this->dumper()->getHashTable()) {
32370b57cec5SDimitry Andric     OS << "\n Symbol table of .hash for image:\n";
32380b57cec5SDimitry Andric     if (ELFT::Is64Bits)
32390b57cec5SDimitry Andric       OS << "  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name";
32400b57cec5SDimitry Andric     else
32410b57cec5SDimitry Andric       OS << "  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name";
32420b57cec5SDimitry Andric     OS << "\n";
32430b57cec5SDimitry Andric 
32440b57cec5SDimitry Andric     auto Buckets = SysVHash->buckets();
32450b57cec5SDimitry Andric     auto Chains = SysVHash->chains();
32460b57cec5SDimitry Andric     for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) {
32470b57cec5SDimitry Andric       if (Buckets[Buc] == ELF::STN_UNDEF)
32480b57cec5SDimitry Andric         continue;
32490b57cec5SDimitry Andric       for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) {
32500b57cec5SDimitry Andric         if (Ch == ELF::STN_UNDEF)
32510b57cec5SDimitry Andric           break;
32520b57cec5SDimitry Andric         printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc);
32530b57cec5SDimitry Andric       }
32540b57cec5SDimitry Andric     }
32550b57cec5SDimitry Andric   }
32560b57cec5SDimitry Andric 
32570b57cec5SDimitry Andric   // Try printing .gnu.hash
32580b57cec5SDimitry Andric   if (auto GnuHash = this->dumper()->getGnuHashTable()) {
32590b57cec5SDimitry Andric     OS << "\n Symbol table of .gnu.hash for image:\n";
32600b57cec5SDimitry Andric     if (ELFT::Is64Bits)
32610b57cec5SDimitry Andric       OS << "  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name";
32620b57cec5SDimitry Andric     else
32630b57cec5SDimitry Andric       OS << "  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name";
32640b57cec5SDimitry Andric     OS << "\n";
32650b57cec5SDimitry Andric     auto Buckets = GnuHash->buckets();
32660b57cec5SDimitry Andric     for (uint32_t Buc = 0; Buc < GnuHash->nbuckets; Buc++) {
32670b57cec5SDimitry Andric       if (Buckets[Buc] == ELF::STN_UNDEF)
32680b57cec5SDimitry Andric         continue;
32690b57cec5SDimitry Andric       uint32_t Index = Buckets[Buc];
32700b57cec5SDimitry Andric       uint32_t GnuHashable = Index - GnuHash->symndx;
32710b57cec5SDimitry Andric       // Print whole chain
32720b57cec5SDimitry Andric       while (true) {
32730b57cec5SDimitry Andric         printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc);
32740b57cec5SDimitry Andric         // Chain ends at symbol with stopper bit
32750b57cec5SDimitry Andric         if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
32760b57cec5SDimitry Andric           break;
32770b57cec5SDimitry Andric       }
32780b57cec5SDimitry Andric     }
32790b57cec5SDimitry Andric   }
32800b57cec5SDimitry Andric }
32810b57cec5SDimitry Andric 
32820b57cec5SDimitry Andric static inline std::string printPhdrFlags(unsigned Flag) {
32830b57cec5SDimitry Andric   std::string Str;
32840b57cec5SDimitry Andric   Str = (Flag & PF_R) ? "R" : " ";
32850b57cec5SDimitry Andric   Str += (Flag & PF_W) ? "W" : " ";
32860b57cec5SDimitry Andric   Str += (Flag & PF_X) ? "E" : " ";
32870b57cec5SDimitry Andric   return Str;
32880b57cec5SDimitry Andric }
32890b57cec5SDimitry Andric 
32900b57cec5SDimitry Andric // SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO
32910b57cec5SDimitry Andric // PT_TLS must only have SHF_TLS sections
32920b57cec5SDimitry Andric template <class ELFT>
32930b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkTLSSections(const Elf_Phdr &Phdr,
32940b57cec5SDimitry Andric                                       const Elf_Shdr &Sec) {
32950b57cec5SDimitry Andric   return (((Sec.sh_flags & ELF::SHF_TLS) &&
32960b57cec5SDimitry Andric            ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||
32970b57cec5SDimitry Andric             (Phdr.p_type == ELF::PT_GNU_RELRO))) ||
32980b57cec5SDimitry Andric           (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS));
32990b57cec5SDimitry Andric }
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric // Non-SHT_NOBITS must have its offset inside the segment
33020b57cec5SDimitry Andric // Only non-zero section can be at end of segment
33030b57cec5SDimitry Andric template <class ELFT>
33040b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
33050b57cec5SDimitry Andric   if (Sec.sh_type == ELF::SHT_NOBITS)
33060b57cec5SDimitry Andric     return true;
33070b57cec5SDimitry Andric   bool IsSpecial =
33080b57cec5SDimitry Andric       (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
33090b57cec5SDimitry Andric   // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
33100b57cec5SDimitry Andric   auto SectionSize =
33110b57cec5SDimitry Andric       (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
33120b57cec5SDimitry Andric   if (Sec.sh_offset >= Phdr.p_offset)
33130b57cec5SDimitry Andric     return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset)
33140b57cec5SDimitry Andric             /*only non-zero sized sections at end*/
33150b57cec5SDimitry Andric             && (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz));
33160b57cec5SDimitry Andric   return false;
33170b57cec5SDimitry Andric }
33180b57cec5SDimitry Andric 
33190b57cec5SDimitry Andric // SHF_ALLOC must have VMA inside segment
33200b57cec5SDimitry Andric // Only non-zero section can be at end of segment
33210b57cec5SDimitry Andric template <class ELFT>
33220b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
33230b57cec5SDimitry Andric   if (!(Sec.sh_flags & ELF::SHF_ALLOC))
33240b57cec5SDimitry Andric     return true;
33250b57cec5SDimitry Andric   bool IsSpecial =
33260b57cec5SDimitry Andric       (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
33270b57cec5SDimitry Andric   // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
33280b57cec5SDimitry Andric   auto SectionSize =
33290b57cec5SDimitry Andric       (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
33300b57cec5SDimitry Andric   if (Sec.sh_addr >= Phdr.p_vaddr)
33310b57cec5SDimitry Andric     return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) &&
33320b57cec5SDimitry Andric             (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz));
33330b57cec5SDimitry Andric   return false;
33340b57cec5SDimitry Andric }
33350b57cec5SDimitry Andric 
33360b57cec5SDimitry Andric // No section with zero size must be at start or end of PT_DYNAMIC
33370b57cec5SDimitry Andric template <class ELFT>
33380b57cec5SDimitry Andric bool GNUStyle<ELFT>::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
33390b57cec5SDimitry Andric   if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0)
33400b57cec5SDimitry Andric     return true;
33410b57cec5SDimitry Andric   // Is section within the phdr both based on offset and VMA ?
33420b57cec5SDimitry Andric   return ((Sec.sh_type == ELF::SHT_NOBITS) ||
33430b57cec5SDimitry Andric           (Sec.sh_offset > Phdr.p_offset &&
33440b57cec5SDimitry Andric            Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) &&
33450b57cec5SDimitry Andric          (!(Sec.sh_flags & ELF::SHF_ALLOC) ||
33460b57cec5SDimitry Andric           (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz));
33470b57cec5SDimitry Andric }
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric template <class ELFT>
33500b57cec5SDimitry Andric void GNUStyle<ELFT>::printProgramHeaders(
33510b57cec5SDimitry Andric     const ELFO *Obj, bool PrintProgramHeaders,
33520b57cec5SDimitry Andric     cl::boolOrDefault PrintSectionMapping) {
33530b57cec5SDimitry Andric   if (PrintProgramHeaders)
33540b57cec5SDimitry Andric     printProgramHeaders(Obj);
33550b57cec5SDimitry Andric 
33560b57cec5SDimitry Andric   // Display the section mapping along with the program headers, unless
33570b57cec5SDimitry Andric   // -section-mapping is explicitly set to false.
33580b57cec5SDimitry Andric   if (PrintSectionMapping != cl::BOU_FALSE)
33590b57cec5SDimitry Andric     printSectionMapping(Obj);
33600b57cec5SDimitry Andric }
33610b57cec5SDimitry Andric 
33620b57cec5SDimitry Andric template <class ELFT>
33630b57cec5SDimitry Andric void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
33640b57cec5SDimitry Andric   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
33650b57cec5SDimitry Andric   const Elf_Ehdr *Header = Obj->getHeader();
33660b57cec5SDimitry Andric   Field Fields[8] = {2,         17,        26,        37 + Bias,
33670b57cec5SDimitry Andric                      48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};
33680b57cec5SDimitry Andric   OS << "\nElf file type is "
33690b57cec5SDimitry Andric      << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n"
33700b57cec5SDimitry Andric      << "Entry point " << format_hex(Header->e_entry, 3) << "\n"
33710b57cec5SDimitry Andric      << "There are " << Header->e_phnum << " program headers,"
33720b57cec5SDimitry Andric      << " starting at offset " << Header->e_phoff << "\n\n"
33730b57cec5SDimitry Andric      << "Program Headers:\n";
33740b57cec5SDimitry Andric   if (ELFT::Is64Bits)
33750b57cec5SDimitry Andric     OS << "  Type           Offset   VirtAddr           PhysAddr         "
33760b57cec5SDimitry Andric        << "  FileSiz  MemSiz   Flg Align\n";
33770b57cec5SDimitry Andric   else
33780b57cec5SDimitry Andric     OS << "  Type           Offset   VirtAddr   PhysAddr   FileSiz "
33790b57cec5SDimitry Andric        << "MemSiz  Flg Align\n";
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric   unsigned Width = ELFT::Is64Bits ? 18 : 10;
33820b57cec5SDimitry Andric   unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7;
33830b57cec5SDimitry Andric   for (const auto &Phdr : unwrapOrError(Obj->program_headers())) {
33840b57cec5SDimitry Andric     Fields[0].Str = getElfPtType(Header->e_machine, Phdr.p_type);
33850b57cec5SDimitry Andric     Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8));
33860b57cec5SDimitry Andric     Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width));
33870b57cec5SDimitry Andric     Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width));
33880b57cec5SDimitry Andric     Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth));
33890b57cec5SDimitry Andric     Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth));
33900b57cec5SDimitry Andric     Fields[6].Str = printPhdrFlags(Phdr.p_flags);
33910b57cec5SDimitry Andric     Fields[7].Str = to_string(format_hex(Phdr.p_align, 1));
33920b57cec5SDimitry Andric     for (auto Field : Fields)
33930b57cec5SDimitry Andric       printField(Field);
33940b57cec5SDimitry Andric     if (Phdr.p_type == ELF::PT_INTERP) {
33950b57cec5SDimitry Andric       OS << "\n      [Requesting program interpreter: ";
33960b57cec5SDimitry Andric       OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]";
33970b57cec5SDimitry Andric     }
33980b57cec5SDimitry Andric     OS << "\n";
33990b57cec5SDimitry Andric   }
34000b57cec5SDimitry Andric }
34010b57cec5SDimitry Andric 
34020b57cec5SDimitry Andric template <class ELFT>
34030b57cec5SDimitry Andric void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) {
34040b57cec5SDimitry Andric   OS << "\n Section to Segment mapping:\n  Segment Sections...\n";
34050b57cec5SDimitry Andric   DenseSet<const Elf_Shdr *> BelongsToSegment;
34060b57cec5SDimitry Andric   int Phnum = 0;
34070b57cec5SDimitry Andric   for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
34080b57cec5SDimitry Andric     std::string Sections;
34090b57cec5SDimitry Andric     OS << format("   %2.2d     ", Phnum++);
34100b57cec5SDimitry Andric     for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
34110b57cec5SDimitry Andric       // Check if each section is in a segment and then print mapping.
34120b57cec5SDimitry Andric       // readelf additionally makes sure it does not print zero sized sections
34130b57cec5SDimitry Andric       // at end of segments and for PT_DYNAMIC both start and end of section
34140b57cec5SDimitry Andric       // .tbss must only be shown in PT_TLS section.
34150b57cec5SDimitry Andric       bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) &&
34160b57cec5SDimitry Andric                           ((Sec.sh_flags & ELF::SHF_TLS) != 0) &&
34170b57cec5SDimitry Andric                           Phdr.p_type != ELF::PT_TLS;
34180b57cec5SDimitry Andric       if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) &&
34190b57cec5SDimitry Andric           checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) &&
34200b57cec5SDimitry Andric           checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL)) {
34210b57cec5SDimitry Andric         Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " ";
34220b57cec5SDimitry Andric         BelongsToSegment.insert(&Sec);
34230b57cec5SDimitry Andric       }
34240b57cec5SDimitry Andric     }
34250b57cec5SDimitry Andric     OS << Sections << "\n";
34260b57cec5SDimitry Andric     OS.flush();
34270b57cec5SDimitry Andric   }
34280b57cec5SDimitry Andric 
34290b57cec5SDimitry Andric   // Display sections that do not belong to a segment.
34300b57cec5SDimitry Andric   std::string Sections;
34310b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
34320b57cec5SDimitry Andric     if (BelongsToSegment.find(&Sec) == BelongsToSegment.end())
34330b57cec5SDimitry Andric       Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + ' ';
34340b57cec5SDimitry Andric   }
34350b57cec5SDimitry Andric   if (!Sections.empty()) {
34360b57cec5SDimitry Andric     OS << "   None  " << Sections << '\n';
34370b57cec5SDimitry Andric     OS.flush();
34380b57cec5SDimitry Andric   }
34390b57cec5SDimitry Andric }
34400b57cec5SDimitry Andric 
34410b57cec5SDimitry Andric template <class ELFT>
34420b57cec5SDimitry Andric void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R,
34430b57cec5SDimitry Andric                                             bool IsRela) {
34440b57cec5SDimitry Andric   uint32_t SymIndex = R.getSymbol(Obj->isMips64EL());
34450b57cec5SDimitry Andric   const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
34460b57cec5SDimitry Andric   std::string SymbolName = maybeDemangle(
34470b57cec5SDimitry Andric       unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
34480b57cec5SDimitry Andric   printRelocation(Obj, Sym, SymbolName, R, IsRela);
34490b57cec5SDimitry Andric }
34500b57cec5SDimitry Andric 
34510b57cec5SDimitry Andric template <class ELFT> void GNUStyle<ELFT>::printDynamic(const ELFO *Obj) {
34520b57cec5SDimitry Andric   Elf_Dyn_Range Table = this->dumper()->dynamic_table();
34530b57cec5SDimitry Andric   if (Table.empty())
34540b57cec5SDimitry Andric     return;
34550b57cec5SDimitry Andric 
34560b57cec5SDimitry Andric   const DynRegionInfo &DynamicTableRegion =
34570b57cec5SDimitry Andric       this->dumper()->getDynamicTableRegion();
34580b57cec5SDimitry Andric 
34590b57cec5SDimitry Andric   OS << "Dynamic section at offset "
34600b57cec5SDimitry Andric      << format_hex(reinterpret_cast<const uint8_t *>(DynamicTableRegion.Addr) -
34610b57cec5SDimitry Andric                        Obj->base(),
34620b57cec5SDimitry Andric                    1)
34630b57cec5SDimitry Andric      << " contains " << Table.size() << " entries:\n";
34640b57cec5SDimitry Andric 
34650b57cec5SDimitry Andric   bool Is64 = ELFT::Is64Bits;
34660b57cec5SDimitry Andric   if (Is64)
34670b57cec5SDimitry Andric     OS << "  Tag                Type                 Name/Value\n";
34680b57cec5SDimitry Andric   else
34690b57cec5SDimitry Andric     OS << "  Tag        Type                 Name/Value\n";
34700b57cec5SDimitry Andric   for (auto Entry : Table) {
34710b57cec5SDimitry Andric     uintX_t Tag = Entry.getTag();
34720b57cec5SDimitry Andric     std::string TypeString = std::string("(") +
34730b57cec5SDimitry Andric                              getTypeString(Obj->getHeader()->e_machine, Tag) +
34740b57cec5SDimitry Andric                              ")";
34750b57cec5SDimitry Andric     OS << "  " << format_hex(Tag, Is64 ? 18 : 10)
34760b57cec5SDimitry Andric        << format(" %-20s ", TypeString.c_str());
34770b57cec5SDimitry Andric     this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
34780b57cec5SDimitry Andric     OS << "\n";
34790b57cec5SDimitry Andric   }
34800b57cec5SDimitry Andric }
34810b57cec5SDimitry Andric 
34820b57cec5SDimitry Andric template <class ELFT>
34830b57cec5SDimitry Andric void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
34840b57cec5SDimitry Andric   const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion();
34850b57cec5SDimitry Andric   const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion();
34860b57cec5SDimitry Andric   const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion();
34870b57cec5SDimitry Andric   const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion();
34880b57cec5SDimitry Andric   if (DynRelaRegion.Size > 0) {
34890b57cec5SDimitry Andric     OS << "\n'RELA' relocation section at offset "
34900b57cec5SDimitry Andric        << format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) -
34910b57cec5SDimitry Andric                          Obj->base(),
34920b57cec5SDimitry Andric                      1)
34930b57cec5SDimitry Andric        << " contains " << DynRelaRegion.Size << " bytes:\n";
34940b57cec5SDimitry Andric     printRelocHeader(ELF::SHT_RELA);
34950b57cec5SDimitry Andric     for (const Elf_Rela &Rela : this->dumper()->dyn_relas())
34960b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela, true);
34970b57cec5SDimitry Andric   }
34980b57cec5SDimitry Andric   if (DynRelRegion.Size > 0) {
34990b57cec5SDimitry Andric     OS << "\n'REL' relocation section at offset "
35000b57cec5SDimitry Andric        << format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) -
35010b57cec5SDimitry Andric                          Obj->base(),
35020b57cec5SDimitry Andric                      1)
35030b57cec5SDimitry Andric        << " contains " << DynRelRegion.Size << " bytes:\n";
35040b57cec5SDimitry Andric     printRelocHeader(ELF::SHT_REL);
35050b57cec5SDimitry Andric     for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) {
35060b57cec5SDimitry Andric       Elf_Rela Rela;
35070b57cec5SDimitry Andric       Rela.r_offset = Rel.r_offset;
35080b57cec5SDimitry Andric       Rela.r_info = Rel.r_info;
35090b57cec5SDimitry Andric       Rela.r_addend = 0;
35100b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela, false);
35110b57cec5SDimitry Andric     }
35120b57cec5SDimitry Andric   }
35130b57cec5SDimitry Andric   if (DynRelrRegion.Size > 0) {
35140b57cec5SDimitry Andric     OS << "\n'RELR' relocation section at offset "
35150b57cec5SDimitry Andric        << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) -
35160b57cec5SDimitry Andric                          Obj->base(),
35170b57cec5SDimitry Andric                      1)
35180b57cec5SDimitry Andric        << " contains " << DynRelrRegion.Size << " bytes:\n";
35190b57cec5SDimitry Andric     printRelocHeader(ELF::SHT_REL);
35200b57cec5SDimitry Andric     Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
35210b57cec5SDimitry Andric     std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
35220b57cec5SDimitry Andric     for (const Elf_Rela &Rela : RelrRelas) {
35230b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela, false);
35240b57cec5SDimitry Andric     }
35250b57cec5SDimitry Andric   }
35260b57cec5SDimitry Andric   if (DynPLTRelRegion.Size) {
35270b57cec5SDimitry Andric     OS << "\n'PLT' relocation section at offset "
35280b57cec5SDimitry Andric        << format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) -
35290b57cec5SDimitry Andric                          Obj->base(),
35300b57cec5SDimitry Andric                      1)
35310b57cec5SDimitry Andric        << " contains " << DynPLTRelRegion.Size << " bytes:\n";
35320b57cec5SDimitry Andric   }
35330b57cec5SDimitry Andric   if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
35340b57cec5SDimitry Andric     printRelocHeader(ELF::SHT_RELA);
35350b57cec5SDimitry Andric     for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
35360b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela, true);
35370b57cec5SDimitry Andric   } else {
35380b57cec5SDimitry Andric     printRelocHeader(ELF::SHT_REL);
35390b57cec5SDimitry Andric     for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) {
35400b57cec5SDimitry Andric       Elf_Rela Rela;
35410b57cec5SDimitry Andric       Rela.r_offset = Rel.r_offset;
35420b57cec5SDimitry Andric       Rela.r_info = Rel.r_info;
35430b57cec5SDimitry Andric       Rela.r_addend = 0;
35440b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela, false);
35450b57cec5SDimitry Andric     }
35460b57cec5SDimitry Andric   }
35470b57cec5SDimitry Andric }
35480b57cec5SDimitry Andric 
35490b57cec5SDimitry Andric template <class ELFT>
35500b57cec5SDimitry Andric static void printGNUVersionSectionProlog(formatted_raw_ostream &OS,
35510b57cec5SDimitry Andric                                          const Twine &Name, unsigned EntriesNum,
35520b57cec5SDimitry Andric                                          const ELFFile<ELFT> *Obj,
35530b57cec5SDimitry Andric                                          const typename ELFT::Shdr *Sec) {
35540b57cec5SDimitry Andric   StringRef SecName = unwrapOrError(Obj->getSectionName(Sec));
35550b57cec5SDimitry Andric   OS << Name << " section '" << SecName << "' "
35560b57cec5SDimitry Andric      << "contains " << EntriesNum << " entries:\n";
35570b57cec5SDimitry Andric 
35580b57cec5SDimitry Andric   const typename ELFT::Shdr *SymTab =
35590b57cec5SDimitry Andric       unwrapOrError(Obj->getSection(Sec->sh_link));
35600b57cec5SDimitry Andric   StringRef SymTabName = unwrapOrError(Obj->getSectionName(SymTab));
35610b57cec5SDimitry Andric   OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16)
35620b57cec5SDimitry Andric      << "  Offset: " << format_hex(Sec->sh_offset, 8)
35630b57cec5SDimitry Andric      << "  Link: " << Sec->sh_link << " (" << SymTabName << ")\n";
35640b57cec5SDimitry Andric }
35650b57cec5SDimitry Andric 
35660b57cec5SDimitry Andric template <class ELFT>
35670b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
35680b57cec5SDimitry Andric                                                const Elf_Shdr *Sec) {
35690b57cec5SDimitry Andric   if (!Sec)
35700b57cec5SDimitry Andric     return;
35710b57cec5SDimitry Andric 
35720b57cec5SDimitry Andric   unsigned Entries = Sec->sh_size / sizeof(Elf_Versym);
35730b57cec5SDimitry Andric   printGNUVersionSectionProlog(OS, "Version symbols", Entries, Obj, Sec);
35740b57cec5SDimitry Andric 
35750b57cec5SDimitry Andric   const uint8_t *VersymBuf =
35760b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
35770b57cec5SDimitry Andric   const ELFDumper<ELFT> *Dumper = this->dumper();
35780b57cec5SDimitry Andric   StringRef StrTable = Dumper->getDynamicStringTable();
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric   // readelf prints 4 entries per line.
35810b57cec5SDimitry Andric   for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {
35820b57cec5SDimitry Andric     OS << "  " << format_hex_no_prefix(VersymRow, 3) << ":";
35830b57cec5SDimitry Andric 
35840b57cec5SDimitry Andric     for (uint64_t VersymIndex = 0;
35850b57cec5SDimitry Andric          (VersymIndex < 4) && (VersymIndex + VersymRow) < Entries;
35860b57cec5SDimitry Andric          ++VersymIndex) {
35870b57cec5SDimitry Andric       const Elf_Versym *Versym =
35880b57cec5SDimitry Andric           reinterpret_cast<const Elf_Versym *>(VersymBuf);
35890b57cec5SDimitry Andric       switch (Versym->vs_index) {
35900b57cec5SDimitry Andric       case 0:
35910b57cec5SDimitry Andric         OS << "   0 (*local*)    ";
35920b57cec5SDimitry Andric         break;
35930b57cec5SDimitry Andric       case 1:
35940b57cec5SDimitry Andric         OS << "   1 (*global*)   ";
35950b57cec5SDimitry Andric         break;
35960b57cec5SDimitry Andric       default:
35970b57cec5SDimitry Andric         OS << format("%4x%c", Versym->vs_index & VERSYM_VERSION,
35980b57cec5SDimitry Andric                      Versym->vs_index & VERSYM_HIDDEN ? 'h' : ' ');
35990b57cec5SDimitry Andric 
36000b57cec5SDimitry Andric         bool IsDefault = true;
36010b57cec5SDimitry Andric         std::string VersionName = Dumper->getSymbolVersionByIndex(
36020b57cec5SDimitry Andric             StrTable, Versym->vs_index, IsDefault);
36030b57cec5SDimitry Andric 
36040b57cec5SDimitry Andric         if (!VersionName.empty())
36050b57cec5SDimitry Andric           VersionName = "(" + VersionName + ")";
36060b57cec5SDimitry Andric         else
36070b57cec5SDimitry Andric           VersionName = "(*invalid*)";
36080b57cec5SDimitry Andric         OS << left_justify(VersionName, 13);
36090b57cec5SDimitry Andric       }
36100b57cec5SDimitry Andric       VersymBuf += sizeof(Elf_Versym);
36110b57cec5SDimitry Andric     }
36120b57cec5SDimitry Andric     OS << '\n';
36130b57cec5SDimitry Andric   }
36140b57cec5SDimitry Andric   OS << '\n';
36150b57cec5SDimitry Andric }
36160b57cec5SDimitry Andric 
36170b57cec5SDimitry Andric static std::string versionFlagToString(unsigned Flags) {
36180b57cec5SDimitry Andric   if (Flags == 0)
36190b57cec5SDimitry Andric     return "none";
36200b57cec5SDimitry Andric 
36210b57cec5SDimitry Andric   std::string Ret;
36220b57cec5SDimitry Andric   auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) {
36230b57cec5SDimitry Andric     if (!(Flags & Flag))
36240b57cec5SDimitry Andric       return;
36250b57cec5SDimitry Andric     if (!Ret.empty())
36260b57cec5SDimitry Andric       Ret += " | ";
36270b57cec5SDimitry Andric     Ret += Name;
36280b57cec5SDimitry Andric     Flags &= ~Flag;
36290b57cec5SDimitry Andric   };
36300b57cec5SDimitry Andric 
36310b57cec5SDimitry Andric   AddFlag(VER_FLG_BASE, "BASE");
36320b57cec5SDimitry Andric   AddFlag(VER_FLG_WEAK, "WEAK");
36330b57cec5SDimitry Andric   AddFlag(VER_FLG_INFO, "INFO");
36340b57cec5SDimitry Andric   AddFlag(~0, "<unknown>");
36350b57cec5SDimitry Andric   return Ret;
36360b57cec5SDimitry Andric }
36370b57cec5SDimitry Andric 
36380b57cec5SDimitry Andric template <class ELFT>
36390b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
36400b57cec5SDimitry Andric                                                    const Elf_Shdr *Sec) {
36410b57cec5SDimitry Andric   if (!Sec)
36420b57cec5SDimitry Andric     return;
36430b57cec5SDimitry Andric 
36440b57cec5SDimitry Andric   unsigned VerDefsNum = Sec->sh_info;
36450b57cec5SDimitry Andric   printGNUVersionSectionProlog(OS, "Version definition", VerDefsNum, Obj, Sec);
36460b57cec5SDimitry Andric 
36470b57cec5SDimitry Andric   const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link));
36480b57cec5SDimitry Andric   StringRef StringTable(
36490b57cec5SDimitry Andric       reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
36500b57cec5SDimitry Andric       (size_t)StrTabSec->sh_size);
36510b57cec5SDimitry Andric 
36520b57cec5SDimitry Andric   const uint8_t *VerdefBuf = unwrapOrError(Obj->getSectionContents(Sec)).data();
36530b57cec5SDimitry Andric   const uint8_t *Begin = VerdefBuf;
36540b57cec5SDimitry Andric 
36550b57cec5SDimitry Andric   while (VerDefsNum--) {
36560b57cec5SDimitry Andric     const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf);
36570b57cec5SDimitry Andric     OS << format("  0x%04x: Rev: %u  Flags: %s  Index: %u  Cnt: %u",
36580b57cec5SDimitry Andric                  VerdefBuf - Begin, (unsigned)Verdef->vd_version,
36590b57cec5SDimitry Andric                  versionFlagToString(Verdef->vd_flags).c_str(),
36600b57cec5SDimitry Andric                  (unsigned)Verdef->vd_ndx, (unsigned)Verdef->vd_cnt);
36610b57cec5SDimitry Andric 
36620b57cec5SDimitry Andric     const uint8_t *VerdauxBuf = VerdefBuf + Verdef->vd_aux;
36630b57cec5SDimitry Andric     const Elf_Verdaux *Verdaux =
36640b57cec5SDimitry Andric         reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf);
36650b57cec5SDimitry Andric     OS << format("  Name: %s\n",
36660b57cec5SDimitry Andric                  StringTable.drop_front(Verdaux->vda_name).data());
36670b57cec5SDimitry Andric 
36680b57cec5SDimitry Andric     for (unsigned I = 1; I < Verdef->vd_cnt; ++I) {
36690b57cec5SDimitry Andric       VerdauxBuf += Verdaux->vda_next;
36700b57cec5SDimitry Andric       Verdaux = reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf);
36710b57cec5SDimitry Andric       OS << format("  0x%04x: Parent %u: %s\n", VerdauxBuf - Begin, I,
36720b57cec5SDimitry Andric                    StringTable.drop_front(Verdaux->vda_name).data());
36730b57cec5SDimitry Andric     }
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric     VerdefBuf += Verdef->vd_next;
36760b57cec5SDimitry Andric   }
36770b57cec5SDimitry Andric   OS << '\n';
36780b57cec5SDimitry Andric }
36790b57cec5SDimitry Andric 
36800b57cec5SDimitry Andric template <class ELFT>
36810b57cec5SDimitry Andric void GNUStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
36820b57cec5SDimitry Andric                                                    const Elf_Shdr *Sec) {
36830b57cec5SDimitry Andric   if (!Sec)
36840b57cec5SDimitry Andric     return;
36850b57cec5SDimitry Andric 
36860b57cec5SDimitry Andric   unsigned VerneedNum = Sec->sh_info;
36870b57cec5SDimitry Andric   printGNUVersionSectionProlog(OS, "Version needs", VerneedNum, Obj, Sec);
36880b57cec5SDimitry Andric 
36890b57cec5SDimitry Andric   ArrayRef<uint8_t> SecData = unwrapOrError(Obj->getSectionContents(Sec));
36900b57cec5SDimitry Andric 
36910b57cec5SDimitry Andric   const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link));
36920b57cec5SDimitry Andric   StringRef StringTable = {
36930b57cec5SDimitry Andric       reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
36940b57cec5SDimitry Andric       (size_t)StrTabSec->sh_size};
36950b57cec5SDimitry Andric 
36960b57cec5SDimitry Andric   const uint8_t *VerneedBuf = SecData.data();
36970b57cec5SDimitry Andric   for (unsigned I = 0; I < VerneedNum; ++I) {
36980b57cec5SDimitry Andric     const Elf_Verneed *Verneed =
36990b57cec5SDimitry Andric         reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
37000b57cec5SDimitry Andric 
37010b57cec5SDimitry Andric     OS << format("  0x%04x: Version: %u  File: %s  Cnt: %u\n",
37020b57cec5SDimitry Andric                  reinterpret_cast<const uint8_t *>(Verneed) - SecData.begin(),
37030b57cec5SDimitry Andric                  (unsigned)Verneed->vn_version,
37040b57cec5SDimitry Andric                  StringTable.drop_front(Verneed->vn_file).data(),
37050b57cec5SDimitry Andric                  (unsigned)Verneed->vn_cnt);
37060b57cec5SDimitry Andric 
37070b57cec5SDimitry Andric     const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
37080b57cec5SDimitry Andric     for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
37090b57cec5SDimitry Andric       const Elf_Vernaux *Vernaux =
37100b57cec5SDimitry Andric           reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
37110b57cec5SDimitry Andric 
37120b57cec5SDimitry Andric       OS << format("  0x%04x:   Name: %s  Flags: %s  Version: %u\n",
37130b57cec5SDimitry Andric                    reinterpret_cast<const uint8_t *>(Vernaux) - SecData.begin(),
37140b57cec5SDimitry Andric                    StringTable.drop_front(Vernaux->vna_name).data(),
37150b57cec5SDimitry Andric                    versionFlagToString(Vernaux->vna_flags).c_str(),
37160b57cec5SDimitry Andric                    (unsigned)Vernaux->vna_other);
37170b57cec5SDimitry Andric       VernauxBuf += Vernaux->vna_next;
37180b57cec5SDimitry Andric     }
37190b57cec5SDimitry Andric     VerneedBuf += Verneed->vn_next;
37200b57cec5SDimitry Andric   }
37210b57cec5SDimitry Andric   OS << '\n';
37220b57cec5SDimitry Andric }
37230b57cec5SDimitry Andric 
37240b57cec5SDimitry Andric // Hash histogram shows  statistics of how efficient the hash was for the
37250b57cec5SDimitry Andric // dynamic symbol table. The table shows number of hash buckets for different
37260b57cec5SDimitry Andric // lengths of chains as absolute number and percentage of the total buckets.
37270b57cec5SDimitry Andric // Additionally cumulative coverage of symbols for each set of buckets.
37280b57cec5SDimitry Andric template <class ELFT>
37290b57cec5SDimitry Andric void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
37300b57cec5SDimitry Andric   // Print histogram for .hash section
37310b57cec5SDimitry Andric   if (const Elf_Hash *HashTable = this->dumper()->getHashTable()) {
37320b57cec5SDimitry Andric     size_t NBucket = HashTable->nbucket;
37330b57cec5SDimitry Andric     size_t NChain = HashTable->nchain;
37340b57cec5SDimitry Andric     ArrayRef<Elf_Word> Buckets = HashTable->buckets();
37350b57cec5SDimitry Andric     ArrayRef<Elf_Word> Chains = HashTable->chains();
37360b57cec5SDimitry Andric     size_t TotalSyms = 0;
37370b57cec5SDimitry Andric     // If hash table is correct, we have at least chains with 0 length
37380b57cec5SDimitry Andric     size_t MaxChain = 1;
37390b57cec5SDimitry Andric     size_t CumulativeNonZero = 0;
37400b57cec5SDimitry Andric 
37410b57cec5SDimitry Andric     if (NChain == 0 || NBucket == 0)
37420b57cec5SDimitry Andric       return;
37430b57cec5SDimitry Andric 
37440b57cec5SDimitry Andric     std::vector<size_t> ChainLen(NBucket, 0);
37450b57cec5SDimitry Andric     // Go over all buckets and and note chain lengths of each bucket (total
37460b57cec5SDimitry Andric     // unique chain lengths).
37470b57cec5SDimitry Andric     for (size_t B = 0; B < NBucket; B++) {
37480b57cec5SDimitry Andric       for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C])
37490b57cec5SDimitry Andric         if (MaxChain <= ++ChainLen[B])
37500b57cec5SDimitry Andric           MaxChain++;
37510b57cec5SDimitry Andric       TotalSyms += ChainLen[B];
37520b57cec5SDimitry Andric     }
37530b57cec5SDimitry Andric 
37540b57cec5SDimitry Andric     if (!TotalSyms)
37550b57cec5SDimitry Andric       return;
37560b57cec5SDimitry Andric 
37570b57cec5SDimitry Andric     std::vector<size_t> Count(MaxChain, 0) ;
37580b57cec5SDimitry Andric     // Count how long is the chain for each bucket
37590b57cec5SDimitry Andric     for (size_t B = 0; B < NBucket; B++)
37600b57cec5SDimitry Andric       ++Count[ChainLen[B]];
37610b57cec5SDimitry Andric     // Print Number of buckets with each chain lengths and their cumulative
37620b57cec5SDimitry Andric     // coverage of the symbols
37630b57cec5SDimitry Andric     OS << "Histogram for bucket list length (total of " << NBucket
37640b57cec5SDimitry Andric        << " buckets)\n"
37650b57cec5SDimitry Andric        << " Length  Number     % of total  Coverage\n";
37660b57cec5SDimitry Andric     for (size_t I = 0; I < MaxChain; I++) {
37670b57cec5SDimitry Andric       CumulativeNonZero += Count[I] * I;
37680b57cec5SDimitry Andric       OS << format("%7lu  %-10lu (%5.1f%%)     %5.1f%%\n", I, Count[I],
37690b57cec5SDimitry Andric                    (Count[I] * 100.0) / NBucket,
37700b57cec5SDimitry Andric                    (CumulativeNonZero * 100.0) / TotalSyms);
37710b57cec5SDimitry Andric     }
37720b57cec5SDimitry Andric   }
37730b57cec5SDimitry Andric 
37740b57cec5SDimitry Andric   // Print histogram for .gnu.hash section
37750b57cec5SDimitry Andric   if (const Elf_GnuHash *GnuHashTable = this->dumper()->getGnuHashTable()) {
37760b57cec5SDimitry Andric     size_t NBucket = GnuHashTable->nbuckets;
37770b57cec5SDimitry Andric     ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets();
37780b57cec5SDimitry Andric     unsigned NumSyms = this->dumper()->dynamic_symbols().size();
37790b57cec5SDimitry Andric     if (!NumSyms)
37800b57cec5SDimitry Andric       return;
37810b57cec5SDimitry Andric     ArrayRef<Elf_Word> Chains = GnuHashTable->values(NumSyms);
37820b57cec5SDimitry Andric     size_t Symndx = GnuHashTable->symndx;
37830b57cec5SDimitry Andric     size_t TotalSyms = 0;
37840b57cec5SDimitry Andric     size_t MaxChain = 1;
37850b57cec5SDimitry Andric     size_t CumulativeNonZero = 0;
37860b57cec5SDimitry Andric 
37870b57cec5SDimitry Andric     if (Chains.empty() || NBucket == 0)
37880b57cec5SDimitry Andric       return;
37890b57cec5SDimitry Andric 
37900b57cec5SDimitry Andric     std::vector<size_t> ChainLen(NBucket, 0);
37910b57cec5SDimitry Andric 
37920b57cec5SDimitry Andric     for (size_t B = 0; B < NBucket; B++) {
37930b57cec5SDimitry Andric       if (!Buckets[B])
37940b57cec5SDimitry Andric         continue;
37950b57cec5SDimitry Andric       size_t Len = 1;
37960b57cec5SDimitry Andric       for (size_t C = Buckets[B] - Symndx;
37970b57cec5SDimitry Andric            C < Chains.size() && (Chains[C] & 1) == 0; C++)
37980b57cec5SDimitry Andric         if (MaxChain < ++Len)
37990b57cec5SDimitry Andric           MaxChain++;
38000b57cec5SDimitry Andric       ChainLen[B] = Len;
38010b57cec5SDimitry Andric       TotalSyms += Len;
38020b57cec5SDimitry Andric     }
38030b57cec5SDimitry Andric     MaxChain++;
38040b57cec5SDimitry Andric 
38050b57cec5SDimitry Andric     if (!TotalSyms)
38060b57cec5SDimitry Andric       return;
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric     std::vector<size_t> Count(MaxChain, 0) ;
38090b57cec5SDimitry Andric     for (size_t B = 0; B < NBucket; B++)
38100b57cec5SDimitry Andric       ++Count[ChainLen[B]];
38110b57cec5SDimitry Andric     // Print Number of buckets with each chain lengths and their cumulative
38120b57cec5SDimitry Andric     // coverage of the symbols
38130b57cec5SDimitry Andric     OS << "Histogram for `.gnu.hash' bucket list length (total of " << NBucket
38140b57cec5SDimitry Andric        << " buckets)\n"
38150b57cec5SDimitry Andric        << " Length  Number     % of total  Coverage\n";
38160b57cec5SDimitry Andric     for (size_t I = 0; I <MaxChain; I++) {
38170b57cec5SDimitry Andric       CumulativeNonZero += Count[I] * I;
38180b57cec5SDimitry Andric       OS << format("%7lu  %-10lu (%5.1f%%)     %5.1f%%\n", I, Count[I],
38190b57cec5SDimitry Andric                    (Count[I] * 100.0) / NBucket,
38200b57cec5SDimitry Andric                    (CumulativeNonZero * 100.0) / TotalSyms);
38210b57cec5SDimitry Andric     }
38220b57cec5SDimitry Andric   }
38230b57cec5SDimitry Andric }
38240b57cec5SDimitry Andric 
38250b57cec5SDimitry Andric template <class ELFT>
38260b57cec5SDimitry Andric void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
38270b57cec5SDimitry Andric   OS << "GNUStyle::printCGProfile not implemented\n";
38280b57cec5SDimitry Andric }
38290b57cec5SDimitry Andric 
38300b57cec5SDimitry Andric template <class ELFT>
38310b57cec5SDimitry Andric void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
38320b57cec5SDimitry Andric     OS << "GNUStyle::printAddrsig not implemented\n";
38330b57cec5SDimitry Andric }
38340b57cec5SDimitry Andric 
38350b57cec5SDimitry Andric static StringRef getGenericNoteTypeName(const uint32_t NT) {
38360b57cec5SDimitry Andric   static const struct {
38370b57cec5SDimitry Andric     uint32_t ID;
38380b57cec5SDimitry Andric     const char *Name;
38390b57cec5SDimitry Andric   } Notes[] = {
38400b57cec5SDimitry Andric       {ELF::NT_VERSION, "NT_VERSION (version)"},
38410b57cec5SDimitry Andric       {ELF::NT_ARCH, "NT_ARCH (architecture)"},
38420b57cec5SDimitry Andric       {ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"},
38430b57cec5SDimitry Andric       {ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"},
38440b57cec5SDimitry Andric   };
38450b57cec5SDimitry Andric 
38460b57cec5SDimitry Andric   for (const auto &Note : Notes)
38470b57cec5SDimitry Andric     if (Note.ID == NT)
38480b57cec5SDimitry Andric       return Note.Name;
38490b57cec5SDimitry Andric 
38500b57cec5SDimitry Andric   return "";
38510b57cec5SDimitry Andric }
38520b57cec5SDimitry Andric 
38530b57cec5SDimitry Andric static std::string getGNUNoteTypeName(const uint32_t NT) {
38540b57cec5SDimitry Andric   static const struct {
38550b57cec5SDimitry Andric     uint32_t ID;
38560b57cec5SDimitry Andric     const char *Name;
38570b57cec5SDimitry Andric   } Notes[] = {
38580b57cec5SDimitry Andric       {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"},
38590b57cec5SDimitry Andric       {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},
38600b57cec5SDimitry Andric       {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},
38610b57cec5SDimitry Andric       {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},
38620b57cec5SDimitry Andric       {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
38630b57cec5SDimitry Andric   };
38640b57cec5SDimitry Andric 
38650b57cec5SDimitry Andric   for (const auto &Note : Notes)
38660b57cec5SDimitry Andric     if (Note.ID == NT)
38670b57cec5SDimitry Andric       return std::string(Note.Name);
38680b57cec5SDimitry Andric 
38690b57cec5SDimitry Andric   std::string string;
38700b57cec5SDimitry Andric   raw_string_ostream OS(string);
38710b57cec5SDimitry Andric   OS << format("Unknown note type (0x%08x)", NT);
38720b57cec5SDimitry Andric   return OS.str();
38730b57cec5SDimitry Andric }
38740b57cec5SDimitry Andric 
38750b57cec5SDimitry Andric static std::string getFreeBSDNoteTypeName(const uint32_t NT) {
38760b57cec5SDimitry Andric   static const struct {
38770b57cec5SDimitry Andric     uint32_t ID;
38780b57cec5SDimitry Andric     const char *Name;
38790b57cec5SDimitry Andric   } Notes[] = {
38800b57cec5SDimitry Andric       {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},
38810b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},
38820b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"},
38830b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"},
38840b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"},
38850b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"},
38860b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"},
38870b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"},
38880b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS,
38890b57cec5SDimitry Andric        "NT_PROCSTAT_PSSTRINGS (ps_strings data)"},
38900b57cec5SDimitry Andric       {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"},
38910b57cec5SDimitry Andric   };
38920b57cec5SDimitry Andric 
38930b57cec5SDimitry Andric   for (const auto &Note : Notes)
38940b57cec5SDimitry Andric     if (Note.ID == NT)
38950b57cec5SDimitry Andric       return std::string(Note.Name);
38960b57cec5SDimitry Andric 
38970b57cec5SDimitry Andric   std::string string;
38980b57cec5SDimitry Andric   raw_string_ostream OS(string);
38990b57cec5SDimitry Andric   OS << format("Unknown note type (0x%08x)", NT);
39000b57cec5SDimitry Andric   return OS.str();
39010b57cec5SDimitry Andric }
39020b57cec5SDimitry Andric 
39030b57cec5SDimitry Andric static std::string getAMDNoteTypeName(const uint32_t NT) {
39040b57cec5SDimitry Andric   static const struct {
39050b57cec5SDimitry Andric     uint32_t ID;
39060b57cec5SDimitry Andric     const char *Name;
39070b57cec5SDimitry Andric   } Notes[] = {{ELF::NT_AMD_AMDGPU_HSA_METADATA,
39080b57cec5SDimitry Andric                 "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"},
39090b57cec5SDimitry Andric                {ELF::NT_AMD_AMDGPU_ISA, "NT_AMD_AMDGPU_ISA (ISA Version)"},
39100b57cec5SDimitry Andric                {ELF::NT_AMD_AMDGPU_PAL_METADATA,
39110b57cec5SDimitry Andric                 "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"}};
39120b57cec5SDimitry Andric 
39130b57cec5SDimitry Andric   for (const auto &Note : Notes)
39140b57cec5SDimitry Andric     if (Note.ID == NT)
39150b57cec5SDimitry Andric       return std::string(Note.Name);
39160b57cec5SDimitry Andric 
39170b57cec5SDimitry Andric   std::string string;
39180b57cec5SDimitry Andric   raw_string_ostream OS(string);
39190b57cec5SDimitry Andric   OS << format("Unknown note type (0x%08x)", NT);
39200b57cec5SDimitry Andric   return OS.str();
39210b57cec5SDimitry Andric }
39220b57cec5SDimitry Andric 
39230b57cec5SDimitry Andric static std::string getAMDGPUNoteTypeName(const uint32_t NT) {
39240b57cec5SDimitry Andric   if (NT == ELF::NT_AMDGPU_METADATA)
39250b57cec5SDimitry Andric     return std::string("NT_AMDGPU_METADATA (AMDGPU Metadata)");
39260b57cec5SDimitry Andric 
39270b57cec5SDimitry Andric   std::string string;
39280b57cec5SDimitry Andric   raw_string_ostream OS(string);
39290b57cec5SDimitry Andric   OS << format("Unknown note type (0x%08x)", NT);
39300b57cec5SDimitry Andric   return OS.str();
39310b57cec5SDimitry Andric }
39320b57cec5SDimitry Andric 
39330b57cec5SDimitry Andric template <typename ELFT>
39340b57cec5SDimitry Andric static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
39350b57cec5SDimitry Andric                                   ArrayRef<uint8_t> Data) {
39360b57cec5SDimitry Andric   std::string str;
39370b57cec5SDimitry Andric   raw_string_ostream OS(str);
39380b57cec5SDimitry Andric   uint32_t PrData;
39390b57cec5SDimitry Andric   auto DumpBit = [&](uint32_t Flag, StringRef Name) {
39400b57cec5SDimitry Andric     if (PrData & Flag) {
39410b57cec5SDimitry Andric       PrData &= ~Flag;
39420b57cec5SDimitry Andric       OS << Name;
39430b57cec5SDimitry Andric       if (PrData)
39440b57cec5SDimitry Andric         OS << ", ";
39450b57cec5SDimitry Andric     }
39460b57cec5SDimitry Andric   };
39470b57cec5SDimitry Andric 
39480b57cec5SDimitry Andric   switch (Type) {
39490b57cec5SDimitry Andric   default:
39500b57cec5SDimitry Andric     OS << format("<application-specific type 0x%x>", Type);
39510b57cec5SDimitry Andric     return OS.str();
39520b57cec5SDimitry Andric   case GNU_PROPERTY_STACK_SIZE: {
39530b57cec5SDimitry Andric     OS << "stack size: ";
39540b57cec5SDimitry Andric     if (DataSize == sizeof(typename ELFT::uint))
39550b57cec5SDimitry Andric       OS << formatv("{0:x}",
39560b57cec5SDimitry Andric                     (uint64_t)(*(const typename ELFT::Addr *)Data.data()));
39570b57cec5SDimitry Andric     else
39580b57cec5SDimitry Andric       OS << format("<corrupt length: 0x%x>", DataSize);
39590b57cec5SDimitry Andric     return OS.str();
39600b57cec5SDimitry Andric   }
39610b57cec5SDimitry Andric   case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
39620b57cec5SDimitry Andric     OS << "no copy on protected";
39630b57cec5SDimitry Andric     if (DataSize)
39640b57cec5SDimitry Andric       OS << format(" <corrupt length: 0x%x>", DataSize);
39650b57cec5SDimitry Andric     return OS.str();
39660b57cec5SDimitry Andric   case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
39670b57cec5SDimitry Andric   case GNU_PROPERTY_X86_FEATURE_1_AND:
39680b57cec5SDimitry Andric     OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
39690b57cec5SDimitry Andric                                                         : "x86 feature: ");
39700b57cec5SDimitry Andric     if (DataSize != 4) {
39710b57cec5SDimitry Andric       OS << format("<corrupt length: 0x%x>", DataSize);
39720b57cec5SDimitry Andric       return OS.str();
39730b57cec5SDimitry Andric     }
39740b57cec5SDimitry Andric     PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data());
39750b57cec5SDimitry Andric     if (PrData == 0) {
39760b57cec5SDimitry Andric       OS << "<None>";
39770b57cec5SDimitry Andric       return OS.str();
39780b57cec5SDimitry Andric     }
39790b57cec5SDimitry Andric     if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
39800b57cec5SDimitry Andric       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
39810b57cec5SDimitry Andric       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
39820b57cec5SDimitry Andric     } else {
39830b57cec5SDimitry Andric       DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
39840b57cec5SDimitry Andric       DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
39850b57cec5SDimitry Andric     }
39860b57cec5SDimitry Andric     if (PrData)
39870b57cec5SDimitry Andric       OS << format("<unknown flags: 0x%x>", PrData);
39880b57cec5SDimitry Andric     return OS.str();
39890b57cec5SDimitry Andric   case GNU_PROPERTY_X86_ISA_1_NEEDED:
39900b57cec5SDimitry Andric   case GNU_PROPERTY_X86_ISA_1_USED:
39910b57cec5SDimitry Andric     OS << "x86 ISA "
39920b57cec5SDimitry Andric        << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");
39930b57cec5SDimitry Andric     if (DataSize != 4) {
39940b57cec5SDimitry Andric       OS << format("<corrupt length: 0x%x>", DataSize);
39950b57cec5SDimitry Andric       return OS.str();
39960b57cec5SDimitry Andric     }
39970b57cec5SDimitry Andric     PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data());
39980b57cec5SDimitry Andric     if (PrData == 0) {
39990b57cec5SDimitry Andric       OS << "<None>";
40000b57cec5SDimitry Andric       return OS.str();
40010b57cec5SDimitry Andric     }
40020b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_CMOV, "CMOV");
40030b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSE, "SSE");
40040b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSE2, "SSE2");
40050b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSE3, "SSE3");
40060b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSSE3, "SSSE3");
40070b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_1, "SSE4_1");
40080b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_2, "SSE4_2");
40090b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX, "AVX");
40100b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX2, "AVX2");
40110b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_FMA, "FMA");
40120b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512F, "AVX512F");
40130b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512CD, "AVX512CD");
40140b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512ER, "AVX512ER");
40150b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512PF, "AVX512PF");
40160b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512VL, "AVX512VL");
40170b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512DQ, "AVX512DQ");
40180b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512BW, "AVX512BW");
40190b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS, "AVX512_4FMAPS");
40200b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW, "AVX512_4VNNIW");
40210b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_BITALG, "AVX512_BITALG");
40220b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_IFMA, "AVX512_IFMA");
40230b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI, "AVX512_VBMI");
40240b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2, "AVX512_VBMI2");
40250b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VNNI, "AVX512_VNNI");
40260b57cec5SDimitry Andric     if (PrData)
40270b57cec5SDimitry Andric       OS << format("<unknown flags: 0x%x>", PrData);
40280b57cec5SDimitry Andric     return OS.str();
40290b57cec5SDimitry Andric     break;
40300b57cec5SDimitry Andric   case GNU_PROPERTY_X86_FEATURE_2_NEEDED:
40310b57cec5SDimitry Andric   case GNU_PROPERTY_X86_FEATURE_2_USED:
40320b57cec5SDimitry Andric     OS << "x86 feature "
40330b57cec5SDimitry Andric        << (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: ");
40340b57cec5SDimitry Andric     if (DataSize != 4) {
40350b57cec5SDimitry Andric       OS << format("<corrupt length: 0x%x>", DataSize);
40360b57cec5SDimitry Andric       return OS.str();
40370b57cec5SDimitry Andric     }
40380b57cec5SDimitry Andric     PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data());
40390b57cec5SDimitry Andric     if (PrData == 0) {
40400b57cec5SDimitry Andric       OS << "<None>";
40410b57cec5SDimitry Andric       return OS.str();
40420b57cec5SDimitry Andric     }
40430b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86");
40440b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87");
40450b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX");
40460b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM");
40470b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM");
40480b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM");
40490b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR");
40500b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE");
40510b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT");
40520b57cec5SDimitry Andric     DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC");
40530b57cec5SDimitry Andric     if (PrData)
40540b57cec5SDimitry Andric       OS << format("<unknown flags: 0x%x>", PrData);
40550b57cec5SDimitry Andric     return OS.str();
40560b57cec5SDimitry Andric   }
40570b57cec5SDimitry Andric }
40580b57cec5SDimitry Andric 
40590b57cec5SDimitry Andric template <typename ELFT>
40600b57cec5SDimitry Andric static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
40610b57cec5SDimitry Andric   using Elf_Word = typename ELFT::Word;
40620b57cec5SDimitry Andric 
40630b57cec5SDimitry Andric   SmallVector<std::string, 4> Properties;
40640b57cec5SDimitry Andric   while (Arr.size() >= 8) {
40650b57cec5SDimitry Andric     uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());
40660b57cec5SDimitry Andric     uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);
40670b57cec5SDimitry Andric     Arr = Arr.drop_front(8);
40680b57cec5SDimitry Andric 
40690b57cec5SDimitry Andric     // Take padding size into account if present.
40700b57cec5SDimitry Andric     uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));
40710b57cec5SDimitry Andric     std::string str;
40720b57cec5SDimitry Andric     raw_string_ostream OS(str);
40730b57cec5SDimitry Andric     if (Arr.size() < PaddedSize) {
40740b57cec5SDimitry Andric       OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize);
40750b57cec5SDimitry Andric       Properties.push_back(OS.str());
40760b57cec5SDimitry Andric       break;
40770b57cec5SDimitry Andric     }
40780b57cec5SDimitry Andric     Properties.push_back(
40790b57cec5SDimitry Andric         getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
40800b57cec5SDimitry Andric     Arr = Arr.drop_front(PaddedSize);
40810b57cec5SDimitry Andric   }
40820b57cec5SDimitry Andric 
40830b57cec5SDimitry Andric   if (!Arr.empty())
40840b57cec5SDimitry Andric     Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>");
40850b57cec5SDimitry Andric 
40860b57cec5SDimitry Andric   return Properties;
40870b57cec5SDimitry Andric }
40880b57cec5SDimitry Andric 
40890b57cec5SDimitry Andric struct GNUAbiTag {
40900b57cec5SDimitry Andric   std::string OSName;
40910b57cec5SDimitry Andric   std::string ABI;
40920b57cec5SDimitry Andric   bool IsValid;
40930b57cec5SDimitry Andric };
40940b57cec5SDimitry Andric 
40950b57cec5SDimitry Andric template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) {
40960b57cec5SDimitry Andric   typedef typename ELFT::Word Elf_Word;
40970b57cec5SDimitry Andric 
40980b57cec5SDimitry Andric   ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()),
40990b57cec5SDimitry Andric                            reinterpret_cast<const Elf_Word *>(Desc.end()));
41000b57cec5SDimitry Andric 
41010b57cec5SDimitry Andric   if (Words.size() < 4)
41020b57cec5SDimitry Andric     return {"", "", /*IsValid=*/false};
41030b57cec5SDimitry Andric 
41040b57cec5SDimitry Andric   static const char *OSNames[] = {
41050b57cec5SDimitry Andric       "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",
41060b57cec5SDimitry Andric   };
41070b57cec5SDimitry Andric   StringRef OSName = "Unknown";
41080b57cec5SDimitry Andric   if (Words[0] < array_lengthof(OSNames))
41090b57cec5SDimitry Andric     OSName = OSNames[Words[0]];
41100b57cec5SDimitry Andric   uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3];
41110b57cec5SDimitry Andric   std::string str;
41120b57cec5SDimitry Andric   raw_string_ostream ABI(str);
41130b57cec5SDimitry Andric   ABI << Major << "." << Minor << "." << Patch;
41140b57cec5SDimitry Andric   return {OSName, ABI.str(), /*IsValid=*/true};
41150b57cec5SDimitry Andric }
41160b57cec5SDimitry Andric 
41170b57cec5SDimitry Andric static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) {
41180b57cec5SDimitry Andric   std::string str;
41190b57cec5SDimitry Andric   raw_string_ostream OS(str);
41200b57cec5SDimitry Andric   for (const auto &B : Desc)
41210b57cec5SDimitry Andric     OS << format_hex_no_prefix(B, 2);
41220b57cec5SDimitry Andric   return OS.str();
41230b57cec5SDimitry Andric }
41240b57cec5SDimitry Andric 
41250b57cec5SDimitry Andric static StringRef getGNUGoldVersion(ArrayRef<uint8_t> Desc) {
41260b57cec5SDimitry Andric   return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
41270b57cec5SDimitry Andric }
41280b57cec5SDimitry Andric 
41290b57cec5SDimitry Andric template <typename ELFT>
41300b57cec5SDimitry Andric static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
41310b57cec5SDimitry Andric                          ArrayRef<uint8_t> Desc) {
41320b57cec5SDimitry Andric   switch (NoteType) {
41330b57cec5SDimitry Andric   default:
41340b57cec5SDimitry Andric     return;
41350b57cec5SDimitry Andric   case ELF::NT_GNU_ABI_TAG: {
41360b57cec5SDimitry Andric     const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
41370b57cec5SDimitry Andric     if (!AbiTag.IsValid)
41380b57cec5SDimitry Andric       OS << "    <corrupt GNU_ABI_TAG>";
41390b57cec5SDimitry Andric     else
41400b57cec5SDimitry Andric       OS << "    OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI;
41410b57cec5SDimitry Andric     break;
41420b57cec5SDimitry Andric   }
41430b57cec5SDimitry Andric   case ELF::NT_GNU_BUILD_ID: {
41440b57cec5SDimitry Andric     OS << "    Build ID: " << getGNUBuildId(Desc);
41450b57cec5SDimitry Andric     break;
41460b57cec5SDimitry Andric   }
41470b57cec5SDimitry Andric   case ELF::NT_GNU_GOLD_VERSION:
41480b57cec5SDimitry Andric     OS << "    Version: " << getGNUGoldVersion(Desc);
41490b57cec5SDimitry Andric     break;
41500b57cec5SDimitry Andric   case ELF::NT_GNU_PROPERTY_TYPE_0:
41510b57cec5SDimitry Andric     OS << "    Properties:";
41520b57cec5SDimitry Andric     for (const auto &Property : getGNUPropertyList<ELFT>(Desc))
41530b57cec5SDimitry Andric       OS << "    " << Property << "\n";
41540b57cec5SDimitry Andric     break;
41550b57cec5SDimitry Andric   }
41560b57cec5SDimitry Andric   OS << '\n';
41570b57cec5SDimitry Andric }
41580b57cec5SDimitry Andric 
41590b57cec5SDimitry Andric struct AMDNote {
41600b57cec5SDimitry Andric   std::string Type;
41610b57cec5SDimitry Andric   std::string Value;
41620b57cec5SDimitry Andric };
41630b57cec5SDimitry Andric 
41640b57cec5SDimitry Andric template <typename ELFT>
41650b57cec5SDimitry Andric static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
41660b57cec5SDimitry Andric   switch (NoteType) {
41670b57cec5SDimitry Andric   default:
41680b57cec5SDimitry Andric     return {"", ""};
41690b57cec5SDimitry Andric   case ELF::NT_AMD_AMDGPU_HSA_METADATA:
41700b57cec5SDimitry Andric     return {
41710b57cec5SDimitry Andric         "HSA Metadata",
41720b57cec5SDimitry Andric         std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};
41730b57cec5SDimitry Andric   case ELF::NT_AMD_AMDGPU_ISA:
41740b57cec5SDimitry Andric     return {
41750b57cec5SDimitry Andric         "ISA Version",
41760b57cec5SDimitry Andric         std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};
41770b57cec5SDimitry Andric   }
41780b57cec5SDimitry Andric }
41790b57cec5SDimitry Andric 
41800b57cec5SDimitry Andric struct AMDGPUNote {
41810b57cec5SDimitry Andric   std::string Type;
41820b57cec5SDimitry Andric   std::string Value;
41830b57cec5SDimitry Andric };
41840b57cec5SDimitry Andric 
41850b57cec5SDimitry Andric template <typename ELFT>
41860b57cec5SDimitry Andric static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
41870b57cec5SDimitry Andric   switch (NoteType) {
41880b57cec5SDimitry Andric   default:
41890b57cec5SDimitry Andric     return {"", ""};
41900b57cec5SDimitry Andric   case ELF::NT_AMDGPU_METADATA: {
41910b57cec5SDimitry Andric     auto MsgPackString =
41920b57cec5SDimitry Andric         StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
41930b57cec5SDimitry Andric     msgpack::Document MsgPackDoc;
41940b57cec5SDimitry Andric     if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))
41950b57cec5SDimitry Andric       return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"};
41960b57cec5SDimitry Andric 
41970b57cec5SDimitry Andric     AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
41980b57cec5SDimitry Andric     if (!Verifier.verify(MsgPackDoc.getRoot()))
41990b57cec5SDimitry Andric       return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"};
42000b57cec5SDimitry Andric 
42010b57cec5SDimitry Andric     std::string HSAMetadataString;
42020b57cec5SDimitry Andric     raw_string_ostream StrOS(HSAMetadataString);
42030b57cec5SDimitry Andric     MsgPackDoc.toYAML(StrOS);
42040b57cec5SDimitry Andric 
42050b57cec5SDimitry Andric     return {"AMDGPU Metadata", StrOS.str()};
42060b57cec5SDimitry Andric   }
42070b57cec5SDimitry Andric   }
42080b57cec5SDimitry Andric }
42090b57cec5SDimitry Andric 
42100b57cec5SDimitry Andric template <class ELFT>
42110b57cec5SDimitry Andric void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
42120b57cec5SDimitry Andric   auto PrintHeader = [&](const typename ELFT::Off Offset,
42130b57cec5SDimitry Andric                          const typename ELFT::Addr Size) {
42140b57cec5SDimitry Andric     OS << "Displaying notes found at file offset " << format_hex(Offset, 10)
42150b57cec5SDimitry Andric        << " with length " << format_hex(Size, 10) << ":\n"
42160b57cec5SDimitry Andric        << "  Owner                 Data size\tDescription\n";
42170b57cec5SDimitry Andric   };
42180b57cec5SDimitry Andric 
42190b57cec5SDimitry Andric   auto ProcessNote = [&](const Elf_Note &Note) {
42200b57cec5SDimitry Andric     StringRef Name = Note.getName();
42210b57cec5SDimitry Andric     ArrayRef<uint8_t> Descriptor = Note.getDesc();
42220b57cec5SDimitry Andric     Elf_Word Type = Note.getType();
42230b57cec5SDimitry Andric 
42240b57cec5SDimitry Andric     OS << "  " << Name << std::string(22 - Name.size(), ' ')
42250b57cec5SDimitry Andric        << format_hex(Descriptor.size(), 10) << '\t';
42260b57cec5SDimitry Andric 
42270b57cec5SDimitry Andric     if (Name == "GNU") {
42280b57cec5SDimitry Andric       OS << getGNUNoteTypeName(Type) << '\n';
42290b57cec5SDimitry Andric       printGNUNote<ELFT>(OS, Type, Descriptor);
42300b57cec5SDimitry Andric     } else if (Name == "FreeBSD") {
42310b57cec5SDimitry Andric       OS << getFreeBSDNoteTypeName(Type) << '\n';
42320b57cec5SDimitry Andric     } else if (Name == "AMD") {
42330b57cec5SDimitry Andric       OS << getAMDNoteTypeName(Type) << '\n';
42340b57cec5SDimitry Andric       const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
42350b57cec5SDimitry Andric       if (!N.Type.empty())
42360b57cec5SDimitry Andric         OS << "    " << N.Type << ":\n        " << N.Value << '\n';
42370b57cec5SDimitry Andric     } else if (Name == "AMDGPU") {
42380b57cec5SDimitry Andric       OS << getAMDGPUNoteTypeName(Type) << '\n';
42390b57cec5SDimitry Andric       const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
42400b57cec5SDimitry Andric       if (!N.Type.empty())
42410b57cec5SDimitry Andric         OS << "    " << N.Type << ":\n        " << N.Value << '\n';
42420b57cec5SDimitry Andric     } else {
42430b57cec5SDimitry Andric       StringRef NoteType = getGenericNoteTypeName(Type);
42440b57cec5SDimitry Andric       if (!NoteType.empty())
42450b57cec5SDimitry Andric         OS << NoteType;
42460b57cec5SDimitry Andric       else
42470b57cec5SDimitry Andric         OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
42480b57cec5SDimitry Andric     }
42490b57cec5SDimitry Andric     OS << '\n';
42500b57cec5SDimitry Andric   };
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric   if (Obj->getHeader()->e_type == ELF::ET_CORE) {
42530b57cec5SDimitry Andric     for (const auto &P : unwrapOrError(Obj->program_headers())) {
42540b57cec5SDimitry Andric       if (P.p_type != PT_NOTE)
42550b57cec5SDimitry Andric         continue;
42560b57cec5SDimitry Andric       PrintHeader(P.p_offset, P.p_filesz);
42570b57cec5SDimitry Andric       Error Err = Error::success();
42580b57cec5SDimitry Andric       for (const auto &Note : Obj->notes(P, Err))
42590b57cec5SDimitry Andric         ProcessNote(Note);
42600b57cec5SDimitry Andric       if (Err)
42610b57cec5SDimitry Andric         error(std::move(Err));
42620b57cec5SDimitry Andric     }
42630b57cec5SDimitry Andric   } else {
42640b57cec5SDimitry Andric     for (const auto &S : unwrapOrError(Obj->sections())) {
42650b57cec5SDimitry Andric       if (S.sh_type != SHT_NOTE)
42660b57cec5SDimitry Andric         continue;
42670b57cec5SDimitry Andric       PrintHeader(S.sh_offset, S.sh_size);
42680b57cec5SDimitry Andric       Error Err = Error::success();
42690b57cec5SDimitry Andric       for (const auto &Note : Obj->notes(S, Err))
42700b57cec5SDimitry Andric         ProcessNote(Note);
42710b57cec5SDimitry Andric       if (Err)
42720b57cec5SDimitry Andric         error(std::move(Err));
42730b57cec5SDimitry Andric     }
42740b57cec5SDimitry Andric   }
42750b57cec5SDimitry Andric }
42760b57cec5SDimitry Andric 
42770b57cec5SDimitry Andric template <class ELFT>
42780b57cec5SDimitry Andric void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
42790b57cec5SDimitry Andric   OS << "printELFLinkerOptions not implemented!\n";
42800b57cec5SDimitry Andric }
42810b57cec5SDimitry Andric 
42820b57cec5SDimitry Andric template <class ELFT>
42830b57cec5SDimitry Andric void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
42840b57cec5SDimitry Andric   size_t Bias = ELFT::Is64Bits ? 8 : 0;
42850b57cec5SDimitry Andric   auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
42860b57cec5SDimitry Andric     OS.PadToColumn(2);
42870b57cec5SDimitry Andric     OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
42880b57cec5SDimitry Andric     OS.PadToColumn(11 + Bias);
42890b57cec5SDimitry Andric     OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";
42900b57cec5SDimitry Andric     OS.PadToColumn(22 + Bias);
42910b57cec5SDimitry Andric     OS << format_hex_no_prefix(*E, 8 + Bias);
42920b57cec5SDimitry Andric     OS.PadToColumn(31 + 2 * Bias);
42930b57cec5SDimitry Andric     OS << Purpose << "\n";
42940b57cec5SDimitry Andric   };
42950b57cec5SDimitry Andric 
42960b57cec5SDimitry Andric   OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");
42970b57cec5SDimitry Andric   OS << " Canonical gp value: "
42980b57cec5SDimitry Andric      << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";
42990b57cec5SDimitry Andric 
43000b57cec5SDimitry Andric   OS << " Reserved entries:\n";
43010b57cec5SDimitry Andric   if (ELFT::Is64Bits)
43020b57cec5SDimitry Andric     OS << "           Address     Access          Initial Purpose\n";
43030b57cec5SDimitry Andric   else
43040b57cec5SDimitry Andric     OS << "   Address     Access  Initial Purpose\n";
43050b57cec5SDimitry Andric   PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");
43060b57cec5SDimitry Andric   if (Parser.getGotModulePointer())
43070b57cec5SDimitry Andric     PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");
43080b57cec5SDimitry Andric 
43090b57cec5SDimitry Andric   if (!Parser.getLocalEntries().empty()) {
43100b57cec5SDimitry Andric     OS << "\n";
43110b57cec5SDimitry Andric     OS << " Local entries:\n";
43120b57cec5SDimitry Andric     if (ELFT::Is64Bits)
43130b57cec5SDimitry Andric       OS << "           Address     Access          Initial\n";
43140b57cec5SDimitry Andric     else
43150b57cec5SDimitry Andric       OS << "   Address     Access  Initial\n";
43160b57cec5SDimitry Andric     for (auto &E : Parser.getLocalEntries())
43170b57cec5SDimitry Andric       PrintEntry(&E, "");
43180b57cec5SDimitry Andric   }
43190b57cec5SDimitry Andric 
43200b57cec5SDimitry Andric   if (Parser.IsStatic)
43210b57cec5SDimitry Andric     return;
43220b57cec5SDimitry Andric 
43230b57cec5SDimitry Andric   if (!Parser.getGlobalEntries().empty()) {
43240b57cec5SDimitry Andric     OS << "\n";
43250b57cec5SDimitry Andric     OS << " Global entries:\n";
43260b57cec5SDimitry Andric     if (ELFT::Is64Bits)
43270b57cec5SDimitry Andric       OS << "           Address     Access          Initial         Sym.Val."
43280b57cec5SDimitry Andric          << " Type    Ndx Name\n";
43290b57cec5SDimitry Andric     else
43300b57cec5SDimitry Andric       OS << "   Address     Access  Initial Sym.Val. Type    Ndx Name\n";
43310b57cec5SDimitry Andric     for (auto &E : Parser.getGlobalEntries()) {
43320b57cec5SDimitry Andric       const Elf_Sym *Sym = Parser.getGotSym(&E);
43330b57cec5SDimitry Andric       std::string SymName = this->dumper()->getFullSymbolName(
43340b57cec5SDimitry Andric           Sym, this->dumper()->getDynamicStringTable(), false);
43350b57cec5SDimitry Andric 
43360b57cec5SDimitry Andric       OS.PadToColumn(2);
43370b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
43380b57cec5SDimitry Andric       OS.PadToColumn(11 + Bias);
43390b57cec5SDimitry Andric       OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";
43400b57cec5SDimitry Andric       OS.PadToColumn(22 + Bias);
43410b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(E, 8 + Bias));
43420b57cec5SDimitry Andric       OS.PadToColumn(31 + 2 * Bias);
43430b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
43440b57cec5SDimitry Andric       OS.PadToColumn(40 + 3 * Bias);
43450b57cec5SDimitry Andric       OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
43460b57cec5SDimitry Andric       OS.PadToColumn(48 + 3 * Bias);
43470b57cec5SDimitry Andric       OS << getSymbolSectionNdx(Parser.Obj, Sym,
43480b57cec5SDimitry Andric                                 this->dumper()->dynamic_symbols().begin());
43490b57cec5SDimitry Andric       OS.PadToColumn(52 + 3 * Bias);
43500b57cec5SDimitry Andric       OS << SymName << "\n";
43510b57cec5SDimitry Andric     }
43520b57cec5SDimitry Andric   }
43530b57cec5SDimitry Andric 
43540b57cec5SDimitry Andric   if (!Parser.getOtherEntries().empty())
43550b57cec5SDimitry Andric     OS << "\n Number of TLS and multi-GOT entries "
43560b57cec5SDimitry Andric        << Parser.getOtherEntries().size() << "\n";
43570b57cec5SDimitry Andric }
43580b57cec5SDimitry Andric 
43590b57cec5SDimitry Andric template <class ELFT>
43600b57cec5SDimitry Andric void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
43610b57cec5SDimitry Andric   size_t Bias = ELFT::Is64Bits ? 8 : 0;
43620b57cec5SDimitry Andric   auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
43630b57cec5SDimitry Andric     OS.PadToColumn(2);
43640b57cec5SDimitry Andric     OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias);
43650b57cec5SDimitry Andric     OS.PadToColumn(11 + Bias);
43660b57cec5SDimitry Andric     OS << format_hex_no_prefix(*E, 8 + Bias);
43670b57cec5SDimitry Andric     OS.PadToColumn(20 + 2 * Bias);
43680b57cec5SDimitry Andric     OS << Purpose << "\n";
43690b57cec5SDimitry Andric   };
43700b57cec5SDimitry Andric 
43710b57cec5SDimitry Andric   OS << "PLT GOT:\n\n";
43720b57cec5SDimitry Andric 
43730b57cec5SDimitry Andric   OS << " Reserved entries:\n";
43740b57cec5SDimitry Andric   OS << "   Address  Initial Purpose\n";
43750b57cec5SDimitry Andric   PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");
43760b57cec5SDimitry Andric   if (Parser.getPltModulePointer())
43770b57cec5SDimitry Andric     PrintEntry(Parser.getPltModulePointer(), "Module pointer");
43780b57cec5SDimitry Andric 
43790b57cec5SDimitry Andric   if (!Parser.getPltEntries().empty()) {
43800b57cec5SDimitry Andric     OS << "\n";
43810b57cec5SDimitry Andric     OS << " Entries:\n";
43820b57cec5SDimitry Andric     OS << "   Address  Initial Sym.Val. Type    Ndx Name\n";
43830b57cec5SDimitry Andric     for (auto &E : Parser.getPltEntries()) {
43840b57cec5SDimitry Andric       const Elf_Sym *Sym = Parser.getPltSym(&E);
43850b57cec5SDimitry Andric       std::string SymName = this->dumper()->getFullSymbolName(
43860b57cec5SDimitry Andric           Sym, this->dumper()->getDynamicStringTable(), false);
43870b57cec5SDimitry Andric 
43880b57cec5SDimitry Andric       OS.PadToColumn(2);
43890b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias));
43900b57cec5SDimitry Andric       OS.PadToColumn(11 + Bias);
43910b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(E, 8 + Bias));
43920b57cec5SDimitry Andric       OS.PadToColumn(20 + 2 * Bias);
43930b57cec5SDimitry Andric       OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
43940b57cec5SDimitry Andric       OS.PadToColumn(29 + 3 * Bias);
43950b57cec5SDimitry Andric       OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
43960b57cec5SDimitry Andric       OS.PadToColumn(37 + 3 * Bias);
43970b57cec5SDimitry Andric       OS << getSymbolSectionNdx(Parser.Obj, Sym,
43980b57cec5SDimitry Andric                                 this->dumper()->dynamic_symbols().begin());
43990b57cec5SDimitry Andric       OS.PadToColumn(41 + 3 * Bias);
44000b57cec5SDimitry Andric       OS << SymName << "\n";
44010b57cec5SDimitry Andric     }
44020b57cec5SDimitry Andric   }
44030b57cec5SDimitry Andric }
44040b57cec5SDimitry Andric 
44050b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
44060b57cec5SDimitry Andric   const Elf_Ehdr *E = Obj->getHeader();
44070b57cec5SDimitry Andric   {
44080b57cec5SDimitry Andric     DictScope D(W, "ElfHeader");
44090b57cec5SDimitry Andric     {
44100b57cec5SDimitry Andric       DictScope D(W, "Ident");
44110b57cec5SDimitry Andric       W.printBinary("Magic", makeArrayRef(E->e_ident).slice(ELF::EI_MAG0, 4));
44120b57cec5SDimitry Andric       W.printEnum("Class", E->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass));
44130b57cec5SDimitry Andric       W.printEnum("DataEncoding", E->e_ident[ELF::EI_DATA],
44140b57cec5SDimitry Andric                   makeArrayRef(ElfDataEncoding));
44150b57cec5SDimitry Andric       W.printNumber("FileVersion", E->e_ident[ELF::EI_VERSION]);
44160b57cec5SDimitry Andric 
44170b57cec5SDimitry Andric       auto OSABI = makeArrayRef(ElfOSABI);
44180b57cec5SDimitry Andric       if (E->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
44190b57cec5SDimitry Andric           E->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
44200b57cec5SDimitry Andric         switch (E->e_machine) {
44210b57cec5SDimitry Andric         case ELF::EM_AMDGPU:
44220b57cec5SDimitry Andric           OSABI = makeArrayRef(AMDGPUElfOSABI);
44230b57cec5SDimitry Andric           break;
44240b57cec5SDimitry Andric         case ELF::EM_ARM:
44250b57cec5SDimitry Andric           OSABI = makeArrayRef(ARMElfOSABI);
44260b57cec5SDimitry Andric           break;
44270b57cec5SDimitry Andric         case ELF::EM_TI_C6000:
44280b57cec5SDimitry Andric           OSABI = makeArrayRef(C6000ElfOSABI);
44290b57cec5SDimitry Andric           break;
44300b57cec5SDimitry Andric         }
44310b57cec5SDimitry Andric       }
44320b57cec5SDimitry Andric       W.printEnum("OS/ABI", E->e_ident[ELF::EI_OSABI], OSABI);
44330b57cec5SDimitry Andric       W.printNumber("ABIVersion", E->e_ident[ELF::EI_ABIVERSION]);
44340b57cec5SDimitry Andric       W.printBinary("Unused", makeArrayRef(E->e_ident).slice(ELF::EI_PAD));
44350b57cec5SDimitry Andric     }
44360b57cec5SDimitry Andric 
44370b57cec5SDimitry Andric     W.printEnum("Type", E->e_type, makeArrayRef(ElfObjectFileType));
44380b57cec5SDimitry Andric     W.printEnum("Machine", E->e_machine, makeArrayRef(ElfMachineType));
44390b57cec5SDimitry Andric     W.printNumber("Version", E->e_version);
44400b57cec5SDimitry Andric     W.printHex("Entry", E->e_entry);
44410b57cec5SDimitry Andric     W.printHex("ProgramHeaderOffset", E->e_phoff);
44420b57cec5SDimitry Andric     W.printHex("SectionHeaderOffset", E->e_shoff);
44430b57cec5SDimitry Andric     if (E->e_machine == EM_MIPS)
44440b57cec5SDimitry Andric       W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderMipsFlags),
44450b57cec5SDimitry Andric                    unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
44460b57cec5SDimitry Andric                    unsigned(ELF::EF_MIPS_MACH));
44470b57cec5SDimitry Andric     else if (E->e_machine == EM_AMDGPU)
44480b57cec5SDimitry Andric       W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags),
44490b57cec5SDimitry Andric                    unsigned(ELF::EF_AMDGPU_MACH));
44500b57cec5SDimitry Andric     else if (E->e_machine == EM_RISCV)
44510b57cec5SDimitry Andric       W.printFlags("Flags", E->e_flags, makeArrayRef(ElfHeaderRISCVFlags));
44520b57cec5SDimitry Andric     else
44530b57cec5SDimitry Andric       W.printFlags("Flags", E->e_flags);
44540b57cec5SDimitry Andric     W.printNumber("HeaderSize", E->e_ehsize);
44550b57cec5SDimitry Andric     W.printNumber("ProgramHeaderEntrySize", E->e_phentsize);
44560b57cec5SDimitry Andric     W.printNumber("ProgramHeaderCount", E->e_phnum);
44570b57cec5SDimitry Andric     W.printNumber("SectionHeaderEntrySize", E->e_shentsize);
44580b57cec5SDimitry Andric     W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj));
44590b57cec5SDimitry Andric     W.printString("StringTableSectionIndex",
44600b57cec5SDimitry Andric                   getSectionHeaderTableIndexString(Obj));
44610b57cec5SDimitry Andric   }
44620b57cec5SDimitry Andric }
44630b57cec5SDimitry Andric 
44640b57cec5SDimitry Andric template <class ELFT>
44650b57cec5SDimitry Andric void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) {
44660b57cec5SDimitry Andric   DictScope Lists(W, "Groups");
44670b57cec5SDimitry Andric   std::vector<GroupSection> V = getGroups<ELFT>(Obj);
44680b57cec5SDimitry Andric   DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
44690b57cec5SDimitry Andric   for (const GroupSection &G : V) {
44700b57cec5SDimitry Andric     DictScope D(W, "Group");
44710b57cec5SDimitry Andric     W.printNumber("Name", G.Name, G.ShName);
44720b57cec5SDimitry Andric     W.printNumber("Index", G.Index);
44730b57cec5SDimitry Andric     W.printNumber("Link", G.Link);
44740b57cec5SDimitry Andric     W.printNumber("Info", G.Info);
44750b57cec5SDimitry Andric     W.printHex("Type", getGroupType(G.Type), G.Type);
44760b57cec5SDimitry Andric     W.startLine() << "Signature: " << G.Signature << "\n";
44770b57cec5SDimitry Andric 
44780b57cec5SDimitry Andric     ListScope L(W, "Section(s) in group");
44790b57cec5SDimitry Andric     for (const GroupMember &GM : G.Members) {
44800b57cec5SDimitry Andric       const GroupSection *MainGroup = Map[GM.Index];
44810b57cec5SDimitry Andric       if (MainGroup != &G) {
44820b57cec5SDimitry Andric         W.flush();
44830b57cec5SDimitry Andric         errs() << "Error: " << GM.Name << " (" << GM.Index
44840b57cec5SDimitry Andric                << ") in a group " + G.Name + " (" << G.Index
44850b57cec5SDimitry Andric                << ") is already in a group " + MainGroup->Name + " ("
44860b57cec5SDimitry Andric                << MainGroup->Index << ")\n";
44870b57cec5SDimitry Andric         errs().flush();
44880b57cec5SDimitry Andric         continue;
44890b57cec5SDimitry Andric       }
44900b57cec5SDimitry Andric       W.startLine() << GM.Name << " (" << GM.Index << ")\n";
44910b57cec5SDimitry Andric     }
44920b57cec5SDimitry Andric   }
44930b57cec5SDimitry Andric 
44940b57cec5SDimitry Andric   if (V.empty())
44950b57cec5SDimitry Andric     W.startLine() << "There are no group sections in the file.\n";
44960b57cec5SDimitry Andric }
44970b57cec5SDimitry Andric 
44980b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
44990b57cec5SDimitry Andric   ListScope D(W, "Relocations");
45000b57cec5SDimitry Andric 
45010b57cec5SDimitry Andric   int SectionNumber = -1;
45020b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
45030b57cec5SDimitry Andric     ++SectionNumber;
45040b57cec5SDimitry Andric 
45050b57cec5SDimitry Andric     if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
45060b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL &&
45070b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_ANDROID_RELA &&
45080b57cec5SDimitry Andric         Sec.sh_type != ELF::SHT_ANDROID_RELR)
45090b57cec5SDimitry Andric       continue;
45100b57cec5SDimitry Andric 
45110b57cec5SDimitry Andric     StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
45120b57cec5SDimitry Andric 
45130b57cec5SDimitry Andric     W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
45140b57cec5SDimitry Andric     W.indent();
45150b57cec5SDimitry Andric 
45160b57cec5SDimitry Andric     printRelocations(&Sec, Obj);
45170b57cec5SDimitry Andric 
45180b57cec5SDimitry Andric     W.unindent();
45190b57cec5SDimitry Andric     W.startLine() << "}\n";
45200b57cec5SDimitry Andric   }
45210b57cec5SDimitry Andric }
45220b57cec5SDimitry Andric 
45230b57cec5SDimitry Andric template <class ELFT>
45240b57cec5SDimitry Andric void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
45250b57cec5SDimitry Andric   const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link));
45260b57cec5SDimitry Andric 
45270b57cec5SDimitry Andric   switch (Sec->sh_type) {
45280b57cec5SDimitry Andric   case ELF::SHT_REL:
45290b57cec5SDimitry Andric     for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) {
45300b57cec5SDimitry Andric       Elf_Rela Rela;
45310b57cec5SDimitry Andric       Rela.r_offset = R.r_offset;
45320b57cec5SDimitry Andric       Rela.r_info = R.r_info;
45330b57cec5SDimitry Andric       Rela.r_addend = 0;
45340b57cec5SDimitry Andric       printRelocation(Obj, Rela, SymTab);
45350b57cec5SDimitry Andric     }
45360b57cec5SDimitry Andric     break;
45370b57cec5SDimitry Andric   case ELF::SHT_RELA:
45380b57cec5SDimitry Andric     for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
45390b57cec5SDimitry Andric       printRelocation(Obj, R, SymTab);
45400b57cec5SDimitry Andric     break;
45410b57cec5SDimitry Andric   case ELF::SHT_RELR:
45420b57cec5SDimitry Andric   case ELF::SHT_ANDROID_RELR: {
45430b57cec5SDimitry Andric     Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec));
45440b57cec5SDimitry Andric     if (opts::RawRelr) {
45450b57cec5SDimitry Andric       for (const Elf_Relr &R : Relrs)
45460b57cec5SDimitry Andric         W.startLine() << W.hex(R) << "\n";
45470b57cec5SDimitry Andric     } else {
45480b57cec5SDimitry Andric       std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
45490b57cec5SDimitry Andric       for (const Elf_Rela &R : RelrRelas)
45500b57cec5SDimitry Andric         printRelocation(Obj, R, SymTab);
45510b57cec5SDimitry Andric     }
45520b57cec5SDimitry Andric     break;
45530b57cec5SDimitry Andric   }
45540b57cec5SDimitry Andric   case ELF::SHT_ANDROID_REL:
45550b57cec5SDimitry Andric   case ELF::SHT_ANDROID_RELA:
45560b57cec5SDimitry Andric     for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
45570b57cec5SDimitry Andric       printRelocation(Obj, R, SymTab);
45580b57cec5SDimitry Andric     break;
45590b57cec5SDimitry Andric   }
45600b57cec5SDimitry Andric }
45610b57cec5SDimitry Andric 
45620b57cec5SDimitry Andric template <class ELFT>
45630b57cec5SDimitry Andric void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel,
45640b57cec5SDimitry Andric                                       const Elf_Shdr *SymTab) {
45650b57cec5SDimitry Andric   SmallString<32> RelocName;
45660b57cec5SDimitry Andric   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
45670b57cec5SDimitry Andric   std::string TargetName;
45680b57cec5SDimitry Andric   const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab));
45690b57cec5SDimitry Andric   if (Sym && Sym->getType() == ELF::STT_SECTION) {
45700b57cec5SDimitry Andric     const Elf_Shdr *Sec = unwrapOrError(
45710b57cec5SDimitry Andric         Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
45720b57cec5SDimitry Andric     TargetName = unwrapOrError(Obj->getSectionName(Sec));
45730b57cec5SDimitry Andric   } else if (Sym) {
45740b57cec5SDimitry Andric     StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
45750b57cec5SDimitry Andric     TargetName = this->dumper()->getFullSymbolName(
45760b57cec5SDimitry Andric         Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */);
45770b57cec5SDimitry Andric   }
45780b57cec5SDimitry Andric 
45790b57cec5SDimitry Andric   if (opts::ExpandRelocs) {
45800b57cec5SDimitry Andric     DictScope Group(W, "Relocation");
45810b57cec5SDimitry Andric     W.printHex("Offset", Rel.r_offset);
45820b57cec5SDimitry Andric     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
45830b57cec5SDimitry Andric     W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-",
45840b57cec5SDimitry Andric                   Rel.getSymbol(Obj->isMips64EL()));
45850b57cec5SDimitry Andric     W.printHex("Addend", Rel.r_addend);
45860b57cec5SDimitry Andric   } else {
45870b57cec5SDimitry Andric     raw_ostream &OS = W.startLine();
45880b57cec5SDimitry Andric     OS << W.hex(Rel.r_offset) << " " << RelocName << " "
45890b57cec5SDimitry Andric        << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Rel.r_addend)
45900b57cec5SDimitry Andric        << "\n";
45910b57cec5SDimitry Andric   }
45920b57cec5SDimitry Andric }
45930b57cec5SDimitry Andric 
45940b57cec5SDimitry Andric template <class ELFT>
45950b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
45960b57cec5SDimitry Andric   ListScope SectionsD(W, "Sections");
45970b57cec5SDimitry Andric 
45980b57cec5SDimitry Andric   int SectionIndex = -1;
45990b57cec5SDimitry Andric   ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
46000b57cec5SDimitry Andric   const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject();
46010b57cec5SDimitry Andric   for (const Elf_Shdr &Sec : Sections) {
46020b57cec5SDimitry Andric     StringRef Name = getSectionName(Sec, *ElfObj, Sections);
46030b57cec5SDimitry Andric     DictScope SectionD(W, "Section");
46040b57cec5SDimitry Andric     W.printNumber("Index", ++SectionIndex);
46050b57cec5SDimitry Andric     W.printNumber("Name", Name, Sec.sh_name);
46060b57cec5SDimitry Andric     W.printHex(
46070b57cec5SDimitry Andric         "Type",
46080b57cec5SDimitry Andric         object::getELFSectionTypeName(Obj->getHeader()->e_machine, Sec.sh_type),
46090b57cec5SDimitry Andric         Sec.sh_type);
46100b57cec5SDimitry Andric     std::vector<EnumEntry<unsigned>> SectionFlags(std::begin(ElfSectionFlags),
46110b57cec5SDimitry Andric                                                   std::end(ElfSectionFlags));
46120b57cec5SDimitry Andric     switch (Obj->getHeader()->e_machine) {
46130b57cec5SDimitry Andric     case EM_ARM:
46140b57cec5SDimitry Andric       SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags),
46150b57cec5SDimitry Andric                           std::end(ElfARMSectionFlags));
46160b57cec5SDimitry Andric       break;
46170b57cec5SDimitry Andric     case EM_HEXAGON:
46180b57cec5SDimitry Andric       SectionFlags.insert(SectionFlags.end(),
46190b57cec5SDimitry Andric                           std::begin(ElfHexagonSectionFlags),
46200b57cec5SDimitry Andric                           std::end(ElfHexagonSectionFlags));
46210b57cec5SDimitry Andric       break;
46220b57cec5SDimitry Andric     case EM_MIPS:
46230b57cec5SDimitry Andric       SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags),
46240b57cec5SDimitry Andric                           std::end(ElfMipsSectionFlags));
46250b57cec5SDimitry Andric       break;
46260b57cec5SDimitry Andric     case EM_X86_64:
46270b57cec5SDimitry Andric       SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags),
46280b57cec5SDimitry Andric                           std::end(ElfX86_64SectionFlags));
46290b57cec5SDimitry Andric       break;
46300b57cec5SDimitry Andric     case EM_XCORE:
46310b57cec5SDimitry Andric       SectionFlags.insert(SectionFlags.end(), std::begin(ElfXCoreSectionFlags),
46320b57cec5SDimitry Andric                           std::end(ElfXCoreSectionFlags));
46330b57cec5SDimitry Andric       break;
46340b57cec5SDimitry Andric     default:
46350b57cec5SDimitry Andric       // Nothing to do.
46360b57cec5SDimitry Andric       break;
46370b57cec5SDimitry Andric     }
46380b57cec5SDimitry Andric     W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags));
46390b57cec5SDimitry Andric     W.printHex("Address", Sec.sh_addr);
46400b57cec5SDimitry Andric     W.printHex("Offset", Sec.sh_offset);
46410b57cec5SDimitry Andric     W.printNumber("Size", Sec.sh_size);
46420b57cec5SDimitry Andric     W.printNumber("Link", Sec.sh_link);
46430b57cec5SDimitry Andric     W.printNumber("Info", Sec.sh_info);
46440b57cec5SDimitry Andric     W.printNumber("AddressAlignment", Sec.sh_addralign);
46450b57cec5SDimitry Andric     W.printNumber("EntrySize", Sec.sh_entsize);
46460b57cec5SDimitry Andric 
46470b57cec5SDimitry Andric     if (opts::SectionRelocations) {
46480b57cec5SDimitry Andric       ListScope D(W, "Relocations");
46490b57cec5SDimitry Andric       printRelocations(&Sec, Obj);
46500b57cec5SDimitry Andric     }
46510b57cec5SDimitry Andric 
46520b57cec5SDimitry Andric     if (opts::SectionSymbols) {
46530b57cec5SDimitry Andric       ListScope D(W, "Symbols");
46540b57cec5SDimitry Andric       const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec();
46550b57cec5SDimitry Andric       StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
46560b57cec5SDimitry Andric 
46570b57cec5SDimitry Andric       for (const Elf_Sym &Sym : unwrapOrError(Obj->symbols(Symtab))) {
46580b57cec5SDimitry Andric         const Elf_Shdr *SymSec = unwrapOrError(
46590b57cec5SDimitry Andric             Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable()));
46600b57cec5SDimitry Andric         if (SymSec == &Sec)
46610b57cec5SDimitry Andric           printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(),
46620b57cec5SDimitry Andric                       StrTable, false);
46630b57cec5SDimitry Andric       }
46640b57cec5SDimitry Andric     }
46650b57cec5SDimitry Andric 
46660b57cec5SDimitry Andric     if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) {
46670b57cec5SDimitry Andric       ArrayRef<uint8_t> Data = unwrapOrError(Obj->getSectionContents(&Sec));
46680b57cec5SDimitry Andric       W.printBinaryBlock(
46690b57cec5SDimitry Andric           "SectionData",
46700b57cec5SDimitry Andric           StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()));
46710b57cec5SDimitry Andric     }
46720b57cec5SDimitry Andric   }
46730b57cec5SDimitry Andric }
46740b57cec5SDimitry Andric 
46750b57cec5SDimitry Andric template <class ELFT>
46760b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
46770b57cec5SDimitry Andric                                   const Elf_Sym *First, StringRef StrTable,
46780b57cec5SDimitry Andric                                   bool IsDynamic) {
46790b57cec5SDimitry Andric   unsigned SectionIndex = 0;
46800b57cec5SDimitry Andric   StringRef SectionName;
46810b57cec5SDimitry Andric   this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex);
46820b57cec5SDimitry Andric   std::string FullSymbolName =
46830b57cec5SDimitry Andric       this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);
46840b57cec5SDimitry Andric   unsigned char SymbolType = Symbol->getType();
46850b57cec5SDimitry Andric 
46860b57cec5SDimitry Andric   DictScope D(W, "Symbol");
46870b57cec5SDimitry Andric   W.printNumber("Name", FullSymbolName, Symbol->st_name);
46880b57cec5SDimitry Andric   W.printHex("Value", Symbol->st_value);
46890b57cec5SDimitry Andric   W.printNumber("Size", Symbol->st_size);
46900b57cec5SDimitry Andric   W.printEnum("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
46910b57cec5SDimitry Andric   if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
46920b57cec5SDimitry Andric       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
46930b57cec5SDimitry Andric     W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes));
46940b57cec5SDimitry Andric   else
46950b57cec5SDimitry Andric     W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes));
46960b57cec5SDimitry Andric   if (Symbol->st_other == 0)
46970b57cec5SDimitry Andric     // Usually st_other flag is zero. Do not pollute the output
46980b57cec5SDimitry Andric     // by flags enumeration in that case.
46990b57cec5SDimitry Andric     W.printNumber("Other", 0);
47000b57cec5SDimitry Andric   else {
47010b57cec5SDimitry Andric     std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),
47020b57cec5SDimitry Andric                                                    std::end(ElfSymOtherFlags));
47030b57cec5SDimitry Andric     if (Obj->getHeader()->e_machine == EM_MIPS) {
47040b57cec5SDimitry Andric       // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16
47050b57cec5SDimitry Andric       // flag overlapped with other ST_MIPS_xxx flags. So consider both
47060b57cec5SDimitry Andric       // cases separately.
47070b57cec5SDimitry Andric       if ((Symbol->st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)
47080b57cec5SDimitry Andric         SymOtherFlags.insert(SymOtherFlags.end(),
47090b57cec5SDimitry Andric                              std::begin(ElfMips16SymOtherFlags),
47100b57cec5SDimitry Andric                              std::end(ElfMips16SymOtherFlags));
47110b57cec5SDimitry Andric       else
47120b57cec5SDimitry Andric         SymOtherFlags.insert(SymOtherFlags.end(),
47130b57cec5SDimitry Andric                              std::begin(ElfMipsSymOtherFlags),
47140b57cec5SDimitry Andric                              std::end(ElfMipsSymOtherFlags));
47150b57cec5SDimitry Andric     }
47160b57cec5SDimitry Andric     W.printFlags("Other", Symbol->st_other, makeArrayRef(SymOtherFlags), 0x3u);
47170b57cec5SDimitry Andric   }
47180b57cec5SDimitry Andric   W.printHex("Section", SectionName, SectionIndex);
47190b57cec5SDimitry Andric }
47200b57cec5SDimitry Andric 
47210b57cec5SDimitry Andric template <class ELFT>
47220b57cec5SDimitry Andric void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols,
47230b57cec5SDimitry Andric                                    bool PrintDynamicSymbols) {
47240b57cec5SDimitry Andric   if (PrintSymbols)
47250b57cec5SDimitry Andric     printSymbols(Obj);
47260b57cec5SDimitry Andric   if (PrintDynamicSymbols)
47270b57cec5SDimitry Andric     printDynamicSymbols(Obj);
47280b57cec5SDimitry Andric }
47290b57cec5SDimitry Andric 
47300b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) {
47310b57cec5SDimitry Andric   ListScope Group(W, "Symbols");
47320b57cec5SDimitry Andric   this->dumper()->printSymbolsHelper(false);
47330b57cec5SDimitry Andric }
47340b57cec5SDimitry Andric 
47350b57cec5SDimitry Andric template <class ELFT>
47360b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
47370b57cec5SDimitry Andric   ListScope Group(W, "DynamicSymbols");
47380b57cec5SDimitry Andric   this->dumper()->printSymbolsHelper(true);
47390b57cec5SDimitry Andric }
47400b57cec5SDimitry Andric 
47410b57cec5SDimitry Andric template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Obj) {
47420b57cec5SDimitry Andric   Elf_Dyn_Range Table = this->dumper()->dynamic_table();
47430b57cec5SDimitry Andric   if (Table.empty())
47440b57cec5SDimitry Andric     return;
47450b57cec5SDimitry Andric 
47460b57cec5SDimitry Andric   raw_ostream &OS = W.getOStream();
47470b57cec5SDimitry Andric   W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";
47480b57cec5SDimitry Andric 
47490b57cec5SDimitry Andric   bool Is64 = ELFT::Is64Bits;
47500b57cec5SDimitry Andric   if (Is64)
47510b57cec5SDimitry Andric     W.startLine() << "  Tag                Type                 Name/Value\n";
47520b57cec5SDimitry Andric   else
47530b57cec5SDimitry Andric     W.startLine() << "  Tag        Type                 Name/Value\n";
47540b57cec5SDimitry Andric   for (auto Entry : Table) {
47550b57cec5SDimitry Andric     uintX_t Tag = Entry.getTag();
47560b57cec5SDimitry Andric     W.startLine() << "  " << format_hex(Tag, Is64 ? 18 : 10, true) << " "
47570b57cec5SDimitry Andric                   << format("%-21s",
47580b57cec5SDimitry Andric                             getTypeString(Obj->getHeader()->e_machine, Tag));
47590b57cec5SDimitry Andric     this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
47600b57cec5SDimitry Andric     OS << "\n";
47610b57cec5SDimitry Andric   }
47620b57cec5SDimitry Andric 
47630b57cec5SDimitry Andric   W.startLine() << "]\n";
47640b57cec5SDimitry Andric }
47650b57cec5SDimitry Andric 
47660b57cec5SDimitry Andric template <class ELFT>
47670b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
47680b57cec5SDimitry Andric   const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion();
47690b57cec5SDimitry Andric   const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion();
47700b57cec5SDimitry Andric   const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion();
47710b57cec5SDimitry Andric   const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion();
47720b57cec5SDimitry Andric   if (DynRelRegion.Size && DynRelaRegion.Size)
47730b57cec5SDimitry Andric     report_fatal_error("There are both REL and RELA dynamic relocations");
47740b57cec5SDimitry Andric   W.startLine() << "Dynamic Relocations {\n";
47750b57cec5SDimitry Andric   W.indent();
47760b57cec5SDimitry Andric   if (DynRelaRegion.Size > 0)
47770b57cec5SDimitry Andric     for (const Elf_Rela &Rela : this->dumper()->dyn_relas())
47780b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela);
47790b57cec5SDimitry Andric   else
47800b57cec5SDimitry Andric     for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) {
47810b57cec5SDimitry Andric       Elf_Rela Rela;
47820b57cec5SDimitry Andric       Rela.r_offset = Rel.r_offset;
47830b57cec5SDimitry Andric       Rela.r_info = Rel.r_info;
47840b57cec5SDimitry Andric       Rela.r_addend = 0;
47850b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela);
47860b57cec5SDimitry Andric     }
47870b57cec5SDimitry Andric   if (DynRelrRegion.Size > 0) {
47880b57cec5SDimitry Andric     Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
47890b57cec5SDimitry Andric     std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
47900b57cec5SDimitry Andric     for (const Elf_Rela &Rela : RelrRelas)
47910b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela);
47920b57cec5SDimitry Andric   }
47930b57cec5SDimitry Andric   if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela))
47940b57cec5SDimitry Andric     for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
47950b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela);
47960b57cec5SDimitry Andric   else
47970b57cec5SDimitry Andric     for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) {
47980b57cec5SDimitry Andric       Elf_Rela Rela;
47990b57cec5SDimitry Andric       Rela.r_offset = Rel.r_offset;
48000b57cec5SDimitry Andric       Rela.r_info = Rel.r_info;
48010b57cec5SDimitry Andric       Rela.r_addend = 0;
48020b57cec5SDimitry Andric       printDynamicRelocation(Obj, Rela);
48030b57cec5SDimitry Andric     }
48040b57cec5SDimitry Andric   W.unindent();
48050b57cec5SDimitry Andric   W.startLine() << "}\n";
48060b57cec5SDimitry Andric }
48070b57cec5SDimitry Andric 
48080b57cec5SDimitry Andric template <class ELFT>
48090b57cec5SDimitry Andric void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) {
48100b57cec5SDimitry Andric   SmallString<32> RelocName;
48110b57cec5SDimitry Andric   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
48120b57cec5SDimitry Andric   std::string SymbolName;
48130b57cec5SDimitry Andric   uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
48140b57cec5SDimitry Andric   const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
48150b57cec5SDimitry Andric   SymbolName = maybeDemangle(
48160b57cec5SDimitry Andric       unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
48170b57cec5SDimitry Andric   if (opts::ExpandRelocs) {
48180b57cec5SDimitry Andric     DictScope Group(W, "Relocation");
48190b57cec5SDimitry Andric     W.printHex("Offset", Rel.r_offset);
48200b57cec5SDimitry Andric     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
48210b57cec5SDimitry Andric     W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-");
48220b57cec5SDimitry Andric     W.printHex("Addend", Rel.r_addend);
48230b57cec5SDimitry Andric   } else {
48240b57cec5SDimitry Andric     raw_ostream &OS = W.startLine();
48250b57cec5SDimitry Andric     OS << W.hex(Rel.r_offset) << " " << RelocName << " "
48260b57cec5SDimitry Andric        << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Rel.r_addend)
48270b57cec5SDimitry Andric        << "\n";
48280b57cec5SDimitry Andric   }
48290b57cec5SDimitry Andric }
48300b57cec5SDimitry Andric 
48310b57cec5SDimitry Andric template <class ELFT>
48320b57cec5SDimitry Andric void LLVMStyle<ELFT>::printProgramHeaders(
48330b57cec5SDimitry Andric     const ELFO *Obj, bool PrintProgramHeaders,
48340b57cec5SDimitry Andric     cl::boolOrDefault PrintSectionMapping) {
48350b57cec5SDimitry Andric   if (PrintProgramHeaders)
48360b57cec5SDimitry Andric     printProgramHeaders(Obj);
48370b57cec5SDimitry Andric   if (PrintSectionMapping == cl::BOU_TRUE)
48380b57cec5SDimitry Andric     printSectionMapping(Obj);
48390b57cec5SDimitry Andric }
48400b57cec5SDimitry Andric 
48410b57cec5SDimitry Andric template <class ELFT>
48420b57cec5SDimitry Andric void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
48430b57cec5SDimitry Andric   ListScope L(W, "ProgramHeaders");
48440b57cec5SDimitry Andric 
48450b57cec5SDimitry Andric   for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
48460b57cec5SDimitry Andric     DictScope P(W, "ProgramHeader");
48470b57cec5SDimitry Andric     W.printHex("Type",
48480b57cec5SDimitry Andric                getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
48490b57cec5SDimitry Andric                Phdr.p_type);
48500b57cec5SDimitry Andric     W.printHex("Offset", Phdr.p_offset);
48510b57cec5SDimitry Andric     W.printHex("VirtualAddress", Phdr.p_vaddr);
48520b57cec5SDimitry Andric     W.printHex("PhysicalAddress", Phdr.p_paddr);
48530b57cec5SDimitry Andric     W.printNumber("FileSize", Phdr.p_filesz);
48540b57cec5SDimitry Andric     W.printNumber("MemSize", Phdr.p_memsz);
48550b57cec5SDimitry Andric     W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
48560b57cec5SDimitry Andric     W.printNumber("Alignment", Phdr.p_align);
48570b57cec5SDimitry Andric   }
48580b57cec5SDimitry Andric }
48590b57cec5SDimitry Andric 
48600b57cec5SDimitry Andric template <class ELFT>
48610b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
48620b57cec5SDimitry Andric                                                 const Elf_Shdr *Sec) {
48630b57cec5SDimitry Andric   DictScope SS(W, "Version symbols");
48640b57cec5SDimitry Andric   if (!Sec)
48650b57cec5SDimitry Andric     return;
48660b57cec5SDimitry Andric 
48670b57cec5SDimitry Andric   StringRef SecName = unwrapOrError(Obj->getSectionName(Sec));
48680b57cec5SDimitry Andric   W.printNumber("Section Name", SecName, Sec->sh_name);
48690b57cec5SDimitry Andric   W.printHex("Address", Sec->sh_addr);
48700b57cec5SDimitry Andric   W.printHex("Offset", Sec->sh_offset);
48710b57cec5SDimitry Andric   W.printNumber("Link", Sec->sh_link);
48720b57cec5SDimitry Andric 
48730b57cec5SDimitry Andric   const uint8_t *VersymBuf =
48740b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
48750b57cec5SDimitry Andric   const ELFDumper<ELFT> *Dumper = this->dumper();
48760b57cec5SDimitry Andric   StringRef StrTable = Dumper->getDynamicStringTable();
48770b57cec5SDimitry Andric 
48780b57cec5SDimitry Andric   // Same number of entries in the dynamic symbol table (DT_SYMTAB).
48790b57cec5SDimitry Andric   ListScope Syms(W, "Symbols");
48800b57cec5SDimitry Andric   for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) {
48810b57cec5SDimitry Andric     DictScope S(W, "Symbol");
48820b57cec5SDimitry Andric     const Elf_Versym *Versym = reinterpret_cast<const Elf_Versym *>(VersymBuf);
48830b57cec5SDimitry Andric     std::string FullSymbolName =
48840b57cec5SDimitry Andric         Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */);
48850b57cec5SDimitry Andric     W.printNumber("Version", Versym->vs_index & VERSYM_VERSION);
48860b57cec5SDimitry Andric     W.printString("Name", FullSymbolName);
48870b57cec5SDimitry Andric     VersymBuf += sizeof(Elf_Versym);
48880b57cec5SDimitry Andric   }
48890b57cec5SDimitry Andric }
48900b57cec5SDimitry Andric 
48910b57cec5SDimitry Andric template <class ELFT>
48920b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
48930b57cec5SDimitry Andric                                                     const Elf_Shdr *Sec) {
48940b57cec5SDimitry Andric   DictScope SD(W, "SHT_GNU_verdef");
48950b57cec5SDimitry Andric   if (!Sec)
48960b57cec5SDimitry Andric     return;
48970b57cec5SDimitry Andric 
48980b57cec5SDimitry Andric   const uint8_t *SecStartAddress =
48990b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
49000b57cec5SDimitry Andric   const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size;
49010b57cec5SDimitry Andric   const uint8_t *VerdefBuf = SecStartAddress;
49020b57cec5SDimitry Andric   const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link));
49030b57cec5SDimitry Andric 
49040b57cec5SDimitry Andric   unsigned VerDefsNum = Sec->sh_info;
49050b57cec5SDimitry Andric   while (VerDefsNum--) {
49060b57cec5SDimitry Andric     if (VerdefBuf + sizeof(Elf_Verdef) > SecEndAddress)
49070b57cec5SDimitry Andric       // FIXME: report_fatal_error is not a good way to report error. We should
49080b57cec5SDimitry Andric       // emit a parsing error here and below.
49090b57cec5SDimitry Andric       report_fatal_error("invalid offset in the section");
49100b57cec5SDimitry Andric 
49110b57cec5SDimitry Andric     const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(VerdefBuf);
49120b57cec5SDimitry Andric     DictScope Def(W, "Definition");
49130b57cec5SDimitry Andric     W.printNumber("Version", Verdef->vd_version);
49140b57cec5SDimitry Andric     W.printEnum("Flags", Verdef->vd_flags, makeArrayRef(SymVersionFlags));
49150b57cec5SDimitry Andric     W.printNumber("Index", Verdef->vd_ndx);
49160b57cec5SDimitry Andric     W.printNumber("Hash", Verdef->vd_hash);
49170b57cec5SDimitry Andric     W.printString("Name", StringRef(reinterpret_cast<const char *>(
49180b57cec5SDimitry Andric                               Obj->base() + StrTab->sh_offset +
49190b57cec5SDimitry Andric                               Verdef->getAux()->vda_name)));
49200b57cec5SDimitry Andric     if (!Verdef->vd_cnt)
49210b57cec5SDimitry Andric       report_fatal_error("at least one definition string must exist");
49220b57cec5SDimitry Andric     if (Verdef->vd_cnt > 2)
49230b57cec5SDimitry Andric       report_fatal_error("more than one predecessor is not expected");
49240b57cec5SDimitry Andric 
49250b57cec5SDimitry Andric     if (Verdef->vd_cnt == 2) {
49260b57cec5SDimitry Andric       const uint8_t *VerdauxBuf =
49270b57cec5SDimitry Andric           VerdefBuf + Verdef->vd_aux + Verdef->getAux()->vda_next;
49280b57cec5SDimitry Andric       const Elf_Verdaux *Verdaux =
49290b57cec5SDimitry Andric           reinterpret_cast<const Elf_Verdaux *>(VerdauxBuf);
49300b57cec5SDimitry Andric       W.printString("Predecessor",
49310b57cec5SDimitry Andric                     StringRef(reinterpret_cast<const char *>(
49320b57cec5SDimitry Andric                         Obj->base() + StrTab->sh_offset + Verdaux->vda_name)));
49330b57cec5SDimitry Andric     }
49340b57cec5SDimitry Andric     VerdefBuf += Verdef->vd_next;
49350b57cec5SDimitry Andric   }
49360b57cec5SDimitry Andric }
49370b57cec5SDimitry Andric 
49380b57cec5SDimitry Andric template <class ELFT>
49390b57cec5SDimitry Andric void LLVMStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
49400b57cec5SDimitry Andric                                                     const Elf_Shdr *Sec) {
49410b57cec5SDimitry Andric   DictScope SD(W, "SHT_GNU_verneed");
49420b57cec5SDimitry Andric   if (!Sec)
49430b57cec5SDimitry Andric     return;
49440b57cec5SDimitry Andric 
49450b57cec5SDimitry Andric   const uint8_t *SecData =
49460b57cec5SDimitry Andric       reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
49470b57cec5SDimitry Andric   const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link));
49480b57cec5SDimitry Andric 
49490b57cec5SDimitry Andric   const uint8_t *VerneedBuf = SecData;
49500b57cec5SDimitry Andric   unsigned VerneedNum = Sec->sh_info;
49510b57cec5SDimitry Andric   for (unsigned I = 0; I < VerneedNum; ++I) {
49520b57cec5SDimitry Andric     const Elf_Verneed *Verneed =
49530b57cec5SDimitry Andric         reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
49540b57cec5SDimitry Andric     DictScope Entry(W, "Dependency");
49550b57cec5SDimitry Andric     W.printNumber("Version", Verneed->vn_version);
49560b57cec5SDimitry Andric     W.printNumber("Count", Verneed->vn_cnt);
49570b57cec5SDimitry Andric     W.printString("FileName",
49580b57cec5SDimitry Andric                   StringRef(reinterpret_cast<const char *>(
49590b57cec5SDimitry Andric                       Obj->base() + StrTab->sh_offset + Verneed->vn_file)));
49600b57cec5SDimitry Andric 
49610b57cec5SDimitry Andric     const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
49620b57cec5SDimitry Andric     ListScope L(W, "Entries");
49630b57cec5SDimitry Andric     for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
49640b57cec5SDimitry Andric       const Elf_Vernaux *Vernaux =
49650b57cec5SDimitry Andric           reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
49660b57cec5SDimitry Andric       DictScope Entry(W, "Entry");
49670b57cec5SDimitry Andric       W.printNumber("Hash", Vernaux->vna_hash);
49680b57cec5SDimitry Andric       W.printEnum("Flags", Vernaux->vna_flags, makeArrayRef(SymVersionFlags));
49690b57cec5SDimitry Andric       W.printNumber("Index", Vernaux->vna_other);
49700b57cec5SDimitry Andric       W.printString("Name",
49710b57cec5SDimitry Andric                     StringRef(reinterpret_cast<const char *>(
49720b57cec5SDimitry Andric                         Obj->base() + StrTab->sh_offset + Vernaux->vna_name)));
49730b57cec5SDimitry Andric       VernauxBuf += Vernaux->vna_next;
49740b57cec5SDimitry Andric     }
49750b57cec5SDimitry Andric     VerneedBuf += Verneed->vn_next;
49760b57cec5SDimitry Andric   }
49770b57cec5SDimitry Andric }
49780b57cec5SDimitry Andric 
49790b57cec5SDimitry Andric template <class ELFT>
49800b57cec5SDimitry Andric void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
49810b57cec5SDimitry Andric   W.startLine() << "Hash Histogram not implemented!\n";
49820b57cec5SDimitry Andric }
49830b57cec5SDimitry Andric 
49840b57cec5SDimitry Andric template <class ELFT>
49850b57cec5SDimitry Andric void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
49860b57cec5SDimitry Andric   ListScope L(W, "CGProfile");
49870b57cec5SDimitry Andric   if (!this->dumper()->getDotCGProfileSec())
49880b57cec5SDimitry Andric     return;
49890b57cec5SDimitry Andric   auto CGProfile =
49900b57cec5SDimitry Andric       unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>(
49910b57cec5SDimitry Andric           this->dumper()->getDotCGProfileSec()));
49920b57cec5SDimitry Andric   for (const Elf_CGProfile &CGPE : CGProfile) {
49930b57cec5SDimitry Andric     DictScope D(W, "CGProfileEntry");
49940b57cec5SDimitry Andric     W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from),
49950b57cec5SDimitry Andric                   CGPE.cgp_from);
49960b57cec5SDimitry Andric     W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to),
49970b57cec5SDimitry Andric                   CGPE.cgp_to);
49980b57cec5SDimitry Andric     W.printNumber("Weight", CGPE.cgp_weight);
49990b57cec5SDimitry Andric   }
50000b57cec5SDimitry Andric }
50010b57cec5SDimitry Andric 
50020b57cec5SDimitry Andric template <class ELFT>
50030b57cec5SDimitry Andric void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
50040b57cec5SDimitry Andric   ListScope L(W, "Addrsig");
50050b57cec5SDimitry Andric   if (!this->dumper()->getDotAddrsigSec())
50060b57cec5SDimitry Andric     return;
50070b57cec5SDimitry Andric   ArrayRef<uint8_t> Contents = unwrapOrError(
50080b57cec5SDimitry Andric       Obj->getSectionContents(this->dumper()->getDotAddrsigSec()));
50090b57cec5SDimitry Andric   const uint8_t *Cur = Contents.begin();
50100b57cec5SDimitry Andric   const uint8_t *End = Contents.end();
50110b57cec5SDimitry Andric   while (Cur != End) {
50120b57cec5SDimitry Andric     unsigned Size;
50130b57cec5SDimitry Andric     const char *Err;
50140b57cec5SDimitry Andric     uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err);
50150b57cec5SDimitry Andric     if (Err)
50160b57cec5SDimitry Andric       reportError(Err);
50170b57cec5SDimitry Andric     W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex),
50180b57cec5SDimitry Andric                   SymIndex);
50190b57cec5SDimitry Andric     Cur += Size;
50200b57cec5SDimitry Andric   }
50210b57cec5SDimitry Andric }
50220b57cec5SDimitry Andric 
50230b57cec5SDimitry Andric template <typename ELFT>
50240b57cec5SDimitry Andric static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
50250b57cec5SDimitry Andric                                   ScopedPrinter &W) {
50260b57cec5SDimitry Andric   switch (NoteType) {
50270b57cec5SDimitry Andric   default:
50280b57cec5SDimitry Andric     return;
50290b57cec5SDimitry Andric   case ELF::NT_GNU_ABI_TAG: {
50300b57cec5SDimitry Andric     const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
50310b57cec5SDimitry Andric     if (!AbiTag.IsValid) {
50320b57cec5SDimitry Andric       W.printString("ABI", "<corrupt GNU_ABI_TAG>");
50330b57cec5SDimitry Andric     } else {
50340b57cec5SDimitry Andric       W.printString("OS", AbiTag.OSName);
50350b57cec5SDimitry Andric       W.printString("ABI", AbiTag.ABI);
50360b57cec5SDimitry Andric     }
50370b57cec5SDimitry Andric     break;
50380b57cec5SDimitry Andric   }
50390b57cec5SDimitry Andric   case ELF::NT_GNU_BUILD_ID: {
50400b57cec5SDimitry Andric     W.printString("Build ID", getGNUBuildId(Desc));
50410b57cec5SDimitry Andric     break;
50420b57cec5SDimitry Andric   }
50430b57cec5SDimitry Andric   case ELF::NT_GNU_GOLD_VERSION:
50440b57cec5SDimitry Andric     W.printString("Version", getGNUGoldVersion(Desc));
50450b57cec5SDimitry Andric     break;
50460b57cec5SDimitry Andric   case ELF::NT_GNU_PROPERTY_TYPE_0:
50470b57cec5SDimitry Andric     ListScope D(W, "Property");
50480b57cec5SDimitry Andric     for (const auto &Property : getGNUPropertyList<ELFT>(Desc))
50490b57cec5SDimitry Andric       W.printString(Property);
50500b57cec5SDimitry Andric     break;
50510b57cec5SDimitry Andric   }
50520b57cec5SDimitry Andric }
50530b57cec5SDimitry Andric 
50540b57cec5SDimitry Andric template <class ELFT>
50550b57cec5SDimitry Andric void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
50560b57cec5SDimitry Andric   ListScope L(W, "Notes");
50570b57cec5SDimitry Andric 
50580b57cec5SDimitry Andric   auto PrintHeader = [&](const typename ELFT::Off Offset,
50590b57cec5SDimitry Andric                          const typename ELFT::Addr Size) {
50600b57cec5SDimitry Andric     W.printHex("Offset", Offset);
50610b57cec5SDimitry Andric     W.printHex("Size", Size);
50620b57cec5SDimitry Andric   };
50630b57cec5SDimitry Andric 
50640b57cec5SDimitry Andric   auto ProcessNote = [&](const Elf_Note &Note) {
50650b57cec5SDimitry Andric     DictScope D2(W, "Note");
50660b57cec5SDimitry Andric     StringRef Name = Note.getName();
50670b57cec5SDimitry Andric     ArrayRef<uint8_t> Descriptor = Note.getDesc();
50680b57cec5SDimitry Andric     Elf_Word Type = Note.getType();
50690b57cec5SDimitry Andric 
50700b57cec5SDimitry Andric     W.printString("Owner", Name);
50710b57cec5SDimitry Andric     W.printHex("Data size", Descriptor.size());
50720b57cec5SDimitry Andric     if (Name == "GNU") {
50730b57cec5SDimitry Andric       W.printString("Type", getGNUNoteTypeName(Type));
50740b57cec5SDimitry Andric       printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W);
50750b57cec5SDimitry Andric     } else if (Name == "FreeBSD") {
50760b57cec5SDimitry Andric       W.printString("Type", getFreeBSDNoteTypeName(Type));
50770b57cec5SDimitry Andric     } else if (Name == "AMD") {
50780b57cec5SDimitry Andric       W.printString("Type", getAMDNoteTypeName(Type));
50790b57cec5SDimitry Andric       const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
50800b57cec5SDimitry Andric       if (!N.Type.empty())
50810b57cec5SDimitry Andric         W.printString(N.Type, N.Value);
50820b57cec5SDimitry Andric     } else if (Name == "AMDGPU") {
50830b57cec5SDimitry Andric       W.printString("Type", getAMDGPUNoteTypeName(Type));
50840b57cec5SDimitry Andric       const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
50850b57cec5SDimitry Andric       if (!N.Type.empty())
50860b57cec5SDimitry Andric         W.printString(N.Type, N.Value);
50870b57cec5SDimitry Andric     } else {
50880b57cec5SDimitry Andric       StringRef NoteType = getGenericNoteTypeName(Type);
50890b57cec5SDimitry Andric       if (!NoteType.empty())
50900b57cec5SDimitry Andric         W.printString("Type", NoteType);
50910b57cec5SDimitry Andric       else
50920b57cec5SDimitry Andric         W.printString("Type",
50930b57cec5SDimitry Andric                       "Unknown (" + to_string(format_hex(Type, 10)) + ")");
50940b57cec5SDimitry Andric     }
50950b57cec5SDimitry Andric   };
50960b57cec5SDimitry Andric 
50970b57cec5SDimitry Andric   if (Obj->getHeader()->e_type == ELF::ET_CORE) {
50980b57cec5SDimitry Andric     for (const auto &P : unwrapOrError(Obj->program_headers())) {
50990b57cec5SDimitry Andric       if (P.p_type != PT_NOTE)
51000b57cec5SDimitry Andric         continue;
51010b57cec5SDimitry Andric       DictScope D(W, "NoteSection");
51020b57cec5SDimitry Andric       PrintHeader(P.p_offset, P.p_filesz);
51030b57cec5SDimitry Andric       Error Err = Error::success();
51040b57cec5SDimitry Andric       for (const auto &Note : Obj->notes(P, Err))
51050b57cec5SDimitry Andric         ProcessNote(Note);
51060b57cec5SDimitry Andric       if (Err)
51070b57cec5SDimitry Andric         error(std::move(Err));
51080b57cec5SDimitry Andric     }
51090b57cec5SDimitry Andric   } else {
51100b57cec5SDimitry Andric     for (const auto &S : unwrapOrError(Obj->sections())) {
51110b57cec5SDimitry Andric       if (S.sh_type != SHT_NOTE)
51120b57cec5SDimitry Andric         continue;
51130b57cec5SDimitry Andric       DictScope D(W, "NoteSection");
51140b57cec5SDimitry Andric       PrintHeader(S.sh_offset, S.sh_size);
51150b57cec5SDimitry Andric       Error Err = Error::success();
51160b57cec5SDimitry Andric       for (const auto &Note : Obj->notes(S, Err))
51170b57cec5SDimitry Andric         ProcessNote(Note);
51180b57cec5SDimitry Andric       if (Err)
51190b57cec5SDimitry Andric         error(std::move(Err));
51200b57cec5SDimitry Andric     }
51210b57cec5SDimitry Andric   }
51220b57cec5SDimitry Andric }
51230b57cec5SDimitry Andric 
51240b57cec5SDimitry Andric template <class ELFT>
51250b57cec5SDimitry Andric void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
51260b57cec5SDimitry Andric   ListScope L(W, "LinkerOptions");
51270b57cec5SDimitry Andric 
51280b57cec5SDimitry Andric   for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) {
51290b57cec5SDimitry Andric     if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)
51300b57cec5SDimitry Andric       continue;
51310b57cec5SDimitry Andric 
51320b57cec5SDimitry Andric     ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr));
51330b57cec5SDimitry Andric     for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) {
51340b57cec5SDimitry Andric       StringRef Key = StringRef(reinterpret_cast<const char *>(P));
51350b57cec5SDimitry Andric       StringRef Value =
51360b57cec5SDimitry Andric           StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1);
51370b57cec5SDimitry Andric 
51380b57cec5SDimitry Andric       W.printString(Key, Value);
51390b57cec5SDimitry Andric 
51400b57cec5SDimitry Andric       P = P + Key.size() + Value.size() + 2;
51410b57cec5SDimitry Andric     }
51420b57cec5SDimitry Andric   }
51430b57cec5SDimitry Andric }
51440b57cec5SDimitry Andric 
51450b57cec5SDimitry Andric template <class ELFT>
51460b57cec5SDimitry Andric void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
51470b57cec5SDimitry Andric   auto PrintEntry = [&](const Elf_Addr *E) {
51480b57cec5SDimitry Andric     W.printHex("Address", Parser.getGotAddress(E));
51490b57cec5SDimitry Andric     W.printNumber("Access", Parser.getGotOffset(E));
51500b57cec5SDimitry Andric     W.printHex("Initial", *E);
51510b57cec5SDimitry Andric   };
51520b57cec5SDimitry Andric 
51530b57cec5SDimitry Andric   DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");
51540b57cec5SDimitry Andric 
51550b57cec5SDimitry Andric   W.printHex("Canonical gp value", Parser.getGp());
51560b57cec5SDimitry Andric   {
51570b57cec5SDimitry Andric     ListScope RS(W, "Reserved entries");
51580b57cec5SDimitry Andric     {
51590b57cec5SDimitry Andric       DictScope D(W, "Entry");
51600b57cec5SDimitry Andric       PrintEntry(Parser.getGotLazyResolver());
51610b57cec5SDimitry Andric       W.printString("Purpose", StringRef("Lazy resolver"));
51620b57cec5SDimitry Andric     }
51630b57cec5SDimitry Andric 
51640b57cec5SDimitry Andric     if (Parser.getGotModulePointer()) {
51650b57cec5SDimitry Andric       DictScope D(W, "Entry");
51660b57cec5SDimitry Andric       PrintEntry(Parser.getGotModulePointer());
51670b57cec5SDimitry Andric       W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
51680b57cec5SDimitry Andric     }
51690b57cec5SDimitry Andric   }
51700b57cec5SDimitry Andric   {
51710b57cec5SDimitry Andric     ListScope LS(W, "Local entries");
51720b57cec5SDimitry Andric     for (auto &E : Parser.getLocalEntries()) {
51730b57cec5SDimitry Andric       DictScope D(W, "Entry");
51740b57cec5SDimitry Andric       PrintEntry(&E);
51750b57cec5SDimitry Andric     }
51760b57cec5SDimitry Andric   }
51770b57cec5SDimitry Andric 
51780b57cec5SDimitry Andric   if (Parser.IsStatic)
51790b57cec5SDimitry Andric     return;
51800b57cec5SDimitry Andric 
51810b57cec5SDimitry Andric   {
51820b57cec5SDimitry Andric     ListScope GS(W, "Global entries");
51830b57cec5SDimitry Andric     for (auto &E : Parser.getGlobalEntries()) {
51840b57cec5SDimitry Andric       DictScope D(W, "Entry");
51850b57cec5SDimitry Andric 
51860b57cec5SDimitry Andric       PrintEntry(&E);
51870b57cec5SDimitry Andric 
51880b57cec5SDimitry Andric       const Elf_Sym *Sym = Parser.getGotSym(&E);
51890b57cec5SDimitry Andric       W.printHex("Value", Sym->st_value);
51900b57cec5SDimitry Andric       W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
51910b57cec5SDimitry Andric 
51920b57cec5SDimitry Andric       unsigned SectionIndex = 0;
51930b57cec5SDimitry Andric       StringRef SectionName;
51940b57cec5SDimitry Andric       this->dumper()->getSectionNameIndex(
51950b57cec5SDimitry Andric           Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
51960b57cec5SDimitry Andric           SectionIndex);
51970b57cec5SDimitry Andric       W.printHex("Section", SectionName, SectionIndex);
51980b57cec5SDimitry Andric 
51990b57cec5SDimitry Andric       std::string SymName = this->dumper()->getFullSymbolName(
52000b57cec5SDimitry Andric           Sym, this->dumper()->getDynamicStringTable(), true);
52010b57cec5SDimitry Andric       W.printNumber("Name", SymName, Sym->st_name);
52020b57cec5SDimitry Andric     }
52030b57cec5SDimitry Andric   }
52040b57cec5SDimitry Andric 
52050b57cec5SDimitry Andric   W.printNumber("Number of TLS and multi-GOT entries",
52060b57cec5SDimitry Andric                 uint64_t(Parser.getOtherEntries().size()));
52070b57cec5SDimitry Andric }
52080b57cec5SDimitry Andric 
52090b57cec5SDimitry Andric template <class ELFT>
52100b57cec5SDimitry Andric void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
52110b57cec5SDimitry Andric   auto PrintEntry = [&](const Elf_Addr *E) {
52120b57cec5SDimitry Andric     W.printHex("Address", Parser.getPltAddress(E));
52130b57cec5SDimitry Andric     W.printHex("Initial", *E);
52140b57cec5SDimitry Andric   };
52150b57cec5SDimitry Andric 
52160b57cec5SDimitry Andric   DictScope GS(W, "PLT GOT");
52170b57cec5SDimitry Andric 
52180b57cec5SDimitry Andric   {
52190b57cec5SDimitry Andric     ListScope RS(W, "Reserved entries");
52200b57cec5SDimitry Andric     {
52210b57cec5SDimitry Andric       DictScope D(W, "Entry");
52220b57cec5SDimitry Andric       PrintEntry(Parser.getPltLazyResolver());
52230b57cec5SDimitry Andric       W.printString("Purpose", StringRef("PLT lazy resolver"));
52240b57cec5SDimitry Andric     }
52250b57cec5SDimitry Andric 
52260b57cec5SDimitry Andric     if (auto E = Parser.getPltModulePointer()) {
52270b57cec5SDimitry Andric       DictScope D(W, "Entry");
52280b57cec5SDimitry Andric       PrintEntry(E);
52290b57cec5SDimitry Andric       W.printString("Purpose", StringRef("Module pointer"));
52300b57cec5SDimitry Andric     }
52310b57cec5SDimitry Andric   }
52320b57cec5SDimitry Andric   {
52330b57cec5SDimitry Andric     ListScope LS(W, "Entries");
52340b57cec5SDimitry Andric     for (auto &E : Parser.getPltEntries()) {
52350b57cec5SDimitry Andric       DictScope D(W, "Entry");
52360b57cec5SDimitry Andric       PrintEntry(&E);
52370b57cec5SDimitry Andric 
52380b57cec5SDimitry Andric       const Elf_Sym *Sym = Parser.getPltSym(&E);
52390b57cec5SDimitry Andric       W.printHex("Value", Sym->st_value);
52400b57cec5SDimitry Andric       W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
52410b57cec5SDimitry Andric 
52420b57cec5SDimitry Andric       unsigned SectionIndex = 0;
52430b57cec5SDimitry Andric       StringRef SectionName;
52440b57cec5SDimitry Andric       this->dumper()->getSectionNameIndex(
52450b57cec5SDimitry Andric           Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
52460b57cec5SDimitry Andric           SectionIndex);
52470b57cec5SDimitry Andric       W.printHex("Section", SectionName, SectionIndex);
52480b57cec5SDimitry Andric 
52490b57cec5SDimitry Andric       std::string SymName =
52500b57cec5SDimitry Andric           this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true);
52510b57cec5SDimitry Andric       W.printNumber("Name", SymName, Sym->st_name);
52520b57cec5SDimitry Andric     }
52530b57cec5SDimitry Andric   }
52540b57cec5SDimitry Andric }
5255