1f4a2713aSLionel Sambuc //===-- ELFDumper.cpp - ELF-specific dumper ---------------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief This file implements the ELF-specific dumper for llvm-readobj.
12f4a2713aSLionel Sambuc ///
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "llvm-readobj.h"
16*0a6a1f1dSLionel Sambuc #include "ARMAttributeParser.h"
17*0a6a1f1dSLionel Sambuc #include "ARMEHABIPrinter.h"
18f4a2713aSLionel Sambuc #include "Error.h"
19f4a2713aSLionel Sambuc #include "ObjDumper.h"
20f4a2713aSLionel Sambuc #include "StreamWriter.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Optional.h"
22f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringExtras.h"
24f4a2713aSLionel Sambuc #include "llvm/Object/ELFObjectFile.h"
25*0a6a1f1dSLionel Sambuc #include "llvm/Support/ARMBuildAttributes.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/Compiler.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/MathExtras.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
30f4a2713aSLionel Sambuc 
31f4a2713aSLionel Sambuc using namespace llvm;
32f4a2713aSLionel Sambuc using namespace llvm::object;
33f4a2713aSLionel Sambuc using namespace ELF;
34f4a2713aSLionel Sambuc 
35f4a2713aSLionel Sambuc #define LLVM_READOBJ_ENUM_CASE(ns, enum) \
36f4a2713aSLionel Sambuc   case ns::enum: return #enum;
37f4a2713aSLionel Sambuc 
38f4a2713aSLionel Sambuc namespace {
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc template<typename ELFT>
41f4a2713aSLionel Sambuc class ELFDumper : public ObjDumper {
42f4a2713aSLionel Sambuc public:
ELFDumper(const ELFFile<ELFT> * Obj,StreamWriter & Writer)43f4a2713aSLionel Sambuc   ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
44f4a2713aSLionel Sambuc       : ObjDumper(Writer), Obj(Obj) {}
45f4a2713aSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc   void printFileHeaders() override;
47*0a6a1f1dSLionel Sambuc   void printSections() override;
48*0a6a1f1dSLionel Sambuc   void printRelocations() override;
49*0a6a1f1dSLionel Sambuc   void printSymbols() override;
50*0a6a1f1dSLionel Sambuc   void printDynamicSymbols() override;
51*0a6a1f1dSLionel Sambuc   void printUnwindInfo() override;
52f4a2713aSLionel Sambuc 
53*0a6a1f1dSLionel Sambuc   void printDynamicTable() override;
54*0a6a1f1dSLionel Sambuc   void printNeededLibraries() override;
55*0a6a1f1dSLionel Sambuc   void printProgramHeaders() override;
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc   void printAttributes() override;
58*0a6a1f1dSLionel Sambuc   void printMipsPLTGOT() override;
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc private:
61f4a2713aSLionel Sambuc   typedef ELFFile<ELFT> ELFO;
62f4a2713aSLionel Sambuc   typedef typename ELFO::Elf_Shdr Elf_Shdr;
63f4a2713aSLionel Sambuc   typedef typename ELFO::Elf_Sym Elf_Sym;
64f4a2713aSLionel Sambuc 
65f4a2713aSLionel Sambuc   void printSymbol(typename ELFO::Elf_Sym_Iter Symbol);
66f4a2713aSLionel Sambuc 
67f4a2713aSLionel Sambuc   void printRelocations(const Elf_Shdr *Sec);
68f4a2713aSLionel Sambuc   void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel);
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc   const ELFO *Obj;
71f4a2713aSLionel Sambuc };
72f4a2713aSLionel Sambuc 
errorOrDefault(ErrorOr<T> Val,T Default=T ())73f4a2713aSLionel Sambuc template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) {
74f4a2713aSLionel Sambuc   if (!Val) {
75*0a6a1f1dSLionel Sambuc     error(Val.getError());
76f4a2713aSLionel Sambuc     return Default;
77f4a2713aSLionel Sambuc   }
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc   return *Val;
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc } // namespace
82f4a2713aSLionel Sambuc 
83f4a2713aSLionel Sambuc namespace llvm {
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc template <class ELFT>
createELFDumper(const ELFFile<ELFT> * Obj,StreamWriter & Writer,std::unique_ptr<ObjDumper> & Result)86*0a6a1f1dSLionel Sambuc static std::error_code createELFDumper(const ELFFile<ELFT> *Obj,
87f4a2713aSLionel Sambuc                                        StreamWriter &Writer,
88*0a6a1f1dSLionel Sambuc                                        std::unique_ptr<ObjDumper> &Result) {
89f4a2713aSLionel Sambuc   Result.reset(new ELFDumper<ELFT>(Obj, Writer));
90f4a2713aSLionel Sambuc   return readobj_error::success;
91f4a2713aSLionel Sambuc }
92f4a2713aSLionel Sambuc 
createELFDumper(const object::ObjectFile * Obj,StreamWriter & Writer,std::unique_ptr<ObjDumper> & Result)93*0a6a1f1dSLionel Sambuc std::error_code createELFDumper(const object::ObjectFile *Obj,
94f4a2713aSLionel Sambuc                                 StreamWriter &Writer,
95*0a6a1f1dSLionel Sambuc                                 std::unique_ptr<ObjDumper> &Result) {
96f4a2713aSLionel Sambuc   // Little-endian 32-bit
97f4a2713aSLionel Sambuc   if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
98f4a2713aSLionel Sambuc     return createELFDumper(ELFObj->getELFFile(), Writer, Result);
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc   // Big-endian 32-bit
101f4a2713aSLionel Sambuc   if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
102f4a2713aSLionel Sambuc     return createELFDumper(ELFObj->getELFFile(), Writer, Result);
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc   // Little-endian 64-bit
105f4a2713aSLionel Sambuc   if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
106f4a2713aSLionel Sambuc     return createELFDumper(ELFObj->getELFFile(), Writer, Result);
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc   // Big-endian 64-bit
109f4a2713aSLionel Sambuc   if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
110f4a2713aSLionel Sambuc     return createELFDumper(ELFObj->getELFFile(), Writer, Result);
111f4a2713aSLionel Sambuc 
112f4a2713aSLionel Sambuc   return readobj_error::unsupported_obj_file_format;
113f4a2713aSLionel Sambuc }
114f4a2713aSLionel Sambuc 
115f4a2713aSLionel Sambuc } // namespace llvm
116f4a2713aSLionel Sambuc 
117*0a6a1f1dSLionel Sambuc template <typename ELFO>
getFullSymbolName(const ELFO & Obj,typename ELFO::Elf_Sym_Iter Symbol)118*0a6a1f1dSLionel Sambuc static std::string getFullSymbolName(const ELFO &Obj,
119*0a6a1f1dSLionel Sambuc                                      typename ELFO::Elf_Sym_Iter Symbol) {
120*0a6a1f1dSLionel Sambuc   StringRef SymbolName = errorOrDefault(Obj.getSymbolName(Symbol));
121*0a6a1f1dSLionel Sambuc   if (!Symbol.isDynamic())
122*0a6a1f1dSLionel Sambuc     return SymbolName;
123*0a6a1f1dSLionel Sambuc 
124*0a6a1f1dSLionel Sambuc   std::string FullSymbolName(SymbolName);
125*0a6a1f1dSLionel Sambuc 
126*0a6a1f1dSLionel Sambuc   bool IsDefault;
127*0a6a1f1dSLionel Sambuc   ErrorOr<StringRef> Version =
128*0a6a1f1dSLionel Sambuc       Obj.getSymbolVersion(nullptr, &*Symbol, IsDefault);
129*0a6a1f1dSLionel Sambuc   if (Version) {
130*0a6a1f1dSLionel Sambuc     FullSymbolName += (IsDefault ? "@@" : "@");
131*0a6a1f1dSLionel Sambuc     FullSymbolName += *Version;
132*0a6a1f1dSLionel Sambuc   } else
133*0a6a1f1dSLionel Sambuc     error(Version.getError());
134*0a6a1f1dSLionel Sambuc   return FullSymbolName;
135*0a6a1f1dSLionel Sambuc }
136*0a6a1f1dSLionel Sambuc 
137*0a6a1f1dSLionel Sambuc template <typename ELFO>
138*0a6a1f1dSLionel Sambuc static void
getSectionNameIndex(const ELFO & Obj,typename ELFO::Elf_Sym_Iter Symbol,StringRef & SectionName,unsigned & SectionIndex)139*0a6a1f1dSLionel Sambuc getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol,
140*0a6a1f1dSLionel Sambuc                     StringRef &SectionName, unsigned &SectionIndex) {
141*0a6a1f1dSLionel Sambuc   SectionIndex = Symbol->st_shndx;
142*0a6a1f1dSLionel Sambuc   if (SectionIndex == SHN_UNDEF) {
143*0a6a1f1dSLionel Sambuc     SectionName = "Undefined";
144*0a6a1f1dSLionel Sambuc   } else if (SectionIndex >= SHN_LOPROC && SectionIndex <= SHN_HIPROC) {
145*0a6a1f1dSLionel Sambuc     SectionName = "Processor Specific";
146*0a6a1f1dSLionel Sambuc   } else if (SectionIndex >= SHN_LOOS && SectionIndex <= SHN_HIOS) {
147*0a6a1f1dSLionel Sambuc     SectionName = "Operating System Specific";
148*0a6a1f1dSLionel Sambuc   } else if (SectionIndex > SHN_HIOS && SectionIndex < SHN_ABS) {
149*0a6a1f1dSLionel Sambuc     SectionName = "Reserved";
150*0a6a1f1dSLionel Sambuc   } else if (SectionIndex == SHN_ABS) {
151*0a6a1f1dSLionel Sambuc     SectionName = "Absolute";
152*0a6a1f1dSLionel Sambuc   } else if (SectionIndex == SHN_COMMON) {
153*0a6a1f1dSLionel Sambuc     SectionName = "Common";
154*0a6a1f1dSLionel Sambuc   } else {
155*0a6a1f1dSLionel Sambuc     if (SectionIndex == SHN_XINDEX)
156*0a6a1f1dSLionel Sambuc       SectionIndex = Obj.getSymbolTableIndex(&*Symbol);
157*0a6a1f1dSLionel Sambuc     assert(SectionIndex != SHN_XINDEX &&
158*0a6a1f1dSLionel Sambuc            "getSymbolTableIndex should handle this");
159*0a6a1f1dSLionel Sambuc     const typename ELFO::Elf_Shdr *Sec = Obj.getSection(SectionIndex);
160*0a6a1f1dSLionel Sambuc     SectionName = errorOrDefault(Obj.getSectionName(Sec));
161*0a6a1f1dSLionel Sambuc   }
162*0a6a1f1dSLionel Sambuc }
163*0a6a1f1dSLionel Sambuc 
164*0a6a1f1dSLionel Sambuc template <class ELFT>
165*0a6a1f1dSLionel Sambuc static const typename ELFFile<ELFT>::Elf_Shdr *
findSectionByAddress(const ELFFile<ELFT> * Obj,uint64_t Addr)166*0a6a1f1dSLionel Sambuc findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) {
167*0a6a1f1dSLionel Sambuc   for (const auto &Shdr : Obj->sections())
168*0a6a1f1dSLionel Sambuc     if (Shdr.sh_addr == Addr)
169*0a6a1f1dSLionel Sambuc       return &Shdr;
170*0a6a1f1dSLionel Sambuc   return nullptr;
171*0a6a1f1dSLionel Sambuc }
172*0a6a1f1dSLionel Sambuc 
173f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfClass[] = {
174f4a2713aSLionel Sambuc   { "None",   ELF::ELFCLASSNONE },
175f4a2713aSLionel Sambuc   { "32-bit", ELF::ELFCLASS32   },
176f4a2713aSLionel Sambuc   { "64-bit", ELF::ELFCLASS64   },
177f4a2713aSLionel Sambuc };
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfDataEncoding[] = {
180f4a2713aSLionel Sambuc   { "None",         ELF::ELFDATANONE },
181f4a2713aSLionel Sambuc   { "LittleEndian", ELF::ELFDATA2LSB },
182f4a2713aSLionel Sambuc   { "BigEndian",    ELF::ELFDATA2MSB },
183f4a2713aSLionel Sambuc };
184f4a2713aSLionel Sambuc 
185f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfObjectFileType[] = {
186f4a2713aSLionel Sambuc   { "None",         ELF::ET_NONE },
187f4a2713aSLionel Sambuc   { "Relocatable",  ELF::ET_REL  },
188f4a2713aSLionel Sambuc   { "Executable",   ELF::ET_EXEC },
189f4a2713aSLionel Sambuc   { "SharedObject", ELF::ET_DYN  },
190f4a2713aSLionel Sambuc   { "Core",         ELF::ET_CORE },
191f4a2713aSLionel Sambuc };
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfOSABI[] = {
194f4a2713aSLionel Sambuc   { "SystemV",      ELF::ELFOSABI_NONE         },
195f4a2713aSLionel Sambuc   { "HPUX",         ELF::ELFOSABI_HPUX         },
196f4a2713aSLionel Sambuc   { "NetBSD",       ELF::ELFOSABI_NETBSD       },
197f4a2713aSLionel Sambuc   { "GNU/Linux",    ELF::ELFOSABI_LINUX        },
198f4a2713aSLionel Sambuc   { "GNU/Hurd",     ELF::ELFOSABI_HURD         },
199f4a2713aSLionel Sambuc   { "Solaris",      ELF::ELFOSABI_SOLARIS      },
200f4a2713aSLionel Sambuc   { "AIX",          ELF::ELFOSABI_AIX          },
201f4a2713aSLionel Sambuc   { "IRIX",         ELF::ELFOSABI_IRIX         },
202f4a2713aSLionel Sambuc   { "FreeBSD",      ELF::ELFOSABI_FREEBSD      },
203f4a2713aSLionel Sambuc   { "TRU64",        ELF::ELFOSABI_TRU64        },
204f4a2713aSLionel Sambuc   { "Modesto",      ELF::ELFOSABI_MODESTO      },
205f4a2713aSLionel Sambuc   { "OpenBSD",      ELF::ELFOSABI_OPENBSD      },
206f4a2713aSLionel Sambuc   { "OpenVMS",      ELF::ELFOSABI_OPENVMS      },
207f4a2713aSLionel Sambuc   { "NSK",          ELF::ELFOSABI_NSK          },
208f4a2713aSLionel Sambuc   { "AROS",         ELF::ELFOSABI_AROS         },
209f4a2713aSLionel Sambuc   { "FenixOS",      ELF::ELFOSABI_FENIXOS      },
210f4a2713aSLionel Sambuc   { "C6000_ELFABI", ELF::ELFOSABI_C6000_ELFABI },
211f4a2713aSLionel Sambuc   { "C6000_LINUX" , ELF::ELFOSABI_C6000_LINUX  },
212f4a2713aSLionel Sambuc   { "ARM",          ELF::ELFOSABI_ARM          },
213f4a2713aSLionel Sambuc   { "Standalone"  , ELF::ELFOSABI_STANDALONE   }
214f4a2713aSLionel Sambuc };
215f4a2713aSLionel Sambuc 
216f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfMachineType[] = {
217f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_NONE         ),
218f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_M32          ),
219f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARC        ),
220f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_386          ),
221f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68K          ),
222f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_88K          ),
223f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_486          ),
224f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_860          ),
225f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS         ),
226f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_S370         ),
227f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS_RS3_LE  ),
228f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PARISC       ),
229f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_VPP500       ),
230f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARC32PLUS  ),
231f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_960          ),
232f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PPC          ),
233f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PPC64        ),
234f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_S390         ),
235f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SPU          ),
236f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_V800         ),
237f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_FR20         ),
238f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_RH32         ),
239f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_RCE          ),
240f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ARM          ),
241f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ALPHA        ),
242f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SH           ),
243f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SPARCV9      ),
244f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TRICORE      ),
245f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC          ),
246f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_300       ),
247f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_300H      ),
248f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_H8S          ),
249f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_H8_500       ),
250f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_IA_64        ),
251f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MIPS_X       ),
252f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_COLDFIRE     ),
253f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC12       ),
254f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MMA          ),
255f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PCP          ),
256f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_NCPU         ),
257f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_NDR1         ),
258f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_STARCORE     ),
259f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ME16         ),
260f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ST100        ),
261f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TINYJ        ),
262f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_X86_64       ),
263f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PDSP         ),
264f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PDP10        ),
265f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PDP11        ),
266f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_FX66         ),
267f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ST9PLUS      ),
268f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ST7          ),
269f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC16       ),
270f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC11       ),
271f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC08       ),
272f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_68HC05       ),
273f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SVX          ),
274f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ST19         ),
275f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_VAX          ),
276f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CRIS         ),
277f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_JAVELIN      ),
278f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_FIREPATH     ),
279f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ZSP          ),
280f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MMIX         ),
281f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_HUANY        ),
282f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PRISM        ),
283f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_AVR          ),
284f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_FR30         ),
285f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_D10V         ),
286f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_D30V         ),
287f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_V850         ),
288f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_M32R         ),
289f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MN10300      ),
290f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MN10200      ),
291f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_PJ           ),
292f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_OPENRISC     ),
293f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC_COMPACT  ),
294f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_XTENSA       ),
295f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE    ),
296f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TMM_GPP      ),
297f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_NS32K        ),
298f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TPC          ),
299f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SNP1K        ),
300f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ST200        ),
301f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_IP2K         ),
302f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MAX          ),
303f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CR           ),
304f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_F2MC16       ),
305f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MSP430       ),
306f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_BLACKFIN     ),
307f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SE_C33       ),
308f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SEP          ),
309f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ARCA         ),
310f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_UNICORE      ),
311f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_EXCESS       ),
312f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_DXP          ),
313f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ALTERA_NIOS2 ),
314f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CRX          ),
315f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_XGATE        ),
316f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_C166         ),
317f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_M16C         ),
318f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_DSPIC30F     ),
319f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CE           ),
320f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_M32C         ),
321f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TSK3000      ),
322f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_RS08         ),
323f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SHARC        ),
324f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG2        ),
325f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SCORE7       ),
326f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_DSP24        ),
327f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE3   ),
328f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_LATTICEMICO32),
329f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SE_C17       ),
330f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C6000     ),
331f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C2000     ),
332f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TI_C5500     ),
333f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MMDSP_PLUS   ),
334f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CYPRESS_M8C  ),
335f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_R32C         ),
336f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TRIMEDIA     ),
337f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_HEXAGON      ),
338f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_8051         ),
339f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_STXP7X       ),
340f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_NDS32        ),
341f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG1        ),
342f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG1X       ),
343f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MAXQ30       ),
344f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_XIMO16       ),
345f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MANIK        ),
346f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CRAYNV2      ),
347f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_RX           ),
348f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_METAG        ),
349f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_MCST_ELBRUS  ),
350f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ECOG16       ),
351f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CR16         ),
352f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ETPU         ),
353f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_SLE9X        ),
354f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_L10M         ),
355f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_K10M         ),
356f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_AARCH64      ),
357f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_AVR32        ),
358f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_STM8         ),
359f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TILE64       ),
360f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEPRO      ),
361f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CUDA         ),
362f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEGX       ),
363f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_CLOUDSHIELD  ),
364f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_COREA_1ST    ),
365f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_COREA_2ND    ),
366f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_ARC_COMPACT2 ),
367f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_OPEN8        ),
368f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_RL78         ),
369f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5   ),
370f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR        ),
371f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX      )
372f4a2713aSLionel Sambuc };
373f4a2713aSLionel Sambuc 
374f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfSymbolBindings[] = {
375f4a2713aSLionel Sambuc   { "Local",  ELF::STB_LOCAL  },
376f4a2713aSLionel Sambuc   { "Global", ELF::STB_GLOBAL },
377f4a2713aSLionel Sambuc   { "Weak",   ELF::STB_WEAK   }
378f4a2713aSLionel Sambuc };
379f4a2713aSLionel Sambuc 
380f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfSymbolTypes[] = {
381f4a2713aSLionel Sambuc   { "None",      ELF::STT_NOTYPE    },
382f4a2713aSLionel Sambuc   { "Object",    ELF::STT_OBJECT    },
383f4a2713aSLionel Sambuc   { "Function",  ELF::STT_FUNC      },
384f4a2713aSLionel Sambuc   { "Section",   ELF::STT_SECTION   },
385f4a2713aSLionel Sambuc   { "File",      ELF::STT_FILE      },
386f4a2713aSLionel Sambuc   { "Common",    ELF::STT_COMMON    },
387f4a2713aSLionel Sambuc   { "TLS",       ELF::STT_TLS       },
388f4a2713aSLionel Sambuc   { "GNU_IFunc", ELF::STT_GNU_IFUNC }
389f4a2713aSLionel Sambuc };
390f4a2713aSLionel Sambuc 
getElfSectionType(unsigned Arch,unsigned Type)391f4a2713aSLionel Sambuc static const char *getElfSectionType(unsigned Arch, unsigned Type) {
392f4a2713aSLionel Sambuc   switch (Arch) {
393f4a2713aSLionel Sambuc   case ELF::EM_ARM:
394f4a2713aSLionel Sambuc     switch (Type) {
395f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_EXIDX);
396f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP);
397f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES);
398f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY);
399f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION);
400f4a2713aSLionel Sambuc     }
401f4a2713aSLionel Sambuc   case ELF::EM_HEXAGON:
402f4a2713aSLionel Sambuc     switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); }
403f4a2713aSLionel Sambuc   case ELF::EM_X86_64:
404f4a2713aSLionel Sambuc     switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); }
405f4a2713aSLionel Sambuc   case ELF::EM_MIPS:
406f4a2713aSLionel Sambuc   case ELF::EM_MIPS_RS3_LE:
407f4a2713aSLionel Sambuc     switch (Type) {
408f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_REGINFO);
409f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_OPTIONS);
410*0a6a1f1dSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS);
411f4a2713aSLionel Sambuc     }
412f4a2713aSLionel Sambuc   }
413f4a2713aSLionel Sambuc 
414f4a2713aSLionel Sambuc   switch (Type) {
415f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_NULL              );
416f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_PROGBITS          );
417f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB            );
418f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_STRTAB            );
419f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_RELA              );
420f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_HASH              );
421f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNAMIC           );
422f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOTE              );
423f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_NOBITS            );
424f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_REL               );
425f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_SHLIB             );
426f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_DYNSYM            );
427f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_INIT_ARRAY        );
428f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_FINI_ARRAY        );
429f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_PREINIT_ARRAY     );
430f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GROUP             );
431f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX      );
432f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES    );
433f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_HASH          );
434f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verdef        );
435f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_verneed       );
436f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, SHT_GNU_versym        );
437f4a2713aSLionel Sambuc   default: return "";
438f4a2713aSLionel Sambuc   }
439f4a2713aSLionel Sambuc }
440f4a2713aSLionel Sambuc 
441f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfSectionFlags[] = {
442f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_WRITE           ),
443f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_ALLOC           ),
444f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXCLUDE         ),
445f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXECINSTR       ),
446f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MERGE           ),
447f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_STRINGS         ),
448f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_INFO_LINK       ),
449f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_LINK_ORDER      ),
450f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_OS_NONCONFORMING),
451f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_GROUP           ),
452f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_TLS             ),
453f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION),
454f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION),
455f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP    )
456f4a2713aSLionel Sambuc };
457f4a2713aSLionel Sambuc 
getElfSegmentType(unsigned Arch,unsigned Type)458f4a2713aSLionel Sambuc static const char *getElfSegmentType(unsigned Arch, unsigned Type) {
459f4a2713aSLionel Sambuc   // Check potentially overlapped processor-specific
460f4a2713aSLionel Sambuc   // program header type.
461f4a2713aSLionel Sambuc   switch (Arch) {
462f4a2713aSLionel Sambuc   case ELF::EM_ARM:
463f4a2713aSLionel Sambuc     switch (Type) {
464f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX);
465f4a2713aSLionel Sambuc     }
466f4a2713aSLionel Sambuc   case ELF::EM_MIPS:
467f4a2713aSLionel Sambuc   case ELF::EM_MIPS_RS3_LE:
468f4a2713aSLionel Sambuc     switch (Type) {
469f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);
470f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);
471f4a2713aSLionel Sambuc     LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);
472f4a2713aSLionel Sambuc     }
473f4a2713aSLionel Sambuc   }
474f4a2713aSLionel Sambuc 
475f4a2713aSLionel Sambuc   switch (Type) {
476f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL   );
477f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD   );
478f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC);
479f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP );
480f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE   );
481f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB  );
482f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR   );
483f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS    );
484f4a2713aSLionel Sambuc 
485f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME);
486f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND);
487f4a2713aSLionel Sambuc 
488f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK);
489f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);
490f4a2713aSLionel Sambuc   default: return "";
491f4a2713aSLionel Sambuc   }
492f4a2713aSLionel Sambuc }
493f4a2713aSLionel Sambuc 
494f4a2713aSLionel Sambuc static const EnumEntry<unsigned> ElfSegmentFlags[] = {
495f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, PF_X),
496f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, PF_W),
497f4a2713aSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, PF_R)
498f4a2713aSLionel Sambuc };
499f4a2713aSLionel Sambuc 
500*0a6a1f1dSLionel Sambuc static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
501*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER),
502*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC),
503*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC),
504*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2),
505*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE),
506*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008),
507*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32),
508*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS),
509*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16),
510*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1),
511*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2),
512*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3),
513*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4),
514*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5),
515*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32),
516*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64),
517*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2),
518*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2),
519*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6),
520*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
521*0a6a1f1dSLionel Sambuc };
522*0a6a1f1dSLionel Sambuc 
523f4a2713aSLionel Sambuc template<class ELFT>
printFileHeaders()524f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printFileHeaders() {
525f4a2713aSLionel Sambuc   const typename ELFO::Elf_Ehdr *Header = Obj->getHeader();
526f4a2713aSLionel Sambuc 
527f4a2713aSLionel Sambuc   {
528f4a2713aSLionel Sambuc     DictScope D(W, "ElfHeader");
529f4a2713aSLionel Sambuc     {
530f4a2713aSLionel Sambuc       DictScope D(W, "Ident");
531f4a2713aSLionel Sambuc       W.printBinary("Magic", makeArrayRef(Header->e_ident).slice(ELF::EI_MAG0,
532f4a2713aSLionel Sambuc                                                                  4));
533f4a2713aSLionel Sambuc       W.printEnum  ("Class", Header->e_ident[ELF::EI_CLASS],
534f4a2713aSLionel Sambuc                       makeArrayRef(ElfClass));
535f4a2713aSLionel Sambuc       W.printEnum  ("DataEncoding", Header->e_ident[ELF::EI_DATA],
536f4a2713aSLionel Sambuc                       makeArrayRef(ElfDataEncoding));
537f4a2713aSLionel Sambuc       W.printNumber("FileVersion", Header->e_ident[ELF::EI_VERSION]);
538f4a2713aSLionel Sambuc       W.printEnum  ("OS/ABI", Header->e_ident[ELF::EI_OSABI],
539f4a2713aSLionel Sambuc                       makeArrayRef(ElfOSABI));
540f4a2713aSLionel Sambuc       W.printNumber("ABIVersion", Header->e_ident[ELF::EI_ABIVERSION]);
541f4a2713aSLionel Sambuc       W.printBinary("Unused", makeArrayRef(Header->e_ident).slice(ELF::EI_PAD));
542f4a2713aSLionel Sambuc     }
543f4a2713aSLionel Sambuc 
544f4a2713aSLionel Sambuc     W.printEnum  ("Type", Header->e_type, makeArrayRef(ElfObjectFileType));
545f4a2713aSLionel Sambuc     W.printEnum  ("Machine", Header->e_machine, makeArrayRef(ElfMachineType));
546f4a2713aSLionel Sambuc     W.printNumber("Version", Header->e_version);
547f4a2713aSLionel Sambuc     W.printHex   ("Entry", Header->e_entry);
548f4a2713aSLionel Sambuc     W.printHex   ("ProgramHeaderOffset", Header->e_phoff);
549f4a2713aSLionel Sambuc     W.printHex   ("SectionHeaderOffset", Header->e_shoff);
550*0a6a1f1dSLionel Sambuc     if (Header->e_machine == EM_MIPS)
551*0a6a1f1dSLionel Sambuc       W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags),
552*0a6a1f1dSLionel Sambuc                    unsigned(ELF::EF_MIPS_ARCH));
553*0a6a1f1dSLionel Sambuc     else
554f4a2713aSLionel Sambuc       W.printFlags("Flags", Header->e_flags);
555f4a2713aSLionel Sambuc     W.printNumber("HeaderSize", Header->e_ehsize);
556f4a2713aSLionel Sambuc     W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize);
557f4a2713aSLionel Sambuc     W.printNumber("ProgramHeaderCount", Header->e_phnum);
558f4a2713aSLionel Sambuc     W.printNumber("SectionHeaderEntrySize", Header->e_shentsize);
559f4a2713aSLionel Sambuc     W.printNumber("SectionHeaderCount", Header->e_shnum);
560f4a2713aSLionel Sambuc     W.printNumber("StringTableSectionIndex", Header->e_shstrndx);
561f4a2713aSLionel Sambuc   }
562f4a2713aSLionel Sambuc }
563f4a2713aSLionel Sambuc 
564f4a2713aSLionel Sambuc template<class ELFT>
printSections()565f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printSections() {
566f4a2713aSLionel Sambuc   ListScope SectionsD(W, "Sections");
567f4a2713aSLionel Sambuc 
568f4a2713aSLionel Sambuc   int SectionIndex = -1;
569f4a2713aSLionel Sambuc   for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(),
570f4a2713aSLionel Sambuc                                     SecE = Obj->end_sections();
571f4a2713aSLionel Sambuc        SecI != SecE; ++SecI) {
572f4a2713aSLionel Sambuc     ++SectionIndex;
573f4a2713aSLionel Sambuc 
574f4a2713aSLionel Sambuc     const Elf_Shdr *Section = &*SecI;
575f4a2713aSLionel Sambuc     StringRef Name = errorOrDefault(Obj->getSectionName(Section));
576f4a2713aSLionel Sambuc 
577f4a2713aSLionel Sambuc     DictScope SectionD(W, "Section");
578f4a2713aSLionel Sambuc     W.printNumber("Index", SectionIndex);
579f4a2713aSLionel Sambuc     W.printNumber("Name", Name, Section->sh_name);
580f4a2713aSLionel Sambuc     W.printHex("Type",
581f4a2713aSLionel Sambuc                getElfSectionType(Obj->getHeader()->e_machine, Section->sh_type),
582f4a2713aSLionel Sambuc                Section->sh_type);
583f4a2713aSLionel Sambuc     W.printFlags ("Flags", Section->sh_flags, makeArrayRef(ElfSectionFlags));
584f4a2713aSLionel Sambuc     W.printHex   ("Address", Section->sh_addr);
585f4a2713aSLionel Sambuc     W.printHex   ("Offset", Section->sh_offset);
586f4a2713aSLionel Sambuc     W.printNumber("Size", Section->sh_size);
587f4a2713aSLionel Sambuc     W.printNumber("Link", Section->sh_link);
588f4a2713aSLionel Sambuc     W.printNumber("Info", Section->sh_info);
589f4a2713aSLionel Sambuc     W.printNumber("AddressAlignment", Section->sh_addralign);
590f4a2713aSLionel Sambuc     W.printNumber("EntrySize", Section->sh_entsize);
591f4a2713aSLionel Sambuc 
592f4a2713aSLionel Sambuc     if (opts::SectionRelocations) {
593f4a2713aSLionel Sambuc       ListScope D(W, "Relocations");
594f4a2713aSLionel Sambuc       printRelocations(Section);
595f4a2713aSLionel Sambuc     }
596f4a2713aSLionel Sambuc 
597f4a2713aSLionel Sambuc     if (opts::SectionSymbols) {
598f4a2713aSLionel Sambuc       ListScope D(W, "Symbols");
599f4a2713aSLionel Sambuc       for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(),
600f4a2713aSLionel Sambuc                                        SymE = Obj->end_symbols();
601f4a2713aSLionel Sambuc            SymI != SymE; ++SymI) {
602f4a2713aSLionel Sambuc         if (Obj->getSection(&*SymI) == Section)
603f4a2713aSLionel Sambuc           printSymbol(SymI);
604f4a2713aSLionel Sambuc       }
605f4a2713aSLionel Sambuc     }
606f4a2713aSLionel Sambuc 
607*0a6a1f1dSLionel Sambuc     if (opts::SectionData && Section->sh_type != ELF::SHT_NOBITS) {
608f4a2713aSLionel Sambuc       ArrayRef<uint8_t> Data = errorOrDefault(Obj->getSectionContents(Section));
609f4a2713aSLionel Sambuc       W.printBinaryBlock("SectionData",
610f4a2713aSLionel Sambuc                          StringRef((const char *)Data.data(), Data.size()));
611f4a2713aSLionel Sambuc     }
612f4a2713aSLionel Sambuc   }
613f4a2713aSLionel Sambuc }
614f4a2713aSLionel Sambuc 
615f4a2713aSLionel Sambuc template<class ELFT>
printRelocations()616f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printRelocations() {
617f4a2713aSLionel Sambuc   ListScope D(W, "Relocations");
618f4a2713aSLionel Sambuc 
619f4a2713aSLionel Sambuc   int SectionNumber = -1;
620f4a2713aSLionel Sambuc   for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(),
621f4a2713aSLionel Sambuc                                     SecE = Obj->end_sections();
622f4a2713aSLionel Sambuc        SecI != SecE; ++SecI) {
623f4a2713aSLionel Sambuc     ++SectionNumber;
624f4a2713aSLionel Sambuc 
625f4a2713aSLionel Sambuc     if (SecI->sh_type != ELF::SHT_REL && SecI->sh_type != ELF::SHT_RELA)
626f4a2713aSLionel Sambuc       continue;
627f4a2713aSLionel Sambuc 
628f4a2713aSLionel Sambuc     StringRef Name = errorOrDefault(Obj->getSectionName(&*SecI));
629f4a2713aSLionel Sambuc 
630f4a2713aSLionel Sambuc     W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
631f4a2713aSLionel Sambuc     W.indent();
632f4a2713aSLionel Sambuc 
633f4a2713aSLionel Sambuc     printRelocations(&*SecI);
634f4a2713aSLionel Sambuc 
635f4a2713aSLionel Sambuc     W.unindent();
636f4a2713aSLionel Sambuc     W.startLine() << "}\n";
637f4a2713aSLionel Sambuc   }
638f4a2713aSLionel Sambuc }
639f4a2713aSLionel Sambuc 
640f4a2713aSLionel Sambuc template <class ELFT>
printRelocations(const Elf_Shdr * Sec)641f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
642f4a2713aSLionel Sambuc   switch (Sec->sh_type) {
643f4a2713aSLionel Sambuc   case ELF::SHT_REL:
644f4a2713aSLionel Sambuc     for (typename ELFO::Elf_Rel_Iter RI = Obj->begin_rel(Sec),
645f4a2713aSLionel Sambuc                                      RE = Obj->end_rel(Sec);
646f4a2713aSLionel Sambuc          RI != RE; ++RI) {
647f4a2713aSLionel Sambuc       typename ELFO::Elf_Rela Rela;
648f4a2713aSLionel Sambuc       Rela.r_offset = RI->r_offset;
649f4a2713aSLionel Sambuc       Rela.r_info = RI->r_info;
650f4a2713aSLionel Sambuc       Rela.r_addend = 0;
651f4a2713aSLionel Sambuc       printRelocation(Sec, Rela);
652f4a2713aSLionel Sambuc     }
653f4a2713aSLionel Sambuc     break;
654f4a2713aSLionel Sambuc   case ELF::SHT_RELA:
655f4a2713aSLionel Sambuc     for (typename ELFO::Elf_Rela_Iter RI = Obj->begin_rela(Sec),
656f4a2713aSLionel Sambuc                                       RE = Obj->end_rela(Sec);
657f4a2713aSLionel Sambuc          RI != RE; ++RI) {
658f4a2713aSLionel Sambuc       printRelocation(Sec, *RI);
659f4a2713aSLionel Sambuc     }
660f4a2713aSLionel Sambuc     break;
661f4a2713aSLionel Sambuc   }
662f4a2713aSLionel Sambuc }
663f4a2713aSLionel Sambuc 
664f4a2713aSLionel Sambuc template <class ELFT>
printRelocation(const Elf_Shdr * Sec,typename ELFO::Elf_Rela Rel)665f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec,
666f4a2713aSLionel Sambuc                                       typename ELFO::Elf_Rela Rel) {
667f4a2713aSLionel Sambuc   SmallString<32> RelocName;
668f4a2713aSLionel Sambuc   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
669f4a2713aSLionel Sambuc   StringRef SymbolName;
670f4a2713aSLionel Sambuc   std::pair<const Elf_Shdr *, const Elf_Sym *> Sym =
671f4a2713aSLionel Sambuc       Obj->getRelocationSymbol(Sec, &Rel);
672f4a2713aSLionel Sambuc   if (Sym.first)
673f4a2713aSLionel Sambuc     SymbolName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second));
674f4a2713aSLionel Sambuc 
675f4a2713aSLionel Sambuc   if (opts::ExpandRelocs) {
676f4a2713aSLionel Sambuc     DictScope Group(W, "Relocation");
677f4a2713aSLionel Sambuc     W.printHex("Offset", Rel.r_offset);
678f4a2713aSLionel Sambuc     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
679*0a6a1f1dSLionel Sambuc     W.printNumber("Symbol", SymbolName.size() > 0 ? SymbolName : "-",
680*0a6a1f1dSLionel Sambuc                   Rel.getSymbol(Obj->isMips64EL()));
681f4a2713aSLionel Sambuc     W.printHex("Addend", Rel.r_addend);
682f4a2713aSLionel Sambuc   } else {
683f4a2713aSLionel Sambuc     raw_ostream& OS = W.startLine();
684f4a2713aSLionel Sambuc     OS << W.hex(Rel.r_offset)
685f4a2713aSLionel Sambuc        << " " << RelocName
686f4a2713aSLionel Sambuc        << " " << (SymbolName.size() > 0 ? SymbolName : "-")
687f4a2713aSLionel Sambuc        << " " << W.hex(Rel.r_addend)
688f4a2713aSLionel Sambuc        << "\n";
689f4a2713aSLionel Sambuc   }
690f4a2713aSLionel Sambuc }
691f4a2713aSLionel Sambuc 
692f4a2713aSLionel Sambuc template<class ELFT>
printSymbols()693f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printSymbols() {
694f4a2713aSLionel Sambuc   ListScope Group(W, "Symbols");
695f4a2713aSLionel Sambuc   for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(),
696f4a2713aSLionel Sambuc                                    SymE = Obj->end_symbols();
697f4a2713aSLionel Sambuc        SymI != SymE; ++SymI) {
698f4a2713aSLionel Sambuc     printSymbol(SymI);
699f4a2713aSLionel Sambuc   }
700f4a2713aSLionel Sambuc }
701f4a2713aSLionel Sambuc 
702f4a2713aSLionel Sambuc template<class ELFT>
printDynamicSymbols()703f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printDynamicSymbols() {
704f4a2713aSLionel Sambuc   ListScope Group(W, "DynamicSymbols");
705f4a2713aSLionel Sambuc 
706f4a2713aSLionel Sambuc   for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_dynamic_symbols(),
707f4a2713aSLionel Sambuc                                    SymE = Obj->end_dynamic_symbols();
708f4a2713aSLionel Sambuc        SymI != SymE; ++SymI) {
709f4a2713aSLionel Sambuc     printSymbol(SymI);
710f4a2713aSLionel Sambuc   }
711f4a2713aSLionel Sambuc }
712f4a2713aSLionel Sambuc 
713f4a2713aSLionel Sambuc template <class ELFT>
printSymbol(typename ELFO::Elf_Sym_Iter Symbol)714f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
715*0a6a1f1dSLionel Sambuc   unsigned SectionIndex = 0;
716*0a6a1f1dSLionel Sambuc   StringRef SectionName;
717*0a6a1f1dSLionel Sambuc   getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex);
718*0a6a1f1dSLionel Sambuc   std::string FullSymbolName = getFullSymbolName(*Obj, Symbol);
719f4a2713aSLionel Sambuc 
720f4a2713aSLionel Sambuc   DictScope D(W, "Symbol");
721f4a2713aSLionel Sambuc   W.printNumber("Name", FullSymbolName, Symbol->st_name);
722f4a2713aSLionel Sambuc   W.printHex   ("Value", Symbol->st_value);
723f4a2713aSLionel Sambuc   W.printNumber("Size", Symbol->st_size);
724f4a2713aSLionel Sambuc   W.printEnum  ("Binding", Symbol->getBinding(),
725f4a2713aSLionel Sambuc                   makeArrayRef(ElfSymbolBindings));
726f4a2713aSLionel Sambuc   W.printEnum  ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes));
727f4a2713aSLionel Sambuc   W.printNumber("Other", Symbol->st_other);
728*0a6a1f1dSLionel Sambuc   W.printHex("Section", SectionName, SectionIndex);
729f4a2713aSLionel Sambuc }
730f4a2713aSLionel Sambuc 
731f4a2713aSLionel Sambuc #define LLVM_READOBJ_TYPE_CASE(name) \
732f4a2713aSLionel Sambuc   case DT_##name: return #name
733f4a2713aSLionel Sambuc 
getTypeString(uint64_t Type)734f4a2713aSLionel Sambuc static const char *getTypeString(uint64_t Type) {
735f4a2713aSLionel Sambuc   switch (Type) {
736f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(BIND_NOW);
737f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(DEBUG);
738f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(FINI);
739f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(FINI_ARRAY);
740f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(FINI_ARRAYSZ);
741f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(FLAGS);
742f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(HASH);
743f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(INIT);
744f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(INIT_ARRAY);
745f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(INIT_ARRAYSZ);
746f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAY);
747f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(PREINIT_ARRAYSZ);
748f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(JMPREL);
749f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(NEEDED);
750f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(NULL);
751f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(PLTGOT);
752f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(PLTREL);
753f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(PLTRELSZ);
754f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(REL);
755f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELA);
756f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELENT);
757f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELSZ);
758f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELAENT);
759f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELASZ);
760f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RPATH);
761f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RUNPATH);
762f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(SONAME);
763f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(STRSZ);
764f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(STRTAB);
765f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(SYMBOLIC);
766f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(SYMENT);
767f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(SYMTAB);
768f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(TEXTREL);
769f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(VERNEED);
770f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(VERNEEDNUM);
771f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(VERSYM);
772*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(RELCOUNT);
773*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(GNU_HASH);
774f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION);
775f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS);
776f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS);
777f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO);
778f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO);
779f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO);
780f4a2713aSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM);
781*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP);
782*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT);
783f4a2713aSLionel Sambuc   default: return "unknown";
784f4a2713aSLionel Sambuc   }
785f4a2713aSLionel Sambuc }
786f4a2713aSLionel Sambuc 
787f4a2713aSLionel Sambuc #undef LLVM_READOBJ_TYPE_CASE
788f4a2713aSLionel Sambuc 
789*0a6a1f1dSLionel Sambuc #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \
790*0a6a1f1dSLionel Sambuc   { #enum, prefix##_##enum }
791*0a6a1f1dSLionel Sambuc 
792*0a6a1f1dSLionel Sambuc static const EnumEntry<unsigned> ElfDynamicDTFlags[] = {
793*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),
794*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),
795*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),
796*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),
797*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)
798*0a6a1f1dSLionel Sambuc };
799*0a6a1f1dSLionel Sambuc 
800*0a6a1f1dSLionel Sambuc static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {
801*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),
802*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),
803*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),
804*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),
805*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),
806*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),
807*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),
808*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),
809*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),
810*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),
811*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),
812*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),
813*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),
814*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),
815*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),
816*0a6a1f1dSLionel Sambuc   LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)
817*0a6a1f1dSLionel Sambuc };
818*0a6a1f1dSLionel Sambuc 
819*0a6a1f1dSLionel Sambuc #undef LLVM_READOBJ_DT_FLAG_ENT
820*0a6a1f1dSLionel Sambuc 
821*0a6a1f1dSLionel Sambuc template <typename T, typename TFlag>
printFlags(T Value,ArrayRef<EnumEntry<TFlag>> Flags,raw_ostream & OS)822*0a6a1f1dSLionel Sambuc void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
823*0a6a1f1dSLionel Sambuc   typedef EnumEntry<TFlag> FlagEntry;
824*0a6a1f1dSLionel Sambuc   typedef SmallVector<FlagEntry, 10> FlagVector;
825*0a6a1f1dSLionel Sambuc   FlagVector SetFlags;
826*0a6a1f1dSLionel Sambuc 
827*0a6a1f1dSLionel Sambuc   for (const auto &Flag : Flags) {
828*0a6a1f1dSLionel Sambuc     if (Flag.Value == 0)
829*0a6a1f1dSLionel Sambuc       continue;
830*0a6a1f1dSLionel Sambuc 
831*0a6a1f1dSLionel Sambuc     if ((Value & Flag.Value) == Flag.Value)
832*0a6a1f1dSLionel Sambuc       SetFlags.push_back(Flag);
833*0a6a1f1dSLionel Sambuc   }
834*0a6a1f1dSLionel Sambuc 
835*0a6a1f1dSLionel Sambuc   for (const auto &Flag : SetFlags) {
836*0a6a1f1dSLionel Sambuc     OS << Flag.Name << " ";
837*0a6a1f1dSLionel Sambuc   }
838*0a6a1f1dSLionel Sambuc }
839*0a6a1f1dSLionel Sambuc 
840f4a2713aSLionel Sambuc template <class ELFT>
printValue(const ELFFile<ELFT> * O,uint64_t Type,uint64_t Value,bool Is64,raw_ostream & OS)841f4a2713aSLionel Sambuc static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
842f4a2713aSLionel Sambuc                        bool Is64, raw_ostream &OS) {
843f4a2713aSLionel Sambuc   switch (Type) {
844f4a2713aSLionel Sambuc   case DT_PLTREL:
845f4a2713aSLionel Sambuc     if (Value == DT_REL) {
846f4a2713aSLionel Sambuc       OS << "REL";
847f4a2713aSLionel Sambuc       break;
848f4a2713aSLionel Sambuc     } else if (Value == DT_RELA) {
849f4a2713aSLionel Sambuc       OS << "RELA";
850f4a2713aSLionel Sambuc       break;
851f4a2713aSLionel Sambuc     }
852f4a2713aSLionel Sambuc   // Fallthrough.
853f4a2713aSLionel Sambuc   case DT_PLTGOT:
854f4a2713aSLionel Sambuc   case DT_HASH:
855f4a2713aSLionel Sambuc   case DT_STRTAB:
856f4a2713aSLionel Sambuc   case DT_SYMTAB:
857f4a2713aSLionel Sambuc   case DT_RELA:
858f4a2713aSLionel Sambuc   case DT_INIT:
859f4a2713aSLionel Sambuc   case DT_FINI:
860f4a2713aSLionel Sambuc   case DT_REL:
861f4a2713aSLionel Sambuc   case DT_JMPREL:
862f4a2713aSLionel Sambuc   case DT_INIT_ARRAY:
863f4a2713aSLionel Sambuc   case DT_FINI_ARRAY:
864f4a2713aSLionel Sambuc   case DT_PREINIT_ARRAY:
865f4a2713aSLionel Sambuc   case DT_DEBUG:
866f4a2713aSLionel Sambuc   case DT_VERNEED:
867f4a2713aSLionel Sambuc   case DT_VERSYM:
868*0a6a1f1dSLionel Sambuc   case DT_GNU_HASH:
869f4a2713aSLionel Sambuc   case DT_NULL:
870f4a2713aSLionel Sambuc   case DT_MIPS_BASE_ADDRESS:
871f4a2713aSLionel Sambuc   case DT_MIPS_GOTSYM:
872*0a6a1f1dSLionel Sambuc   case DT_MIPS_RLD_MAP:
873*0a6a1f1dSLionel Sambuc   case DT_MIPS_PLTGOT:
874f4a2713aSLionel Sambuc     OS << format("0x%" PRIX64, Value);
875f4a2713aSLionel Sambuc     break;
876*0a6a1f1dSLionel Sambuc   case DT_RELCOUNT:
877f4a2713aSLionel Sambuc   case DT_VERNEEDNUM:
878f4a2713aSLionel Sambuc   case DT_MIPS_RLD_VERSION:
879f4a2713aSLionel Sambuc   case DT_MIPS_LOCAL_GOTNO:
880f4a2713aSLionel Sambuc   case DT_MIPS_SYMTABNO:
881f4a2713aSLionel Sambuc   case DT_MIPS_UNREFEXTNO:
882f4a2713aSLionel Sambuc     OS << Value;
883f4a2713aSLionel Sambuc     break;
884f4a2713aSLionel Sambuc   case DT_PLTRELSZ:
885f4a2713aSLionel Sambuc   case DT_RELASZ:
886f4a2713aSLionel Sambuc   case DT_RELAENT:
887f4a2713aSLionel Sambuc   case DT_STRSZ:
888f4a2713aSLionel Sambuc   case DT_SYMENT:
889f4a2713aSLionel Sambuc   case DT_RELSZ:
890f4a2713aSLionel Sambuc   case DT_RELENT:
891f4a2713aSLionel Sambuc   case DT_INIT_ARRAYSZ:
892f4a2713aSLionel Sambuc   case DT_FINI_ARRAYSZ:
893f4a2713aSLionel Sambuc   case DT_PREINIT_ARRAYSZ:
894f4a2713aSLionel Sambuc     OS << Value << " (bytes)";
895f4a2713aSLionel Sambuc     break;
896f4a2713aSLionel Sambuc   case DT_NEEDED:
897f4a2713aSLionel Sambuc     OS << "SharedLibrary (" << O->getDynamicString(Value) << ")";
898f4a2713aSLionel Sambuc     break;
899f4a2713aSLionel Sambuc   case DT_SONAME:
900f4a2713aSLionel Sambuc     OS << "LibrarySoname (" << O->getDynamicString(Value) << ")";
901f4a2713aSLionel Sambuc     break;
902f4a2713aSLionel Sambuc   case DT_RPATH:
903f4a2713aSLionel Sambuc   case DT_RUNPATH:
904f4a2713aSLionel Sambuc     OS << O->getDynamicString(Value);
905f4a2713aSLionel Sambuc     break;
906*0a6a1f1dSLionel Sambuc   case DT_MIPS_FLAGS:
907*0a6a1f1dSLionel Sambuc     printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
908*0a6a1f1dSLionel Sambuc     break;
909*0a6a1f1dSLionel Sambuc   case DT_FLAGS:
910*0a6a1f1dSLionel Sambuc     printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
911*0a6a1f1dSLionel Sambuc     break;
912f4a2713aSLionel Sambuc   }
913f4a2713aSLionel Sambuc }
914f4a2713aSLionel Sambuc 
915f4a2713aSLionel Sambuc template<class ELFT>
printUnwindInfo()916f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printUnwindInfo() {
917f4a2713aSLionel Sambuc   W.startLine() << "UnwindInfo not implemented.\n";
918f4a2713aSLionel Sambuc }
919f4a2713aSLionel Sambuc 
920*0a6a1f1dSLionel Sambuc namespace {
921*0a6a1f1dSLionel Sambuc template <>
printUnwindInfo()922*0a6a1f1dSLionel Sambuc void ELFDumper<ELFType<support::little, 2, false> >::printUnwindInfo() {
923*0a6a1f1dSLionel Sambuc   const unsigned Machine = Obj->getHeader()->e_machine;
924*0a6a1f1dSLionel Sambuc   if (Machine == EM_ARM) {
925*0a6a1f1dSLionel Sambuc     ARM::EHABI::PrinterContext<ELFType<support::little, 2, false> > Ctx(W, Obj);
926*0a6a1f1dSLionel Sambuc     return Ctx.PrintUnwindInformation();
927*0a6a1f1dSLionel Sambuc   }
928*0a6a1f1dSLionel Sambuc   W.startLine() << "UnwindInfo not implemented.\n";
929*0a6a1f1dSLionel Sambuc }
930*0a6a1f1dSLionel Sambuc }
931*0a6a1f1dSLionel Sambuc 
932f4a2713aSLionel Sambuc template<class ELFT>
printDynamicTable()933f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printDynamicTable() {
934*0a6a1f1dSLionel Sambuc   auto DynTable = Obj->dynamic_table(true);
935f4a2713aSLionel Sambuc 
936*0a6a1f1dSLionel Sambuc   ptrdiff_t Total = std::distance(DynTable.begin(), DynTable.end());
937*0a6a1f1dSLionel Sambuc   if (Total == 0)
938f4a2713aSLionel Sambuc     return;
939f4a2713aSLionel Sambuc 
940f4a2713aSLionel Sambuc   raw_ostream &OS = W.getOStream();
941f4a2713aSLionel Sambuc   W.startLine() << "DynamicSection [ (" << Total << " entries)\n";
942f4a2713aSLionel Sambuc 
943f4a2713aSLionel Sambuc   bool Is64 = ELFT::Is64Bits;
944f4a2713aSLionel Sambuc 
945f4a2713aSLionel Sambuc   W.startLine()
946f4a2713aSLionel Sambuc      << "  Tag" << (Is64 ? "                " : "        ") << "Type"
947f4a2713aSLionel Sambuc      << "                 " << "Name/Value\n";
948*0a6a1f1dSLionel Sambuc   for (const auto &Entry : DynTable) {
949f4a2713aSLionel Sambuc     W.startLine()
950f4a2713aSLionel Sambuc        << "  "
951*0a6a1f1dSLionel Sambuc        << format(Is64 ? "0x%016" PRIX64 : "0x%08" PRIX64, Entry.getTag())
952*0a6a1f1dSLionel Sambuc        << " " << format("%-21s", getTypeString(Entry.getTag()));
953*0a6a1f1dSLionel Sambuc     printValue(Obj, Entry.getTag(), Entry.getVal(), Is64, OS);
954f4a2713aSLionel Sambuc     OS << "\n";
955f4a2713aSLionel Sambuc   }
956f4a2713aSLionel Sambuc 
957f4a2713aSLionel Sambuc   W.startLine() << "]\n";
958f4a2713aSLionel Sambuc }
959f4a2713aSLionel Sambuc 
960f4a2713aSLionel Sambuc template<class ELFT>
printNeededLibraries()961f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printNeededLibraries() {
962f4a2713aSLionel Sambuc   ListScope D(W, "NeededLibraries");
963f4a2713aSLionel Sambuc 
964f4a2713aSLionel Sambuc   typedef std::vector<StringRef> LibsTy;
965f4a2713aSLionel Sambuc   LibsTy Libs;
966f4a2713aSLionel Sambuc 
967*0a6a1f1dSLionel Sambuc   for (const auto &Entry : Obj->dynamic_table())
968*0a6a1f1dSLionel Sambuc     if (Entry.d_tag == ELF::DT_NEEDED)
969*0a6a1f1dSLionel Sambuc       Libs.push_back(Obj->getDynamicString(Entry.d_un.d_val));
970f4a2713aSLionel Sambuc 
971f4a2713aSLionel Sambuc   std::stable_sort(Libs.begin(), Libs.end());
972f4a2713aSLionel Sambuc 
973f4a2713aSLionel Sambuc   for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); I != E; ++I) {
974f4a2713aSLionel Sambuc     outs() << "  " << *I << "\n";
975f4a2713aSLionel Sambuc   }
976f4a2713aSLionel Sambuc }
977f4a2713aSLionel Sambuc 
978f4a2713aSLionel Sambuc template<class ELFT>
printProgramHeaders()979f4a2713aSLionel Sambuc void ELFDumper<ELFT>::printProgramHeaders() {
980f4a2713aSLionel Sambuc   ListScope L(W, "ProgramHeaders");
981f4a2713aSLionel Sambuc 
982f4a2713aSLionel Sambuc   for (typename ELFO::Elf_Phdr_Iter PI = Obj->begin_program_headers(),
983f4a2713aSLionel Sambuc                                     PE = Obj->end_program_headers();
984f4a2713aSLionel Sambuc                                     PI != PE; ++PI) {
985f4a2713aSLionel Sambuc     DictScope P(W, "ProgramHeader");
986f4a2713aSLionel Sambuc     W.printHex   ("Type",
987f4a2713aSLionel Sambuc                   getElfSegmentType(Obj->getHeader()->e_machine, PI->p_type),
988f4a2713aSLionel Sambuc                   PI->p_type);
989f4a2713aSLionel Sambuc     W.printHex   ("Offset", PI->p_offset);
990f4a2713aSLionel Sambuc     W.printHex   ("VirtualAddress", PI->p_vaddr);
991f4a2713aSLionel Sambuc     W.printHex   ("PhysicalAddress", PI->p_paddr);
992f4a2713aSLionel Sambuc     W.printNumber("FileSize", PI->p_filesz);
993f4a2713aSLionel Sambuc     W.printNumber("MemSize", PI->p_memsz);
994f4a2713aSLionel Sambuc     W.printFlags ("Flags", PI->p_flags, makeArrayRef(ElfSegmentFlags));
995f4a2713aSLionel Sambuc     W.printNumber("Alignment", PI->p_align);
996f4a2713aSLionel Sambuc   }
997f4a2713aSLionel Sambuc }
998*0a6a1f1dSLionel Sambuc 
999*0a6a1f1dSLionel Sambuc template <class ELFT>
printAttributes()1000*0a6a1f1dSLionel Sambuc void ELFDumper<ELFT>::printAttributes() {
1001*0a6a1f1dSLionel Sambuc   W.startLine() << "Attributes not implemented.\n";
1002*0a6a1f1dSLionel Sambuc }
1003*0a6a1f1dSLionel Sambuc 
1004*0a6a1f1dSLionel Sambuc namespace {
1005*0a6a1f1dSLionel Sambuc template <>
printAttributes()1006*0a6a1f1dSLionel Sambuc void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() {
1007*0a6a1f1dSLionel Sambuc   if (Obj->getHeader()->e_machine != EM_ARM) {
1008*0a6a1f1dSLionel Sambuc     W.startLine() << "Attributes not implemented.\n";
1009*0a6a1f1dSLionel Sambuc     return;
1010*0a6a1f1dSLionel Sambuc   }
1011*0a6a1f1dSLionel Sambuc 
1012*0a6a1f1dSLionel Sambuc   DictScope BA(W, "BuildAttributes");
1013*0a6a1f1dSLionel Sambuc   for (ELFO::Elf_Shdr_Iter SI = Obj->begin_sections(), SE = Obj->end_sections();
1014*0a6a1f1dSLionel Sambuc        SI != SE; ++SI) {
1015*0a6a1f1dSLionel Sambuc     if (SI->sh_type != ELF::SHT_ARM_ATTRIBUTES)
1016*0a6a1f1dSLionel Sambuc       continue;
1017*0a6a1f1dSLionel Sambuc 
1018*0a6a1f1dSLionel Sambuc     ErrorOr<ArrayRef<uint8_t> > Contents = Obj->getSectionContents(&(*SI));
1019*0a6a1f1dSLionel Sambuc     if (!Contents)
1020*0a6a1f1dSLionel Sambuc       continue;
1021*0a6a1f1dSLionel Sambuc 
1022*0a6a1f1dSLionel Sambuc     if ((*Contents)[0] != ARMBuildAttrs::Format_Version) {
1023*0a6a1f1dSLionel Sambuc       errs() << "unrecognised FormatVersion: 0x" << utohexstr((*Contents)[0])
1024*0a6a1f1dSLionel Sambuc              << '\n';
1025*0a6a1f1dSLionel Sambuc       continue;
1026*0a6a1f1dSLionel Sambuc     }
1027*0a6a1f1dSLionel Sambuc 
1028*0a6a1f1dSLionel Sambuc     W.printHex("FormatVersion", (*Contents)[0]);
1029*0a6a1f1dSLionel Sambuc     if (Contents->size() == 1)
1030*0a6a1f1dSLionel Sambuc       continue;
1031*0a6a1f1dSLionel Sambuc 
1032*0a6a1f1dSLionel Sambuc     ARMAttributeParser(W).Parse(*Contents);
1033*0a6a1f1dSLionel Sambuc   }
1034*0a6a1f1dSLionel Sambuc }
1035*0a6a1f1dSLionel Sambuc }
1036*0a6a1f1dSLionel Sambuc 
1037*0a6a1f1dSLionel Sambuc namespace {
1038*0a6a1f1dSLionel Sambuc template <class ELFT> class MipsGOTParser {
1039*0a6a1f1dSLionel Sambuc public:
1040*0a6a1f1dSLionel Sambuc   typedef object::ELFFile<ELFT> ObjectFile;
1041*0a6a1f1dSLionel Sambuc   typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
1042*0a6a1f1dSLionel Sambuc 
MipsGOTParser(const ObjectFile * Obj,StreamWriter & W)1043*0a6a1f1dSLionel Sambuc   MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
1044*0a6a1f1dSLionel Sambuc 
1045*0a6a1f1dSLionel Sambuc   void parseGOT(const Elf_Shdr &GOTShdr);
1046*0a6a1f1dSLionel Sambuc 
1047*0a6a1f1dSLionel Sambuc private:
1048*0a6a1f1dSLionel Sambuc   typedef typename ObjectFile::Elf_Sym_Iter Elf_Sym_Iter;
1049*0a6a1f1dSLionel Sambuc   typedef typename ObjectFile::Elf_Addr GOTEntry;
1050*0a6a1f1dSLionel Sambuc   typedef typename ObjectFile::template ELFEntityIterator<const GOTEntry>
1051*0a6a1f1dSLionel Sambuc   GOTIter;
1052*0a6a1f1dSLionel Sambuc 
1053*0a6a1f1dSLionel Sambuc   const ObjectFile *Obj;
1054*0a6a1f1dSLionel Sambuc   StreamWriter &W;
1055*0a6a1f1dSLionel Sambuc 
1056*0a6a1f1dSLionel Sambuc   std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
1057*0a6a1f1dSLionel Sambuc   GOTIter makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
1058*0a6a1f1dSLionel Sambuc 
1059*0a6a1f1dSLionel Sambuc   bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
1060*0a6a1f1dSLionel Sambuc   void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
1061*0a6a1f1dSLionel Sambuc   void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
1062*0a6a1f1dSLionel Sambuc                            Elf_Sym_Iter Sym);
1063*0a6a1f1dSLionel Sambuc };
1064*0a6a1f1dSLionel Sambuc }
1065*0a6a1f1dSLionel Sambuc 
1066*0a6a1f1dSLionel Sambuc template <class ELFT>
parseGOT(const Elf_Shdr & GOTShdr)1067*0a6a1f1dSLionel Sambuc void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) {
1068*0a6a1f1dSLionel Sambuc   // See "Global Offset Table" in Chapter 5 in the following document
1069*0a6a1f1dSLionel Sambuc   // for detailed GOT description.
1070*0a6a1f1dSLionel Sambuc   // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1071*0a6a1f1dSLionel Sambuc 
1072*0a6a1f1dSLionel Sambuc   ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(&GOTShdr);
1073*0a6a1f1dSLionel Sambuc   if (!GOT) {
1074*0a6a1f1dSLionel Sambuc     W.startLine() << "The .got section is empty.\n";
1075*0a6a1f1dSLionel Sambuc     return;
1076*0a6a1f1dSLionel Sambuc   }
1077*0a6a1f1dSLionel Sambuc 
1078*0a6a1f1dSLionel Sambuc   uint64_t DtLocalGotNum;
1079*0a6a1f1dSLionel Sambuc   uint64_t DtGotSym;
1080*0a6a1f1dSLionel Sambuc   if (!getGOTTags(DtLocalGotNum, DtGotSym))
1081*0a6a1f1dSLionel Sambuc     return;
1082*0a6a1f1dSLionel Sambuc 
1083*0a6a1f1dSLionel Sambuc   if (DtLocalGotNum > getGOTTotal(*GOT)) {
1084*0a6a1f1dSLionel Sambuc     W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
1085*0a6a1f1dSLionel Sambuc     return;
1086*0a6a1f1dSLionel Sambuc   }
1087*0a6a1f1dSLionel Sambuc 
1088*0a6a1f1dSLionel Sambuc   Elf_Sym_Iter DynSymBegin = Obj->begin_dynamic_symbols();
1089*0a6a1f1dSLionel Sambuc   Elf_Sym_Iter DynSymEnd = Obj->end_dynamic_symbols();
1090*0a6a1f1dSLionel Sambuc   std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
1091*0a6a1f1dSLionel Sambuc 
1092*0a6a1f1dSLionel Sambuc   if (DtGotSym > DynSymTotal) {
1093*0a6a1f1dSLionel Sambuc     W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
1094*0a6a1f1dSLionel Sambuc     return;
1095*0a6a1f1dSLionel Sambuc   }
1096*0a6a1f1dSLionel Sambuc 
1097*0a6a1f1dSLionel Sambuc   std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
1098*0a6a1f1dSLionel Sambuc 
1099*0a6a1f1dSLionel Sambuc   if (DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) {
1100*0a6a1f1dSLionel Sambuc     W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
1101*0a6a1f1dSLionel Sambuc     return;
1102*0a6a1f1dSLionel Sambuc   }
1103*0a6a1f1dSLionel Sambuc 
1104*0a6a1f1dSLionel Sambuc   GOTIter GotBegin = makeGOTIter(*GOT, 0);
1105*0a6a1f1dSLionel Sambuc   GOTIter GotLocalEnd = makeGOTIter(*GOT, DtLocalGotNum);
1106*0a6a1f1dSLionel Sambuc   GOTIter It = GotBegin;
1107*0a6a1f1dSLionel Sambuc 
1108*0a6a1f1dSLionel Sambuc   DictScope GS(W, "Primary GOT");
1109*0a6a1f1dSLionel Sambuc 
1110*0a6a1f1dSLionel Sambuc   W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
1111*0a6a1f1dSLionel Sambuc   {
1112*0a6a1f1dSLionel Sambuc     ListScope RS(W, "Reserved entries");
1113*0a6a1f1dSLionel Sambuc 
1114*0a6a1f1dSLionel Sambuc     {
1115*0a6a1f1dSLionel Sambuc       DictScope D(W, "Entry");
1116*0a6a1f1dSLionel Sambuc       printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1117*0a6a1f1dSLionel Sambuc       W.printString("Purpose", StringRef("Lazy resolver"));
1118*0a6a1f1dSLionel Sambuc     }
1119*0a6a1f1dSLionel Sambuc 
1120*0a6a1f1dSLionel Sambuc     if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
1121*0a6a1f1dSLionel Sambuc       DictScope D(W, "Entry");
1122*0a6a1f1dSLionel Sambuc       printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1123*0a6a1f1dSLionel Sambuc       W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
1124*0a6a1f1dSLionel Sambuc     }
1125*0a6a1f1dSLionel Sambuc   }
1126*0a6a1f1dSLionel Sambuc   {
1127*0a6a1f1dSLionel Sambuc     ListScope LS(W, "Local entries");
1128*0a6a1f1dSLionel Sambuc     for (; It != GotLocalEnd; ++It) {
1129*0a6a1f1dSLionel Sambuc       DictScope D(W, "Entry");
1130*0a6a1f1dSLionel Sambuc       printGotEntry(GOTShdr.sh_addr, GotBegin, It);
1131*0a6a1f1dSLionel Sambuc     }
1132*0a6a1f1dSLionel Sambuc   }
1133*0a6a1f1dSLionel Sambuc   {
1134*0a6a1f1dSLionel Sambuc     ListScope GS(W, "Global entries");
1135*0a6a1f1dSLionel Sambuc 
1136*0a6a1f1dSLionel Sambuc     GOTIter GotGlobalEnd = makeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
1137*0a6a1f1dSLionel Sambuc     Elf_Sym_Iter GotDynSym = DynSymBegin + DtGotSym;
1138*0a6a1f1dSLionel Sambuc     for (; It != GotGlobalEnd; ++It) {
1139*0a6a1f1dSLionel Sambuc       DictScope D(W, "Entry");
1140*0a6a1f1dSLionel Sambuc       printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++);
1141*0a6a1f1dSLionel Sambuc     }
1142*0a6a1f1dSLionel Sambuc   }
1143*0a6a1f1dSLionel Sambuc 
1144*0a6a1f1dSLionel Sambuc   std::size_t SpecGotNum = getGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
1145*0a6a1f1dSLionel Sambuc   W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum));
1146*0a6a1f1dSLionel Sambuc }
1147*0a6a1f1dSLionel Sambuc 
1148*0a6a1f1dSLionel Sambuc template <class ELFT>
getGOTTotal(ArrayRef<uint8_t> GOT) const1149*0a6a1f1dSLionel Sambuc std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const {
1150*0a6a1f1dSLionel Sambuc   return GOT.size() / sizeof(GOTEntry);
1151*0a6a1f1dSLionel Sambuc }
1152*0a6a1f1dSLionel Sambuc 
1153*0a6a1f1dSLionel Sambuc template <class ELFT>
1154*0a6a1f1dSLionel Sambuc typename MipsGOTParser<ELFT>::GOTIter
makeGOTIter(ArrayRef<uint8_t> GOT,std::size_t EntryNum)1155*0a6a1f1dSLionel Sambuc MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
1156*0a6a1f1dSLionel Sambuc   const char *Data = reinterpret_cast<const char *>(GOT.data());
1157*0a6a1f1dSLionel Sambuc   return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
1158*0a6a1f1dSLionel Sambuc }
1159*0a6a1f1dSLionel Sambuc 
1160*0a6a1f1dSLionel Sambuc template <class ELFT>
getGOTTags(uint64_t & LocalGotNum,uint64_t & GotSym)1161*0a6a1f1dSLionel Sambuc bool MipsGOTParser<ELFT>::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
1162*0a6a1f1dSLionel Sambuc   bool FoundLocalGotNum = false;
1163*0a6a1f1dSLionel Sambuc   bool FoundGotSym = false;
1164*0a6a1f1dSLionel Sambuc   for (const auto &Entry : Obj->dynamic_table()) {
1165*0a6a1f1dSLionel Sambuc     switch (Entry.getTag()) {
1166*0a6a1f1dSLionel Sambuc     case ELF::DT_MIPS_LOCAL_GOTNO:
1167*0a6a1f1dSLionel Sambuc       LocalGotNum = Entry.getVal();
1168*0a6a1f1dSLionel Sambuc       FoundLocalGotNum = true;
1169*0a6a1f1dSLionel Sambuc       break;
1170*0a6a1f1dSLionel Sambuc     case ELF::DT_MIPS_GOTSYM:
1171*0a6a1f1dSLionel Sambuc       GotSym = Entry.getVal();
1172*0a6a1f1dSLionel Sambuc       FoundGotSym = true;
1173*0a6a1f1dSLionel Sambuc       break;
1174*0a6a1f1dSLionel Sambuc     }
1175*0a6a1f1dSLionel Sambuc   }
1176*0a6a1f1dSLionel Sambuc 
1177*0a6a1f1dSLionel Sambuc   if (!FoundLocalGotNum) {
1178*0a6a1f1dSLionel Sambuc     W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
1179*0a6a1f1dSLionel Sambuc     return false;
1180*0a6a1f1dSLionel Sambuc   }
1181*0a6a1f1dSLionel Sambuc 
1182*0a6a1f1dSLionel Sambuc   if (!FoundGotSym) {
1183*0a6a1f1dSLionel Sambuc     W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
1184*0a6a1f1dSLionel Sambuc     return false;
1185*0a6a1f1dSLionel Sambuc   }
1186*0a6a1f1dSLionel Sambuc 
1187*0a6a1f1dSLionel Sambuc   return true;
1188*0a6a1f1dSLionel Sambuc }
1189*0a6a1f1dSLionel Sambuc 
1190*0a6a1f1dSLionel Sambuc template <class ELFT>
printGotEntry(uint64_t GotAddr,GOTIter BeginIt,GOTIter It)1191*0a6a1f1dSLionel Sambuc void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1192*0a6a1f1dSLionel Sambuc                                         GOTIter It) {
1193*0a6a1f1dSLionel Sambuc   int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
1194*0a6a1f1dSLionel Sambuc   W.printHex("Address", GotAddr + Offset);
1195*0a6a1f1dSLionel Sambuc   W.printNumber("Access", Offset - 0x7ff0);
1196*0a6a1f1dSLionel Sambuc   W.printHex("Initial", *It);
1197*0a6a1f1dSLionel Sambuc }
1198*0a6a1f1dSLionel Sambuc 
1199*0a6a1f1dSLionel Sambuc template <class ELFT>
printGlobalGotEntry(uint64_t GotAddr,GOTIter BeginIt,GOTIter It,Elf_Sym_Iter Sym)1200*0a6a1f1dSLionel Sambuc void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1201*0a6a1f1dSLionel Sambuc                                               GOTIter It, Elf_Sym_Iter Sym) {
1202*0a6a1f1dSLionel Sambuc   printGotEntry(GotAddr, BeginIt, It);
1203*0a6a1f1dSLionel Sambuc 
1204*0a6a1f1dSLionel Sambuc   W.printHex("Value", Sym->st_value);
1205*0a6a1f1dSLionel Sambuc   W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
1206*0a6a1f1dSLionel Sambuc 
1207*0a6a1f1dSLionel Sambuc   unsigned SectionIndex = 0;
1208*0a6a1f1dSLionel Sambuc   StringRef SectionName;
1209*0a6a1f1dSLionel Sambuc   getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
1210*0a6a1f1dSLionel Sambuc   W.printHex("Section", SectionName, SectionIndex);
1211*0a6a1f1dSLionel Sambuc 
1212*0a6a1f1dSLionel Sambuc   std::string FullSymbolName = getFullSymbolName(*Obj, Sym);
1213*0a6a1f1dSLionel Sambuc   W.printNumber("Name", FullSymbolName, Sym->st_name);
1214*0a6a1f1dSLionel Sambuc }
1215*0a6a1f1dSLionel Sambuc 
printMipsPLTGOT()1216*0a6a1f1dSLionel Sambuc template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
1217*0a6a1f1dSLionel Sambuc   if (Obj->getHeader()->e_machine != EM_MIPS) {
1218*0a6a1f1dSLionel Sambuc     W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
1219*0a6a1f1dSLionel Sambuc     return;
1220*0a6a1f1dSLionel Sambuc   }
1221*0a6a1f1dSLionel Sambuc 
1222*0a6a1f1dSLionel Sambuc   llvm::Optional<uint64_t> DtPltGot;
1223*0a6a1f1dSLionel Sambuc   for (const auto &Entry : Obj->dynamic_table()) {
1224*0a6a1f1dSLionel Sambuc     if (Entry.getTag() == ELF::DT_PLTGOT) {
1225*0a6a1f1dSLionel Sambuc       DtPltGot = Entry.getVal();
1226*0a6a1f1dSLionel Sambuc       break;
1227*0a6a1f1dSLionel Sambuc     }
1228*0a6a1f1dSLionel Sambuc   }
1229*0a6a1f1dSLionel Sambuc 
1230*0a6a1f1dSLionel Sambuc   if (!DtPltGot) {
1231*0a6a1f1dSLionel Sambuc     W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
1232*0a6a1f1dSLionel Sambuc     return;
1233*0a6a1f1dSLionel Sambuc   }
1234*0a6a1f1dSLionel Sambuc 
1235*0a6a1f1dSLionel Sambuc   const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
1236*0a6a1f1dSLionel Sambuc   if (!GotShdr) {
1237*0a6a1f1dSLionel Sambuc     W.startLine() << "There is no .got section in the file.\n";
1238*0a6a1f1dSLionel Sambuc     return;
1239*0a6a1f1dSLionel Sambuc   }
1240*0a6a1f1dSLionel Sambuc 
1241*0a6a1f1dSLionel Sambuc   MipsGOTParser<ELFT>(Obj, W).parseGOT(*GotShdr);
1242*0a6a1f1dSLionel Sambuc }
1243