| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1 | //===- ELFDumper.cpp - ELF-specific dumper --------------------------------===// | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | /// | 
|  | 10 | /// \file | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 11 | /// This file implements the ELF-specific dumper for llvm-readobj. | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 12 | /// | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 15 | #include "ARMEHABIPrinter.h" | 
| Rafael Auler | 86fb7bf | 2018-03-08 00:46:53 +0000 | [diff] [blame] | 16 | #include "DwarfCFIEHPrinter.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 17 | #include "Error.h" | 
|  | 18 | #include "ObjDumper.h" | 
|  | 19 | #include "StackMapPrinter.h" | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 20 | #include "llvm-readobj.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/ArrayRef.h" | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/DenseMap.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/Optional.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 24 | #include "llvm/ADT/PointerIntPair.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 25 | #include "llvm/ADT/SmallString.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/SmallVector.h" | 
|  | 27 | #include "llvm/ADT/STLExtras.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 28 | #include "llvm/ADT/StringExtras.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 29 | #include "llvm/ADT/StringRef.h" | 
|  | 30 | #include "llvm/ADT/Twine.h" | 
|  | 31 | #include "llvm/BinaryFormat/ELF.h" | 
|  | 32 | #include "llvm/Object/ELF.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 33 | #include "llvm/Object/ELFObjectFile.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 34 | #include "llvm/Object/ELFTypes.h" | 
|  | 35 | #include "llvm/Object/Error.h" | 
|  | 36 | #include "llvm/Object/ObjectFile.h" | 
|  | 37 | #include "llvm/Object/StackMapParser.h" | 
| Konstantin Zhuravlyov | b3c605d | 2017-10-14 18:21:42 +0000 | [diff] [blame] | 38 | #include "llvm/Support/AMDGPUMetadata.h" | 
| Sam Parker | 34315ee | 2017-01-13 10:50:01 +0000 | [diff] [blame] | 39 | #include "llvm/Support/ARMAttributeParser.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 40 | #include "llvm/Support/ARMBuildAttributes.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 41 | #include "llvm/Support/Casting.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 42 | #include "llvm/Support/Compiler.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 43 | #include "llvm/Support/Endian.h" | 
|  | 44 | #include "llvm/Support/ErrorHandling.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 45 | #include "llvm/Support/Format.h" | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 46 | #include "llvm/Support/FormattedStream.h" | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 47 | #include "llvm/Support/LEB128.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 48 | #include "llvm/Support/MathExtras.h" | 
|  | 49 | #include "llvm/Support/MipsABIFlags.h" | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 50 | #include "llvm/Support/ScopedPrinter.h" | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 51 | #include "llvm/Support/raw_ostream.h" | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 52 | #include <algorithm> | 
|  | 53 | #include <cinttypes> | 
|  | 54 | #include <cstddef> | 
|  | 55 | #include <cstdint> | 
|  | 56 | #include <cstdlib> | 
|  | 57 | #include <iterator> | 
|  | 58 | #include <memory> | 
|  | 59 | #include <string> | 
|  | 60 | #include <system_error> | 
|  | 61 | #include <vector> | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 62 |  | 
|  | 63 | using namespace llvm; | 
|  | 64 | using namespace llvm::object; | 
|  | 65 | using namespace ELF; | 
|  | 66 |  | 
|  | 67 | #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ | 
|  | 68 | case ns::enum: return #enum; | 
|  | 69 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 70 | #define ENUM_ENT(enum, altName) \ | 
|  | 71 | { #enum, altName, ELF::enum } | 
|  | 72 |  | 
|  | 73 | #define ENUM_ENT_1(enum) \ | 
|  | 74 | { #enum, #enum, ELF::enum } | 
|  | 75 |  | 
| Hemant Kulkarni | 7d564ba | 2016-03-28 17:20:23 +0000 | [diff] [blame] | 76 | #define LLVM_READOBJ_PHDR_ENUM(ns, enum)                                       \ | 
|  | 77 | case ns::enum:                                                               \ | 
|  | 78 | return std::string(#enum).substr(3); | 
|  | 79 |  | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 80 | #define TYPEDEF_ELF_TYPES(ELFT)                                                \ | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 81 | using ELFO = ELFFile<ELFT>;                                                  \ | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 82 | using Elf_Addr = typename ELFT::Addr;                                        \ | 
|  | 83 | using Elf_Shdr = typename ELFT::Shdr;                                        \ | 
|  | 84 | using Elf_Sym = typename ELFT::Sym;                                          \ | 
|  | 85 | using Elf_Dyn = typename ELFT::Dyn;                                          \ | 
|  | 86 | using Elf_Dyn_Range = typename ELFT::DynRange;                               \ | 
|  | 87 | using Elf_Rel = typename ELFT::Rel;                                          \ | 
|  | 88 | using Elf_Rela = typename ELFT::Rela;                                        \ | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 89 | using Elf_Relr = typename ELFT::Relr;                                        \ | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 90 | using Elf_Rel_Range = typename ELFT::RelRange;                               \ | 
|  | 91 | using Elf_Rela_Range = typename ELFT::RelaRange;                             \ | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 92 | using Elf_Relr_Range = typename ELFT::RelrRange;                             \ | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 93 | using Elf_Phdr = typename ELFT::Phdr;                                        \ | 
|  | 94 | using Elf_Half = typename ELFT::Half;                                        \ | 
|  | 95 | using Elf_Ehdr = typename ELFT::Ehdr;                                        \ | 
|  | 96 | using Elf_Word = typename ELFT::Word;                                        \ | 
|  | 97 | using Elf_Hash = typename ELFT::Hash;                                        \ | 
|  | 98 | using Elf_GnuHash = typename ELFT::GnuHash;                                  \ | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 99 | using Elf_Note  = typename ELFT::Note;                                       \ | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 100 | using Elf_Sym_Range = typename ELFT::SymRange;                               \ | 
|  | 101 | using Elf_Versym = typename ELFT::Versym;                                    \ | 
|  | 102 | using Elf_Verneed = typename ELFT::Verneed;                                  \ | 
|  | 103 | using Elf_Vernaux = typename ELFT::Vernaux;                                  \ | 
|  | 104 | using Elf_Verdef = typename ELFT::Verdef;                                    \ | 
|  | 105 | using Elf_Verdaux = typename ELFT::Verdaux;                                  \ | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 106 | using Elf_CGProfile = typename ELFT::CGProfile;                              \ | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 107 | using uintX_t = typename ELFT::uint; | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 108 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 109 | namespace { | 
|  | 110 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 111 | template <class ELFT> class DumpStyle; | 
|  | 112 |  | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 113 | /// Represents a contiguous uniform range in the file. We cannot just create a | 
|  | 114 | /// range directly because when creating one of these from the .dynamic table | 
|  | 115 | /// the size, entity size and virtual address are different entries in arbitrary | 
|  | 116 | /// order (DT_REL, DT_RELSZ, DT_RELENT for example). | 
| Rafael Espindola | 65a6fd8 | 2016-02-16 14:27:33 +0000 | [diff] [blame] | 117 | struct DynRegionInfo { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 118 | DynRegionInfo() = default; | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 119 | DynRegionInfo(const void *A, uint64_t S, uint64_t ES) | 
|  | 120 | : Addr(A), Size(S), EntSize(ES) {} | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 121 |  | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 122 | /// Address in current address space. | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 123 | const void *Addr = nullptr; | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 124 | /// Size in bytes of the region. | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 125 | uint64_t Size = 0; | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 126 | /// Size of each entity in the region. | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 127 | uint64_t EntSize = 0; | 
| Rafael Espindola | c70aeda | 2016-02-16 14:50:39 +0000 | [diff] [blame] | 128 |  | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 129 | template <typename Type> ArrayRef<Type> getAsArrayRef() const { | 
| Rafael Espindola | c70aeda | 2016-02-16 14:50:39 +0000 | [diff] [blame] | 130 | const Type *Start = reinterpret_cast<const Type *>(Addr); | 
| Rafael Espindola | 944f655 | 2016-02-16 15:16:00 +0000 | [diff] [blame] | 131 | if (!Start) | 
|  | 132 | return {Start, Start}; | 
| Rafael Espindola | c70aeda | 2016-02-16 14:50:39 +0000 | [diff] [blame] | 133 | if (EntSize != sizeof(Type) || Size % EntSize) | 
|  | 134 | reportError("Invalid entity size"); | 
|  | 135 | return {Start, Start + (Size / EntSize)}; | 
|  | 136 | } | 
| Rafael Espindola | 65a6fd8 | 2016-02-16 14:27:33 +0000 | [diff] [blame] | 137 | }; | 
|  | 138 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 139 | template<typename ELFT> | 
|  | 140 | class ELFDumper : public ObjDumper { | 
|  | 141 | public: | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 142 | ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 143 |  | 
|  | 144 | void printFileHeaders() override; | 
|  | 145 | void printSections() override; | 
|  | 146 | void printRelocations() override; | 
|  | 147 | void printDynamicRelocations() override; | 
|  | 148 | void printSymbols() override; | 
|  | 149 | void printDynamicSymbols() override; | 
|  | 150 | void printUnwindInfo() override; | 
|  | 151 |  | 
|  | 152 | void printDynamicTable() override; | 
|  | 153 | void printNeededLibraries() override; | 
|  | 154 | void printProgramHeaders() override; | 
|  | 155 | void printHashTable() override; | 
|  | 156 | void printGnuHashTable() override; | 
|  | 157 | void printLoadName() override; | 
|  | 158 | void printVersionInfo() override; | 
| Hemant Kulkarni | ab4a46f | 2016-01-26 19:46:39 +0000 | [diff] [blame] | 159 | void printGroupSections() override; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 160 |  | 
|  | 161 | void printAttributes() override; | 
|  | 162 | void printMipsPLTGOT() override; | 
|  | 163 | void printMipsABIFlags() override; | 
|  | 164 | void printMipsReginfo() override; | 
| Simon Atanasyan | 8a71b53 | 2016-05-04 05:58:57 +0000 | [diff] [blame] | 165 | void printMipsOptions() override; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 166 |  | 
|  | 167 | void printStackMap() const override; | 
|  | 168 |  | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 169 | void printHashHistogram() override; | 
|  | 170 |  | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 171 | void printCGProfile() override; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 172 | void printAddrsig() override; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 173 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 174 | void printNotes() override; | 
|  | 175 |  | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 176 | void printELFLinkerOptions() override; | 
|  | 177 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 178 | private: | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 179 | std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 180 |  | 
| Rafael Espindola | 6bc2990 | 2016-10-06 14:07:26 +0000 | [diff] [blame] | 181 | TYPEDEF_ELF_TYPES(ELFT) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 182 |  | 
| Rafael Espindola | e17c3f3 | 2016-02-17 16:48:00 +0000 | [diff] [blame] | 183 | DynRegionInfo checkDRI(DynRegionInfo DRI) { | 
|  | 184 | if (DRI.Addr < Obj->base() || | 
|  | 185 | (const uint8_t *)DRI.Addr + DRI.Size > Obj->base() + Obj->getBufSize()) | 
|  | 186 | error(llvm::object::object_error::parse_failed); | 
|  | 187 | return DRI; | 
|  | 188 | } | 
|  | 189 |  | 
|  | 190 | DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) { | 
|  | 191 | return checkDRI({Obj->base() + P->p_offset, P->p_filesz, EntSize}); | 
|  | 192 | } | 
|  | 193 |  | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 194 | DynRegionInfo createDRIFrom(const Elf_Shdr *S) { | 
| Rafael Espindola | e17c3f3 | 2016-02-17 16:48:00 +0000 | [diff] [blame] | 195 | return checkDRI({Obj->base() + S->sh_offset, S->sh_size, S->sh_entsize}); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 196 | } | 
|  | 197 |  | 
| Michael J. Spencer | 60d82b2 | 2016-02-11 04:59:37 +0000 | [diff] [blame] | 198 | void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments); | 
|  | 199 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 200 | void printValue(uint64_t Type, uint64_t Value); | 
|  | 201 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 202 | StringRef getDynamicString(uint64_t Offset) const; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 203 | StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 204 | bool &IsDefault) const; | 
|  | 205 | void LoadVersionMap() const; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 206 | void LoadVersionNeeds(const Elf_Shdr *ec) const; | 
|  | 207 | void LoadVersionDefs(const Elf_Shdr *sec) const; | 
|  | 208 |  | 
|  | 209 | const ELFO *Obj; | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 210 | DynRegionInfo DynRelRegion; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 211 | DynRegionInfo DynRelaRegion; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 212 | DynRegionInfo DynRelrRegion; | 
| Rafael Espindola | 944f655 | 2016-02-16 15:16:00 +0000 | [diff] [blame] | 213 | DynRegionInfo DynPLTRelRegion; | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 214 | DynRegionInfo DynSymRegion; | 
| Rafael Espindola | e17c3f3 | 2016-02-17 16:48:00 +0000 | [diff] [blame] | 215 | DynRegionInfo DynamicTable; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 216 | StringRef DynamicStringTable; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 217 | StringRef SOName; | 
|  | 218 | const Elf_Hash *HashTable = nullptr; | 
|  | 219 | const Elf_GnuHash *GnuHashTable = nullptr; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 220 | const Elf_Shdr *DotSymtabSec = nullptr; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 221 | const Elf_Shdr *DotCGProfileSec = nullptr; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 222 | const Elf_Shdr *DotAddrsigSec = nullptr; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 223 | StringRef DynSymtabName; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 224 | ArrayRef<Elf_Word> ShndxTable; | 
|  | 225 |  | 
|  | 226 | const Elf_Shdr *dot_gnu_version_sec = nullptr;   // .gnu.version | 
|  | 227 | const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r | 
|  | 228 | const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d | 
|  | 229 |  | 
|  | 230 | // Records for each version index the corresponding Verdef or Vernaux entry. | 
|  | 231 | // This is filled the first time LoadVersionMap() is called. | 
|  | 232 | class VersionMapEntry : public PointerIntPair<const void *, 1> { | 
|  | 233 | public: | 
|  | 234 | // If the integer is 0, this is an Elf_Verdef*. | 
|  | 235 | // If the integer is 1, this is an Elf_Vernaux*. | 
|  | 236 | VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {} | 
|  | 237 | VersionMapEntry(const Elf_Verdef *verdef) | 
|  | 238 | : PointerIntPair<const void *, 1>(verdef, 0) {} | 
|  | 239 | VersionMapEntry(const Elf_Vernaux *vernaux) | 
|  | 240 | : PointerIntPair<const void *, 1>(vernaux, 1) {} | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 241 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 242 | bool isNull() const { return getPointer() == nullptr; } | 
|  | 243 | bool isVerdef() const { return !isNull() && getInt() == 0; } | 
|  | 244 | bool isVernaux() const { return !isNull() && getInt() == 1; } | 
|  | 245 | const Elf_Verdef *getVerdef() const { | 
|  | 246 | return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr; | 
|  | 247 | } | 
|  | 248 | const Elf_Vernaux *getVernaux() const { | 
|  | 249 | return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr; | 
|  | 250 | } | 
|  | 251 | }; | 
|  | 252 | mutable SmallVector<VersionMapEntry, 16> VersionMap; | 
|  | 253 |  | 
|  | 254 | public: | 
|  | 255 | Elf_Dyn_Range dynamic_table() const { | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 256 | return DynamicTable.getAsArrayRef<Elf_Dyn>(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 257 | } | 
|  | 258 |  | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 259 | Elf_Sym_Range dynamic_symbols() const { | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 260 | return DynSymRegion.getAsArrayRef<Elf_Sym>(); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 261 | } | 
|  | 262 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 263 | Elf_Rel_Range dyn_rels() const; | 
|  | 264 | Elf_Rela_Range dyn_relas() const; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 265 | Elf_Relr_Range dyn_relrs() const; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 266 | std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 267 | bool IsDynamic) const; | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 268 | void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, | 
|  | 269 | StringRef &SectionName, | 
|  | 270 | unsigned &SectionIndex) const; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 271 | StringRef getStaticSymbolName(uint32_t Index) const; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 272 |  | 
|  | 273 | void printSymbolsHelper(bool IsDynamic) const; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 274 | const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 275 | const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 276 | const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 277 | ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; } | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 278 | StringRef getDynamicStringTable() const { return DynamicStringTable; } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 279 | const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } | 
|  | 280 | const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 281 | const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 282 | const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 283 | const Elf_Hash *getHashTable() const { return HashTable; } | 
|  | 284 | const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 285 | }; | 
|  | 286 |  | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 287 | template <class ELFT> | 
|  | 288 | void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { | 
|  | 289 | StringRef StrTable, SymtabName; | 
|  | 290 | size_t Entries = 0; | 
|  | 291 | Elf_Sym_Range Syms(nullptr, nullptr); | 
|  | 292 | if (IsDynamic) { | 
|  | 293 | StrTable = DynamicStringTable; | 
|  | 294 | Syms = dynamic_symbols(); | 
|  | 295 | SymtabName = DynSymtabName; | 
|  | 296 | if (DynSymRegion.Addr) | 
|  | 297 | Entries = DynSymRegion.Size / DynSymRegion.EntSize; | 
|  | 298 | } else { | 
|  | 299 | if (!DotSymtabSec) | 
|  | 300 | return; | 
|  | 301 | StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); | 
| Rafael Espindola | 9ea6834 | 2016-11-03 13:43:30 +0000 | [diff] [blame] | 302 | Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 303 | SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec)); | 
|  | 304 | Entries = DotSymtabSec->getEntityCount(); | 
|  | 305 | } | 
|  | 306 | if (Syms.begin() == Syms.end()) | 
|  | 307 | return; | 
|  | 308 | ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries); | 
|  | 309 | for (const auto &Sym : Syms) | 
|  | 310 | ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic); | 
|  | 311 | } | 
|  | 312 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 313 | template <class ELFT> class MipsGOTParser; | 
|  | 314 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 315 | template <typename ELFT> class DumpStyle { | 
|  | 316 | public: | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 317 | using Elf_Shdr = typename ELFT::Shdr; | 
|  | 318 | using Elf_Sym = typename ELFT::Sym; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 319 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 320 | DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {} | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 321 | virtual ~DumpStyle() = default; | 
|  | 322 |  | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 323 | virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0; | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 324 | virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 325 | virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0; | 
|  | 326 | virtual void printSections(const ELFFile<ELFT> *Obj) = 0; | 
|  | 327 | virtual void printSymbols(const ELFFile<ELFT> *Obj) = 0; | 
|  | 328 | virtual void printDynamicSymbols(const ELFFile<ELFT> *Obj) = 0; | 
|  | 329 | virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 330 | virtual void printSymtabMessage(const ELFFile<ELFT> *obj, StringRef Name, | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 331 | size_t Offset) {} | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 332 | virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol, | 
|  | 333 | const Elf_Sym *FirstSym, StringRef StrTable, | 
|  | 334 | bool IsDynamic) = 0; | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 335 | virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0; | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 336 | virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 337 | virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 338 | virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 339 | virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 340 | virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0; | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 341 | virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0; | 
|  | 342 | virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 343 | const ELFDumper<ELFT> *dumper() const { return Dumper; } | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 344 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 345 | private: | 
|  | 346 | const ELFDumper<ELFT> *Dumper; | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 347 | }; | 
|  | 348 |  | 
|  | 349 | template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> { | 
|  | 350 | formatted_raw_ostream OS; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 351 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 352 | public: | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 353 | TYPEDEF_ELF_TYPES(ELFT) | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 354 |  | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 355 | GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 356 | : DumpStyle<ELFT>(Dumper), OS(W.getOStream()) {} | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 357 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 358 | void printFileHeaders(const ELFO *Obj) override; | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 359 | void printGroupSections(const ELFFile<ELFT> *Obj) override; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 360 | void printRelocations(const ELFO *Obj) override; | 
|  | 361 | void printSections(const ELFO *Obj) override; | 
|  | 362 | void printSymbols(const ELFO *Obj) override; | 
|  | 363 | void printDynamicSymbols(const ELFO *Obj) override; | 
|  | 364 | void printDynamicRelocations(const ELFO *Obj) override; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 365 | void printSymtabMessage(const ELFO *Obj, StringRef Name, | 
|  | 366 | size_t Offset) override; | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 367 | void printProgramHeaders(const ELFO *Obj) override; | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 368 | void printHashHistogram(const ELFFile<ELFT> *Obj) override; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 369 | void printCGProfile(const ELFFile<ELFT> *Obj) override; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 370 | void printAddrsig(const ELFFile<ELFT> *Obj) override; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 371 | void printNotes(const ELFFile<ELFT> *Obj) override; | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 372 | void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 373 | void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; | 
|  | 374 | void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 375 |  | 
|  | 376 | private: | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 377 | struct Field { | 
|  | 378 | StringRef Str; | 
|  | 379 | unsigned Column; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 380 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 381 | Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} | 
|  | 382 | Field(unsigned Col) : Str(""), Column(Col) {} | 
|  | 383 | }; | 
|  | 384 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 385 | template <typename T, typename TEnum> | 
|  | 386 | std::string printEnum(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) { | 
|  | 387 | for (const auto &EnumItem : EnumValues) | 
|  | 388 | if (EnumItem.Value == Value) | 
|  | 389 | return EnumItem.AltName; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 390 | return to_hexString(Value, false); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 391 | } | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 392 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 393 | formatted_raw_ostream &printField(struct Field F) { | 
|  | 394 | if (F.Column != 0) | 
|  | 395 | OS.PadToColumn(F.Column); | 
|  | 396 | OS << F.Str; | 
|  | 397 | OS.flush(); | 
|  | 398 | return OS; | 
|  | 399 | } | 
| Hemant Kulkarni | a6ee9fd | 2016-11-23 18:04:23 +0000 | [diff] [blame] | 400 | void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, | 
|  | 401 | StringRef StrTable, uint32_t Bucket); | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 402 | void printRelocHeader(unsigned SType); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 403 | void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, | 
|  | 404 | const Elf_Rela &R, bool IsRela); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 405 | void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, | 
|  | 406 | StringRef StrTable, bool IsDynamic) override; | 
|  | 407 | std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol, | 
|  | 408 | const Elf_Sym *FirstSym); | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 409 | void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela); | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 410 | bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | 
|  | 411 | bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | 
|  | 412 | bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | 
|  | 413 | bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 414 | }; | 
|  | 415 |  | 
|  | 416 | template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> { | 
|  | 417 | public: | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 418 | TYPEDEF_ELF_TYPES(ELFT) | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 419 |  | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 420 | LLVMStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 421 | : DumpStyle<ELFT>(Dumper), W(W) {} | 
|  | 422 |  | 
|  | 423 | void printFileHeaders(const ELFO *Obj) override; | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 424 | void printGroupSections(const ELFFile<ELFT> *Obj) override; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 425 | void printRelocations(const ELFO *Obj) override; | 
|  | 426 | void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj); | 
|  | 427 | void printSections(const ELFO *Obj) override; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 428 | void printSymbols(const ELFO *Obj) override; | 
|  | 429 | void printDynamicSymbols(const ELFO *Obj) override; | 
|  | 430 | void printDynamicRelocations(const ELFO *Obj) override; | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 431 | void printProgramHeaders(const ELFO *Obj) override; | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 432 | void printHashHistogram(const ELFFile<ELFT> *Obj) override; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 433 | void printCGProfile(const ELFFile<ELFT> *Obj) override; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 434 | void printAddrsig(const ELFFile<ELFT> *Obj) override; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 435 | void printNotes(const ELFFile<ELFT> *Obj) override; | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 436 | void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override; | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 437 | void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override; | 
|  | 438 | void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override; | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 439 |  | 
|  | 440 | private: | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 441 | void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 442 | void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 443 | void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, | 
|  | 444 | StringRef StrTable, bool IsDynamic) override; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 445 |  | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 446 | ScopedPrinter &W; | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 447 | }; | 
|  | 448 |  | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 449 | } // end anonymous namespace | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 450 |  | 
|  | 451 | namespace llvm { | 
|  | 452 |  | 
|  | 453 | template <class ELFT> | 
|  | 454 | static std::error_code createELFDumper(const ELFFile<ELFT> *Obj, | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 455 | ScopedPrinter &Writer, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 456 | std::unique_ptr<ObjDumper> &Result) { | 
|  | 457 | Result.reset(new ELFDumper<ELFT>(Obj, Writer)); | 
|  | 458 | return readobj_error::success; | 
|  | 459 | } | 
|  | 460 |  | 
|  | 461 | std::error_code createELFDumper(const object::ObjectFile *Obj, | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 462 | ScopedPrinter &Writer, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 463 | std::unique_ptr<ObjDumper> &Result) { | 
|  | 464 | // Little-endian 32-bit | 
|  | 465 | if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) | 
|  | 466 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | 
|  | 467 |  | 
|  | 468 | // Big-endian 32-bit | 
|  | 469 | if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) | 
|  | 470 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | 
|  | 471 |  | 
|  | 472 | // Little-endian 64-bit | 
|  | 473 | if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) | 
|  | 474 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | 
|  | 475 |  | 
|  | 476 | // Big-endian 64-bit | 
|  | 477 | if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) | 
|  | 478 | return createELFDumper(ELFObj->getELFFile(), Writer, Result); | 
|  | 479 |  | 
|  | 480 | return readobj_error::unsupported_obj_file_format; | 
|  | 481 | } | 
|  | 482 |  | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 483 | } // end namespace llvm | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 484 |  | 
|  | 485 | // Iterate through the versions needed section, and place each Elf_Vernaux | 
|  | 486 | // in the VersionMap according to its index. | 
|  | 487 | template <class ELFT> | 
|  | 488 | void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { | 
|  | 489 | unsigned vn_size = sec->sh_size;  // Size of section in bytes | 
|  | 490 | unsigned vn_count = sec->sh_info; // Number of Verneed entries | 
|  | 491 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | 
|  | 492 | const char *sec_end = sec_start + vn_size; | 
|  | 493 | // The first Verneed entry is at the start of the section. | 
|  | 494 | const char *p = sec_start; | 
|  | 495 | for (unsigned i = 0; i < vn_count; i++) { | 
|  | 496 | if (p + sizeof(Elf_Verneed) > sec_end) | 
|  | 497 | report_fatal_error("Section ended unexpectedly while scanning " | 
|  | 498 | "version needed records."); | 
|  | 499 | const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p); | 
|  | 500 | if (vn->vn_version != ELF::VER_NEED_CURRENT) | 
|  | 501 | report_fatal_error("Unexpected verneed version"); | 
|  | 502 | // Iterate through the Vernaux entries | 
|  | 503 | const char *paux = p + vn->vn_aux; | 
|  | 504 | for (unsigned j = 0; j < vn->vn_cnt; j++) { | 
|  | 505 | if (paux + sizeof(Elf_Vernaux) > sec_end) | 
|  | 506 | report_fatal_error("Section ended unexpected while scanning auxiliary " | 
|  | 507 | "version needed records."); | 
|  | 508 | const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); | 
|  | 509 | size_t index = vna->vna_other & ELF::VERSYM_VERSION; | 
|  | 510 | if (index >= VersionMap.size()) | 
|  | 511 | VersionMap.resize(index + 1); | 
|  | 512 | VersionMap[index] = VersionMapEntry(vna); | 
|  | 513 | paux += vna->vna_next; | 
|  | 514 | } | 
|  | 515 | p += vn->vn_next; | 
|  | 516 | } | 
|  | 517 | } | 
|  | 518 |  | 
|  | 519 | // Iterate through the version definitions, and place each Elf_Verdef | 
|  | 520 | // in the VersionMap according to its index. | 
|  | 521 | template <class ELFT> | 
|  | 522 | void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { | 
|  | 523 | unsigned vd_size = sec->sh_size;  // Size of section in bytes | 
|  | 524 | unsigned vd_count = sec->sh_info; // Number of Verdef entries | 
|  | 525 | const char *sec_start = (const char *)Obj->base() + sec->sh_offset; | 
|  | 526 | const char *sec_end = sec_start + vd_size; | 
|  | 527 | // The first Verdef entry is at the start of the section. | 
|  | 528 | const char *p = sec_start; | 
|  | 529 | for (unsigned i = 0; i < vd_count; i++) { | 
|  | 530 | if (p + sizeof(Elf_Verdef) > sec_end) | 
|  | 531 | report_fatal_error("Section ended unexpectedly while scanning " | 
|  | 532 | "version definitions."); | 
|  | 533 | const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p); | 
|  | 534 | if (vd->vd_version != ELF::VER_DEF_CURRENT) | 
|  | 535 | report_fatal_error("Unexpected verdef version"); | 
|  | 536 | size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; | 
|  | 537 | if (index >= VersionMap.size()) | 
|  | 538 | VersionMap.resize(index + 1); | 
|  | 539 | VersionMap[index] = VersionMapEntry(vd); | 
|  | 540 | p += vd->vd_next; | 
|  | 541 | } | 
|  | 542 | } | 
|  | 543 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 544 | template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() const { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 545 | // If there is no dynamic symtab or version table, there is nothing to do. | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 546 | if (!DynSymRegion.Addr || !dot_gnu_version_sec) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 547 | return; | 
|  | 548 |  | 
|  | 549 | // Has the VersionMap already been loaded? | 
|  | 550 | if (VersionMap.size() > 0) | 
|  | 551 | return; | 
|  | 552 |  | 
|  | 553 | // The first two version indexes are reserved. | 
|  | 554 | // Index 0 is LOCAL, index 1 is GLOBAL. | 
|  | 555 | VersionMap.push_back(VersionMapEntry()); | 
|  | 556 | VersionMap.push_back(VersionMapEntry()); | 
|  | 557 |  | 
|  | 558 | if (dot_gnu_version_d_sec) | 
|  | 559 | LoadVersionDefs(dot_gnu_version_d_sec); | 
|  | 560 |  | 
|  | 561 | if (dot_gnu_version_r_sec) | 
|  | 562 | LoadVersionNeeds(dot_gnu_version_r_sec); | 
|  | 563 | } | 
|  | 564 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 565 | template <typename ELFO, class ELFT> | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 566 | static void printVersionSymbolSection(ELFDumper<ELFT> *Dumper, const ELFO *Obj, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 567 | const typename ELFO::Elf_Shdr *Sec, | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 568 | ScopedPrinter &W) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 569 | DictScope SS(W, "Version symbols"); | 
|  | 570 | if (!Sec) | 
|  | 571 | return; | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 572 | StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 573 | W.printNumber("Section Name", Name, Sec->sh_name); | 
|  | 574 | W.printHex("Address", Sec->sh_addr); | 
|  | 575 | W.printHex("Offset", Sec->sh_offset); | 
|  | 576 | W.printNumber("Link", Sec->sh_link); | 
|  | 577 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 578 | const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset; | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 579 | StringRef StrTable = Dumper->getDynamicStringTable(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 580 |  | 
|  | 581 | // Same number of entries in the dynamic symbol table (DT_SYMTAB). | 
|  | 582 | ListScope Syms(W, "Symbols"); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 583 | for (const typename ELFO::Elf_Sym &Sym : Dumper->dynamic_symbols()) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 584 | DictScope S(W, "Symbol"); | 
|  | 585 | std::string FullSymbolName = | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 586 | Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 587 | W.printNumber("Version", *P); | 
|  | 588 | W.printString("Name", FullSymbolName); | 
|  | 589 | P += sizeof(typename ELFO::Elf_Half); | 
|  | 590 | } | 
|  | 591 | } | 
|  | 592 |  | 
| George Rimar | cd36e18 | 2016-06-07 11:04:49 +0000 | [diff] [blame] | 593 | static const EnumEntry<unsigned> SymVersionFlags[] = { | 
|  | 594 | {"Base", "BASE", VER_FLG_BASE}, | 
|  | 595 | {"Weak", "WEAK", VER_FLG_WEAK}, | 
|  | 596 | {"Info", "INFO", VER_FLG_INFO}}; | 
|  | 597 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 598 | template <typename ELFO, class ELFT> | 
|  | 599 | static void printVersionDefinitionSection(ELFDumper<ELFT> *Dumper, | 
|  | 600 | const ELFO *Obj, | 
|  | 601 | const typename ELFO::Elf_Shdr *Sec, | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 602 | ScopedPrinter &W) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 603 | using VerDef = typename ELFO::Elf_Verdef; | 
|  | 604 | using VerdAux = typename ELFO::Elf_Verdaux; | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 605 |  | 
|  | 606 | DictScope SD(W, "SHT_GNU_verdef"); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 607 | if (!Sec) | 
|  | 608 | return; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 609 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 610 | // The number of entries in the section SHT_GNU_verdef | 
|  | 611 | // is determined by DT_VERDEFNUM tag. | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 612 | unsigned VerDefsNum = 0; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 613 | for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) { | 
|  | 614 | if (Dyn.d_tag == DT_VERDEFNUM) | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 615 | VerDefsNum = Dyn.d_un.d_val; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 616 | } | 
|  | 617 | const uint8_t *SecStartAddress = | 
|  | 618 | (const uint8_t *)Obj->base() + Sec->sh_offset; | 
|  | 619 | const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size; | 
|  | 620 | const uint8_t *P = SecStartAddress; | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 621 | const typename ELFO::Elf_Shdr *StrTab = | 
|  | 622 | unwrapOrError(Obj->getSection(Sec->sh_link)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 623 |  | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 624 | while (VerDefsNum--) { | 
|  | 625 | if (P + sizeof(VerDef) > SecEndAddress) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 626 | report_fatal_error("invalid offset in the section"); | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 627 |  | 
|  | 628 | auto *VD = reinterpret_cast<const VerDef *>(P); | 
|  | 629 | DictScope Def(W, "Definition"); | 
|  | 630 | W.printNumber("Version", VD->vd_version); | 
|  | 631 | W.printEnum("Flags", VD->vd_flags, makeArrayRef(SymVersionFlags)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 632 | W.printNumber("Index", VD->vd_ndx); | 
| Davide Italiano | 22b3ad86 | 2016-05-02 02:30:18 +0000 | [diff] [blame] | 633 | W.printNumber("Hash", VD->vd_hash); | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 634 | W.printString("Name", | 
|  | 635 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | 
|  | 636 | VD->getAux()->vda_name))); | 
| George Rimar | ff8b539 | 2016-06-22 13:43:38 +0000 | [diff] [blame] | 637 | if (!VD->vd_cnt) | 
|  | 638 | report_fatal_error("at least one definition string must exist"); | 
|  | 639 | if (VD->vd_cnt > 2) | 
|  | 640 | report_fatal_error("more than one predecessor is not expected"); | 
|  | 641 |  | 
|  | 642 | if (VD->vd_cnt == 2) { | 
|  | 643 | const uint8_t *PAux = P + VD->vd_aux + VD->getAux()->vda_next; | 
|  | 644 | const VerdAux *Aux = reinterpret_cast<const VerdAux *>(PAux); | 
|  | 645 | W.printString("Predecessor", | 
|  | 646 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | 
|  | 647 | Aux->vda_name))); | 
|  | 648 | } | 
|  | 649 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 650 | P += VD->vd_next; | 
|  | 651 | } | 
|  | 652 | } | 
|  | 653 |  | 
| George Rimar | cd36e18 | 2016-06-07 11:04:49 +0000 | [diff] [blame] | 654 | template <typename ELFO, class ELFT> | 
|  | 655 | static void printVersionDependencySection(ELFDumper<ELFT> *Dumper, | 
|  | 656 | const ELFO *Obj, | 
|  | 657 | const typename ELFO::Elf_Shdr *Sec, | 
|  | 658 | ScopedPrinter &W) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 659 | using VerNeed = typename ELFO::Elf_Verneed; | 
|  | 660 | using VernAux = typename ELFO::Elf_Vernaux; | 
| George Rimar | cd36e18 | 2016-06-07 11:04:49 +0000 | [diff] [blame] | 661 |  | 
|  | 662 | DictScope SD(W, "SHT_GNU_verneed"); | 
|  | 663 | if (!Sec) | 
|  | 664 | return; | 
|  | 665 |  | 
|  | 666 | unsigned VerNeedNum = 0; | 
|  | 667 | for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) | 
|  | 668 | if (Dyn.d_tag == DT_VERNEEDNUM) | 
|  | 669 | VerNeedNum = Dyn.d_un.d_val; | 
|  | 670 |  | 
|  | 671 | const uint8_t *SecData = (const uint8_t *)Obj->base() + Sec->sh_offset; | 
|  | 672 | const typename ELFO::Elf_Shdr *StrTab = | 
|  | 673 | unwrapOrError(Obj->getSection(Sec->sh_link)); | 
|  | 674 |  | 
|  | 675 | const uint8_t *P = SecData; | 
|  | 676 | for (unsigned I = 0; I < VerNeedNum; ++I) { | 
|  | 677 | const VerNeed *Need = reinterpret_cast<const VerNeed *>(P); | 
|  | 678 | DictScope Entry(W, "Dependency"); | 
|  | 679 | W.printNumber("Version", Need->vn_version); | 
|  | 680 | W.printNumber("Count", Need->vn_cnt); | 
|  | 681 | W.printString("FileName", | 
|  | 682 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | 
|  | 683 | Need->vn_file))); | 
|  | 684 |  | 
|  | 685 | const uint8_t *PAux = P + Need->vn_aux; | 
|  | 686 | for (unsigned J = 0; J < Need->vn_cnt; ++J) { | 
|  | 687 | const VernAux *Aux = reinterpret_cast<const VernAux *>(PAux); | 
|  | 688 | DictScope Entry(W, "Entry"); | 
|  | 689 | W.printNumber("Hash", Aux->vna_hash); | 
|  | 690 | W.printEnum("Flags", Aux->vna_flags, makeArrayRef(SymVersionFlags)); | 
|  | 691 | W.printNumber("Index", Aux->vna_other); | 
|  | 692 | W.printString("Name", | 
|  | 693 | StringRef((const char *)(Obj->base() + StrTab->sh_offset + | 
|  | 694 | Aux->vna_name))); | 
|  | 695 | PAux += Aux->vna_next; | 
|  | 696 | } | 
|  | 697 | P += Need->vn_next; | 
|  | 698 | } | 
|  | 699 | } | 
|  | 700 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 701 | template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() { | 
|  | 702 | // Dump version symbol section. | 
|  | 703 | printVersionSymbolSection(this, Obj, dot_gnu_version_sec, W); | 
|  | 704 |  | 
|  | 705 | // Dump version definition section. | 
|  | 706 | printVersionDefinitionSection(this, Obj, dot_gnu_version_d_sec, W); | 
| George Rimar | cd36e18 | 2016-06-07 11:04:49 +0000 | [diff] [blame] | 707 |  | 
|  | 708 | // Dump version dependency section. | 
|  | 709 | printVersionDependencySection(this, Obj, dot_gnu_version_r_sec, W); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 710 | } | 
|  | 711 |  | 
|  | 712 | template <typename ELFT> | 
|  | 713 | StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, | 
|  | 714 | const Elf_Sym *symb, | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 715 | bool &IsDefault) const { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 716 | // This is a dynamic symbol. Look in the GNU symbol version table. | 
|  | 717 | if (!dot_gnu_version_sec) { | 
|  | 718 | // No version table. | 
|  | 719 | IsDefault = false; | 
|  | 720 | return StringRef(""); | 
|  | 721 | } | 
|  | 722 |  | 
|  | 723 | // Determine the position in the symbol table of this entry. | 
|  | 724 | size_t entry_index = (reinterpret_cast<uintptr_t>(symb) - | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 725 | reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) / | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 726 | sizeof(Elf_Sym); | 
|  | 727 |  | 
|  | 728 | // Get the corresponding version index entry | 
| Rafael Espindola | ed1395a | 2016-11-03 18:05:33 +0000 | [diff] [blame] | 729 | const Elf_Versym *vs = unwrapOrError( | 
|  | 730 | Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 731 | size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; | 
|  | 732 |  | 
|  | 733 | // Special markers for unversioned symbols. | 
|  | 734 | if (version_index == ELF::VER_NDX_LOCAL || | 
|  | 735 | version_index == ELF::VER_NDX_GLOBAL) { | 
|  | 736 | IsDefault = false; | 
|  | 737 | return StringRef(""); | 
|  | 738 | } | 
|  | 739 |  | 
|  | 740 | // Lookup this symbol in the version table | 
|  | 741 | LoadVersionMap(); | 
|  | 742 | if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) | 
|  | 743 | reportError("Invalid version entry"); | 
|  | 744 | const VersionMapEntry &entry = VersionMap[version_index]; | 
|  | 745 |  | 
|  | 746 | // Get the version name string | 
|  | 747 | size_t name_offset; | 
|  | 748 | if (entry.isVerdef()) { | 
|  | 749 | // The first Verdaux entry holds the name. | 
|  | 750 | name_offset = entry.getVerdef()->getAux()->vda_name; | 
|  | 751 | IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); | 
|  | 752 | } else { | 
|  | 753 | name_offset = entry.getVernaux()->vna_name; | 
|  | 754 | IsDefault = false; | 
|  | 755 | } | 
|  | 756 | if (name_offset >= StrTab.size()) | 
|  | 757 | reportError("Invalid string offset"); | 
|  | 758 | return StringRef(StrTab.data() + name_offset); | 
|  | 759 | } | 
|  | 760 |  | 
|  | 761 | template <typename ELFT> | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 762 | StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const { | 
|  | 763 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); | 
|  | 764 | Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); | 
|  | 765 | if (Index >= Syms.size()) | 
|  | 766 | reportError("Invalid symbol index"); | 
|  | 767 | const Elf_Sym *Sym = &Syms[Index]; | 
|  | 768 | return unwrapOrError(Sym->getName(StrTable)); | 
|  | 769 | } | 
|  | 770 |  | 
|  | 771 | template <typename ELFT> | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 772 | std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, | 
|  | 773 | StringRef StrTable, | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 774 | bool IsDynamic) const { | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 775 | StringRef SymbolName = unwrapOrError(Symbol->getName(StrTable)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 776 | if (!IsDynamic) | 
|  | 777 | return SymbolName; | 
|  | 778 |  | 
|  | 779 | std::string FullSymbolName(SymbolName); | 
|  | 780 |  | 
|  | 781 | bool IsDefault; | 
|  | 782 | StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault); | 
|  | 783 | FullSymbolName += (IsDefault ? "@@" : "@"); | 
|  | 784 | FullSymbolName += Version; | 
|  | 785 | return FullSymbolName; | 
|  | 786 | } | 
|  | 787 |  | 
| Rafael Espindola | 714c295 | 2016-11-03 14:41:17 +0000 | [diff] [blame] | 788 | template <typename ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 789 | void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol, | 
|  | 790 | const Elf_Sym *FirstSym, | 
|  | 791 | StringRef &SectionName, | 
|  | 792 | unsigned &SectionIndex) const { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 793 | SectionIndex = Symbol->st_shndx; | 
|  | 794 | if (Symbol->isUndefined()) | 
|  | 795 | SectionName = "Undefined"; | 
|  | 796 | else if (Symbol->isProcessorSpecific()) | 
|  | 797 | SectionName = "Processor Specific"; | 
|  | 798 | else if (Symbol->isOSSpecific()) | 
|  | 799 | SectionName = "Operating System Specific"; | 
|  | 800 | else if (Symbol->isAbsolute()) | 
|  | 801 | SectionName = "Absolute"; | 
|  | 802 | else if (Symbol->isCommon()) | 
|  | 803 | SectionName = "Common"; | 
|  | 804 | else if (Symbol->isReserved() && SectionIndex != SHN_XINDEX) | 
|  | 805 | SectionName = "Reserved"; | 
|  | 806 | else { | 
|  | 807 | if (SectionIndex == SHN_XINDEX) | 
| Rafael Espindola | 714c295 | 2016-11-03 14:41:17 +0000 | [diff] [blame] | 808 | SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( | 
|  | 809 | Symbol, FirstSym, ShndxTable)); | 
|  | 810 | const typename ELFT::Shdr *Sec = | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 811 | unwrapOrError(Obj->getSection(SectionIndex)); | 
|  | 812 | SectionName = unwrapOrError(Obj->getSectionName(Sec)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 813 | } | 
|  | 814 | } | 
|  | 815 |  | 
|  | 816 | template <class ELFO> | 
| Simon Atanasyan | cb1175c | 2016-02-09 18:45:35 +0000 | [diff] [blame] | 817 | static const typename ELFO::Elf_Shdr * | 
|  | 818 | findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 819 | for (const auto &Shdr : unwrapOrError(Obj->sections())) | 
| Simon Atanasyan | cb1175c | 2016-02-09 18:45:35 +0000 | [diff] [blame] | 820 | if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 821 | return &Shdr; | 
|  | 822 | return nullptr; | 
|  | 823 | } | 
|  | 824 |  | 
|  | 825 | template <class ELFO> | 
|  | 826 | static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, | 
|  | 827 | StringRef Name) { | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 828 | for (const auto &Shdr : unwrapOrError(Obj.sections())) { | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 829 | if (Name == unwrapOrError(Obj.getSectionName(&Shdr))) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 830 | return &Shdr; | 
|  | 831 | } | 
|  | 832 | return nullptr; | 
|  | 833 | } | 
|  | 834 |  | 
|  | 835 | static const EnumEntry<unsigned> ElfClass[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 836 | {"None",   "none",   ELF::ELFCLASSNONE}, | 
|  | 837 | {"32-bit", "ELF32",  ELF::ELFCLASS32}, | 
|  | 838 | {"64-bit", "ELF64",  ELF::ELFCLASS64}, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 839 | }; | 
|  | 840 |  | 
|  | 841 | static const EnumEntry<unsigned> ElfDataEncoding[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 842 | {"None",         "none",                          ELF::ELFDATANONE}, | 
|  | 843 | {"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB}, | 
|  | 844 | {"BigEndian",    "2's complement, big endian",    ELF::ELFDATA2MSB}, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 845 | }; | 
|  | 846 |  | 
|  | 847 | static const EnumEntry<unsigned> ElfObjectFileType[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 848 | {"None",         "NONE (none)",              ELF::ET_NONE}, | 
|  | 849 | {"Relocatable",  "REL (Relocatable file)",   ELF::ET_REL}, | 
|  | 850 | {"Executable",   "EXEC (Executable file)",   ELF::ET_EXEC}, | 
|  | 851 | {"SharedObject", "DYN (Shared object file)", ELF::ET_DYN}, | 
|  | 852 | {"Core",         "CORE (Core file)",         ELF::ET_CORE}, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 853 | }; | 
|  | 854 |  | 
|  | 855 | static const EnumEntry<unsigned> ElfOSABI[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 856 | {"SystemV",      "UNIX - System V",      ELF::ELFOSABI_NONE}, | 
|  | 857 | {"HPUX",         "UNIX - HP-UX",         ELF::ELFOSABI_HPUX}, | 
|  | 858 | {"NetBSD",       "UNIX - NetBSD",        ELF::ELFOSABI_NETBSD}, | 
|  | 859 | {"GNU/Linux",    "UNIX - GNU",           ELF::ELFOSABI_LINUX}, | 
|  | 860 | {"GNU/Hurd",     "GNU/Hurd",             ELF::ELFOSABI_HURD}, | 
|  | 861 | {"Solaris",      "UNIX - Solaris",       ELF::ELFOSABI_SOLARIS}, | 
|  | 862 | {"AIX",          "UNIX - AIX",           ELF::ELFOSABI_AIX}, | 
|  | 863 | {"IRIX",         "UNIX - IRIX",          ELF::ELFOSABI_IRIX}, | 
|  | 864 | {"FreeBSD",      "UNIX - FreeBSD",       ELF::ELFOSABI_FREEBSD}, | 
|  | 865 | {"TRU64",        "UNIX - TRU64",         ELF::ELFOSABI_TRU64}, | 
|  | 866 | {"Modesto",      "Novell - Modesto",     ELF::ELFOSABI_MODESTO}, | 
|  | 867 | {"OpenBSD",      "UNIX - OpenBSD",       ELF::ELFOSABI_OPENBSD}, | 
|  | 868 | {"OpenVMS",      "VMS - OpenVMS",        ELF::ELFOSABI_OPENVMS}, | 
|  | 869 | {"NSK",          "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, | 
|  | 870 | {"AROS",         "AROS",                 ELF::ELFOSABI_AROS}, | 
|  | 871 | {"FenixOS",      "FenixOS",              ELF::ELFOSABI_FENIXOS}, | 
|  | 872 | {"CloudABI",     "CloudABI",             ELF::ELFOSABI_CLOUDABI}, | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 873 | {"Standalone",   "Standalone App",       ELF::ELFOSABI_STANDALONE} | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 874 | }; | 
|  | 875 |  | 
| Konstantin Zhuravlyov | 121125f | 2017-10-02 20:49:58 +0000 | [diff] [blame] | 876 | static const EnumEntry<unsigned> AMDGPUElfOSABI[] = { | 
| Konstantin Zhuravlyov | 0aa94d3 | 2017-10-03 21:14:14 +0000 | [diff] [blame] | 877 | {"AMDGPU_HSA",    "AMDGPU - HSA",    ELF::ELFOSABI_AMDGPU_HSA}, | 
|  | 878 | {"AMDGPU_PAL",    "AMDGPU - PAL",    ELF::ELFOSABI_AMDGPU_PAL}, | 
|  | 879 | {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D} | 
| Konstantin Zhuravlyov | 121125f | 2017-10-02 20:49:58 +0000 | [diff] [blame] | 880 | }; | 
|  | 881 |  | 
|  | 882 | static const EnumEntry<unsigned> ARMElfOSABI[] = { | 
|  | 883 | {"ARM", "ARM", ELF::ELFOSABI_ARM} | 
|  | 884 | }; | 
|  | 885 |  | 
|  | 886 | static const EnumEntry<unsigned> C6000ElfOSABI[] = { | 
|  | 887 | {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI}, | 
|  | 888 | {"C6000_LINUX",  "Linux C6000",      ELF::ELFOSABI_C6000_LINUX} | 
|  | 889 | }; | 
|  | 890 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 891 | static const EnumEntry<unsigned> ElfMachineType[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 892 | ENUM_ENT(EM_NONE,          "None"), | 
|  | 893 | ENUM_ENT(EM_M32,           "WE32100"), | 
|  | 894 | ENUM_ENT(EM_SPARC,         "Sparc"), | 
|  | 895 | ENUM_ENT(EM_386,           "Intel 80386"), | 
|  | 896 | ENUM_ENT(EM_68K,           "MC68000"), | 
|  | 897 | ENUM_ENT(EM_88K,           "MC88000"), | 
|  | 898 | ENUM_ENT(EM_IAMCU,         "EM_IAMCU"), | 
|  | 899 | ENUM_ENT(EM_860,           "Intel 80860"), | 
|  | 900 | ENUM_ENT(EM_MIPS,          "MIPS R3000"), | 
|  | 901 | ENUM_ENT(EM_S370,          "IBM System/370"), | 
|  | 902 | ENUM_ENT(EM_MIPS_RS3_LE,   "MIPS R3000 little-endian"), | 
|  | 903 | ENUM_ENT(EM_PARISC,        "HPPA"), | 
|  | 904 | ENUM_ENT(EM_VPP500,        "Fujitsu VPP500"), | 
|  | 905 | ENUM_ENT(EM_SPARC32PLUS,   "Sparc v8+"), | 
|  | 906 | ENUM_ENT(EM_960,           "Intel 80960"), | 
|  | 907 | ENUM_ENT(EM_PPC,           "PowerPC"), | 
|  | 908 | ENUM_ENT(EM_PPC64,         "PowerPC64"), | 
|  | 909 | ENUM_ENT(EM_S390,          "IBM S/390"), | 
|  | 910 | ENUM_ENT(EM_SPU,           "SPU"), | 
|  | 911 | ENUM_ENT(EM_V800,          "NEC V800 series"), | 
|  | 912 | ENUM_ENT(EM_FR20,          "Fujistsu FR20"), | 
|  | 913 | ENUM_ENT(EM_RH32,          "TRW RH-32"), | 
|  | 914 | ENUM_ENT(EM_RCE,           "Motorola RCE"), | 
|  | 915 | ENUM_ENT(EM_ARM,           "ARM"), | 
|  | 916 | ENUM_ENT(EM_ALPHA,         "EM_ALPHA"), | 
|  | 917 | ENUM_ENT(EM_SH,            "Hitachi SH"), | 
|  | 918 | ENUM_ENT(EM_SPARCV9,       "Sparc v9"), | 
|  | 919 | ENUM_ENT(EM_TRICORE,       "Siemens Tricore"), | 
|  | 920 | ENUM_ENT(EM_ARC,           "ARC"), | 
|  | 921 | ENUM_ENT(EM_H8_300,        "Hitachi H8/300"), | 
|  | 922 | ENUM_ENT(EM_H8_300H,       "Hitachi H8/300H"), | 
|  | 923 | ENUM_ENT(EM_H8S,           "Hitachi H8S"), | 
|  | 924 | ENUM_ENT(EM_H8_500,        "Hitachi H8/500"), | 
|  | 925 | ENUM_ENT(EM_IA_64,         "Intel IA-64"), | 
|  | 926 | ENUM_ENT(EM_MIPS_X,        "Stanford MIPS-X"), | 
|  | 927 | ENUM_ENT(EM_COLDFIRE,      "Motorola Coldfire"), | 
|  | 928 | ENUM_ENT(EM_68HC12,        "Motorola MC68HC12 Microcontroller"), | 
|  | 929 | ENUM_ENT(EM_MMA,           "Fujitsu Multimedia Accelerator"), | 
|  | 930 | ENUM_ENT(EM_PCP,           "Siemens PCP"), | 
|  | 931 | ENUM_ENT(EM_NCPU,          "Sony nCPU embedded RISC processor"), | 
|  | 932 | ENUM_ENT(EM_NDR1,          "Denso NDR1 microprocesspr"), | 
|  | 933 | ENUM_ENT(EM_STARCORE,      "Motorola Star*Core processor"), | 
|  | 934 | ENUM_ENT(EM_ME16,          "Toyota ME16 processor"), | 
|  | 935 | ENUM_ENT(EM_ST100,         "STMicroelectronics ST100 processor"), | 
|  | 936 | ENUM_ENT(EM_TINYJ,         "Advanced Logic Corp. TinyJ embedded processor"), | 
|  | 937 | ENUM_ENT(EM_X86_64,        "Advanced Micro Devices X86-64"), | 
|  | 938 | ENUM_ENT(EM_PDSP,          "Sony DSP processor"), | 
|  | 939 | ENUM_ENT(EM_PDP10,         "Digital Equipment Corp. PDP-10"), | 
|  | 940 | ENUM_ENT(EM_PDP11,         "Digital Equipment Corp. PDP-11"), | 
|  | 941 | ENUM_ENT(EM_FX66,          "Siemens FX66 microcontroller"), | 
|  | 942 | ENUM_ENT(EM_ST9PLUS,       "STMicroelectronics ST9+ 8/16 bit microcontroller"), | 
|  | 943 | ENUM_ENT(EM_ST7,           "STMicroelectronics ST7 8-bit microcontroller"), | 
|  | 944 | ENUM_ENT(EM_68HC16,        "Motorola MC68HC16 Microcontroller"), | 
|  | 945 | ENUM_ENT(EM_68HC11,        "Motorola MC68HC11 Microcontroller"), | 
|  | 946 | ENUM_ENT(EM_68HC08,        "Motorola MC68HC08 Microcontroller"), | 
|  | 947 | ENUM_ENT(EM_68HC05,        "Motorola MC68HC05 Microcontroller"), | 
|  | 948 | ENUM_ENT(EM_SVX,           "Silicon Graphics SVx"), | 
|  | 949 | ENUM_ENT(EM_ST19,          "STMicroelectronics ST19 8-bit microcontroller"), | 
|  | 950 | ENUM_ENT(EM_VAX,           "Digital VAX"), | 
|  | 951 | ENUM_ENT(EM_CRIS,          "Axis Communications 32-bit embedded processor"), | 
|  | 952 | ENUM_ENT(EM_JAVELIN,       "Infineon Technologies 32-bit embedded cpu"), | 
|  | 953 | ENUM_ENT(EM_FIREPATH,      "Element 14 64-bit DSP processor"), | 
|  | 954 | ENUM_ENT(EM_ZSP,           "LSI Logic's 16-bit DSP processor"), | 
|  | 955 | ENUM_ENT(EM_MMIX,          "Donald Knuth's educational 64-bit processor"), | 
|  | 956 | ENUM_ENT(EM_HUANY,         "Harvard Universitys's machine-independent object format"), | 
|  | 957 | ENUM_ENT(EM_PRISM,         "Vitesse Prism"), | 
|  | 958 | ENUM_ENT(EM_AVR,           "Atmel AVR 8-bit microcontroller"), | 
|  | 959 | ENUM_ENT(EM_FR30,          "Fujitsu FR30"), | 
|  | 960 | ENUM_ENT(EM_D10V,          "Mitsubishi D10V"), | 
|  | 961 | ENUM_ENT(EM_D30V,          "Mitsubishi D30V"), | 
|  | 962 | ENUM_ENT(EM_V850,          "NEC v850"), | 
|  | 963 | ENUM_ENT(EM_M32R,          "Renesas M32R (formerly Mitsubishi M32r)"), | 
|  | 964 | ENUM_ENT(EM_MN10300,       "Matsushita MN10300"), | 
|  | 965 | ENUM_ENT(EM_MN10200,       "Matsushita MN10200"), | 
|  | 966 | ENUM_ENT(EM_PJ,            "picoJava"), | 
|  | 967 | ENUM_ENT(EM_OPENRISC,      "OpenRISC 32-bit embedded processor"), | 
|  | 968 | ENUM_ENT(EM_ARC_COMPACT,   "EM_ARC_COMPACT"), | 
|  | 969 | ENUM_ENT(EM_XTENSA,        "Tensilica Xtensa Processor"), | 
|  | 970 | ENUM_ENT(EM_VIDEOCORE,     "Alphamosaic VideoCore processor"), | 
|  | 971 | ENUM_ENT(EM_TMM_GPP,       "Thompson Multimedia General Purpose Processor"), | 
|  | 972 | ENUM_ENT(EM_NS32K,         "National Semiconductor 32000 series"), | 
|  | 973 | ENUM_ENT(EM_TPC,           "Tenor Network TPC processor"), | 
|  | 974 | ENUM_ENT(EM_SNP1K,         "EM_SNP1K"), | 
|  | 975 | ENUM_ENT(EM_ST200,         "STMicroelectronics ST200 microcontroller"), | 
|  | 976 | ENUM_ENT(EM_IP2K,          "Ubicom IP2xxx 8-bit microcontrollers"), | 
|  | 977 | ENUM_ENT(EM_MAX,           "MAX Processor"), | 
|  | 978 | ENUM_ENT(EM_CR,            "National Semiconductor CompactRISC"), | 
|  | 979 | ENUM_ENT(EM_F2MC16,        "Fujitsu F2MC16"), | 
|  | 980 | ENUM_ENT(EM_MSP430,        "Texas Instruments msp430 microcontroller"), | 
|  | 981 | ENUM_ENT(EM_BLACKFIN,      "Analog Devices Blackfin"), | 
|  | 982 | ENUM_ENT(EM_SE_C33,        "S1C33 Family of Seiko Epson processors"), | 
|  | 983 | ENUM_ENT(EM_SEP,           "Sharp embedded microprocessor"), | 
|  | 984 | ENUM_ENT(EM_ARCA,          "Arca RISC microprocessor"), | 
|  | 985 | ENUM_ENT(EM_UNICORE,       "Unicore"), | 
|  | 986 | ENUM_ENT(EM_EXCESS,        "eXcess 16/32/64-bit configurable embedded CPU"), | 
|  | 987 | ENUM_ENT(EM_DXP,           "Icera Semiconductor Inc. Deep Execution Processor"), | 
|  | 988 | ENUM_ENT(EM_ALTERA_NIOS2,  "Altera Nios"), | 
|  | 989 | ENUM_ENT(EM_CRX,           "National Semiconductor CRX microprocessor"), | 
|  | 990 | ENUM_ENT(EM_XGATE,         "Motorola XGATE embedded processor"), | 
|  | 991 | ENUM_ENT(EM_C166,          "Infineon Technologies xc16x"), | 
|  | 992 | ENUM_ENT(EM_M16C,          "Renesas M16C"), | 
|  | 993 | ENUM_ENT(EM_DSPIC30F,      "Microchip Technology dsPIC30F Digital Signal Controller"), | 
|  | 994 | ENUM_ENT(EM_CE,            "Freescale Communication Engine RISC core"), | 
|  | 995 | ENUM_ENT(EM_M32C,          "Renesas M32C"), | 
|  | 996 | ENUM_ENT(EM_TSK3000,       "Altium TSK3000 core"), | 
|  | 997 | ENUM_ENT(EM_RS08,          "Freescale RS08 embedded processor"), | 
|  | 998 | ENUM_ENT(EM_SHARC,         "EM_SHARC"), | 
|  | 999 | ENUM_ENT(EM_ECOG2,         "Cyan Technology eCOG2 microprocessor"), | 
|  | 1000 | ENUM_ENT(EM_SCORE7,        "SUNPLUS S+Core"), | 
|  | 1001 | ENUM_ENT(EM_DSP24,         "New Japan Radio (NJR) 24-bit DSP Processor"), | 
|  | 1002 | ENUM_ENT(EM_VIDEOCORE3,    "Broadcom VideoCore III processor"), | 
|  | 1003 | ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"), | 
|  | 1004 | ENUM_ENT(EM_SE_C17,        "Seiko Epson C17 family"), | 
|  | 1005 | ENUM_ENT(EM_TI_C6000,      "Texas Instruments TMS320C6000 DSP family"), | 
|  | 1006 | ENUM_ENT(EM_TI_C2000,      "Texas Instruments TMS320C2000 DSP family"), | 
|  | 1007 | ENUM_ENT(EM_TI_C5500,      "Texas Instruments TMS320C55x DSP family"), | 
|  | 1008 | ENUM_ENT(EM_MMDSP_PLUS,    "STMicroelectronics 64bit VLIW Data Signal Processor"), | 
|  | 1009 | ENUM_ENT(EM_CYPRESS_M8C,   "Cypress M8C microprocessor"), | 
|  | 1010 | ENUM_ENT(EM_R32C,          "Renesas R32C series microprocessors"), | 
|  | 1011 | ENUM_ENT(EM_TRIMEDIA,      "NXP Semiconductors TriMedia architecture family"), | 
|  | 1012 | ENUM_ENT(EM_HEXAGON,       "Qualcomm Hexagon"), | 
|  | 1013 | ENUM_ENT(EM_8051,          "Intel 8051 and variants"), | 
|  | 1014 | ENUM_ENT(EM_STXP7X,        "STMicroelectronics STxP7x family"), | 
|  | 1015 | ENUM_ENT(EM_NDS32,         "Andes Technology compact code size embedded RISC processor family"), | 
|  | 1016 | ENUM_ENT(EM_ECOG1,         "Cyan Technology eCOG1 microprocessor"), | 
|  | 1017 | ENUM_ENT(EM_ECOG1X,        "Cyan Technology eCOG1X family"), | 
|  | 1018 | ENUM_ENT(EM_MAXQ30,        "Dallas Semiconductor MAXQ30 Core microcontrollers"), | 
|  | 1019 | ENUM_ENT(EM_XIMO16,        "New Japan Radio (NJR) 16-bit DSP Processor"), | 
|  | 1020 | ENUM_ENT(EM_MANIK,         "M2000 Reconfigurable RISC Microprocessor"), | 
|  | 1021 | ENUM_ENT(EM_CRAYNV2,       "Cray Inc. NV2 vector architecture"), | 
|  | 1022 | ENUM_ENT(EM_RX,            "Renesas RX"), | 
|  | 1023 | ENUM_ENT(EM_METAG,         "Imagination Technologies Meta processor architecture"), | 
|  | 1024 | ENUM_ENT(EM_MCST_ELBRUS,   "MCST Elbrus general purpose hardware architecture"), | 
|  | 1025 | ENUM_ENT(EM_ECOG16,        "Cyan Technology eCOG16 family"), | 
|  | 1026 | ENUM_ENT(EM_CR16,          "Xilinx MicroBlaze"), | 
|  | 1027 | ENUM_ENT(EM_ETPU,          "Freescale Extended Time Processing Unit"), | 
|  | 1028 | ENUM_ENT(EM_SLE9X,         "Infineon Technologies SLE9X core"), | 
|  | 1029 | ENUM_ENT(EM_L10M,          "EM_L10M"), | 
|  | 1030 | ENUM_ENT(EM_K10M,          "EM_K10M"), | 
|  | 1031 | ENUM_ENT(EM_AARCH64,       "AArch64"), | 
| Dylan McKay | dffaaa3 | 2017-09-27 22:39:37 +0000 | [diff] [blame] | 1032 | ENUM_ENT(EM_AVR32,         "Atmel Corporation 32-bit microprocessor family"), | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 1033 | ENUM_ENT(EM_STM8,          "STMicroeletronics STM8 8-bit microcontroller"), | 
|  | 1034 | ENUM_ENT(EM_TILE64,        "Tilera TILE64 multicore architecture family"), | 
|  | 1035 | ENUM_ENT(EM_TILEPRO,       "Tilera TILEPro multicore architecture family"), | 
|  | 1036 | ENUM_ENT(EM_CUDA,          "NVIDIA CUDA architecture"), | 
|  | 1037 | ENUM_ENT(EM_TILEGX,        "Tilera TILE-Gx multicore architecture family"), | 
|  | 1038 | ENUM_ENT(EM_CLOUDSHIELD,   "EM_CLOUDSHIELD"), | 
|  | 1039 | ENUM_ENT(EM_COREA_1ST,     "EM_COREA_1ST"), | 
|  | 1040 | ENUM_ENT(EM_COREA_2ND,     "EM_COREA_2ND"), | 
|  | 1041 | ENUM_ENT(EM_ARC_COMPACT2,  "EM_ARC_COMPACT2"), | 
|  | 1042 | ENUM_ENT(EM_OPEN8,         "EM_OPEN8"), | 
|  | 1043 | ENUM_ENT(EM_RL78,          "Renesas RL78"), | 
|  | 1044 | ENUM_ENT(EM_VIDEOCORE5,    "Broadcom VideoCore V processor"), | 
|  | 1045 | ENUM_ENT(EM_78KOR,         "EM_78KOR"), | 
|  | 1046 | ENUM_ENT(EM_56800EX,       "EM_56800EX"), | 
|  | 1047 | ENUM_ENT(EM_AMDGPU,        "EM_AMDGPU"), | 
| Alex Bradbury | 1524f62 | 2016-11-01 16:59:37 +0000 | [diff] [blame] | 1048 | ENUM_ENT(EM_RISCV,         "RISC-V"), | 
| Jacques Pienaar | ea9f25a | 2016-03-01 21:21:42 +0000 | [diff] [blame] | 1049 | ENUM_ENT(EM_LANAI,         "EM_LANAI"), | 
| Alexei Starovoitov | cfb51f5 | 2016-07-15 22:27:55 +0000 | [diff] [blame] | 1050 | ENUM_ENT(EM_BPF,           "EM_BPF"), | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1051 | }; | 
|  | 1052 |  | 
|  | 1053 | static const EnumEntry<unsigned> ElfSymbolBindings[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 1054 | {"Local",  "LOCAL",  ELF::STB_LOCAL}, | 
|  | 1055 | {"Global", "GLOBAL", ELF::STB_GLOBAL}, | 
|  | 1056 | {"Weak",   "WEAK",   ELF::STB_WEAK}, | 
|  | 1057 | {"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}}; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1058 |  | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 1059 | static const EnumEntry<unsigned> ElfSymbolVisibilities[] = { | 
|  | 1060 | {"DEFAULT",   "DEFAULT",   ELF::STV_DEFAULT}, | 
|  | 1061 | {"INTERNAL",  "INTERNAL",  ELF::STV_INTERNAL}, | 
|  | 1062 | {"HIDDEN",    "HIDDEN",    ELF::STV_HIDDEN}, | 
|  | 1063 | {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}}; | 
|  | 1064 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1065 | static const EnumEntry<unsigned> ElfSymbolTypes[] = { | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 1066 | {"None",      "NOTYPE",  ELF::STT_NOTYPE}, | 
|  | 1067 | {"Object",    "OBJECT",  ELF::STT_OBJECT}, | 
|  | 1068 | {"Function",  "FUNC",    ELF::STT_FUNC}, | 
|  | 1069 | {"Section",   "SECTION", ELF::STT_SECTION}, | 
|  | 1070 | {"File",      "FILE",    ELF::STT_FILE}, | 
|  | 1071 | {"Common",    "COMMON",  ELF::STT_COMMON}, | 
|  | 1072 | {"TLS",       "TLS",     ELF::STT_TLS}, | 
|  | 1073 | {"GNU_IFunc", "IFUNC",   ELF::STT_GNU_IFUNC}}; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1074 |  | 
|  | 1075 | static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = { | 
| Konstantin Zhuravlyov | 5b0bf2ff | 2017-06-05 21:33:40 +0000 | [diff] [blame] | 1076 | { "AMDGPU_HSA_KERNEL",            ELF::STT_AMDGPU_HSA_KERNEL } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1077 | }; | 
|  | 1078 |  | 
| Hemant Kulkarni | ab4a46f | 2016-01-26 19:46:39 +0000 | [diff] [blame] | 1079 | static const char *getGroupType(uint32_t Flag) { | 
|  | 1080 | if (Flag & ELF::GRP_COMDAT) | 
|  | 1081 | return "COMDAT"; | 
|  | 1082 | else | 
|  | 1083 | return "(unknown)"; | 
|  | 1084 | } | 
|  | 1085 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1086 | static const EnumEntry<unsigned> ElfSectionFlags[] = { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 1087 | ENUM_ENT(SHF_WRITE,            "W"), | 
|  | 1088 | ENUM_ENT(SHF_ALLOC,            "A"), | 
|  | 1089 | ENUM_ENT(SHF_EXCLUDE,          "E"), | 
|  | 1090 | ENUM_ENT(SHF_EXECINSTR,        "X"), | 
|  | 1091 | ENUM_ENT(SHF_MERGE,            "M"), | 
|  | 1092 | ENUM_ENT(SHF_STRINGS,          "S"), | 
|  | 1093 | ENUM_ENT(SHF_INFO_LINK,        "I"), | 
|  | 1094 | ENUM_ENT(SHF_LINK_ORDER,       "L"), | 
|  | 1095 | ENUM_ENT(SHF_OS_NONCONFORMING, "o"), | 
|  | 1096 | ENUM_ENT(SHF_GROUP,            "G"), | 
|  | 1097 | ENUM_ENT(SHF_TLS,              "T"), | 
| Hemant Kulkarni | 04ac3d7 | 2016-05-12 19:58:52 +0000 | [diff] [blame] | 1098 | ENUM_ENT(SHF_MASKOS,           "o"), | 
|  | 1099 | ENUM_ENT(SHF_MASKPROC,         "p"), | 
| George Rimar | c13c59a | 2016-05-21 10:16:58 +0000 | [diff] [blame] | 1100 | ENUM_ENT_1(SHF_COMPRESSED), | 
|  | 1101 | }; | 
|  | 1102 |  | 
|  | 1103 | static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = { | 
|  | 1104 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION), | 
|  | 1105 | LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION) | 
| Simon Atanasyan | 2d0d853 | 2016-01-20 19:15:18 +0000 | [diff] [blame] | 1106 | }; | 
|  | 1107 |  | 
| Prakhar Bahuguna | 52a7dd7 | 2016-12-15 07:59:08 +0000 | [diff] [blame] | 1108 | static const EnumEntry<unsigned> ElfARMSectionFlags[] = { | 
|  | 1109 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) | 
|  | 1110 | }; | 
|  | 1111 |  | 
| Simon Atanasyan | 2d0d853 | 2016-01-20 19:15:18 +0000 | [diff] [blame] | 1112 | static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { | 
|  | 1113 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL) | 
|  | 1114 | }; | 
|  | 1115 |  | 
|  | 1116 | static const EnumEntry<unsigned> ElfMipsSectionFlags[] = { | 
|  | 1117 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NODUPES), | 
|  | 1118 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NAMES  ), | 
|  | 1119 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_LOCAL  ), | 
|  | 1120 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP), | 
|  | 1121 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_GPREL  ), | 
|  | 1122 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_MERGE  ), | 
|  | 1123 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_ADDR   ), | 
|  | 1124 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_STRING ) | 
|  | 1125 | }; | 
|  | 1126 |  | 
|  | 1127 | static const EnumEntry<unsigned> ElfX86_64SectionFlags[] = { | 
|  | 1128 | LLVM_READOBJ_ENUM_ENT(ELF, SHF_X86_64_LARGE) | 
|  | 1129 | }; | 
|  | 1130 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1131 | static std::string getGNUFlags(uint64_t Flags) { | 
|  | 1132 | std::string Str; | 
|  | 1133 | for (auto Entry : ElfSectionFlags) { | 
|  | 1134 | uint64_t Flag = Entry.Value & Flags; | 
|  | 1135 | Flags &= ~Entry.Value; | 
|  | 1136 | switch (Flag) { | 
|  | 1137 | case ELF::SHF_WRITE: | 
|  | 1138 | case ELF::SHF_ALLOC: | 
|  | 1139 | case ELF::SHF_EXECINSTR: | 
|  | 1140 | case ELF::SHF_MERGE: | 
|  | 1141 | case ELF::SHF_STRINGS: | 
|  | 1142 | case ELF::SHF_INFO_LINK: | 
|  | 1143 | case ELF::SHF_LINK_ORDER: | 
|  | 1144 | case ELF::SHF_OS_NONCONFORMING: | 
|  | 1145 | case ELF::SHF_GROUP: | 
|  | 1146 | case ELF::SHF_TLS: | 
|  | 1147 | case ELF::SHF_EXCLUDE: | 
|  | 1148 | Str += Entry.AltName; | 
|  | 1149 | break; | 
|  | 1150 | default: | 
| Hemant Kulkarni | 04ac3d7 | 2016-05-12 19:58:52 +0000 | [diff] [blame] | 1151 | if (Flag & ELF::SHF_MASKOS) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1152 | Str += "o"; | 
| Hemant Kulkarni | 04ac3d7 | 2016-05-12 19:58:52 +0000 | [diff] [blame] | 1153 | else if (Flag & ELF::SHF_MASKPROC) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1154 | Str += "p"; | 
|  | 1155 | else if (Flag) | 
|  | 1156 | Str += "x"; | 
|  | 1157 | } | 
|  | 1158 | } | 
|  | 1159 | return Str; | 
|  | 1160 | } | 
|  | 1161 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1162 | static const char *getElfSegmentType(unsigned Arch, unsigned Type) { | 
|  | 1163 | // Check potentially overlapped processor-specific | 
|  | 1164 | // program header type. | 
|  | 1165 | switch (Arch) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1166 | case ELF::EM_ARM: | 
|  | 1167 | switch (Type) { | 
|  | 1168 | LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); | 
|  | 1169 | } | 
|  | 1170 | case ELF::EM_MIPS: | 
|  | 1171 | case ELF::EM_MIPS_RS3_LE: | 
|  | 1172 | switch (Type) { | 
|  | 1173 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); | 
|  | 1174 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); | 
|  | 1175 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); | 
|  | 1176 | LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS); | 
|  | 1177 | } | 
|  | 1178 | } | 
|  | 1179 |  | 
|  | 1180 | switch (Type) { | 
|  | 1181 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL   ); | 
|  | 1182 | LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD   ); | 
|  | 1183 | LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC); | 
|  | 1184 | LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP ); | 
|  | 1185 | LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE   ); | 
|  | 1186 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB  ); | 
|  | 1187 | LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR   ); | 
|  | 1188 | LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS    ); | 
|  | 1189 |  | 
|  | 1190 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME); | 
|  | 1191 | LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND); | 
|  | 1192 |  | 
|  | 1193 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); | 
|  | 1194 | LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); | 
| George Rimar | bcfcb9e | 2016-10-18 10:54:56 +0000 | [diff] [blame] | 1195 |  | 
|  | 1196 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); | 
|  | 1197 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); | 
| George Rimar | 114d335 | 2016-12-06 17:55:52 +0000 | [diff] [blame] | 1198 | LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); | 
| George Rimar | bcfcb9e | 2016-10-18 10:54:56 +0000 | [diff] [blame] | 1199 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1200 | default: return ""; | 
|  | 1201 | } | 
|  | 1202 | } | 
|  | 1203 |  | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 1204 | static std::string getElfPtType(unsigned Arch, unsigned Type) { | 
|  | 1205 | switch (Type) { | 
| Hemant Kulkarni | 7d564ba | 2016-03-28 17:20:23 +0000 | [diff] [blame] | 1206 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_NULL) | 
|  | 1207 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_LOAD) | 
|  | 1208 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_DYNAMIC) | 
|  | 1209 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_INTERP) | 
|  | 1210 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_NOTE) | 
|  | 1211 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_SHLIB) | 
|  | 1212 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_PHDR) | 
|  | 1213 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_TLS) | 
|  | 1214 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_EH_FRAME) | 
|  | 1215 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_SUNW_UNWIND) | 
|  | 1216 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_STACK) | 
|  | 1217 | LLVM_READOBJ_PHDR_ENUM(ELF, PT_GNU_RELRO) | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 1218 | default: | 
|  | 1219 | // All machine specific PT_* types | 
|  | 1220 | switch (Arch) { | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 1221 | case ELF::EM_ARM: | 
|  | 1222 | if (Type == ELF::PT_ARM_EXIDX) | 
|  | 1223 | return "EXIDX"; | 
|  | 1224 | return ""; | 
|  | 1225 | case ELF::EM_MIPS: | 
|  | 1226 | case ELF::EM_MIPS_RS3_LE: | 
|  | 1227 | switch (Type) { | 
|  | 1228 | case PT_MIPS_REGINFO: | 
|  | 1229 | return "REGINFO"; | 
|  | 1230 | case PT_MIPS_RTPROC: | 
|  | 1231 | return "RTPROC"; | 
|  | 1232 | case PT_MIPS_OPTIONS: | 
|  | 1233 | return "OPTIONS"; | 
|  | 1234 | case PT_MIPS_ABIFLAGS: | 
|  | 1235 | return "ABIFLAGS"; | 
|  | 1236 | } | 
|  | 1237 | return ""; | 
|  | 1238 | } | 
|  | 1239 | } | 
|  | 1240 | return std::string("<unknown>: ") + to_string(format_hex(Type, 1)); | 
|  | 1241 | } | 
|  | 1242 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1243 | static const EnumEntry<unsigned> ElfSegmentFlags[] = { | 
|  | 1244 | LLVM_READOBJ_ENUM_ENT(ELF, PF_X), | 
|  | 1245 | LLVM_READOBJ_ENUM_ENT(ELF, PF_W), | 
|  | 1246 | LLVM_READOBJ_ENUM_ENT(ELF, PF_R) | 
|  | 1247 | }; | 
|  | 1248 |  | 
|  | 1249 | static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { | 
|  | 1250 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER), | 
|  | 1251 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC), | 
|  | 1252 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC), | 
|  | 1253 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2), | 
|  | 1254 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE), | 
|  | 1255 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_FP64), | 
|  | 1256 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008), | 
|  | 1257 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32), | 
|  | 1258 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O64), | 
|  | 1259 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI32), | 
|  | 1260 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI64), | 
|  | 1261 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_3900), | 
|  | 1262 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4010), | 
|  | 1263 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4100), | 
|  | 1264 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4650), | 
|  | 1265 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4120), | 
|  | 1266 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4111), | 
|  | 1267 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_SB1), | 
|  | 1268 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON), | 
|  | 1269 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_XLR), | 
|  | 1270 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON2), | 
|  | 1271 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON3), | 
|  | 1272 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5400), | 
|  | 1273 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5900), | 
|  | 1274 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5500), | 
|  | 1275 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_9000), | 
|  | 1276 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2E), | 
|  | 1277 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2F), | 
|  | 1278 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS3A), | 
|  | 1279 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS), | 
|  | 1280 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16), | 
|  | 1281 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_MDMX), | 
|  | 1282 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1), | 
|  | 1283 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2), | 
|  | 1284 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3), | 
|  | 1285 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4), | 
|  | 1286 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5), | 
|  | 1287 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32), | 
|  | 1288 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64), | 
|  | 1289 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2), | 
|  | 1290 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2), | 
|  | 1291 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6), | 
|  | 1292 | LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6) | 
|  | 1293 | }; | 
|  | 1294 |  | 
| Konstantin Zhuravlyov | aa0835a | 2017-10-05 16:19:18 +0000 | [diff] [blame] | 1295 | static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = { | 
| Konstantin Zhuravlyov | 9122a63 | 2018-02-16 22:33:59 +0000 | [diff] [blame] | 1296 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE), | 
|  | 1297 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600), | 
|  | 1298 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630), | 
|  | 1299 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880), | 
|  | 1300 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670), | 
|  | 1301 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710), | 
|  | 1302 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730), | 
|  | 1303 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770), | 
|  | 1304 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR), | 
|  | 1305 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS), | 
|  | 1306 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER), | 
|  | 1307 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD), | 
|  | 1308 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO), | 
|  | 1309 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS), | 
|  | 1310 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS), | 
|  | 1311 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN), | 
|  | 1312 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS), | 
|  | 1313 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600), | 
|  | 1314 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601), | 
|  | 1315 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700), | 
|  | 1316 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701), | 
|  | 1317 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702), | 
|  | 1318 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703), | 
|  | 1319 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704), | 
|  | 1320 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801), | 
|  | 1321 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802), | 
|  | 1322 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803), | 
|  | 1323 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810), | 
|  | 1324 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900), | 
|  | 1325 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902), | 
| Matt Arsenault | 0084adc | 2018-04-30 19:08:16 +0000 | [diff] [blame] | 1326 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904), | 
|  | 1327 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906), | 
| Konstantin Zhuravlyov | 9122a63 | 2018-02-16 22:33:59 +0000 | [diff] [blame] | 1328 | LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK) | 
| Konstantin Zhuravlyov | aa0835a | 2017-10-05 16:19:18 +0000 | [diff] [blame] | 1329 | }; | 
|  | 1330 |  | 
| Alex Bradbury | bb89b2b | 2017-10-03 08:41:59 +0000 | [diff] [blame] | 1331 | static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = { | 
|  | 1332 | LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVC), | 
|  | 1333 | LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_SINGLE), | 
|  | 1334 | LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_DOUBLE), | 
|  | 1335 | LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_QUAD), | 
|  | 1336 | LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVE) | 
|  | 1337 | }; | 
|  | 1338 |  | 
| Simon Atanasyan | b7807a0 | 2016-03-24 16:10:37 +0000 | [diff] [blame] | 1339 | static const EnumEntry<unsigned> ElfSymOtherFlags[] = { | 
|  | 1340 | LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), | 
|  | 1341 | LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN), | 
|  | 1342 | LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED) | 
|  | 1343 | }; | 
|  | 1344 |  | 
|  | 1345 | static const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = { | 
|  | 1346 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), | 
|  | 1347 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), | 
|  | 1348 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC), | 
|  | 1349 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS) | 
|  | 1350 | }; | 
|  | 1351 |  | 
|  | 1352 | static const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = { | 
|  | 1353 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL), | 
|  | 1354 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT), | 
|  | 1355 | LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16) | 
|  | 1356 | }; | 
|  | 1357 |  | 
| Simon Atanasyan | 8a71b53 | 2016-05-04 05:58:57 +0000 | [diff] [blame] | 1358 | static const char *getElfMipsOptionsOdkType(unsigned Odk) { | 
|  | 1359 | switch (Odk) { | 
|  | 1360 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL); | 
|  | 1361 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO); | 
|  | 1362 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS); | 
|  | 1363 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD); | 
|  | 1364 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH); | 
|  | 1365 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL); | 
|  | 1366 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS); | 
|  | 1367 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND); | 
|  | 1368 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR); | 
|  | 1369 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP); | 
|  | 1370 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT); | 
|  | 1371 | LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE); | 
|  | 1372 | default: | 
|  | 1373 | return "Unknown"; | 
|  | 1374 | } | 
|  | 1375 | } | 
|  | 1376 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1377 | template <typename ELFT> | 
| Zachary Turner | 88bb163 | 2016-05-03 00:28:04 +0000 | [diff] [blame] | 1378 | ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1379 | : ObjDumper(Writer), Obj(Obj) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1380 | SmallVector<const Elf_Phdr *, 4> LoadSegments; | 
| Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 1381 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1382 | if (Phdr.p_type == ELF::PT_DYNAMIC) { | 
| Rafael Espindola | e17c3f3 | 2016-02-17 16:48:00 +0000 | [diff] [blame] | 1383 | DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1384 | continue; | 
|  | 1385 | } | 
|  | 1386 | if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) | 
|  | 1387 | continue; | 
|  | 1388 | LoadSegments.push_back(&Phdr); | 
|  | 1389 | } | 
|  | 1390 |  | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 1391 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| Michael J. Spencer | 37304f1 | 2016-02-11 04:59:26 +0000 | [diff] [blame] | 1392 | switch (Sec.sh_type) { | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1393 | case ELF::SHT_SYMTAB: | 
|  | 1394 | if (DotSymtabSec != nullptr) | 
| Saleem Abdulrasool | 46ee733 | 2017-09-29 02:45:44 +0000 | [diff] [blame] | 1395 | reportError("Multiple SHT_SYMTAB"); | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1396 | DotSymtabSec = &Sec; | 
|  | 1397 | break; | 
|  | 1398 | case ELF::SHT_DYNSYM: | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 1399 | if (DynSymRegion.Size) | 
| Saleem Abdulrasool | 46ee733 | 2017-09-29 02:45:44 +0000 | [diff] [blame] | 1400 | reportError("Multiple SHT_DYNSYM"); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 1401 | DynSymRegion = createDRIFrom(&Sec); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 1402 | // This is only used (if Elf_Shdr present)for naming section in GNU style | 
|  | 1403 | DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec)); | 
| Dave Lee | 67b4966 | 2017-11-16 18:10:15 +0000 | [diff] [blame] | 1404 | DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec)); | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1405 | break; | 
| Michael J. Spencer | 1c793ef | 2016-02-17 22:30:41 +0000 | [diff] [blame] | 1406 | case ELF::SHT_SYMTAB_SHNDX: | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 1407 | ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec)); | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1408 | break; | 
| Michael J. Spencer | 37304f1 | 2016-02-11 04:59:26 +0000 | [diff] [blame] | 1409 | case ELF::SHT_GNU_versym: | 
|  | 1410 | if (dot_gnu_version_sec != nullptr) | 
|  | 1411 | reportError("Multiple SHT_GNU_versym"); | 
|  | 1412 | dot_gnu_version_sec = &Sec; | 
|  | 1413 | break; | 
|  | 1414 | case ELF::SHT_GNU_verdef: | 
|  | 1415 | if (dot_gnu_version_d_sec != nullptr) | 
|  | 1416 | reportError("Multiple SHT_GNU_verdef"); | 
|  | 1417 | dot_gnu_version_d_sec = &Sec; | 
|  | 1418 | break; | 
|  | 1419 | case ELF::SHT_GNU_verneed: | 
|  | 1420 | if (dot_gnu_version_r_sec != nullptr) | 
| Saleem Abdulrasool | 46ee733 | 2017-09-29 02:45:44 +0000 | [diff] [blame] | 1421 | reportError("Multiple SHT_GNU_verneed"); | 
| Michael J. Spencer | 37304f1 | 2016-02-11 04:59:26 +0000 | [diff] [blame] | 1422 | dot_gnu_version_r_sec = &Sec; | 
|  | 1423 | break; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 1424 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: | 
|  | 1425 | if (DotCGProfileSec != nullptr) | 
|  | 1426 | reportError("Multiple .note.llvm.cgprofile"); | 
|  | 1427 | DotCGProfileSec = &Sec; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 1428 | break; | 
|  | 1429 | case ELF::SHT_LLVM_ADDRSIG: | 
|  | 1430 | if (DotAddrsigSec != nullptr) | 
|  | 1431 | reportError("Multiple .llvm_addrsig"); | 
|  | 1432 | DotAddrsigSec = &Sec; | 
|  | 1433 | break; | 
| Michael J. Spencer | 37304f1 | 2016-02-11 04:59:26 +0000 | [diff] [blame] | 1434 | } | 
|  | 1435 | } | 
|  | 1436 |  | 
| Michael J. Spencer | 60d82b2 | 2016-02-11 04:59:37 +0000 | [diff] [blame] | 1437 | parseDynamicTable(LoadSegments); | 
|  | 1438 |  | 
|  | 1439 | if (opts::Output == opts::GNU) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1440 | ELFDumperStyle.reset(new GNUStyle<ELFT>(Writer, this)); | 
| Michael J. Spencer | 60d82b2 | 2016-02-11 04:59:37 +0000 | [diff] [blame] | 1441 | else | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1442 | ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, this)); | 
| Michael J. Spencer | 60d82b2 | 2016-02-11 04:59:37 +0000 | [diff] [blame] | 1443 | } | 
|  | 1444 |  | 
|  | 1445 | template <typename ELFT> | 
|  | 1446 | void ELFDumper<ELFT>::parseDynamicTable( | 
|  | 1447 | ArrayRef<const Elf_Phdr *> LoadSegments) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1448 | auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { | 
| Peter Collingbourne | 4240c58 | 2017-10-31 22:49:09 +0000 | [diff] [blame] | 1449 | const Elf_Phdr *const *I = | 
|  | 1450 | std::upper_bound(LoadSegments.begin(), LoadSegments.end(), VAddr, | 
|  | 1451 | [](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { | 
|  | 1452 | return VAddr < Phdr->p_vaddr; | 
|  | 1453 | }); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1454 | if (I == LoadSegments.begin()) | 
| Rafael Espindola | 6009db6 | 2016-02-16 14:17:48 +0000 | [diff] [blame] | 1455 | report_fatal_error("Virtual address is not in any segment"); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1456 | --I; | 
|  | 1457 | const Elf_Phdr &Phdr = **I; | 
|  | 1458 | uint64_t Delta = VAddr - Phdr.p_vaddr; | 
|  | 1459 | if (Delta >= Phdr.p_filesz) | 
| Rafael Espindola | 6009db6 | 2016-02-16 14:17:48 +0000 | [diff] [blame] | 1460 | report_fatal_error("Virtual address is not in any segment"); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1461 | return Obj->base() + Phdr.p_offset + Delta; | 
|  | 1462 | }; | 
|  | 1463 |  | 
|  | 1464 | uint64_t SONameOffset = 0; | 
|  | 1465 | const char *StringTableBegin = nullptr; | 
|  | 1466 | uint64_t StringTableSize = 0; | 
|  | 1467 | for (const Elf_Dyn &Dyn : dynamic_table()) { | 
|  | 1468 | switch (Dyn.d_tag) { | 
|  | 1469 | case ELF::DT_HASH: | 
|  | 1470 | HashTable = | 
|  | 1471 | reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr())); | 
|  | 1472 | break; | 
|  | 1473 | case ELF::DT_GNU_HASH: | 
|  | 1474 | GnuHashTable = | 
|  | 1475 | reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr())); | 
|  | 1476 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1477 | case ELF::DT_STRTAB: | 
|  | 1478 | StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr()); | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 1479 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1480 | case ELF::DT_STRSZ: | 
|  | 1481 | StringTableSize = Dyn.getVal(); | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 1482 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1483 | case ELF::DT_SYMTAB: | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 1484 | DynSymRegion.Addr = toMappedAddr(Dyn.getPtr()); | 
|  | 1485 | DynSymRegion.EntSize = sizeof(Elf_Sym); | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 1486 | break; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1487 | case ELF::DT_RELA: | 
|  | 1488 | DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); | 
|  | 1489 | break; | 
|  | 1490 | case ELF::DT_RELASZ: | 
|  | 1491 | DynRelaRegion.Size = Dyn.getVal(); | 
|  | 1492 | break; | 
|  | 1493 | case ELF::DT_RELAENT: | 
|  | 1494 | DynRelaRegion.EntSize = Dyn.getVal(); | 
|  | 1495 | break; | 
|  | 1496 | case ELF::DT_SONAME: | 
|  | 1497 | SONameOffset = Dyn.getVal(); | 
|  | 1498 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1499 | case ELF::DT_REL: | 
|  | 1500 | DynRelRegion.Addr = toMappedAddr(Dyn.getPtr()); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1501 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1502 | case ELF::DT_RELSZ: | 
|  | 1503 | DynRelRegion.Size = Dyn.getVal(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1504 | break; | 
| Michael J. Spencer | 94f060c | 2016-02-11 04:59:32 +0000 | [diff] [blame] | 1505 | case ELF::DT_RELENT: | 
|  | 1506 | DynRelRegion.EntSize = Dyn.getVal(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1507 | break; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 1508 | case ELF::DT_RELR: | 
|  | 1509 | case ELF::DT_ANDROID_RELR: | 
|  | 1510 | DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr()); | 
|  | 1511 | break; | 
|  | 1512 | case ELF::DT_RELRSZ: | 
|  | 1513 | case ELF::DT_ANDROID_RELRSZ: | 
|  | 1514 | DynRelrRegion.Size = Dyn.getVal(); | 
|  | 1515 | break; | 
|  | 1516 | case ELF::DT_RELRENT: | 
|  | 1517 | case ELF::DT_ANDROID_RELRENT: | 
|  | 1518 | DynRelrRegion.EntSize = Dyn.getVal(); | 
|  | 1519 | break; | 
| Rafael Espindola | 944f655 | 2016-02-16 15:16:00 +0000 | [diff] [blame] | 1520 | case ELF::DT_PLTREL: | 
|  | 1521 | if (Dyn.getVal() == DT_REL) | 
|  | 1522 | DynPLTRelRegion.EntSize = sizeof(Elf_Rel); | 
|  | 1523 | else if (Dyn.getVal() == DT_RELA) | 
|  | 1524 | DynPLTRelRegion.EntSize = sizeof(Elf_Rela); | 
|  | 1525 | else | 
|  | 1526 | reportError(Twine("unknown DT_PLTREL value of ") + | 
|  | 1527 | Twine((uint64_t)Dyn.getVal())); | 
|  | 1528 | break; | 
|  | 1529 | case ELF::DT_JMPREL: | 
|  | 1530 | DynPLTRelRegion.Addr = toMappedAddr(Dyn.getPtr()); | 
|  | 1531 | break; | 
|  | 1532 | case ELF::DT_PLTRELSZ: | 
|  | 1533 | DynPLTRelRegion.Size = Dyn.getVal(); | 
|  | 1534 | break; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1535 | } | 
|  | 1536 | } | 
|  | 1537 | if (StringTableBegin) | 
|  | 1538 | DynamicStringTable = StringRef(StringTableBegin, StringTableSize); | 
|  | 1539 | if (SONameOffset) | 
|  | 1540 | SOName = getDynamicString(SONameOffset); | 
| Rafael Espindola | 6009db6 | 2016-02-16 14:17:48 +0000 | [diff] [blame] | 1541 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1542 |  | 
| Rafael Espindola | 6009db6 | 2016-02-16 14:17:48 +0000 | [diff] [blame] | 1543 | template <typename ELFT> | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 1544 | typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const { | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 1545 | return DynRelRegion.getAsArrayRef<Elf_Rel>(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1546 | } | 
|  | 1547 |  | 
|  | 1548 | template <typename ELFT> | 
|  | 1549 | typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const { | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 1550 | return DynRelaRegion.getAsArrayRef<Elf_Rela>(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1551 | } | 
|  | 1552 |  | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 1553 | template <typename ELFT> | 
|  | 1554 | typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const { | 
|  | 1555 | return DynRelrRegion.getAsArrayRef<Elf_Relr>(); | 
|  | 1556 | } | 
|  | 1557 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1558 | template<class ELFT> | 
|  | 1559 | void ELFDumper<ELFT>::printFileHeaders() { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 1560 | ELFDumperStyle->printFileHeaders(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1561 | } | 
|  | 1562 |  | 
|  | 1563 | template<class ELFT> | 
|  | 1564 | void ELFDumper<ELFT>::printSections() { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1565 | ELFDumperStyle->printSections(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1566 | } | 
|  | 1567 |  | 
|  | 1568 | template<class ELFT> | 
|  | 1569 | void ELFDumper<ELFT>::printRelocations() { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1570 | ELFDumperStyle->printRelocations(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1571 | } | 
|  | 1572 |  | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 1573 | template <class ELFT> void ELFDumper<ELFT>::printProgramHeaders() { | 
|  | 1574 | ELFDumperStyle->printProgramHeaders(Obj); | 
|  | 1575 | } | 
|  | 1576 |  | 
| Simon Atanasyan | 72155c3 | 2016-01-16 22:40:09 +0000 | [diff] [blame] | 1577 | template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1578 | ELFDumperStyle->printDynamicRelocations(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1579 | } | 
|  | 1580 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1581 | template<class ELFT> | 
|  | 1582 | void ELFDumper<ELFT>::printSymbols() { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1583 | ELFDumperStyle->printSymbols(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1584 | } | 
|  | 1585 |  | 
|  | 1586 | template<class ELFT> | 
|  | 1587 | void ELFDumper<ELFT>::printDynamicSymbols() { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 1588 | ELFDumperStyle->printDynamicSymbols(Obj); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1589 | } | 
|  | 1590 |  | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 1591 | template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() { | 
|  | 1592 | ELFDumperStyle->printHashHistogram(Obj); | 
|  | 1593 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 1594 |  | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 1595 | template <class ELFT> void ELFDumper<ELFT>::printCGProfile() { | 
|  | 1596 | ELFDumperStyle->printCGProfile(Obj); | 
|  | 1597 | } | 
|  | 1598 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 1599 | template <class ELFT> void ELFDumper<ELFT>::printNotes() { | 
|  | 1600 | ELFDumperStyle->printNotes(Obj); | 
|  | 1601 | } | 
|  | 1602 |  | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 1603 | template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() { | 
|  | 1604 | ELFDumperStyle->printELFLinkerOptions(Obj); | 
|  | 1605 | } | 
|  | 1606 |  | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1607 | static const char *getTypeString(unsigned Arch, uint64_t Type) { | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1608 | #define DYNAMIC_TAG(n, v) | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1609 | switch (Arch) { | 
|  | 1610 | case EM_HEXAGON: | 
|  | 1611 | switch (Type) { | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1612 | #define HEXAGON_DYNAMIC_TAG(name, value)                                       \ | 
|  | 1613 | case DT_##name:                                                              \ | 
|  | 1614 | return #name; | 
|  | 1615 | #include "llvm/BinaryFormat/DynamicTags.def" | 
|  | 1616 | #undef HEXAGON_DYNAMIC_TAG | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1617 | } | 
| Sean Fertile | eaa1607 | 2018-04-13 16:42:48 +0000 | [diff] [blame] | 1618 |  | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1619 | case EM_MIPS: | 
|  | 1620 | switch (Type) { | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1621 | #define MIPS_DYNAMIC_TAG(name, value)                                          \ | 
|  | 1622 | case DT_##name:                                                              \ | 
|  | 1623 | return #name; | 
|  | 1624 | #include "llvm/BinaryFormat/DynamicTags.def" | 
|  | 1625 | #undef MIPS_DYNAMIC_TAG | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1626 | } | 
| Sean Fertile | eaa1607 | 2018-04-13 16:42:48 +0000 | [diff] [blame] | 1627 |  | 
|  | 1628 | case EM_PPC64: | 
|  | 1629 | switch(Type) { | 
|  | 1630 | #define PPC64_DYNAMIC_TAG(name, value)                                         \ | 
|  | 1631 | case DT_##name:                                                            \ | 
|  | 1632 | return #name; | 
|  | 1633 | #include "llvm/BinaryFormat/DynamicTags.def" | 
|  | 1634 | #undef PPC64_DYNAMIC_TAG | 
|  | 1635 | } | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1636 | } | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1637 | #undef DYNAMIC_TAG | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1638 | switch (Type) { | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1639 | // Now handle all dynamic tags except the architecture specific ones | 
|  | 1640 | #define MIPS_DYNAMIC_TAG(name, value) | 
|  | 1641 | #define HEXAGON_DYNAMIC_TAG(name, value) | 
| Sean Fertile | eaa1607 | 2018-04-13 16:42:48 +0000 | [diff] [blame] | 1642 | #define PPC64_DYNAMIC_TAG(name, value) | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1643 | // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. | 
|  | 1644 | #define DYNAMIC_TAG_MARKER(name, value) | 
|  | 1645 | #define DYNAMIC_TAG(name, value)                                               \ | 
|  | 1646 | case DT_##name:                                                              \ | 
|  | 1647 | return #name; | 
|  | 1648 | #include "llvm/BinaryFormat/DynamicTags.def" | 
|  | 1649 | #undef DYNAMIC_TAG | 
|  | 1650 | #undef MIPS_DYNAMIC_TAG | 
|  | 1651 | #undef HEXAGON_DYNAMIC_TAG | 
| Sean Fertile | eaa1607 | 2018-04-13 16:42:48 +0000 | [diff] [blame] | 1652 | #undef PPC64_DYNAMIC_TAG | 
| Alexander Richardson | 3056a84 | 2018-03-21 14:17:50 +0000 | [diff] [blame] | 1653 | #undef DYNAMIC_TAG_MARKER | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1654 | default: return "unknown"; | 
|  | 1655 | } | 
|  | 1656 | } | 
|  | 1657 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1658 | #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ | 
|  | 1659 | { #enum, prefix##_##enum } | 
|  | 1660 |  | 
|  | 1661 | static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { | 
|  | 1662 | LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), | 
|  | 1663 | LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), | 
|  | 1664 | LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), | 
|  | 1665 | LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), | 
|  | 1666 | LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) | 
|  | 1667 | }; | 
|  | 1668 |  | 
|  | 1669 | static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = { | 
|  | 1670 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW), | 
|  | 1671 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL), | 
|  | 1672 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP), | 
|  | 1673 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE), | 
|  | 1674 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR), | 
|  | 1675 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST), | 
|  | 1676 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN), | 
|  | 1677 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN), | 
|  | 1678 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT), | 
|  | 1679 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS), | 
|  | 1680 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE), | 
|  | 1681 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB), | 
|  | 1682 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP), | 
|  | 1683 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT), | 
|  | 1684 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE), | 
|  | 1685 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE), | 
|  | 1686 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT), | 
|  | 1687 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF), | 
|  | 1688 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS), | 
|  | 1689 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR), | 
|  | 1690 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED), | 
|  | 1691 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC), | 
|  | 1692 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE), | 
|  | 1693 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT), | 
|  | 1694 | LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON) | 
|  | 1695 | }; | 
|  | 1696 |  | 
|  | 1697 | static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { | 
|  | 1698 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), | 
|  | 1699 | LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), | 
|  | 1700 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), | 
|  | 1701 | LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), | 
|  | 1702 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), | 
|  | 1703 | LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), | 
|  | 1704 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), | 
|  | 1705 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), | 
|  | 1706 | LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), | 
|  | 1707 | LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), | 
|  | 1708 | LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), | 
|  | 1709 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), | 
|  | 1710 | LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), | 
|  | 1711 | LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), | 
|  | 1712 | LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), | 
|  | 1713 | LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) | 
|  | 1714 | }; | 
|  | 1715 |  | 
|  | 1716 | #undef LLVM_READOBJ_DT_FLAG_ENT | 
|  | 1717 |  | 
|  | 1718 | template <typename T, typename TFlag> | 
|  | 1719 | void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1720 | using FlagEntry = EnumEntry<TFlag>; | 
|  | 1721 | using FlagVector = SmallVector<FlagEntry, 10>; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1722 | FlagVector SetFlags; | 
|  | 1723 |  | 
|  | 1724 | for (const auto &Flag : Flags) { | 
|  | 1725 | if (Flag.Value == 0) | 
|  | 1726 | continue; | 
|  | 1727 |  | 
|  | 1728 | if ((Value & Flag.Value) == Flag.Value) | 
|  | 1729 | SetFlags.push_back(Flag); | 
|  | 1730 | } | 
|  | 1731 |  | 
|  | 1732 | for (const auto &Flag : SetFlags) { | 
|  | 1733 | OS << Flag.Name << " "; | 
|  | 1734 | } | 
|  | 1735 | } | 
|  | 1736 |  | 
|  | 1737 | template <class ELFT> | 
|  | 1738 | StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const { | 
|  | 1739 | if (Value >= DynamicStringTable.size()) | 
|  | 1740 | reportError("Invalid dynamic string table reference"); | 
|  | 1741 | return StringRef(DynamicStringTable.data() + Value); | 
|  | 1742 | } | 
|  | 1743 |  | 
| George Rimar | efd3ffb | 2017-07-14 16:00:16 +0000 | [diff] [blame] | 1744 | static void printLibrary(raw_ostream &OS, const Twine &Tag, const Twine &Name) { | 
|  | 1745 | OS << Tag << ": [" << Name << "]"; | 
|  | 1746 | } | 
|  | 1747 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1748 | template <class ELFT> | 
|  | 1749 | void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { | 
|  | 1750 | raw_ostream &OS = W.getOStream(); | 
| Hemant Kulkarni | cb21f3c | 2016-05-12 22:16:53 +0000 | [diff] [blame] | 1751 | const char* ConvChar = (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1752 | switch (Type) { | 
|  | 1753 | case DT_PLTREL: | 
|  | 1754 | if (Value == DT_REL) { | 
|  | 1755 | OS << "REL"; | 
|  | 1756 | break; | 
|  | 1757 | } else if (Value == DT_RELA) { | 
|  | 1758 | OS << "RELA"; | 
|  | 1759 | break; | 
|  | 1760 | } | 
| Justin Bogner | b03fd12 | 2016-08-17 05:10:15 +0000 | [diff] [blame] | 1761 | LLVM_FALLTHROUGH; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1762 | case DT_PLTGOT: | 
|  | 1763 | case DT_HASH: | 
|  | 1764 | case DT_STRTAB: | 
|  | 1765 | case DT_SYMTAB: | 
|  | 1766 | case DT_RELA: | 
|  | 1767 | case DT_INIT: | 
|  | 1768 | case DT_FINI: | 
|  | 1769 | case DT_REL: | 
|  | 1770 | case DT_JMPREL: | 
|  | 1771 | case DT_INIT_ARRAY: | 
|  | 1772 | case DT_FINI_ARRAY: | 
|  | 1773 | case DT_PREINIT_ARRAY: | 
|  | 1774 | case DT_DEBUG: | 
|  | 1775 | case DT_VERDEF: | 
|  | 1776 | case DT_VERNEED: | 
|  | 1777 | case DT_VERSYM: | 
|  | 1778 | case DT_GNU_HASH: | 
|  | 1779 | case DT_NULL: | 
|  | 1780 | case DT_MIPS_BASE_ADDRESS: | 
|  | 1781 | case DT_MIPS_GOTSYM: | 
|  | 1782 | case DT_MIPS_RLD_MAP: | 
|  | 1783 | case DT_MIPS_RLD_MAP_REL: | 
|  | 1784 | case DT_MIPS_PLTGOT: | 
|  | 1785 | case DT_MIPS_OPTIONS: | 
| Hemant Kulkarni | cb21f3c | 2016-05-12 22:16:53 +0000 | [diff] [blame] | 1786 | OS << format(ConvChar, Value); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1787 | break; | 
| Davide Italiano | 8c50367 | 2016-01-16 06:06:36 +0000 | [diff] [blame] | 1788 | case DT_RELACOUNT: | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1789 | case DT_RELCOUNT: | 
|  | 1790 | case DT_VERDEFNUM: | 
|  | 1791 | case DT_VERNEEDNUM: | 
|  | 1792 | case DT_MIPS_RLD_VERSION: | 
|  | 1793 | case DT_MIPS_LOCAL_GOTNO: | 
|  | 1794 | case DT_MIPS_SYMTABNO: | 
|  | 1795 | case DT_MIPS_UNREFEXTNO: | 
|  | 1796 | OS << Value; | 
|  | 1797 | break; | 
|  | 1798 | case DT_PLTRELSZ: | 
|  | 1799 | case DT_RELASZ: | 
|  | 1800 | case DT_RELAENT: | 
|  | 1801 | case DT_STRSZ: | 
|  | 1802 | case DT_SYMENT: | 
|  | 1803 | case DT_RELSZ: | 
|  | 1804 | case DT_RELENT: | 
|  | 1805 | case DT_INIT_ARRAYSZ: | 
|  | 1806 | case DT_FINI_ARRAYSZ: | 
|  | 1807 | case DT_PREINIT_ARRAYSZ: | 
| Peter Collingbourne | 5c54f15 | 2017-10-27 17:49:40 +0000 | [diff] [blame] | 1808 | case DT_ANDROID_RELSZ: | 
|  | 1809 | case DT_ANDROID_RELASZ: | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1810 | OS << Value << " (bytes)"; | 
|  | 1811 | break; | 
|  | 1812 | case DT_NEEDED: | 
| George Rimar | efd3ffb | 2017-07-14 16:00:16 +0000 | [diff] [blame] | 1813 | printLibrary(OS, "Shared library", getDynamicString(Value)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1814 | break; | 
|  | 1815 | case DT_SONAME: | 
| George Rimar | efd3ffb | 2017-07-14 16:00:16 +0000 | [diff] [blame] | 1816 | printLibrary(OS, "Library soname", getDynamicString(Value)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1817 | break; | 
| George Rimar | d8a4eca | 2016-09-02 07:35:19 +0000 | [diff] [blame] | 1818 | case DT_AUXILIARY: | 
| George Rimar | efd3ffb | 2017-07-14 16:00:16 +0000 | [diff] [blame] | 1819 | printLibrary(OS, "Auxiliary library", getDynamicString(Value)); | 
|  | 1820 | break; | 
|  | 1821 | case DT_FILTER: | 
|  | 1822 | printLibrary(OS, "Filter library", getDynamicString(Value)); | 
| George Rimar | d8a4eca | 2016-09-02 07:35:19 +0000 | [diff] [blame] | 1823 | break; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1824 | case DT_RPATH: | 
|  | 1825 | case DT_RUNPATH: | 
|  | 1826 | OS << getDynamicString(Value); | 
|  | 1827 | break; | 
|  | 1828 | case DT_MIPS_FLAGS: | 
|  | 1829 | printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); | 
|  | 1830 | break; | 
|  | 1831 | case DT_FLAGS: | 
|  | 1832 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); | 
|  | 1833 | break; | 
|  | 1834 | case DT_FLAGS_1: | 
|  | 1835 | printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); | 
|  | 1836 | break; | 
|  | 1837 | default: | 
| Hemant Kulkarni | cb21f3c | 2016-05-12 22:16:53 +0000 | [diff] [blame] | 1838 | OS << format(ConvChar, Value); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1839 | break; | 
|  | 1840 | } | 
|  | 1841 | } | 
|  | 1842 |  | 
|  | 1843 | template<class ELFT> | 
|  | 1844 | void ELFDumper<ELFT>::printUnwindInfo() { | 
| Rafael Auler | 86fb7bf | 2018-03-08 00:46:53 +0000 | [diff] [blame] | 1845 | const unsigned Machine = Obj->getHeader()->e_machine; | 
|  | 1846 | if (Machine == EM_386 || Machine == EM_X86_64) { | 
|  | 1847 | DwarfCFIEH::PrinterContext<ELFT> Ctx(W, Obj); | 
|  | 1848 | return Ctx.printUnwindInformation(); | 
|  | 1849 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1850 | W.startLine() << "UnwindInfo not implemented.\n"; | 
|  | 1851 | } | 
|  | 1852 |  | 
|  | 1853 | namespace { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1854 |  | 
| Rui Ueyama | 1b31eb9 | 2018-01-12 01:40:32 +0000 | [diff] [blame] | 1855 | template <> void ELFDumper<ELF32LE>::printUnwindInfo() { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1856 | const unsigned Machine = Obj->getHeader()->e_machine; | 
|  | 1857 | if (Machine == EM_ARM) { | 
| Rui Ueyama | 1b31eb9 | 2018-01-12 01:40:32 +0000 | [diff] [blame] | 1858 | ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1859 | return Ctx.PrintUnwindInformation(); | 
|  | 1860 | } | 
|  | 1861 | W.startLine() << "UnwindInfo not implemented.\n"; | 
|  | 1862 | } | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1863 |  | 
|  | 1864 | } // end anonymous namespace | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1865 |  | 
|  | 1866 | template<class ELFT> | 
|  | 1867 | void ELFDumper<ELFT>::printDynamicTable() { | 
| Rafael Espindola | e17c3f3 | 2016-02-17 16:48:00 +0000 | [diff] [blame] | 1868 | auto I = dynamic_table().begin(); | 
|  | 1869 | auto E = dynamic_table().end(); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1870 |  | 
|  | 1871 | if (I == E) | 
|  | 1872 | return; | 
|  | 1873 |  | 
|  | 1874 | --E; | 
|  | 1875 | while (I != E && E->getTag() == ELF::DT_NULL) | 
|  | 1876 | --E; | 
|  | 1877 | if (E->getTag() != ELF::DT_NULL) | 
|  | 1878 | ++E; | 
|  | 1879 | ++E; | 
|  | 1880 |  | 
|  | 1881 | ptrdiff_t Total = std::distance(I, E); | 
|  | 1882 | if (Total == 0) | 
|  | 1883 | return; | 
|  | 1884 |  | 
|  | 1885 | raw_ostream &OS = W.getOStream(); | 
|  | 1886 | W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; | 
|  | 1887 |  | 
|  | 1888 | bool Is64 = ELFT::Is64Bits; | 
|  | 1889 |  | 
|  | 1890 | W.startLine() | 
|  | 1891 | << "  Tag" << (Is64 ? "                " : "        ") << "Type" | 
|  | 1892 | << "                 " << "Name/Value\n"; | 
|  | 1893 | while (I != E) { | 
|  | 1894 | const Elf_Dyn &Entry = *I; | 
|  | 1895 | uintX_t Tag = Entry.getTag(); | 
|  | 1896 | ++I; | 
| Hemant Kulkarni | cb21f3c | 2016-05-12 22:16:53 +0000 | [diff] [blame] | 1897 | W.startLine() << "  " << format_hex(Tag, Is64 ? 18 : 10, opts::Output != opts::GNU) << " " | 
| Hemant Kulkarni | e60b294 | 2016-12-27 19:59:29 +0000 | [diff] [blame] | 1898 | << format("%-21s", getTypeString(Obj->getHeader()->e_machine, Tag)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1899 | printValue(Tag, Entry.getVal()); | 
|  | 1900 | OS << "\n"; | 
|  | 1901 | } | 
|  | 1902 |  | 
|  | 1903 | W.startLine() << "]\n"; | 
|  | 1904 | } | 
|  | 1905 |  | 
|  | 1906 | template<class ELFT> | 
|  | 1907 | void ELFDumper<ELFT>::printNeededLibraries() { | 
|  | 1908 | ListScope D(W, "NeededLibraries"); | 
|  | 1909 |  | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1910 | using LibsTy = std::vector<StringRef>; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1911 | LibsTy Libs; | 
|  | 1912 |  | 
|  | 1913 | for (const auto &Entry : dynamic_table()) | 
|  | 1914 | if (Entry.d_tag == ELF::DT_NEEDED) | 
|  | 1915 | Libs.push_back(getDynamicString(Entry.d_un.d_val)); | 
|  | 1916 |  | 
|  | 1917 | std::stable_sort(Libs.begin(), Libs.end()); | 
|  | 1918 |  | 
| Sam Clegg | 88e9a15 | 2018-01-10 00:14:19 +0000 | [diff] [blame] | 1919 | for (const auto &L : Libs) | 
|  | 1920 | W.startLine() << L << "\n"; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1921 | } | 
|  | 1922 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1923 |  | 
|  | 1924 | template <typename ELFT> | 
|  | 1925 | void ELFDumper<ELFT>::printHashTable() { | 
|  | 1926 | DictScope D(W, "HashTable"); | 
|  | 1927 | if (!HashTable) | 
|  | 1928 | return; | 
|  | 1929 | W.printNumber("Num Buckets", HashTable->nbucket); | 
|  | 1930 | W.printNumber("Num Chains", HashTable->nchain); | 
|  | 1931 | W.printList("Buckets", HashTable->buckets()); | 
|  | 1932 | W.printList("Chains", HashTable->chains()); | 
|  | 1933 | } | 
|  | 1934 |  | 
|  | 1935 | template <typename ELFT> | 
|  | 1936 | void ELFDumper<ELFT>::printGnuHashTable() { | 
|  | 1937 | DictScope D(W, "GnuHashTable"); | 
|  | 1938 | if (!GnuHashTable) | 
|  | 1939 | return; | 
|  | 1940 | W.printNumber("Num Buckets", GnuHashTable->nbuckets); | 
|  | 1941 | W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); | 
|  | 1942 | W.printNumber("Num Mask Words", GnuHashTable->maskwords); | 
|  | 1943 | W.printNumber("Shift Count", GnuHashTable->shift2); | 
|  | 1944 | W.printHexList("Bloom Filter", GnuHashTable->filter()); | 
|  | 1945 | W.printList("Buckets", GnuHashTable->buckets()); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 1946 | Elf_Sym_Range Syms = dynamic_symbols(); | 
|  | 1947 | unsigned NumSyms = std::distance(Syms.begin(), Syms.end()); | 
|  | 1948 | if (!NumSyms) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1949 | reportError("No dynamic symbol section"); | 
| Rafael Espindola | ce2fbdd | 2016-02-17 15:38:21 +0000 | [diff] [blame] | 1950 | W.printHexList("Values", GnuHashTable->values(NumSyms)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1951 | } | 
|  | 1952 |  | 
|  | 1953 | template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { | 
| Sam Clegg | 88e9a15 | 2018-01-10 00:14:19 +0000 | [diff] [blame] | 1954 | W.printString("LoadName", SOName); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1955 | } | 
|  | 1956 |  | 
|  | 1957 | template <class ELFT> | 
|  | 1958 | void ELFDumper<ELFT>::printAttributes() { | 
|  | 1959 | W.startLine() << "Attributes not implemented.\n"; | 
|  | 1960 | } | 
|  | 1961 |  | 
|  | 1962 | namespace { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1963 |  | 
| Rui Ueyama | 1b31eb9 | 2018-01-12 01:40:32 +0000 | [diff] [blame] | 1964 | template <> void ELFDumper<ELF32LE>::printAttributes() { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1965 | if (Obj->getHeader()->e_machine != EM_ARM) { | 
|  | 1966 | W.startLine() << "Attributes not implemented.\n"; | 
|  | 1967 | return; | 
|  | 1968 | } | 
|  | 1969 |  | 
|  | 1970 | DictScope BA(W, "BuildAttributes"); | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 1971 | for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1972 | if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) | 
|  | 1973 | continue; | 
|  | 1974 |  | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 1975 | ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec)); | 
|  | 1976 | if (Contents[0] != ARMBuildAttrs::Format_Version) { | 
| Benjamin Kramer | 3a13ed6 | 2017-12-28 16:58:54 +0000 | [diff] [blame] | 1977 | errs() << "unrecognised FormatVersion: 0x" | 
|  | 1978 | << Twine::utohexstr(Contents[0]) << '\n'; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1979 | continue; | 
|  | 1980 | } | 
|  | 1981 |  | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 1982 | W.printHex("FormatVersion", Contents[0]); | 
|  | 1983 | if (Contents.size() == 1) | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1984 | continue; | 
|  | 1985 |  | 
| Sam Parker | df7c6ef | 2017-01-18 13:52:12 +0000 | [diff] [blame] | 1986 | ARMAttributeParser(&W).Parse(Contents, true); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1987 | } | 
|  | 1988 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1989 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1990 | template <class ELFT> class MipsGOTParser { | 
|  | 1991 | public: | 
| Rafael Espindola | 6bc2990 | 2016-10-06 14:07:26 +0000 | [diff] [blame] | 1992 | TYPEDEF_ELF_TYPES(ELFT) | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 1993 | using Entry = typename ELFO::Elf_Addr; | 
|  | 1994 | using Entries = ArrayRef<Entry>; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 1995 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 1996 | const bool IsStatic; | 
|  | 1997 | const ELFO * const Obj; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 1998 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 1999 | MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms); | 
|  | 2000 |  | 
|  | 2001 | bool hasGot() const { return !GotEntries.empty(); } | 
|  | 2002 | bool hasPlt() const { return !PltEntries.empty(); } | 
|  | 2003 |  | 
|  | 2004 | uint64_t getGp() const; | 
|  | 2005 |  | 
|  | 2006 | const Entry *getGotLazyResolver() const; | 
|  | 2007 | const Entry *getGotModulePointer() const; | 
|  | 2008 | const Entry *getPltLazyResolver() const; | 
|  | 2009 | const Entry *getPltModulePointer() const; | 
|  | 2010 |  | 
|  | 2011 | Entries getLocalEntries() const; | 
|  | 2012 | Entries getGlobalEntries() const; | 
|  | 2013 | Entries getOtherEntries() const; | 
|  | 2014 | Entries getPltEntries() const; | 
|  | 2015 |  | 
|  | 2016 | uint64_t getGotAddress(const Entry * E) const; | 
|  | 2017 | int64_t getGotOffset(const Entry * E) const; | 
|  | 2018 | const Elf_Sym *getGotSym(const Entry *E) const; | 
|  | 2019 |  | 
|  | 2020 | uint64_t getPltAddress(const Entry * E) const; | 
|  | 2021 | const Elf_Sym *getPltSym(const Entry *E) const; | 
|  | 2022 |  | 
|  | 2023 | StringRef getPltStrTable() const { return PltStrTable; } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2024 |  | 
|  | 2025 | private: | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2026 | const Elf_Shdr *GotSec; | 
|  | 2027 | size_t LocalNum; | 
|  | 2028 | size_t GlobalNum; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2029 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2030 | const Elf_Shdr *PltSec; | 
|  | 2031 | const Elf_Shdr *PltRelSec; | 
|  | 2032 | const Elf_Shdr *PltSymTable; | 
|  | 2033 | Elf_Sym_Range GotDynSyms; | 
|  | 2034 | StringRef PltStrTable; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2035 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2036 | Entries GotEntries; | 
|  | 2037 | Entries PltEntries; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2038 | }; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 2039 |  | 
|  | 2040 | } // end anonymous namespace | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2041 |  | 
|  | 2042 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2043 | MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, | 
|  | 2044 | Elf_Sym_Range DynSyms) | 
|  | 2045 | : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0), | 
|  | 2046 | GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) { | 
|  | 2047 | // See "Global Offset Table" in Chapter 5 in the following document | 
|  | 2048 | // for detailed GOT description. | 
|  | 2049 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 
|  | 2050 |  | 
|  | 2051 | // Find static GOT secton. | 
|  | 2052 | if (IsStatic) { | 
|  | 2053 | GotSec = findSectionByName(*Obj, ".got"); | 
|  | 2054 | if (!GotSec) | 
|  | 2055 | reportError("Cannot find .got section"); | 
|  | 2056 |  | 
|  | 2057 | ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); | 
|  | 2058 | GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), | 
|  | 2059 | Content.size() / sizeof(Entry)); | 
|  | 2060 | LocalNum = GotEntries.size(); | 
|  | 2061 | return; | 
|  | 2062 | } | 
|  | 2063 |  | 
|  | 2064 | // Lookup dynamic table tags which define GOT/PLT layouts. | 
|  | 2065 | Optional<uint64_t> DtPltGot; | 
|  | 2066 | Optional<uint64_t> DtLocalGotNum; | 
|  | 2067 | Optional<uint64_t> DtGotSym; | 
|  | 2068 | Optional<uint64_t> DtMipsPltGot; | 
|  | 2069 | Optional<uint64_t> DtJmpRel; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2070 | for (const auto &Entry : DynTable) { | 
|  | 2071 | switch (Entry.getTag()) { | 
|  | 2072 | case ELF::DT_PLTGOT: | 
|  | 2073 | DtPltGot = Entry.getVal(); | 
|  | 2074 | break; | 
|  | 2075 | case ELF::DT_MIPS_LOCAL_GOTNO: | 
|  | 2076 | DtLocalGotNum = Entry.getVal(); | 
|  | 2077 | break; | 
|  | 2078 | case ELF::DT_MIPS_GOTSYM: | 
|  | 2079 | DtGotSym = Entry.getVal(); | 
|  | 2080 | break; | 
|  | 2081 | case ELF::DT_MIPS_PLTGOT: | 
|  | 2082 | DtMipsPltGot = Entry.getVal(); | 
|  | 2083 | break; | 
|  | 2084 | case ELF::DT_JMPREL: | 
|  | 2085 | DtJmpRel = Entry.getVal(); | 
|  | 2086 | break; | 
|  | 2087 | } | 
|  | 2088 | } | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2089 |  | 
|  | 2090 | // Find dynamic GOT section. | 
|  | 2091 | if (DtPltGot || DtLocalGotNum || DtGotSym) { | 
|  | 2092 | if (!DtPltGot) | 
|  | 2093 | report_fatal_error("Cannot find PLTGOT dynamic table tag."); | 
|  | 2094 | if (!DtLocalGotNum) | 
|  | 2095 | report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag."); | 
|  | 2096 | if (!DtGotSym) | 
|  | 2097 | report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag."); | 
|  | 2098 |  | 
|  | 2099 | size_t DynSymTotal = DynSyms.size(); | 
|  | 2100 | if (*DtGotSym > DynSymTotal) | 
|  | 2101 | reportError("MIPS_GOTSYM exceeds a number of dynamic symbols"); | 
|  | 2102 |  | 
|  | 2103 | GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot); | 
|  | 2104 | if (!GotSec) | 
|  | 2105 | reportError("There is no not empty GOT section at 0x" + | 
|  | 2106 | Twine::utohexstr(*DtPltGot)); | 
|  | 2107 |  | 
|  | 2108 | LocalNum = *DtLocalGotNum; | 
|  | 2109 | GlobalNum = DynSymTotal - *DtGotSym; | 
|  | 2110 |  | 
|  | 2111 | ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec)); | 
|  | 2112 | GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()), | 
|  | 2113 | Content.size() / sizeof(Entry)); | 
|  | 2114 | GotDynSyms = DynSyms.drop_front(*DtGotSym); | 
|  | 2115 | } | 
|  | 2116 |  | 
|  | 2117 | // Find PLT section. | 
|  | 2118 | if (DtMipsPltGot || DtJmpRel) { | 
|  | 2119 | if (!DtMipsPltGot) | 
|  | 2120 | report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag."); | 
|  | 2121 | if (!DtJmpRel) | 
|  | 2122 | report_fatal_error("Cannot find JMPREL dynamic table tag."); | 
|  | 2123 |  | 
|  | 2124 | PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot); | 
|  | 2125 | if (!PltSec) | 
|  | 2126 | report_fatal_error("There is no not empty PLTGOT section at 0x " + | 
|  | 2127 | Twine::utohexstr(*DtMipsPltGot)); | 
|  | 2128 |  | 
|  | 2129 | PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel); | 
|  | 2130 | if (!PltRelSec) | 
|  | 2131 | report_fatal_error("There is no not empty RELPLT section at 0x" + | 
|  | 2132 | Twine::utohexstr(*DtJmpRel)); | 
|  | 2133 |  | 
|  | 2134 | ArrayRef<uint8_t> PltContent = | 
|  | 2135 | unwrapOrError(Obj->getSectionContents(PltSec)); | 
|  | 2136 | PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()), | 
|  | 2137 | PltContent.size() / sizeof(Entry)); | 
|  | 2138 |  | 
|  | 2139 | PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link)); | 
|  | 2140 | PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable)); | 
|  | 2141 | } | 
|  | 2142 | } | 
|  | 2143 |  | 
|  | 2144 | template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const { | 
|  | 2145 | return GotSec->sh_addr + 0x7ff0; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2146 | } | 
|  | 2147 |  | 
| Simon Atanasyan | d4b693b | 2017-12-02 13:06:35 +0000 | [diff] [blame] | 2148 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2149 | const typename MipsGOTParser<ELFT>::Entry * | 
|  | 2150 | MipsGOTParser<ELFT>::getGotLazyResolver() const { | 
|  | 2151 | return LocalNum > 0 ? &GotEntries[0] : nullptr; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2152 | } | 
|  | 2153 |  | 
|  | 2154 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2155 | const typename MipsGOTParser<ELFT>::Entry * | 
|  | 2156 | MipsGOTParser<ELFT>::getGotModulePointer() const { | 
|  | 2157 | if (LocalNum < 2) | 
|  | 2158 | return nullptr; | 
|  | 2159 | const Entry &E = GotEntries[1]; | 
|  | 2160 | if ((E >> (sizeof(Entry) * 8 - 1)) == 0) | 
|  | 2161 | return nullptr; | 
|  | 2162 | return &E; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2163 | } | 
|  | 2164 |  | 
|  | 2165 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2166 | typename MipsGOTParser<ELFT>::Entries | 
|  | 2167 | MipsGOTParser<ELFT>::getLocalEntries() const { | 
|  | 2168 | size_t Skip = getGotModulePointer() ? 2 : 1; | 
|  | 2169 | if (LocalNum - Skip <= 0) | 
|  | 2170 | return Entries(); | 
|  | 2171 | return GotEntries.slice(Skip, LocalNum - Skip); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2172 | } | 
|  | 2173 |  | 
|  | 2174 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2175 | typename MipsGOTParser<ELFT>::Entries | 
|  | 2176 | MipsGOTParser<ELFT>::getGlobalEntries() const { | 
|  | 2177 | if (GlobalNum == 0) | 
|  | 2178 | return Entries(); | 
|  | 2179 | return GotEntries.slice(LocalNum, GlobalNum); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2180 | } | 
|  | 2181 |  | 
|  | 2182 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2183 | typename MipsGOTParser<ELFT>::Entries | 
|  | 2184 | MipsGOTParser<ELFT>::getOtherEntries() const { | 
|  | 2185 | size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum; | 
|  | 2186 | if (OtherNum == 0) | 
|  | 2187 | return Entries(); | 
|  | 2188 | return GotEntries.slice(LocalNum + GlobalNum, OtherNum); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2189 | } | 
|  | 2190 |  | 
|  | 2191 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2192 | uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const { | 
|  | 2193 | int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); | 
|  | 2194 | return GotSec->sh_addr + Offset; | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2195 | } | 
|  | 2196 |  | 
|  | 2197 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2198 | int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const { | 
|  | 2199 | int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry); | 
|  | 2200 | return Offset - 0x7ff0; | 
|  | 2201 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2202 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2203 | template <class ELFT> | 
|  | 2204 | const typename MipsGOTParser<ELFT>::Elf_Sym * | 
|  | 2205 | MipsGOTParser<ELFT>::getGotSym(const Entry *E) const { | 
|  | 2206 | int64_t Offset = std::distance(GotEntries.data(), E); | 
|  | 2207 | return &GotDynSyms[Offset - LocalNum]; | 
|  | 2208 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2209 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2210 | template <class ELFT> | 
|  | 2211 | const typename MipsGOTParser<ELFT>::Entry * | 
|  | 2212 | MipsGOTParser<ELFT>::getPltLazyResolver() const { | 
|  | 2213 | return PltEntries.empty() ? nullptr : &PltEntries[0]; | 
|  | 2214 | } | 
|  | 2215 |  | 
|  | 2216 | template <class ELFT> | 
|  | 2217 | const typename MipsGOTParser<ELFT>::Entry * | 
|  | 2218 | MipsGOTParser<ELFT>::getPltModulePointer() const { | 
|  | 2219 | return PltEntries.size() < 2 ? nullptr : &PltEntries[1]; | 
|  | 2220 | } | 
|  | 2221 |  | 
|  | 2222 | template <class ELFT> | 
|  | 2223 | typename MipsGOTParser<ELFT>::Entries | 
|  | 2224 | MipsGOTParser<ELFT>::getPltEntries() const { | 
|  | 2225 | if (PltEntries.size() <= 2) | 
|  | 2226 | return Entries(); | 
|  | 2227 | return PltEntries.slice(2, PltEntries.size() - 2); | 
|  | 2228 | } | 
|  | 2229 |  | 
|  | 2230 | template <class ELFT> | 
|  | 2231 | uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const { | 
|  | 2232 | int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry); | 
|  | 2233 | return PltSec->sh_addr + Offset; | 
|  | 2234 | } | 
|  | 2235 |  | 
|  | 2236 | template <class ELFT> | 
|  | 2237 | const typename MipsGOTParser<ELFT>::Elf_Sym * | 
|  | 2238 | MipsGOTParser<ELFT>::getPltSym(const Entry *E) const { | 
|  | 2239 | int64_t Offset = std::distance(getPltEntries().data(), E); | 
|  | 2240 | if (PltRelSec->sh_type == ELF::SHT_REL) { | 
|  | 2241 | Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec)); | 
|  | 2242 | return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); | 
|  | 2243 | } else { | 
|  | 2244 | Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec)); | 
|  | 2245 | return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable)); | 
|  | 2246 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2247 | } | 
|  | 2248 |  | 
|  | 2249 | template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2250 | if (Obj->getHeader()->e_machine != EM_MIPS) | 
|  | 2251 | reportError("MIPS PLT GOT is available for MIPS targets only"); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2252 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 2253 | MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols()); | 
|  | 2254 | if (Parser.hasGot()) | 
|  | 2255 | ELFDumperStyle->printMipsGOT(Parser); | 
|  | 2256 | if (Parser.hasPlt()) | 
|  | 2257 | ELFDumperStyle->printMipsPLT(Parser); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2258 | } | 
|  | 2259 |  | 
|  | 2260 | static const EnumEntry<unsigned> ElfMipsISAExtType[] = { | 
|  | 2261 | {"None",                    Mips::AFL_EXT_NONE}, | 
|  | 2262 | {"Broadcom SB-1",           Mips::AFL_EXT_SB1}, | 
|  | 2263 | {"Cavium Networks Octeon",  Mips::AFL_EXT_OCTEON}, | 
|  | 2264 | {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2}, | 
|  | 2265 | {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP}, | 
|  | 2266 | {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3}, | 
|  | 2267 | {"LSI R4010",               Mips::AFL_EXT_4010}, | 
|  | 2268 | {"Loongson 2E",             Mips::AFL_EXT_LOONGSON_2E}, | 
|  | 2269 | {"Loongson 2F",             Mips::AFL_EXT_LOONGSON_2F}, | 
|  | 2270 | {"Loongson 3A",             Mips::AFL_EXT_LOONGSON_3A}, | 
|  | 2271 | {"MIPS R4650",              Mips::AFL_EXT_4650}, | 
|  | 2272 | {"MIPS R5900",              Mips::AFL_EXT_5900}, | 
|  | 2273 | {"MIPS R10000",             Mips::AFL_EXT_10000}, | 
|  | 2274 | {"NEC VR4100",              Mips::AFL_EXT_4100}, | 
|  | 2275 | {"NEC VR4111/VR4181",       Mips::AFL_EXT_4111}, | 
|  | 2276 | {"NEC VR4120",              Mips::AFL_EXT_4120}, | 
|  | 2277 | {"NEC VR5400",              Mips::AFL_EXT_5400}, | 
|  | 2278 | {"NEC VR5500",              Mips::AFL_EXT_5500}, | 
|  | 2279 | {"RMI Xlr",                 Mips::AFL_EXT_XLR}, | 
|  | 2280 | {"Toshiba R3900",           Mips::AFL_EXT_3900} | 
|  | 2281 | }; | 
|  | 2282 |  | 
|  | 2283 | static const EnumEntry<unsigned> ElfMipsASEFlags[] = { | 
|  | 2284 | {"DSP",                Mips::AFL_ASE_DSP}, | 
|  | 2285 | {"DSPR2",              Mips::AFL_ASE_DSPR2}, | 
|  | 2286 | {"Enhanced VA Scheme", Mips::AFL_ASE_EVA}, | 
|  | 2287 | {"MCU",                Mips::AFL_ASE_MCU}, | 
|  | 2288 | {"MDMX",               Mips::AFL_ASE_MDMX}, | 
|  | 2289 | {"MIPS-3D",            Mips::AFL_ASE_MIPS3D}, | 
|  | 2290 | {"MT",                 Mips::AFL_ASE_MT}, | 
|  | 2291 | {"SmartMIPS",          Mips::AFL_ASE_SMARTMIPS}, | 
|  | 2292 | {"VZ",                 Mips::AFL_ASE_VIRT}, | 
|  | 2293 | {"MSA",                Mips::AFL_ASE_MSA}, | 
|  | 2294 | {"MIPS16",             Mips::AFL_ASE_MIPS16}, | 
|  | 2295 | {"microMIPS",          Mips::AFL_ASE_MICROMIPS}, | 
| Petar Jovanovic | 3408caf | 2018-03-14 14:13:31 +0000 | [diff] [blame] | 2296 | {"XPA",                Mips::AFL_ASE_XPA}, | 
|  | 2297 | {"CRC",                Mips::AFL_ASE_CRC}, | 
| Petar Jovanovic | daf5169 | 2018-05-17 16:30:32 +0000 | [diff] [blame] | 2298 | {"GINV",               Mips::AFL_ASE_GINV}, | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2299 | }; | 
|  | 2300 |  | 
|  | 2301 | static const EnumEntry<unsigned> ElfMipsFpABIType[] = { | 
|  | 2302 | {"Hard or soft float",                  Mips::Val_GNU_MIPS_ABI_FP_ANY}, | 
|  | 2303 | {"Hard float (double precision)",       Mips::Val_GNU_MIPS_ABI_FP_DOUBLE}, | 
|  | 2304 | {"Hard float (single precision)",       Mips::Val_GNU_MIPS_ABI_FP_SINGLE}, | 
|  | 2305 | {"Soft float",                          Mips::Val_GNU_MIPS_ABI_FP_SOFT}, | 
|  | 2306 | {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)", | 
|  | 2307 | Mips::Val_GNU_MIPS_ABI_FP_OLD_64}, | 
|  | 2308 | {"Hard float (32-bit CPU, Any FPU)",    Mips::Val_GNU_MIPS_ABI_FP_XX}, | 
|  | 2309 | {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64}, | 
|  | 2310 | {"Hard float compat (32-bit CPU, 64-bit FPU)", | 
|  | 2311 | Mips::Val_GNU_MIPS_ABI_FP_64A} | 
|  | 2312 | }; | 
|  | 2313 |  | 
|  | 2314 | static const EnumEntry<unsigned> ElfMipsFlags1[] { | 
|  | 2315 | {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG}, | 
|  | 2316 | }; | 
|  | 2317 |  | 
|  | 2318 | static int getMipsRegisterSize(uint8_t Flag) { | 
|  | 2319 | switch (Flag) { | 
|  | 2320 | case Mips::AFL_REG_NONE: | 
|  | 2321 | return 0; | 
|  | 2322 | case Mips::AFL_REG_32: | 
|  | 2323 | return 32; | 
|  | 2324 | case Mips::AFL_REG_64: | 
|  | 2325 | return 64; | 
|  | 2326 | case Mips::AFL_REG_128: | 
|  | 2327 | return 128; | 
|  | 2328 | default: | 
|  | 2329 | return -1; | 
|  | 2330 | } | 
|  | 2331 | } | 
|  | 2332 |  | 
|  | 2333 | template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() { | 
|  | 2334 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags"); | 
|  | 2335 | if (!Shdr) { | 
|  | 2336 | W.startLine() << "There is no .MIPS.abiflags section in the file.\n"; | 
|  | 2337 | return; | 
|  | 2338 | } | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 2339 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | 
|  | 2340 | if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2341 | W.startLine() << "The .MIPS.abiflags section has a wrong size.\n"; | 
|  | 2342 | return; | 
|  | 2343 | } | 
|  | 2344 |  | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 2345 | auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data()); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2346 |  | 
|  | 2347 | raw_ostream &OS = W.getOStream(); | 
|  | 2348 | DictScope GS(W, "MIPS ABI Flags"); | 
|  | 2349 |  | 
|  | 2350 | W.printNumber("Version", Flags->version); | 
|  | 2351 | W.startLine() << "ISA: "; | 
|  | 2352 | if (Flags->isa_rev <= 1) | 
|  | 2353 | OS << format("MIPS%u", Flags->isa_level); | 
|  | 2354 | else | 
|  | 2355 | OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev); | 
|  | 2356 | OS << "\n"; | 
|  | 2357 | W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)); | 
|  | 2358 | W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags)); | 
|  | 2359 | W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)); | 
|  | 2360 | W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size)); | 
|  | 2361 | W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size)); | 
|  | 2362 | W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size)); | 
|  | 2363 | W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1)); | 
|  | 2364 | W.printHex("Flags 2", Flags->flags2); | 
|  | 2365 | } | 
|  | 2366 |  | 
| Simon Atanasyan | 8a71b53 | 2016-05-04 05:58:57 +0000 | [diff] [blame] | 2367 | template <class ELFT> | 
|  | 2368 | static void printMipsReginfoData(ScopedPrinter &W, | 
|  | 2369 | const Elf_Mips_RegInfo<ELFT> &Reginfo) { | 
|  | 2370 | W.printHex("GP", Reginfo.ri_gp_value); | 
|  | 2371 | W.printHex("General Mask", Reginfo.ri_gprmask); | 
|  | 2372 | W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]); | 
|  | 2373 | W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]); | 
|  | 2374 | W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]); | 
|  | 2375 | W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]); | 
|  | 2376 | } | 
|  | 2377 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2378 | template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() { | 
|  | 2379 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo"); | 
|  | 2380 | if (!Shdr) { | 
|  | 2381 | W.startLine() << "There is no .reginfo section in the file.\n"; | 
|  | 2382 | return; | 
|  | 2383 | } | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 2384 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | 
|  | 2385 | if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2386 | W.startLine() << "The .reginfo section has a wrong size.\n"; | 
|  | 2387 | return; | 
|  | 2388 | } | 
|  | 2389 |  | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2390 | DictScope GS(W, "MIPS RegInfo"); | 
| Simon Atanasyan | 8a71b53 | 2016-05-04 05:58:57 +0000 | [diff] [blame] | 2391 | auto *Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Sec.data()); | 
|  | 2392 | printMipsReginfoData(W, *Reginfo); | 
|  | 2393 | } | 
|  | 2394 |  | 
|  | 2395 | template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { | 
|  | 2396 | const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.options"); | 
|  | 2397 | if (!Shdr) { | 
|  | 2398 | W.startLine() << "There is no .MIPS.options section in the file.\n"; | 
|  | 2399 | return; | 
|  | 2400 | } | 
|  | 2401 |  | 
|  | 2402 | DictScope GS(W, "MIPS Options"); | 
|  | 2403 |  | 
|  | 2404 | ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); | 
|  | 2405 | while (!Sec.empty()) { | 
|  | 2406 | if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) { | 
|  | 2407 | W.startLine() << "The .MIPS.options section has a wrong size.\n"; | 
|  | 2408 | return; | 
|  | 2409 | } | 
|  | 2410 | auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(Sec.data()); | 
|  | 2411 | DictScope GS(W, getElfMipsOptionsOdkType(O->kind)); | 
|  | 2412 | switch (O->kind) { | 
|  | 2413 | case ODK_REGINFO: | 
|  | 2414 | printMipsReginfoData(W, O->getRegInfo()); | 
|  | 2415 | break; | 
|  | 2416 | default: | 
|  | 2417 | W.startLine() << "Unsupported MIPS options tag.\n"; | 
|  | 2418 | break; | 
|  | 2419 | } | 
|  | 2420 | Sec = Sec.slice(O->size); | 
|  | 2421 | } | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2422 | } | 
|  | 2423 |  | 
|  | 2424 | template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { | 
|  | 2425 | const Elf_Shdr *StackMapSection = nullptr; | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 2426 | for (const auto &Sec : unwrapOrError(Obj->sections())) { | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 2427 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 2428 | if (Name == ".llvm_stackmaps") { | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2429 | StackMapSection = &Sec; | 
|  | 2430 | break; | 
|  | 2431 | } | 
|  | 2432 | } | 
|  | 2433 |  | 
|  | 2434 | if (!StackMapSection) | 
|  | 2435 | return; | 
|  | 2436 |  | 
| Rafael Espindola | f04f184 | 2016-02-17 16:21:49 +0000 | [diff] [blame] | 2437 | ArrayRef<uint8_t> StackMapContentsArray = | 
|  | 2438 | unwrapOrError(Obj->getSectionContents(StackMapSection)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2439 |  | 
| Sam Clegg | 88e9a15 | 2018-01-10 00:14:19 +0000 | [diff] [blame] | 2440 | prettyPrintStackMap( | 
|  | 2441 | W, StackMapV2Parser<ELFT::TargetEndianness>(StackMapContentsArray)); | 
| George Rimar | 4793676 | 2016-01-16 00:49:19 +0000 | [diff] [blame] | 2442 | } | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2443 |  | 
| Hemant Kulkarni | ab4a46f | 2016-01-26 19:46:39 +0000 | [diff] [blame] | 2444 | template <class ELFT> void ELFDumper<ELFT>::printGroupSections() { | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 2445 | ELFDumperStyle->printGroupSections(Obj); | 
| Hemant Kulkarni | ab4a46f | 2016-01-26 19:46:39 +0000 | [diff] [blame] | 2446 | } | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2447 |  | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 2448 | template <class ELFT> void ELFDumper<ELFT>::printAddrsig() { | 
|  | 2449 | ELFDumperStyle->printAddrsig(Obj); | 
|  | 2450 | } | 
|  | 2451 |  | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2452 | static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, | 
|  | 2453 | StringRef Str2) { | 
|  | 2454 | OS.PadToColumn(2u); | 
|  | 2455 | OS << Str1; | 
|  | 2456 | OS.PadToColumn(37u); | 
|  | 2457 | OS << Str2 << "\n"; | 
|  | 2458 | OS.flush(); | 
|  | 2459 | } | 
|  | 2460 |  | 
| George Rimar | 6fdac3b | 2018-07-18 08:19:58 +0000 | [diff] [blame] | 2461 | template <class ELFT> | 
|  | 2462 | static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) { | 
|  | 2463 | const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); | 
|  | 2464 | if (ElfHeader->e_shnum != 0) | 
|  | 2465 | return to_string(ElfHeader->e_shnum); | 
|  | 2466 |  | 
|  | 2467 | ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); | 
|  | 2468 | if (Arr.empty()) | 
|  | 2469 | return "0"; | 
|  | 2470 | return "0 (" + to_string(Arr[0].sh_size) + ")"; | 
|  | 2471 | } | 
|  | 2472 |  | 
|  | 2473 | template <class ELFT> | 
|  | 2474 | static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) { | 
|  | 2475 | const typename ELFT::Ehdr *ElfHeader = Obj->getHeader(); | 
|  | 2476 | if (ElfHeader->e_shstrndx != SHN_XINDEX) | 
|  | 2477 | return to_string(ElfHeader->e_shstrndx); | 
|  | 2478 |  | 
|  | 2479 | ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections()); | 
|  | 2480 | if (Arr.empty()) | 
|  | 2481 | return "65535 (corrupt: out of range)"; | 
|  | 2482 | return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) + ")"; | 
|  | 2483 | } | 
|  | 2484 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2485 | template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2486 | const Elf_Ehdr *e = Obj->getHeader(); | 
|  | 2487 | OS << "ELF Header:\n"; | 
|  | 2488 | OS << "  Magic:  "; | 
|  | 2489 | std::string Str; | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2490 | for (int i = 0; i < ELF::EI_NIDENT; i++) | 
|  | 2491 | OS << format(" %02x", static_cast<int>(e->e_ident[i])); | 
|  | 2492 | OS << "\n"; | 
|  | 2493 | Str = printEnum(e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2494 | printFields(OS, "Class:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2495 | Str = printEnum(e->e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding)); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2496 | printFields(OS, "Data:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2497 | OS.PadToColumn(2u); | 
|  | 2498 | OS << "Version:"; | 
|  | 2499 | OS.PadToColumn(37u); | 
|  | 2500 | OS << to_hexString(e->e_ident[ELF::EI_VERSION]); | 
|  | 2501 | if (e->e_version == ELF::EV_CURRENT) | 
|  | 2502 | OS << " (current)"; | 
|  | 2503 | OS << "\n"; | 
|  | 2504 | Str = printEnum(e->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI)); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2505 | printFields(OS, "OS/ABI:", Str); | 
| Chandler Carruth | e8fa5ae | 2016-11-03 17:11:11 +0000 | [diff] [blame] | 2506 | Str = "0x" + to_hexString(e->e_ident[ELF::EI_ABIVERSION]); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2507 | printFields(OS, "ABI Version:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2508 | Str = printEnum(e->e_type, makeArrayRef(ElfObjectFileType)); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2509 | printFields(OS, "Type:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2510 | Str = printEnum(e->e_machine, makeArrayRef(ElfMachineType)); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2511 | printFields(OS, "Machine:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2512 | Str = "0x" + to_hexString(e->e_version); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2513 | printFields(OS, "Version:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2514 | Str = "0x" + to_hexString(e->e_entry); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2515 | printFields(OS, "Entry point address:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2516 | Str = to_string(e->e_phoff) + " (bytes into file)"; | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2517 | printFields(OS, "Start of program headers:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2518 | Str = to_string(e->e_shoff) + " (bytes into file)"; | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2519 | printFields(OS, "Start of section headers:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2520 | Str = "0x" + to_hexString(e->e_flags); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2521 | printFields(OS, "Flags:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2522 | Str = to_string(e->e_ehsize) + " (bytes)"; | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2523 | printFields(OS, "Size of this header:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2524 | Str = to_string(e->e_phentsize) + " (bytes)"; | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2525 | printFields(OS, "Size of program headers:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2526 | Str = to_string(e->e_phnum); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2527 | printFields(OS, "Number of program headers:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2528 | Str = to_string(e->e_shentsize) + " (bytes)"; | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2529 | printFields(OS, "Size of section headers:", Str); | 
| George Rimar | 6fdac3b | 2018-07-18 08:19:58 +0000 | [diff] [blame] | 2530 | Str = getSectionHeadersNumString(Obj); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2531 | printFields(OS, "Number of section headers:", Str); | 
| George Rimar | 6fdac3b | 2018-07-18 08:19:58 +0000 | [diff] [blame] | 2532 | Str = getSectionHeaderTableIndexString(Obj); | 
| Hemant Kulkarni | f84cda7 | 2016-02-11 03:41:34 +0000 | [diff] [blame] | 2533 | printFields(OS, "Section header string table index:", Str); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2534 | } | 
|  | 2535 |  | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2536 | namespace { | 
|  | 2537 | struct GroupMember { | 
|  | 2538 | StringRef Name; | 
|  | 2539 | uint64_t Index; | 
|  | 2540 | }; | 
|  | 2541 |  | 
|  | 2542 | struct GroupSection { | 
|  | 2543 | StringRef Name; | 
|  | 2544 | StringRef Signature; | 
|  | 2545 | uint64_t ShName; | 
|  | 2546 | uint64_t Index; | 
| Alexander Shaposhnikov | 8febe3d | 2018-03-12 22:40:09 +0000 | [diff] [blame] | 2547 | uint32_t Link; | 
|  | 2548 | uint32_t Info; | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2549 | uint32_t Type; | 
|  | 2550 | std::vector<GroupMember> Members; | 
|  | 2551 | }; | 
|  | 2552 |  | 
|  | 2553 | template <class ELFT> | 
|  | 2554 | std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) { | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 2555 | using Elf_Shdr = typename ELFT::Shdr; | 
|  | 2556 | using Elf_Sym = typename ELFT::Sym; | 
|  | 2557 | using Elf_Word = typename ELFT::Word; | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2558 |  | 
|  | 2559 | std::vector<GroupSection> Ret; | 
|  | 2560 | uint64_t I = 0; | 
| George Rimar | 3c0f396 | 2017-09-14 07:26:14 +0000 | [diff] [blame] | 2561 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2562 | ++I; | 
|  | 2563 | if (Sec.sh_type != ELF::SHT_GROUP) | 
|  | 2564 | continue; | 
|  | 2565 |  | 
|  | 2566 | const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); | 
|  | 2567 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); | 
|  | 2568 | const Elf_Sym *Sym = | 
|  | 2569 | unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info)); | 
|  | 2570 | auto Data = | 
|  | 2571 | unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec)); | 
|  | 2572 |  | 
|  | 2573 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 2574 | StringRef Signature = StrTable.data() + Sym->st_name; | 
| Alexander Shaposhnikov | 8febe3d | 2018-03-12 22:40:09 +0000 | [diff] [blame] | 2575 | Ret.push_back({Name, | 
|  | 2576 | Signature, | 
|  | 2577 | Sec.sh_name, | 
|  | 2578 | I - 1, | 
|  | 2579 | Sec.sh_link, | 
|  | 2580 | Sec.sh_info, | 
|  | 2581 | Data[0], | 
|  | 2582 | {}}); | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2583 |  | 
|  | 2584 | std::vector<GroupMember> &GM = Ret.back().Members; | 
|  | 2585 | for (uint32_t Ndx : Data.slice(1)) { | 
|  | 2586 | auto Sec = unwrapOrError(Obj->getSection(Ndx)); | 
|  | 2587 | const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); | 
|  | 2588 | GM.push_back({Name, Ndx}); | 
| George Rimar | 3c0f396 | 2017-09-14 07:26:14 +0000 | [diff] [blame] | 2589 | } | 
| George Rimar | c2657cd | 2017-09-14 07:17:04 +0000 | [diff] [blame] | 2590 | } | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2591 | return Ret; | 
|  | 2592 | } | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 2593 |  | 
|  | 2594 | DenseMap<uint64_t, const GroupSection *> | 
|  | 2595 | mapSectionsToGroups(ArrayRef<GroupSection> Groups) { | 
|  | 2596 | DenseMap<uint64_t, const GroupSection *> Ret; | 
|  | 2597 | for (const GroupSection &G : Groups) | 
|  | 2598 | for (const GroupMember &GM : G.Members) | 
|  | 2599 | Ret.insert({GM.Index, &G}); | 
|  | 2600 | return Ret; | 
|  | 2601 | } | 
|  | 2602 |  | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2603 | } // namespace | 
|  | 2604 |  | 
|  | 2605 | template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) { | 
|  | 2606 | std::vector<GroupSection> V = getGroups<ELFT>(Obj); | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 2607 | DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2608 | for (const GroupSection &G : V) { | 
|  | 2609 | OS << "\n" | 
|  | 2610 | << getGroupType(G.Type) << " group section [" | 
|  | 2611 | << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature | 
|  | 2612 | << "] contains " << G.Members.size() << " sections:\n" | 
|  | 2613 | << "   [Index]    Name\n"; | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 2614 | for (const GroupMember &GM : G.Members) { | 
|  | 2615 | const GroupSection *MainGroup = Map[GM.Index]; | 
|  | 2616 | if (MainGroup != &G) { | 
|  | 2617 | OS.flush(); | 
|  | 2618 | errs() << "Error: section [" << format_decimal(GM.Index, 5) | 
|  | 2619 | << "] in group section [" << format_decimal(G.Index, 5) | 
|  | 2620 | << "] already in group section [" | 
|  | 2621 | << format_decimal(MainGroup->Index, 5) << "]"; | 
|  | 2622 | errs().flush(); | 
|  | 2623 | continue; | 
|  | 2624 | } | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2625 | OS << "   [" << format_decimal(GM.Index, 5) << "]   " << GM.Name << "\n"; | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 2626 | } | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 2627 | } | 
|  | 2628 |  | 
|  | 2629 | if (V.empty()) | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 2630 | OS << "There are no section groups in this file.\n"; | 
|  | 2631 | } | 
|  | 2632 |  | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 2633 | template <class ELFT> | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2634 | void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, | 
|  | 2635 | const Elf_Rela &R, bool IsRela) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 2636 | std::string Offset, Info, Addend, Value; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2637 | SmallString<32> RelocName; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2638 | StringRef TargetName; | 
|  | 2639 | const Elf_Sym *Sym = nullptr; | 
| Hemant Kulkarni | 2e3254e | 2016-03-29 14:20:20 +0000 | [diff] [blame] | 2640 | unsigned Width = ELFT::Is64Bits ? 16 : 8; | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 2641 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2642 |  | 
|  | 2643 | // First two fields are bit width dependent. The rest of them are after are | 
|  | 2644 | // fixed width. | 
|  | 2645 | Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; | 
|  | 2646 | Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); | 
| Rafael Espindola | ed1395a | 2016-11-03 18:05:33 +0000 | [diff] [blame] | 2647 | Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab)); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2648 | if (Sym && Sym->getType() == ELF::STT_SECTION) { | 
|  | 2649 | const Elf_Shdr *Sec = unwrapOrError( | 
|  | 2650 | Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); | 
|  | 2651 | TargetName = unwrapOrError(Obj->getSectionName(Sec)); | 
|  | 2652 | } else if (Sym) { | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2653 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2654 | TargetName = unwrapOrError(Sym->getName(StrTable)); | 
|  | 2655 | } | 
|  | 2656 |  | 
|  | 2657 | if (Sym && IsRela) { | 
|  | 2658 | if (R.r_addend < 0) | 
|  | 2659 | Addend = " - "; | 
|  | 2660 | else | 
|  | 2661 | Addend = " + "; | 
|  | 2662 | } | 
|  | 2663 |  | 
|  | 2664 | Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); | 
|  | 2665 | Info = to_string(format_hex_no_prefix(R.r_info, Width)); | 
|  | 2666 |  | 
|  | 2667 | int64_t RelAddend = R.r_addend; | 
|  | 2668 | if (IsRela) | 
|  | 2669 | Addend += to_hexString(std::abs(RelAddend), false); | 
|  | 2670 |  | 
|  | 2671 | if (Sym) | 
|  | 2672 | Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); | 
|  | 2673 |  | 
|  | 2674 | Fields[0].Str = Offset; | 
|  | 2675 | Fields[1].Str = Info; | 
|  | 2676 | Fields[2].Str = RelocName; | 
|  | 2677 | Fields[3].Str = Value; | 
|  | 2678 | Fields[4].Str = TargetName; | 
|  | 2679 | for (auto &field : Fields) | 
|  | 2680 | printField(field); | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 2681 | OS << Addend; | 
|  | 2682 | OS << "\n"; | 
|  | 2683 | } | 
|  | 2684 |  | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2685 | template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) { | 
|  | 2686 | bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; | 
|  | 2687 | bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; | 
|  | 2688 | if (ELFT::Is64Bits) | 
|  | 2689 | OS << "    "; | 
|  | 2690 | else | 
|  | 2691 | OS << " "; | 
|  | 2692 | if (IsRelr && opts::RawRelr) | 
|  | 2693 | OS << "Data  "; | 
|  | 2694 | else | 
|  | 2695 | OS << "Offset"; | 
|  | 2696 | if (ELFT::Is64Bits) | 
|  | 2697 | OS << "             Info             Type" | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 2698 | << "               Symbol's Value  Symbol's Name"; | 
|  | 2699 | else | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2700 | OS << "     Info    Type                Sym. Value  Symbol's Name"; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2701 | if (IsRela) | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2702 | OS << " + Addend"; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2703 | OS << "\n"; | 
|  | 2704 | } | 
|  | 2705 |  | 
|  | 2706 | template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { | 
|  | 2707 | bool HasRelocSections = false; | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 2708 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2709 | if (Sec.sh_type != ELF::SHT_REL && | 
|  | 2710 | Sec.sh_type != ELF::SHT_RELA && | 
|  | 2711 | Sec.sh_type != ELF::SHT_RELR && | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2712 | Sec.sh_type != ELF::SHT_ANDROID_REL && | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2713 | Sec.sh_type != ELF::SHT_ANDROID_RELA && | 
|  | 2714 | Sec.sh_type != ELF::SHT_ANDROID_RELR) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2715 | continue; | 
|  | 2716 | HasRelocSections = true; | 
|  | 2717 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 2718 | unsigned Entries = Sec.getEntityCount(); | 
| Peter Collingbourne | cf017ad | 2018-06-07 00:02:07 +0000 | [diff] [blame] | 2719 | std::vector<Elf_Rela> AndroidRelas; | 
|  | 2720 | if (Sec.sh_type == ELF::SHT_ANDROID_REL || | 
|  | 2721 | Sec.sh_type == ELF::SHT_ANDROID_RELA) { | 
|  | 2722 | // Android's packed relocation section needs to be unpacked first | 
|  | 2723 | // to get the actual number of entries. | 
|  | 2724 | AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); | 
|  | 2725 | Entries = AndroidRelas.size(); | 
|  | 2726 | } | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2727 | std::vector<Elf_Rela> RelrRelas; | 
|  | 2728 | if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || | 
|  | 2729 | Sec.sh_type == ELF::SHT_ANDROID_RELR)) { | 
|  | 2730 | // .relr.dyn relative relocation section needs to be unpacked first | 
|  | 2731 | // to get the actual number of entries. | 
|  | 2732 | Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec)); | 
|  | 2733 | RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | 
|  | 2734 | Entries = RelrRelas.size(); | 
|  | 2735 | } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2736 | uintX_t Offset = Sec.sh_offset; | 
|  | 2737 | OS << "\nRelocation section '" << Name << "' at offset 0x" | 
|  | 2738 | << to_hexString(Offset, false) << " contains " << Entries | 
|  | 2739 | << " entries:\n"; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2740 | printRelocHeader(Sec.sh_type); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2741 | const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2742 | switch (Sec.sh_type) { | 
|  | 2743 | case ELF::SHT_REL: | 
| Rafael Espindola | 354680a | 2016-11-03 19:07:15 +0000 | [diff] [blame] | 2744 | for (const auto &R : unwrapOrError(Obj->rels(&Sec))) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2745 | Elf_Rela Rela; | 
|  | 2746 | Rela.r_offset = R.r_offset; | 
|  | 2747 | Rela.r_info = R.r_info; | 
|  | 2748 | Rela.r_addend = 0; | 
|  | 2749 | printRelocation(Obj, SymTab, Rela, false); | 
|  | 2750 | } | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2751 | break; | 
|  | 2752 | case ELF::SHT_RELA: | 
| Rafael Espindola | 354680a | 2016-11-03 19:07:15 +0000 | [diff] [blame] | 2753 | for (const auto &R : unwrapOrError(Obj->relas(&Sec))) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2754 | printRelocation(Obj, SymTab, R, true); | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2755 | break; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2756 | case ELF::SHT_RELR: | 
|  | 2757 | case ELF::SHT_ANDROID_RELR: | 
|  | 2758 | if (opts::RawRelr) | 
|  | 2759 | for (const auto &R : unwrapOrError(Obj->relrs(&Sec))) | 
|  | 2760 | OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) | 
|  | 2761 | << "\n"; | 
|  | 2762 | else | 
|  | 2763 | for (const auto &R : RelrRelas) | 
|  | 2764 | printRelocation(Obj, SymTab, R, false); | 
|  | 2765 | break; | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2766 | case ELF::SHT_ANDROID_REL: | 
|  | 2767 | case ELF::SHT_ANDROID_RELA: | 
| Peter Collingbourne | cf017ad | 2018-06-07 00:02:07 +0000 | [diff] [blame] | 2768 | for (const auto &R : AndroidRelas) | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 2769 | printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA); | 
|  | 2770 | break; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2771 | } | 
|  | 2772 | } | 
|  | 2773 | if (!HasRelocSections) | 
|  | 2774 | OS << "\nThere are no relocations in this file.\n"; | 
|  | 2775 | } | 
|  | 2776 |  | 
|  | 2777 | std::string getSectionTypeString(unsigned Arch, unsigned Type) { | 
|  | 2778 | using namespace ELF; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 2779 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2780 | switch (Arch) { | 
|  | 2781 | case EM_ARM: | 
|  | 2782 | switch (Type) { | 
|  | 2783 | case SHT_ARM_EXIDX: | 
|  | 2784 | return "ARM_EXIDX"; | 
|  | 2785 | case SHT_ARM_PREEMPTMAP: | 
|  | 2786 | return "ARM_PREEMPTMAP"; | 
|  | 2787 | case SHT_ARM_ATTRIBUTES: | 
|  | 2788 | return "ARM_ATTRIBUTES"; | 
|  | 2789 | case SHT_ARM_DEBUGOVERLAY: | 
|  | 2790 | return "ARM_DEBUGOVERLAY"; | 
|  | 2791 | case SHT_ARM_OVERLAYSECTION: | 
|  | 2792 | return "ARM_OVERLAYSECTION"; | 
|  | 2793 | } | 
|  | 2794 | case EM_X86_64: | 
|  | 2795 | switch (Type) { | 
|  | 2796 | case SHT_X86_64_UNWIND: | 
|  | 2797 | return "X86_64_UNWIND"; | 
|  | 2798 | } | 
|  | 2799 | case EM_MIPS: | 
|  | 2800 | case EM_MIPS_RS3_LE: | 
|  | 2801 | switch (Type) { | 
|  | 2802 | case SHT_MIPS_REGINFO: | 
|  | 2803 | return "MIPS_REGINFO"; | 
|  | 2804 | case SHT_MIPS_OPTIONS: | 
|  | 2805 | return "MIPS_OPTIONS"; | 
|  | 2806 | case SHT_MIPS_ABIFLAGS: | 
|  | 2807 | return "MIPS_ABIFLAGS"; | 
| Simon Atanasyan | 6cfb101 | 2017-03-10 08:22:25 +0000 | [diff] [blame] | 2808 | case SHT_MIPS_DWARF: | 
|  | 2809 | return "SHT_MIPS_DWARF"; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2810 | } | 
|  | 2811 | } | 
|  | 2812 | switch (Type) { | 
|  | 2813 | case SHT_NULL: | 
|  | 2814 | return "NULL"; | 
|  | 2815 | case SHT_PROGBITS: | 
|  | 2816 | return "PROGBITS"; | 
|  | 2817 | case SHT_SYMTAB: | 
|  | 2818 | return "SYMTAB"; | 
|  | 2819 | case SHT_STRTAB: | 
|  | 2820 | return "STRTAB"; | 
|  | 2821 | case SHT_RELA: | 
|  | 2822 | return "RELA"; | 
|  | 2823 | case SHT_HASH: | 
|  | 2824 | return "HASH"; | 
|  | 2825 | case SHT_DYNAMIC: | 
|  | 2826 | return "DYNAMIC"; | 
|  | 2827 | case SHT_NOTE: | 
|  | 2828 | return "NOTE"; | 
|  | 2829 | case SHT_NOBITS: | 
|  | 2830 | return "NOBITS"; | 
|  | 2831 | case SHT_REL: | 
|  | 2832 | return "REL"; | 
|  | 2833 | case SHT_SHLIB: | 
|  | 2834 | return "SHLIB"; | 
|  | 2835 | case SHT_DYNSYM: | 
|  | 2836 | return "DYNSYM"; | 
|  | 2837 | case SHT_INIT_ARRAY: | 
|  | 2838 | return "INIT_ARRAY"; | 
|  | 2839 | case SHT_FINI_ARRAY: | 
|  | 2840 | return "FINI_ARRAY"; | 
|  | 2841 | case SHT_PREINIT_ARRAY: | 
|  | 2842 | return "PREINIT_ARRAY"; | 
|  | 2843 | case SHT_GROUP: | 
|  | 2844 | return "GROUP"; | 
|  | 2845 | case SHT_SYMTAB_SHNDX: | 
|  | 2846 | return "SYMTAB SECTION INDICES"; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 2847 | case SHT_RELR: | 
|  | 2848 | case SHT_ANDROID_RELR: | 
|  | 2849 | return "RELR"; | 
| Peter Collingbourne | f0e26e7 | 2017-06-14 18:52:12 +0000 | [diff] [blame] | 2850 | case SHT_LLVM_ODRTAB: | 
|  | 2851 | return "LLVM_ODRTAB"; | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 2852 | case SHT_LLVM_LINKER_OPTIONS: | 
|  | 2853 | return "LLVM_LINKER_OPTIONS"; | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 2854 | case SHT_LLVM_CALL_GRAPH_PROFILE: | 
|  | 2855 | return "LLVM_CALL_GRAPH_PROFILE"; | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 2856 | case SHT_LLVM_ADDRSIG: | 
|  | 2857 | return "LLVM_ADDRSIG"; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2858 | // FIXME: Parse processor specific GNU attributes | 
|  | 2859 | case SHT_GNU_ATTRIBUTES: | 
|  | 2860 | return "ATTRIBUTES"; | 
|  | 2861 | case SHT_GNU_HASH: | 
|  | 2862 | return "GNU_HASH"; | 
|  | 2863 | case SHT_GNU_verdef: | 
|  | 2864 | return "VERDEF"; | 
|  | 2865 | case SHT_GNU_verneed: | 
|  | 2866 | return "VERNEED"; | 
|  | 2867 | case SHT_GNU_versym: | 
|  | 2868 | return "VERSYM"; | 
|  | 2869 | default: | 
|  | 2870 | return ""; | 
|  | 2871 | } | 
|  | 2872 | return ""; | 
|  | 2873 | } | 
|  | 2874 |  | 
|  | 2875 | template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { | 
|  | 2876 | size_t SectionIndex = 0; | 
|  | 2877 | std::string Number, Type, Size, Address, Offset, Flags, Link, Info, EntrySize, | 
|  | 2878 | Alignment; | 
|  | 2879 | unsigned Bias; | 
|  | 2880 | unsigned Width; | 
|  | 2881 |  | 
|  | 2882 | if (ELFT::Is64Bits) { | 
|  | 2883 | Bias = 0; | 
|  | 2884 | Width = 16; | 
|  | 2885 | } else { | 
|  | 2886 | Bias = 8; | 
|  | 2887 | Width = 8; | 
|  | 2888 | } | 
| George Rimar | a2b553b | 2018-07-19 14:52:57 +0000 | [diff] [blame] | 2889 |  | 
|  | 2890 | ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections()); | 
|  | 2891 | OS << "There are " << to_string(Sections.size()) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2892 | << " section headers, starting at offset " | 
|  | 2893 | << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n"; | 
|  | 2894 | OS << "Section Headers:\n"; | 
|  | 2895 | Field Fields[11] = {{"[Nr]", 2}, | 
|  | 2896 | {"Name", 7}, | 
|  | 2897 | {"Type", 25}, | 
|  | 2898 | {"Address", 41}, | 
|  | 2899 | {"Off", 58 - Bias}, | 
|  | 2900 | {"Size", 65 - Bias}, | 
|  | 2901 | {"ES", 72 - Bias}, | 
|  | 2902 | {"Flg", 75 - Bias}, | 
|  | 2903 | {"Lk", 79 - Bias}, | 
|  | 2904 | {"Inf", 82 - Bias}, | 
|  | 2905 | {"Al", 86 - Bias}}; | 
|  | 2906 | for (auto &f : Fields) | 
|  | 2907 | printField(f); | 
|  | 2908 | OS << "\n"; | 
|  | 2909 |  | 
| George Rimar | a2b553b | 2018-07-19 14:52:57 +0000 | [diff] [blame] | 2910 | for (const Elf_Shdr &Sec : Sections) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 2911 | Number = to_string(SectionIndex); | 
|  | 2912 | Fields[0].Str = Number; | 
|  | 2913 | Fields[1].Str = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 2914 | Type = getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type); | 
|  | 2915 | Fields[2].Str = Type; | 
|  | 2916 | Address = to_string(format_hex_no_prefix(Sec.sh_addr, Width)); | 
|  | 2917 | Fields[3].Str = Address; | 
|  | 2918 | Offset = to_string(format_hex_no_prefix(Sec.sh_offset, 6)); | 
|  | 2919 | Fields[4].Str = Offset; | 
|  | 2920 | Size = to_string(format_hex_no_prefix(Sec.sh_size, 6)); | 
|  | 2921 | Fields[5].Str = Size; | 
|  | 2922 | EntrySize = to_string(format_hex_no_prefix(Sec.sh_entsize, 2)); | 
|  | 2923 | Fields[6].Str = EntrySize; | 
|  | 2924 | Flags = getGNUFlags(Sec.sh_flags); | 
|  | 2925 | Fields[7].Str = Flags; | 
|  | 2926 | Link = to_string(Sec.sh_link); | 
|  | 2927 | Fields[8].Str = Link; | 
|  | 2928 | Info = to_string(Sec.sh_info); | 
|  | 2929 | Fields[9].Str = Info; | 
|  | 2930 | Alignment = to_string(Sec.sh_addralign); | 
|  | 2931 | Fields[10].Str = Alignment; | 
|  | 2932 | OS.PadToColumn(Fields[0].Column); | 
|  | 2933 | OS << "[" << right_justify(Fields[0].Str, 2) << "]"; | 
|  | 2934 | for (int i = 1; i < 7; i++) | 
|  | 2935 | printField(Fields[i]); | 
|  | 2936 | OS.PadToColumn(Fields[7].Column); | 
|  | 2937 | OS << right_justify(Fields[7].Str, 3); | 
|  | 2938 | OS.PadToColumn(Fields[8].Column); | 
|  | 2939 | OS << right_justify(Fields[8].Str, 2); | 
|  | 2940 | OS.PadToColumn(Fields[9].Column); | 
|  | 2941 | OS << right_justify(Fields[9].Str, 3); | 
|  | 2942 | OS.PadToColumn(Fields[10].Column); | 
|  | 2943 | OS << right_justify(Fields[10].Str, 2); | 
|  | 2944 | OS << "\n"; | 
|  | 2945 | ++SectionIndex; | 
|  | 2946 | } | 
|  | 2947 | OS << "Key to Flags:\n" | 
|  | 2948 | << "  W (write), A (alloc), X (execute), M (merge), S (strings), l " | 
|  | 2949 | "(large)\n" | 
|  | 2950 | << "  I (info), L (link order), G (group), T (TLS), E (exclude),\ | 
|  | 2951 | x (unknown)\n" | 
|  | 2952 | << "  O (extra OS processing required) o (OS specific),\ | 
|  | 2953 | p (processor specific)\n"; | 
|  | 2954 | } | 
|  | 2955 |  | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 2956 | template <class ELFT> | 
|  | 2957 | void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name, | 
|  | 2958 | size_t Entries) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 2959 | if (!Name.empty()) | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 2960 | OS << "\nSymbol table '" << Name << "' contains " << Entries | 
|  | 2961 | << " entries:\n"; | 
|  | 2962 | else | 
|  | 2963 | OS << "\n Symbol table for image:\n"; | 
|  | 2964 |  | 
|  | 2965 | if (ELFT::Is64Bits) | 
|  | 2966 | OS << "   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"; | 
|  | 2967 | else | 
|  | 2968 | OS << "   Num:    Value  Size Type    Bind   Vis      Ndx Name\n"; | 
|  | 2969 | } | 
|  | 2970 |  | 
|  | 2971 | template <class ELFT> | 
|  | 2972 | std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj, | 
|  | 2973 | const Elf_Sym *Symbol, | 
|  | 2974 | const Elf_Sym *FirstSym) { | 
|  | 2975 | unsigned SectionIndex = Symbol->st_shndx; | 
|  | 2976 | switch (SectionIndex) { | 
|  | 2977 | case ELF::SHN_UNDEF: | 
|  | 2978 | return "UND"; | 
|  | 2979 | case ELF::SHN_ABS: | 
|  | 2980 | return "ABS"; | 
|  | 2981 | case ELF::SHN_COMMON: | 
|  | 2982 | return "COM"; | 
|  | 2983 | case ELF::SHN_XINDEX: | 
| Rafael Espindola | 714c295 | 2016-11-03 14:41:17 +0000 | [diff] [blame] | 2984 | SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( | 
| Rafael Espindola | 7b2750a | 2016-11-03 13:58:15 +0000 | [diff] [blame] | 2985 | Symbol, FirstSym, this->dumper()->getShndxTable())); | 
| Galina Kistanova | 9ee35cf | 2017-05-31 01:33:39 +0000 | [diff] [blame] | 2986 | LLVM_FALLTHROUGH; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 2987 | default: | 
|  | 2988 | // Find if: | 
|  | 2989 | // Processor specific | 
|  | 2990 | if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC) | 
|  | 2991 | return std::string("PRC[0x") + | 
|  | 2992 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | 
|  | 2993 | // OS specific | 
|  | 2994 | if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS) | 
|  | 2995 | return std::string("OS[0x") + | 
|  | 2996 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | 
|  | 2997 | // Architecture reserved: | 
|  | 2998 | if (SectionIndex >= ELF::SHN_LORESERVE && | 
|  | 2999 | SectionIndex <= ELF::SHN_HIRESERVE) | 
|  | 3000 | return std::string("RSV[0x") + | 
|  | 3001 | to_string(format_hex_no_prefix(SectionIndex, 4)) + "]"; | 
|  | 3002 | // A normal section with an index | 
|  | 3003 | return to_string(format_decimal(SectionIndex, 3)); | 
|  | 3004 | } | 
|  | 3005 | } | 
|  | 3006 |  | 
|  | 3007 | template <class ELFT> | 
|  | 3008 | void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, | 
|  | 3009 | const Elf_Sym *FirstSym, StringRef StrTable, | 
|  | 3010 | bool IsDynamic) { | 
|  | 3011 | static int Idx = 0; | 
|  | 3012 | static bool Dynamic = true; | 
|  | 3013 | size_t Width; | 
|  | 3014 |  | 
|  | 3015 | // If this function was called with a different value from IsDynamic | 
|  | 3016 | // from last call, happens when we move from dynamic to static symbol | 
|  | 3017 | // table, "Num" field should be reset. | 
|  | 3018 | if (!Dynamic != !IsDynamic) { | 
|  | 3019 | Idx = 0; | 
|  | 3020 | Dynamic = false; | 
|  | 3021 | } | 
|  | 3022 | std::string Num, Name, Value, Size, Binding, Type, Visibility, Section; | 
|  | 3023 | unsigned Bias = 0; | 
|  | 3024 | if (ELFT::Is64Bits) { | 
|  | 3025 | Bias = 8; | 
|  | 3026 | Width = 16; | 
|  | 3027 | } else { | 
|  | 3028 | Bias = 0; | 
|  | 3029 | Width = 8; | 
|  | 3030 | } | 
|  | 3031 | Field Fields[8] = {0,         8,         17 + Bias, 23 + Bias, | 
|  | 3032 | 31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias}; | 
|  | 3033 | Num = to_string(format_decimal(Idx++, 6)) + ":"; | 
|  | 3034 | Value = to_string(format_hex_no_prefix(Symbol->st_value, Width)); | 
|  | 3035 | Size = to_string(format_decimal(Symbol->st_size, 5)); | 
|  | 3036 | unsigned char SymbolType = Symbol->getType(); | 
|  | 3037 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | 
|  | 3038 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | 
|  | 3039 | Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | 
|  | 3040 | else | 
|  | 3041 | Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); | 
|  | 3042 | unsigned Vis = Symbol->getVisibility(); | 
|  | 3043 | Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | 
|  | 3044 | Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities)); | 
|  | 3045 | Section = getSymbolSectionNdx(Obj, Symbol, FirstSym); | 
|  | 3046 | Name = this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); | 
|  | 3047 | Fields[0].Str = Num; | 
|  | 3048 | Fields[1].Str = Value; | 
|  | 3049 | Fields[2].Str = Size; | 
|  | 3050 | Fields[3].Str = Type; | 
|  | 3051 | Fields[4].Str = Binding; | 
|  | 3052 | Fields[5].Str = Visibility; | 
|  | 3053 | Fields[6].Str = Section; | 
|  | 3054 | Fields[7].Str = Name; | 
|  | 3055 | for (auto &Entry : Fields) | 
|  | 3056 | printField(Entry); | 
|  | 3057 | OS << "\n"; | 
|  | 3058 | } | 
| Hemant Kulkarni | a6ee9fd | 2016-11-23 18:04:23 +0000 | [diff] [blame] | 3059 | template <class ELFT> | 
|  | 3060 | void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, | 
|  | 3061 | uint32_t Sym, StringRef StrTable, | 
|  | 3062 | uint32_t Bucket) { | 
|  | 3063 | std::string Num, Buc, Name, Value, Size, Binding, Type, Visibility, Section; | 
|  | 3064 | unsigned Width, Bias = 0; | 
|  | 3065 | if (ELFT::Is64Bits) { | 
|  | 3066 | Bias = 8; | 
|  | 3067 | Width = 16; | 
|  | 3068 | } else { | 
|  | 3069 | Bias = 0; | 
|  | 3070 | Width = 8; | 
|  | 3071 | } | 
|  | 3072 | Field Fields[9] = {0,         6,         11,        20 + Bias, 25 + Bias, | 
|  | 3073 | 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; | 
|  | 3074 | Num = to_string(format_decimal(Sym, 5)); | 
|  | 3075 | Buc = to_string(format_decimal(Bucket, 3)) + ":"; | 
|  | 3076 |  | 
|  | 3077 | const auto Symbol = FirstSym + Sym; | 
|  | 3078 | Value = to_string(format_hex_no_prefix(Symbol->st_value, Width)); | 
|  | 3079 | Size = to_string(format_decimal(Symbol->st_size, 5)); | 
|  | 3080 | unsigned char SymbolType = Symbol->getType(); | 
|  | 3081 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | 
|  | 3082 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | 
|  | 3083 | Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | 
|  | 3084 | else | 
|  | 3085 | Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); | 
|  | 3086 | unsigned Vis = Symbol->getVisibility(); | 
|  | 3087 | Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | 
|  | 3088 | Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities)); | 
|  | 3089 | Section = getSymbolSectionNdx(Obj, Symbol, FirstSym); | 
|  | 3090 | Name = this->dumper()->getFullSymbolName(Symbol, StrTable, true); | 
|  | 3091 | Fields[0].Str = Num; | 
|  | 3092 | Fields[1].Str = Buc; | 
|  | 3093 | Fields[2].Str = Value; | 
|  | 3094 | Fields[3].Str = Size; | 
|  | 3095 | Fields[4].Str = Type; | 
|  | 3096 | Fields[5].Str = Binding; | 
|  | 3097 | Fields[6].Str = Visibility; | 
|  | 3098 | Fields[7].Str = Section; | 
|  | 3099 | Fields[8].Str = Name; | 
|  | 3100 | for (auto &Entry : Fields) | 
|  | 3101 | printField(Entry); | 
|  | 3102 | OS << "\n"; | 
|  | 3103 | } | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 3104 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3105 | template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) { | 
| Hemant Kulkarni | a6ee9fd | 2016-11-23 18:04:23 +0000 | [diff] [blame] | 3106 | if (opts::DynamicSymbols) | 
|  | 3107 | return; | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 3108 | this->dumper()->printSymbolsHelper(true); | 
|  | 3109 | this->dumper()->printSymbolsHelper(false); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3110 | } | 
|  | 3111 |  | 
|  | 3112 | template <class ELFT> | 
|  | 3113 | void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 3114 | if (this->dumper()->getDynamicStringTable().empty()) | 
| Hemant Kulkarni | a6ee9fd | 2016-11-23 18:04:23 +0000 | [diff] [blame] | 3115 | return; | 
|  | 3116 | auto StringTable = this->dumper()->getDynamicStringTable(); | 
|  | 3117 | auto DynSyms = this->dumper()->dynamic_symbols(); | 
|  | 3118 | auto GnuHash = this->dumper()->getGnuHashTable(); | 
|  | 3119 | auto SysVHash = this->dumper()->getHashTable(); | 
|  | 3120 |  | 
|  | 3121 | // If no hash or .gnu.hash found, try using symbol table | 
|  | 3122 | if (GnuHash == nullptr && SysVHash == nullptr) | 
|  | 3123 | this->dumper()->printSymbolsHelper(true); | 
|  | 3124 |  | 
|  | 3125 | // Try printing .hash | 
|  | 3126 | if (this->dumper()->getHashTable()) { | 
|  | 3127 | OS << "\n Symbol table of .hash for image:\n"; | 
|  | 3128 | if (ELFT::Is64Bits) | 
|  | 3129 | OS << "  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name"; | 
|  | 3130 | else | 
|  | 3131 | OS << "  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name"; | 
|  | 3132 | OS << "\n"; | 
|  | 3133 |  | 
|  | 3134 | uint32_t NBuckets = SysVHash->nbucket; | 
|  | 3135 | uint32_t NChains = SysVHash->nchain; | 
|  | 3136 | auto Buckets = SysVHash->buckets(); | 
|  | 3137 | auto Chains = SysVHash->chains(); | 
|  | 3138 | for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { | 
|  | 3139 | if (Buckets[Buc] == ELF::STN_UNDEF) | 
|  | 3140 | continue; | 
|  | 3141 | for (uint32_t Ch = Buckets[Buc]; Ch < NChains; Ch = Chains[Ch]) { | 
|  | 3142 | if (Ch == ELF::STN_UNDEF) | 
|  | 3143 | break; | 
|  | 3144 | printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); | 
|  | 3145 | } | 
|  | 3146 | } | 
|  | 3147 | } | 
|  | 3148 |  | 
|  | 3149 | // Try printing .gnu.hash | 
|  | 3150 | if (GnuHash) { | 
|  | 3151 | OS << "\n Symbol table of .gnu.hash for image:\n"; | 
|  | 3152 | if (ELFT::Is64Bits) | 
|  | 3153 | OS << "  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name"; | 
|  | 3154 | else | 
|  | 3155 | OS << "  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name"; | 
|  | 3156 | OS << "\n"; | 
|  | 3157 | uint32_t NBuckets = GnuHash->nbuckets; | 
|  | 3158 | auto Buckets = GnuHash->buckets(); | 
|  | 3159 | for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { | 
|  | 3160 | if (Buckets[Buc] == ELF::STN_UNDEF) | 
|  | 3161 | continue; | 
|  | 3162 | uint32_t Index = Buckets[Buc]; | 
|  | 3163 | uint32_t GnuHashable = Index - GnuHash->symndx; | 
|  | 3164 | // Print whole chain | 
|  | 3165 | while (true) { | 
|  | 3166 | printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc); | 
|  | 3167 | // Chain ends at symbol with stopper bit | 
|  | 3168 | if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1) | 
|  | 3169 | break; | 
|  | 3170 | } | 
|  | 3171 | } | 
|  | 3172 | } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3173 | } | 
|  | 3174 |  | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3175 | static inline std::string printPhdrFlags(unsigned Flag) { | 
|  | 3176 | std::string Str; | 
|  | 3177 | Str = (Flag & PF_R) ? "R" : " "; | 
|  | 3178 | Str += (Flag & PF_W) ? "W" : " "; | 
|  | 3179 | Str += (Flag & PF_X) ? "E" : " "; | 
|  | 3180 | return Str; | 
|  | 3181 | } | 
|  | 3182 |  | 
|  | 3183 | // SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO | 
|  | 3184 | // PT_TLS must only have SHF_TLS sections | 
|  | 3185 | template <class ELFT> | 
|  | 3186 | bool GNUStyle<ELFT>::checkTLSSections(const Elf_Phdr &Phdr, | 
|  | 3187 | const Elf_Shdr &Sec) { | 
|  | 3188 | return (((Sec.sh_flags & ELF::SHF_TLS) && | 
|  | 3189 | ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) || | 
|  | 3190 | (Phdr.p_type == ELF::PT_GNU_RELRO))) || | 
|  | 3191 | (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS)); | 
|  | 3192 | } | 
|  | 3193 |  | 
|  | 3194 | // Non-SHT_NOBITS must have its offset inside the segment | 
|  | 3195 | // Only non-zero section can be at end of segment | 
|  | 3196 | template <class ELFT> | 
|  | 3197 | bool GNUStyle<ELFT>::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | 
|  | 3198 | if (Sec.sh_type == ELF::SHT_NOBITS) | 
|  | 3199 | return true; | 
|  | 3200 | bool IsSpecial = | 
|  | 3201 | (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); | 
|  | 3202 | // .tbss is special, it only has memory in PT_TLS and has NOBITS properties | 
|  | 3203 | auto SectionSize = | 
|  | 3204 | (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; | 
|  | 3205 | if (Sec.sh_offset >= Phdr.p_offset) | 
|  | 3206 | return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset) | 
|  | 3207 | /*only non-zero sized sections at end*/ && | 
|  | 3208 | (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz)); | 
|  | 3209 | return false; | 
|  | 3210 | } | 
|  | 3211 |  | 
|  | 3212 | // SHF_ALLOC must have VMA inside segment | 
|  | 3213 | // Only non-zero section can be at end of segment | 
|  | 3214 | template <class ELFT> | 
|  | 3215 | bool GNUStyle<ELFT>::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | 
|  | 3216 | if (!(Sec.sh_flags & ELF::SHF_ALLOC)) | 
|  | 3217 | return true; | 
|  | 3218 | bool IsSpecial = | 
|  | 3219 | (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0); | 
|  | 3220 | // .tbss is special, it only has memory in PT_TLS and has NOBITS properties | 
|  | 3221 | auto SectionSize = | 
|  | 3222 | (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size; | 
|  | 3223 | if (Sec.sh_addr >= Phdr.p_vaddr) | 
|  | 3224 | return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) && | 
|  | 3225 | (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz)); | 
|  | 3226 | return false; | 
|  | 3227 | } | 
|  | 3228 |  | 
|  | 3229 | // No section with zero size must be at start or end of PT_DYNAMIC | 
|  | 3230 | template <class ELFT> | 
|  | 3231 | bool GNUStyle<ELFT>::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) { | 
|  | 3232 | if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0) | 
|  | 3233 | return true; | 
|  | 3234 | // Is section within the phdr both based on offset and VMA ? | 
|  | 3235 | return ((Sec.sh_type == ELF::SHT_NOBITS) || | 
|  | 3236 | (Sec.sh_offset > Phdr.p_offset && | 
|  | 3237 | Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) && | 
|  | 3238 | (!(Sec.sh_flags & ELF::SHF_ALLOC) || | 
|  | 3239 | (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz)); | 
|  | 3240 | } | 
|  | 3241 |  | 
|  | 3242 | template <class ELFT> | 
|  | 3243 | void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { | 
| Hemant Kulkarni | 2e3254e | 2016-03-29 14:20:20 +0000 | [diff] [blame] | 3244 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | 
|  | 3245 | unsigned Width = ELFT::Is64Bits ? 18 : 10; | 
|  | 3246 | unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7; | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3247 | std::string Type, Offset, VMA, LMA, FileSz, MemSz, Flag, Align; | 
|  | 3248 |  | 
|  | 3249 | const Elf_Ehdr *Header = Obj->getHeader(); | 
|  | 3250 | Field Fields[8] = {2,         17,        26,        37 + Bias, | 
|  | 3251 | 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias}; | 
|  | 3252 | OS << "\nElf file type is " | 
|  | 3253 | << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n" | 
| Hemant Kulkarni | 787c2ed | 2016-05-12 22:51:26 +0000 | [diff] [blame] | 3254 | << "Entry point " << format_hex(Header->e_entry, 3) << "\n" | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3255 | << "There are " << Header->e_phnum << " program headers," | 
|  | 3256 | << " starting at offset " << Header->e_phoff << "\n\n" | 
|  | 3257 | << "Program Headers:\n"; | 
|  | 3258 | if (ELFT::Is64Bits) | 
|  | 3259 | OS << "  Type           Offset   VirtAddr           PhysAddr         " | 
|  | 3260 | << "  FileSiz  MemSiz   Flg Align\n"; | 
|  | 3261 | else | 
|  | 3262 | OS << "  Type           Offset   VirtAddr   PhysAddr   FileSiz " | 
|  | 3263 | << "MemSiz  Flg Align\n"; | 
| Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 3264 | for (const auto &Phdr : unwrapOrError(Obj->program_headers())) { | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3265 | Type = getElfPtType(Header->e_machine, Phdr.p_type); | 
|  | 3266 | Offset = to_string(format_hex(Phdr.p_offset, 8)); | 
|  | 3267 | VMA = to_string(format_hex(Phdr.p_vaddr, Width)); | 
|  | 3268 | LMA = to_string(format_hex(Phdr.p_paddr, Width)); | 
|  | 3269 | FileSz = to_string(format_hex(Phdr.p_filesz, SizeWidth)); | 
|  | 3270 | MemSz = to_string(format_hex(Phdr.p_memsz, SizeWidth)); | 
|  | 3271 | Flag = printPhdrFlags(Phdr.p_flags); | 
|  | 3272 | Align = to_string(format_hex(Phdr.p_align, 1)); | 
|  | 3273 | Fields[0].Str = Type; | 
|  | 3274 | Fields[1].Str = Offset; | 
|  | 3275 | Fields[2].Str = VMA; | 
|  | 3276 | Fields[3].Str = LMA; | 
|  | 3277 | Fields[4].Str = FileSz; | 
|  | 3278 | Fields[5].Str = MemSz; | 
|  | 3279 | Fields[6].Str = Flag; | 
|  | 3280 | Fields[7].Str = Align; | 
|  | 3281 | for (auto Field : Fields) | 
|  | 3282 | printField(Field); | 
|  | 3283 | if (Phdr.p_type == ELF::PT_INTERP) { | 
|  | 3284 | OS << "\n      [Requesting program interpreter: "; | 
|  | 3285 | OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]"; | 
|  | 3286 | } | 
|  | 3287 | OS << "\n"; | 
|  | 3288 | } | 
|  | 3289 | OS << "\n Section to Segment mapping:\n  Segment Sections...\n"; | 
|  | 3290 | int Phnum = 0; | 
| Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 3291 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3292 | std::string Sections; | 
|  | 3293 | OS << format("   %2.2d     ", Phnum++); | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 3294 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 3295 | // Check if each section is in a segment and then print mapping. | 
|  | 3296 | // readelf additionally makes sure it does not print zero sized sections | 
|  | 3297 | // at end of segments and for PT_DYNAMIC both start and end of section | 
|  | 3298 | // .tbss must only be shown in PT_TLS section. | 
|  | 3299 | bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) && | 
|  | 3300 | ((Sec.sh_flags & ELF::SHF_TLS) != 0) && | 
|  | 3301 | Phdr.p_type != ELF::PT_TLS; | 
|  | 3302 | if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) && | 
|  | 3303 | checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) && | 
|  | 3304 | checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL)) | 
|  | 3305 | Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " "; | 
|  | 3306 | } | 
|  | 3307 | OS << Sections << "\n"; | 
|  | 3308 | OS.flush(); | 
|  | 3309 | } | 
|  | 3310 | } | 
|  | 3311 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3312 | template <class ELFT> | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3313 | void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, | 
|  | 3314 | bool IsRela) { | 
|  | 3315 | SmallString<32> RelocName; | 
|  | 3316 | StringRef SymbolName; | 
| Hemant Kulkarni | 2e3254e | 2016-03-29 14:20:20 +0000 | [diff] [blame] | 3317 | unsigned Width = ELFT::Is64Bits ? 16 : 8; | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3318 | unsigned Bias = ELFT::Is64Bits ? 8 : 0; | 
|  | 3319 | // First two fields are bit width dependent. The rest of them are after are | 
|  | 3320 | // fixed width. | 
|  | 3321 | Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; | 
|  | 3322 |  | 
|  | 3323 | uint32_t SymIndex = R.getSymbol(Obj->isMips64EL()); | 
|  | 3324 | const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; | 
|  | 3325 | Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); | 
|  | 3326 | SymbolName = | 
|  | 3327 | unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 3328 | std::string Addend, Info, Offset, Value; | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3329 | Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); | 
|  | 3330 | Info = to_string(format_hex_no_prefix(R.r_info, Width)); | 
|  | 3331 | Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); | 
|  | 3332 | int64_t RelAddend = R.r_addend; | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 3333 | if (!SymbolName.empty() && IsRela) { | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3334 | if (R.r_addend < 0) | 
|  | 3335 | Addend = " - "; | 
|  | 3336 | else | 
|  | 3337 | Addend = " + "; | 
|  | 3338 | } | 
|  | 3339 |  | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 3340 | if (SymbolName.empty() && Sym->getValue() == 0) | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3341 | Value = ""; | 
|  | 3342 |  | 
|  | 3343 | if (IsRela) | 
|  | 3344 | Addend += to_string(format_hex_no_prefix(std::abs(RelAddend), 1)); | 
|  | 3345 |  | 
|  | 3346 |  | 
|  | 3347 | Fields[0].Str = Offset; | 
|  | 3348 | Fields[1].Str = Info; | 
|  | 3349 | Fields[2].Str = RelocName.c_str(); | 
|  | 3350 | Fields[3].Str = Value; | 
|  | 3351 | Fields[4].Str = SymbolName; | 
|  | 3352 | for (auto &Field : Fields) | 
|  | 3353 | printField(Field); | 
|  | 3354 | OS << Addend; | 
|  | 3355 | OS << "\n"; | 
|  | 3356 | } | 
|  | 3357 |  | 
|  | 3358 | template <class ELFT> | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3359 | void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3360 | const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); | 
|  | 3361 | const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3362 | const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3363 | const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); | 
|  | 3364 | if (DynRelaRegion.Size > 0) { | 
|  | 3365 | OS << "\n'RELA' relocation section at offset " | 
|  | 3366 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelaRegion.Addr) - | 
|  | 3367 | Obj->base(), | 
|  | 3368 | 1) << " contains " << DynRelaRegion.Size << " bytes:\n"; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3369 | printRelocHeader(ELF::SHT_RELA); | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3370 | for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) | 
|  | 3371 | printDynamicRelocation(Obj, Rela, true); | 
|  | 3372 | } | 
|  | 3373 | if (DynRelRegion.Size > 0) { | 
|  | 3374 | OS << "\n'REL' relocation section at offset " | 
|  | 3375 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelRegion.Addr) - | 
|  | 3376 | Obj->base(), | 
|  | 3377 | 1) << " contains " << DynRelRegion.Size << " bytes:\n"; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3378 | printRelocHeader(ELF::SHT_REL); | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3379 | for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { | 
|  | 3380 | Elf_Rela Rela; | 
|  | 3381 | Rela.r_offset = Rel.r_offset; | 
|  | 3382 | Rela.r_info = Rel.r_info; | 
|  | 3383 | Rela.r_addend = 0; | 
|  | 3384 | printDynamicRelocation(Obj, Rela, false); | 
|  | 3385 | } | 
|  | 3386 | } | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3387 | if (DynRelrRegion.Size > 0) { | 
|  | 3388 | OS << "\n'RELR' relocation section at offset " | 
|  | 3389 | << format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) - | 
|  | 3390 | Obj->base(), | 
|  | 3391 | 1) << " contains " << DynRelrRegion.Size << " bytes:\n"; | 
|  | 3392 | printRelocHeader(ELF::SHT_REL); | 
|  | 3393 | Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); | 
|  | 3394 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | 
|  | 3395 | for (const Elf_Rela &Rela : RelrRelas) { | 
|  | 3396 | printDynamicRelocation(Obj, Rela, false); | 
|  | 3397 | } | 
|  | 3398 | } | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3399 | if (DynPLTRelRegion.Size) { | 
|  | 3400 | OS << "\n'PLT' relocation section at offset " | 
|  | 3401 | << format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) - | 
|  | 3402 | Obj->base(), | 
|  | 3403 | 1) << " contains " << DynPLTRelRegion.Size << " bytes:\n"; | 
|  | 3404 | } | 
|  | 3405 | if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3406 | printRelocHeader(ELF::SHT_RELA); | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 3407 | for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3408 | printDynamicRelocation(Obj, Rela, true); | 
|  | 3409 | } else { | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 3410 | printRelocHeader(ELF::SHT_REL); | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 3411 | for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { | 
| Hemant Kulkarni | a79c798 | 2016-03-29 02:41:49 +0000 | [diff] [blame] | 3412 | Elf_Rela Rela; | 
|  | 3413 | Rela.r_offset = Rel.r_offset; | 
|  | 3414 | Rela.r_info = Rel.r_info; | 
|  | 3415 | Rela.r_addend = 0; | 
|  | 3416 | printDynamicRelocation(Obj, Rela, false); | 
|  | 3417 | } | 
|  | 3418 | } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3419 | } | 
|  | 3420 |  | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 3421 | // Hash histogram shows  statistics of how efficient the hash was for the | 
|  | 3422 | // dynamic symbol table. The table shows number of hash buckets for different | 
|  | 3423 | // lengths of chains as absolute number and percentage of the total buckets. | 
|  | 3424 | // Additionally cumulative coverage of symbols for each set of buckets. | 
|  | 3425 | template <class ELFT> | 
|  | 3426 | void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { | 
|  | 3427 |  | 
|  | 3428 | const Elf_Hash *HashTable = this->dumper()->getHashTable(); | 
|  | 3429 | const Elf_GnuHash *GnuHashTable = this->dumper()->getGnuHashTable(); | 
|  | 3430 |  | 
|  | 3431 | // Print histogram for .hash section | 
|  | 3432 | if (HashTable) { | 
|  | 3433 | size_t NBucket = HashTable->nbucket; | 
|  | 3434 | size_t NChain = HashTable->nchain; | 
|  | 3435 | ArrayRef<Elf_Word> Buckets = HashTable->buckets(); | 
|  | 3436 | ArrayRef<Elf_Word> Chains = HashTable->chains(); | 
|  | 3437 | size_t TotalSyms = 0; | 
|  | 3438 | // If hash table is correct, we have at least chains with 0 length | 
|  | 3439 | size_t MaxChain = 1; | 
|  | 3440 | size_t CumulativeNonZero = 0; | 
|  | 3441 |  | 
|  | 3442 | if (NChain == 0 || NBucket == 0) | 
|  | 3443 | return; | 
|  | 3444 |  | 
|  | 3445 | std::vector<size_t> ChainLen(NBucket, 0); | 
|  | 3446 | // Go over all buckets and and note chain lengths of each bucket (total | 
|  | 3447 | // unique chain lengths). | 
|  | 3448 | for (size_t B = 0; B < NBucket; B++) { | 
|  | 3449 | for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C]) | 
|  | 3450 | if (MaxChain <= ++ChainLen[B]) | 
|  | 3451 | MaxChain++; | 
|  | 3452 | TotalSyms += ChainLen[B]; | 
|  | 3453 | } | 
|  | 3454 |  | 
|  | 3455 | if (!TotalSyms) | 
|  | 3456 | return; | 
|  | 3457 |  | 
|  | 3458 | std::vector<size_t> Count(MaxChain, 0) ; | 
|  | 3459 | // Count how long is the chain for each bucket | 
|  | 3460 | for (size_t B = 0; B < NBucket; B++) | 
|  | 3461 | ++Count[ChainLen[B]]; | 
|  | 3462 | // Print Number of buckets with each chain lengths and their cumulative | 
|  | 3463 | // coverage of the symbols | 
|  | 3464 | OS << "Histogram for bucket list length (total of " << NBucket | 
|  | 3465 | << " buckets)\n" | 
|  | 3466 | << " Length  Number     % of total  Coverage\n"; | 
|  | 3467 | for (size_t I = 0; I < MaxChain; I++) { | 
|  | 3468 | CumulativeNonZero += Count[I] * I; | 
|  | 3469 | OS << format("%7lu  %-10lu (%5.1f%%)     %5.1f%%\n", I, Count[I], | 
|  | 3470 | (Count[I] * 100.0) / NBucket, | 
|  | 3471 | (CumulativeNonZero * 100.0) / TotalSyms); | 
|  | 3472 | } | 
|  | 3473 | } | 
|  | 3474 |  | 
|  | 3475 | // Print histogram for .gnu.hash section | 
|  | 3476 | if (GnuHashTable) { | 
|  | 3477 | size_t NBucket = GnuHashTable->nbuckets; | 
|  | 3478 | ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets(); | 
|  | 3479 | unsigned NumSyms = this->dumper()->dynamic_symbols().size(); | 
|  | 3480 | if (!NumSyms) | 
|  | 3481 | return; | 
|  | 3482 | ArrayRef<Elf_Word> Chains = GnuHashTable->values(NumSyms); | 
|  | 3483 | size_t Symndx = GnuHashTable->symndx; | 
|  | 3484 | size_t TotalSyms = 0; | 
|  | 3485 | size_t MaxChain = 1; | 
|  | 3486 | size_t CumulativeNonZero = 0; | 
|  | 3487 |  | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 3488 | if (Chains.empty() || NBucket == 0) | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 3489 | return; | 
|  | 3490 |  | 
|  | 3491 | std::vector<size_t> ChainLen(NBucket, 0); | 
|  | 3492 |  | 
|  | 3493 | for (size_t B = 0; B < NBucket; B++) { | 
|  | 3494 | if (!Buckets[B]) | 
|  | 3495 | continue; | 
|  | 3496 | size_t Len = 1; | 
|  | 3497 | for (size_t C = Buckets[B] - Symndx; | 
|  | 3498 | C < Chains.size() && (Chains[C] & 1) == 0; C++) | 
|  | 3499 | if (MaxChain < ++Len) | 
|  | 3500 | MaxChain++; | 
|  | 3501 | ChainLen[B] = Len; | 
|  | 3502 | TotalSyms += Len; | 
|  | 3503 | } | 
|  | 3504 | MaxChain++; | 
|  | 3505 |  | 
|  | 3506 | if (!TotalSyms) | 
|  | 3507 | return; | 
|  | 3508 |  | 
|  | 3509 | std::vector<size_t> Count(MaxChain, 0) ; | 
|  | 3510 | for (size_t B = 0; B < NBucket; B++) | 
|  | 3511 | ++Count[ChainLen[B]]; | 
|  | 3512 | // Print Number of buckets with each chain lengths and their cumulative | 
|  | 3513 | // coverage of the symbols | 
|  | 3514 | OS << "Histogram for `.gnu.hash' bucket list length (total of " << NBucket | 
|  | 3515 | << " buckets)\n" | 
|  | 3516 | << " Length  Number     % of total  Coverage\n"; | 
|  | 3517 | for (size_t I = 0; I <MaxChain; I++) { | 
|  | 3518 | CumulativeNonZero += Count[I] * I; | 
|  | 3519 | OS << format("%7lu  %-10lu (%5.1f%%)     %5.1f%%\n", I, Count[I], | 
|  | 3520 | (Count[I] * 100.0) / NBucket, | 
|  | 3521 | (CumulativeNonZero * 100.0) / TotalSyms); | 
|  | 3522 | } | 
|  | 3523 | } | 
|  | 3524 | } | 
|  | 3525 |  | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 3526 | template <class ELFT> | 
|  | 3527 | void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { | 
|  | 3528 | OS << "GNUStyle::printCGProfile not implemented\n"; | 
|  | 3529 | } | 
|  | 3530 |  | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 3531 | template <class ELFT> | 
|  | 3532 | void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { | 
|  | 3533 | OS << "GNUStyle::printAddrsig not implemented\n"; | 
|  | 3534 | } | 
|  | 3535 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3536 | static std::string getGNUNoteTypeName(const uint32_t NT) { | 
|  | 3537 | static const struct { | 
|  | 3538 | uint32_t ID; | 
|  | 3539 | const char *Name; | 
|  | 3540 | } Notes[] = { | 
|  | 3541 | {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, | 
|  | 3542 | {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, | 
|  | 3543 | {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, | 
|  | 3544 | {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3545 | {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"}, | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3546 | }; | 
|  | 3547 |  | 
|  | 3548 | for (const auto &Note : Notes) | 
|  | 3549 | if (Note.ID == NT) | 
|  | 3550 | return std::string(Note.Name); | 
|  | 3551 |  | 
|  | 3552 | std::string string; | 
|  | 3553 | raw_string_ostream OS(string); | 
|  | 3554 | OS << format("Unknown note type (0x%08x)", NT); | 
| Konstantin Zhuravlyov | 716af74 | 2017-10-14 16:43:46 +0000 | [diff] [blame] | 3555 | return OS.str(); | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3556 | } | 
|  | 3557 |  | 
| Saleem Abdulrasool | 4b08913 | 2017-02-12 18:55:33 +0000 | [diff] [blame] | 3558 | static std::string getFreeBSDNoteTypeName(const uint32_t NT) { | 
|  | 3559 | static const struct { | 
|  | 3560 | uint32_t ID; | 
|  | 3561 | const char *Name; | 
|  | 3562 | } Notes[] = { | 
|  | 3563 | {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"}, | 
|  | 3564 | {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"}, | 
|  | 3565 | {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"}, | 
|  | 3566 | {ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"}, | 
|  | 3567 | {ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"}, | 
|  | 3568 | {ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"}, | 
|  | 3569 | {ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"}, | 
|  | 3570 | {ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"}, | 
|  | 3571 | {ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS, | 
|  | 3572 | "NT_PROCSTAT_PSSTRINGS (ps_strings data)"}, | 
|  | 3573 | {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"}, | 
|  | 3574 | }; | 
|  | 3575 |  | 
|  | 3576 | for (const auto &Note : Notes) | 
|  | 3577 | if (Note.ID == NT) | 
|  | 3578 | return std::string(Note.Name); | 
|  | 3579 |  | 
|  | 3580 | std::string string; | 
|  | 3581 | raw_string_ostream OS(string); | 
|  | 3582 | OS << format("Unknown note type (0x%08x)", NT); | 
| Konstantin Zhuravlyov | 716af74 | 2017-10-14 16:43:46 +0000 | [diff] [blame] | 3583 | return OS.str(); | 
|  | 3584 | } | 
|  | 3585 |  | 
|  | 3586 | static std::string getAMDGPUNoteTypeName(const uint32_t NT) { | 
|  | 3587 | static const struct { | 
|  | 3588 | uint32_t ID; | 
|  | 3589 | const char *Name; | 
|  | 3590 | } Notes[] = { | 
|  | 3591 | {ELF::NT_AMD_AMDGPU_HSA_METADATA, | 
|  | 3592 | "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"}, | 
|  | 3593 | {ELF::NT_AMD_AMDGPU_ISA, | 
|  | 3594 | "NT_AMD_AMDGPU_ISA (ISA Version)"}, | 
|  | 3595 | {ELF::NT_AMD_AMDGPU_PAL_METADATA, | 
|  | 3596 | "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"} | 
|  | 3597 | }; | 
|  | 3598 |  | 
|  | 3599 | for (const auto &Note : Notes) | 
|  | 3600 | if (Note.ID == NT) | 
|  | 3601 | return std::string(Note.Name); | 
|  | 3602 |  | 
|  | 3603 | std::string string; | 
|  | 3604 | raw_string_ostream OS(string); | 
|  | 3605 | OS << format("Unknown note type (0x%08x)", NT); | 
|  | 3606 | return OS.str(); | 
| Saleem Abdulrasool | 4b08913 | 2017-02-12 18:55:33 +0000 | [diff] [blame] | 3607 | } | 
|  | 3608 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3609 | template <typename ELFT> | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3610 | static void printGNUProperty(raw_ostream &OS, uint32_t Type, uint32_t DataSize, | 
|  | 3611 | ArrayRef<uint8_t> Data) { | 
|  | 3612 | switch (Type) { | 
|  | 3613 | default: | 
|  | 3614 | OS << format("    <application-specific type 0x%x>\n", Type); | 
|  | 3615 | return; | 
|  | 3616 | case GNU_PROPERTY_STACK_SIZE: { | 
|  | 3617 | OS << "    stack size: "; | 
|  | 3618 | if (DataSize == sizeof(typename ELFT::uint)) | 
| Alexander Ivchenko | ab60a28 | 2018-06-04 15:14:18 +0000 | [diff] [blame] | 3619 | OS << format("0x%llx\n", | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3620 | (uint64_t)(*(const typename ELFT::Addr *)Data.data())); | 
|  | 3621 | else | 
|  | 3622 | OS << format("<corrupt length: 0x%x>\n", DataSize); | 
|  | 3623 | break; | 
|  | 3624 | } | 
|  | 3625 | case GNU_PROPERTY_NO_COPY_ON_PROTECTED: | 
|  | 3626 | OS << "    no copy on protected"; | 
|  | 3627 | if (DataSize) | 
|  | 3628 | OS << format(" <corrupt length: 0x%x>", DataSize); | 
|  | 3629 | OS << "\n"; | 
|  | 3630 | break; | 
| Alexander Ivchenko | ab60a28 | 2018-06-04 15:14:18 +0000 | [diff] [blame] | 3631 | case GNU_PROPERTY_X86_FEATURE_1_AND: | 
|  | 3632 | OS << "    X86 features: "; | 
|  | 3633 | if (DataSize != 4 && DataSize != 8) { | 
|  | 3634 | OS << format("<corrupt length: 0x%x>\n", DataSize); | 
|  | 3635 | break; | 
|  | 3636 | } | 
|  | 3637 | uint64_t CFProtection = | 
|  | 3638 | (DataSize == 4) | 
|  | 3639 | ? support::endian::read32<ELFT::TargetEndianness>(Data.data()) | 
|  | 3640 | : support::endian::read64<ELFT::TargetEndianness>(Data.data()); | 
|  | 3641 | if (CFProtection == 0) { | 
|  | 3642 | OS << "none\n"; | 
|  | 3643 | break; | 
|  | 3644 | } | 
|  | 3645 | if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_IBT) { | 
|  | 3646 | OS << "IBT"; | 
|  | 3647 | CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_IBT; | 
|  | 3648 | if (CFProtection) | 
|  | 3649 | OS << ", "; | 
|  | 3650 | } | 
|  | 3651 | if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_SHSTK) { | 
|  | 3652 | OS << "SHSTK"; | 
|  | 3653 | CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK; | 
|  | 3654 | if (CFProtection) | 
|  | 3655 | OS << ", "; | 
|  | 3656 | } | 
|  | 3657 | if (CFProtection) | 
|  | 3658 | OS << format("<unknown flags: 0x%llx>", CFProtection); | 
|  | 3659 | OS << "\n"; | 
|  | 3660 | break; | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3661 | } | 
|  | 3662 | } | 
|  | 3663 |  | 
|  | 3664 | template <typename ELFT> | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3665 | static void printGNUNote(raw_ostream &OS, uint32_t NoteType, | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 3666 | ArrayRef<typename ELFT::Word> Words, size_t Size) { | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3667 | using Elf_Word = typename ELFT::Word; | 
|  | 3668 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3669 | switch (NoteType) { | 
|  | 3670 | default: | 
|  | 3671 | return; | 
|  | 3672 | case ELF::NT_GNU_ABI_TAG: { | 
|  | 3673 | static const char *OSNames[] = { | 
|  | 3674 | "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", | 
|  | 3675 | }; | 
|  | 3676 |  | 
|  | 3677 | StringRef OSName = "Unknown"; | 
|  | 3678 | if (Words[0] < array_lengthof(OSNames)) | 
|  | 3679 | OSName = OSNames[Words[0]]; | 
|  | 3680 | uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; | 
|  | 3681 |  | 
|  | 3682 | if (Words.size() < 4) | 
|  | 3683 | OS << "    <corrupt GNU_ABI_TAG>"; | 
|  | 3684 | else | 
|  | 3685 | OS << "    OS: " << OSName << ", ABI: " << Major << "." << Minor << "." | 
|  | 3686 | << Patch; | 
|  | 3687 | break; | 
|  | 3688 | } | 
|  | 3689 | case ELF::NT_GNU_BUILD_ID: { | 
|  | 3690 | OS << "    Build ID: "; | 
| Petr Hosek | 02185c0 | 2017-04-05 18:55:50 +0000 | [diff] [blame] | 3691 | ArrayRef<uint8_t> ID(reinterpret_cast<const uint8_t *>(Words.data()), Size); | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3692 | for (const auto &B : ID) | 
|  | 3693 | OS << format_hex_no_prefix(B, 2); | 
|  | 3694 | break; | 
|  | 3695 | } | 
|  | 3696 | case ELF::NT_GNU_GOLD_VERSION: | 
|  | 3697 | OS << "    Version: " | 
| Petr Hosek | 02185c0 | 2017-04-05 18:55:50 +0000 | [diff] [blame] | 3698 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3699 | break; | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3700 | case ELF::NT_GNU_PROPERTY_TYPE_0: | 
|  | 3701 | OS << "    Properties:"; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3702 |  | 
| George Rimar | 6a14c02 | 2018-03-21 08:34:55 +0000 | [diff] [blame] | 3703 | ArrayRef<uint8_t> Arr(reinterpret_cast<const uint8_t *>(Words.data()), | 
|  | 3704 | Size); | 
|  | 3705 | while (Arr.size() >= 8) { | 
|  | 3706 | uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data()); | 
|  | 3707 | uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4); | 
|  | 3708 | Arr = Arr.drop_front(8); | 
|  | 3709 |  | 
|  | 3710 | // Take padding size into account if present. | 
|  | 3711 | uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint)); | 
|  | 3712 | if (Arr.size() < PaddedSize) { | 
|  | 3713 | OS << format("    <corrupt type (0x%x) datasz: 0x%x>\n", Type, | 
|  | 3714 | DataSize); | 
|  | 3715 | break; | 
|  | 3716 | } | 
|  | 3717 | printGNUProperty<ELFT>(OS, Type, DataSize, Arr.take_front(PaddedSize)); | 
|  | 3718 | Arr = Arr.drop_front(PaddedSize); | 
|  | 3719 | } | 
|  | 3720 |  | 
|  | 3721 | if (!Arr.empty()) | 
|  | 3722 | OS << "    <corrupted GNU_PROPERTY_TYPE_0>"; | 
|  | 3723 | break; | 
|  | 3724 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3725 | OS << '\n'; | 
|  | 3726 | } | 
|  | 3727 |  | 
| Konstantin Zhuravlyov | b3c605d | 2017-10-14 18:21:42 +0000 | [diff] [blame] | 3728 | template <typename ELFT> | 
|  | 3729 | static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType, | 
| Rui Ueyama | 478d635 | 2018-01-12 02:28:31 +0000 | [diff] [blame] | 3730 | ArrayRef<typename ELFT::Word> Words, size_t Size) { | 
| Konstantin Zhuravlyov | b3c605d | 2017-10-14 18:21:42 +0000 | [diff] [blame] | 3731 | switch (NoteType) { | 
|  | 3732 | default: | 
|  | 3733 | return; | 
|  | 3734 | case ELF::NT_AMD_AMDGPU_HSA_METADATA: | 
|  | 3735 | OS << "    HSA Metadata:\n" | 
|  | 3736 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | 
|  | 3737 | break; | 
|  | 3738 | case ELF::NT_AMD_AMDGPU_ISA: | 
|  | 3739 | OS << "    ISA Version:\n" | 
|  | 3740 | << "        " | 
|  | 3741 | << StringRef(reinterpret_cast<const char *>(Words.data()), Size); | 
|  | 3742 | break; | 
|  | 3743 | case ELF::NT_AMD_AMDGPU_PAL_METADATA: | 
|  | 3744 | const uint32_t *PALMetadataBegin = reinterpret_cast<const uint32_t *>(Words.data()); | 
|  | 3745 | const uint32_t *PALMetadataEnd = PALMetadataBegin + Size; | 
|  | 3746 | std::vector<uint32_t> PALMetadata(PALMetadataBegin, PALMetadataEnd); | 
|  | 3747 | std::string PALMetadataString; | 
|  | 3748 | auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString); | 
|  | 3749 | OS << "    PAL Metadata:\n"; | 
|  | 3750 | if (Error) { | 
|  | 3751 | OS << "        Invalid"; | 
|  | 3752 | return; | 
|  | 3753 | } | 
|  | 3754 | OS << PALMetadataString; | 
|  | 3755 | break; | 
|  | 3756 | } | 
|  | 3757 | OS.flush(); | 
|  | 3758 | } | 
|  | 3759 |  | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3760 | template <class ELFT> | 
|  | 3761 | void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { | 
|  | 3762 | const Elf_Ehdr *e = Obj->getHeader(); | 
|  | 3763 | bool IsCore = e->e_type == ELF::ET_CORE; | 
|  | 3764 |  | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3765 | auto PrintHeader = [&](const typename ELFT::Off Offset, | 
|  | 3766 | const typename ELFT::Addr Size) { | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3767 | OS << "Displaying notes found at file offset " << format_hex(Offset, 10) | 
|  | 3768 | << " with length " << format_hex(Size, 10) << ":\n" | 
|  | 3769 | << "  Owner                 Data size\tDescription\n"; | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3770 | }; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3771 |  | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3772 | auto ProcessNote = [&](const Elf_Note &Note) { | 
|  | 3773 | StringRef Name = Note.getName(); | 
|  | 3774 | ArrayRef<Elf_Word> Descriptor = Note.getDesc(); | 
|  | 3775 | Elf_Word Type = Note.getType(); | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3776 |  | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3777 | OS << "  " << Name << std::string(22 - Name.size(), ' ') | 
|  | 3778 | << format_hex(Descriptor.size(), 10) << '\t'; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3779 |  | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3780 | if (Name == "GNU") { | 
|  | 3781 | OS << getGNUNoteTypeName(Type) << '\n'; | 
|  | 3782 | printGNUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); | 
|  | 3783 | } else if (Name == "FreeBSD") { | 
|  | 3784 | OS << getFreeBSDNoteTypeName(Type) << '\n'; | 
|  | 3785 | } else if (Name == "AMD") { | 
|  | 3786 | OS << getAMDGPUNoteTypeName(Type) << '\n'; | 
|  | 3787 | printAMDGPUNote<ELFT>(OS, Type, Descriptor, Descriptor.size()); | 
|  | 3788 | } else { | 
|  | 3789 | OS << "Unknown note type: (" << format_hex(Type, 10) << ')'; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3790 | } | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3791 | OS << '\n'; | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3792 | }; | 
|  | 3793 |  | 
|  | 3794 | if (IsCore) { | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3795 | for (const auto &P : unwrapOrError(Obj->program_headers())) { | 
|  | 3796 | if (P.p_type != PT_NOTE) | 
|  | 3797 | continue; | 
|  | 3798 | PrintHeader(P.p_offset, P.p_filesz); | 
|  | 3799 | Error Err = Error::success(); | 
|  | 3800 | for (const auto &Note : Obj->notes(P, Err)) | 
|  | 3801 | ProcessNote(Note); | 
|  | 3802 | if (Err) | 
|  | 3803 | error(std::move(Err)); | 
|  | 3804 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3805 | } else { | 
| Scott Linder | 77a5f21 | 2018-03-12 19:28:50 +0000 | [diff] [blame] | 3806 | for (const auto &S : unwrapOrError(Obj->sections())) { | 
|  | 3807 | if (S.sh_type != SHT_NOTE) | 
|  | 3808 | continue; | 
|  | 3809 | PrintHeader(S.sh_offset, S.sh_size); | 
|  | 3810 | Error Err = Error::success(); | 
|  | 3811 | for (const auto &Note : Obj->notes(S, Err)) | 
|  | 3812 | ProcessNote(Note); | 
|  | 3813 | if (Err) | 
|  | 3814 | error(std::move(Err)); | 
|  | 3815 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 3816 | } | 
|  | 3817 | } | 
|  | 3818 |  | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 3819 | template <class ELFT> | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 3820 | void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { | 
|  | 3821 | OS << "printELFLinkerOptions not implemented!\n"; | 
|  | 3822 | } | 
|  | 3823 |  | 
|  | 3824 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 3825 | void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { | 
|  | 3826 | size_t Bias = ELFT::Is64Bits ? 8 : 0; | 
|  | 3827 | auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { | 
|  | 3828 | OS.PadToColumn(2); | 
|  | 3829 | OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); | 
|  | 3830 | OS.PadToColumn(11 + Bias); | 
|  | 3831 | OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)"; | 
|  | 3832 | OS.PadToColumn(22 + Bias); | 
|  | 3833 | OS << format_hex_no_prefix(*E, 8 + Bias); | 
|  | 3834 | OS.PadToColumn(31 + 2 * Bias); | 
|  | 3835 | OS << Purpose << "\n"; | 
|  | 3836 | }; | 
|  | 3837 |  | 
|  | 3838 | OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n"); | 
|  | 3839 | OS << " Canonical gp value: " | 
|  | 3840 | << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; | 
|  | 3841 |  | 
|  | 3842 | OS << " Reserved entries:\n"; | 
|  | 3843 | OS << "   Address     Access  Initial Purpose\n"; | 
|  | 3844 | PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); | 
|  | 3845 | if (Parser.getGotModulePointer()) | 
|  | 3846 | PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); | 
|  | 3847 |  | 
|  | 3848 | if (!Parser.getLocalEntries().empty()) { | 
|  | 3849 | OS << "\n"; | 
|  | 3850 | OS << " Local entries:\n"; | 
|  | 3851 | OS << "   Address     Access  Initial\n"; | 
|  | 3852 | for (auto &E : Parser.getLocalEntries()) | 
|  | 3853 | PrintEntry(&E, ""); | 
|  | 3854 | } | 
|  | 3855 |  | 
|  | 3856 | if (Parser.IsStatic) | 
|  | 3857 | return; | 
|  | 3858 |  | 
|  | 3859 | if (!Parser.getGlobalEntries().empty()) { | 
|  | 3860 | OS << "\n"; | 
|  | 3861 | OS << " Global entries:\n"; | 
|  | 3862 | OS << "   Address     Access  Initial Sym.Val. Type    Ndx Name\n"; | 
|  | 3863 | for (auto &E : Parser.getGlobalEntries()) { | 
|  | 3864 | const Elf_Sym *Sym = Parser.getGotSym(&E); | 
|  | 3865 | std::string SymName = this->dumper()->getFullSymbolName( | 
|  | 3866 | Sym, this->dumper()->getDynamicStringTable(), false); | 
|  | 3867 |  | 
|  | 3868 | OS.PadToColumn(2); | 
|  | 3869 | OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); | 
|  | 3870 | OS.PadToColumn(11 + Bias); | 
|  | 3871 | OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)"; | 
|  | 3872 | OS.PadToColumn(22 + Bias); | 
|  | 3873 | OS << to_string(format_hex_no_prefix(E, 8 + Bias)); | 
|  | 3874 | OS.PadToColumn(31 + 2 * Bias); | 
|  | 3875 | OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); | 
|  | 3876 | OS.PadToColumn(40 + 3 * Bias); | 
|  | 3877 | OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); | 
|  | 3878 | OS.PadToColumn(48 + 3 * Bias); | 
|  | 3879 | OS << getSymbolSectionNdx(Parser.Obj, Sym, | 
|  | 3880 | this->dumper()->dynamic_symbols().begin()); | 
|  | 3881 | OS.PadToColumn(52 + 3 * Bias); | 
|  | 3882 | OS << SymName << "\n"; | 
|  | 3883 | } | 
|  | 3884 | } | 
|  | 3885 |  | 
|  | 3886 | if (!Parser.getOtherEntries().empty()) | 
|  | 3887 | OS << "\n Number of TLS and multi-GOT entries " | 
|  | 3888 | << Parser.getOtherEntries().size() << "\n"; | 
|  | 3889 | } | 
|  | 3890 |  | 
|  | 3891 | template <class ELFT> | 
|  | 3892 | void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { | 
|  | 3893 | size_t Bias = ELFT::Is64Bits ? 8 : 0; | 
|  | 3894 | auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) { | 
|  | 3895 | OS.PadToColumn(2); | 
|  | 3896 | OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias); | 
|  | 3897 | OS.PadToColumn(11 + Bias); | 
|  | 3898 | OS << format_hex_no_prefix(*E, 8 + Bias); | 
|  | 3899 | OS.PadToColumn(20 + 2 * Bias); | 
|  | 3900 | OS << Purpose << "\n"; | 
|  | 3901 | }; | 
|  | 3902 |  | 
|  | 3903 | OS << "PLT GOT:\n\n"; | 
|  | 3904 |  | 
|  | 3905 | OS << " Reserved entries:\n"; | 
|  | 3906 | OS << "   Address  Initial Purpose\n"; | 
|  | 3907 | PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver"); | 
|  | 3908 | if (Parser.getPltModulePointer()) | 
|  | 3909 | PrintEntry(Parser.getGotModulePointer(), "Module pointer"); | 
|  | 3910 |  | 
|  | 3911 | if (!Parser.getPltEntries().empty()) { | 
|  | 3912 | OS << "\n"; | 
|  | 3913 | OS << " Entries:\n"; | 
|  | 3914 | OS << "   Address  Initial Sym.Val. Type    Ndx Name\n"; | 
|  | 3915 | for (auto &E : Parser.getPltEntries()) { | 
|  | 3916 | const Elf_Sym *Sym = Parser.getPltSym(&E); | 
|  | 3917 | std::string SymName = this->dumper()->getFullSymbolName( | 
|  | 3918 | Sym, this->dumper()->getDynamicStringTable(), false); | 
|  | 3919 |  | 
|  | 3920 | OS.PadToColumn(2); | 
|  | 3921 | OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias)); | 
|  | 3922 | OS.PadToColumn(11 + Bias); | 
|  | 3923 | OS << to_string(format_hex_no_prefix(E, 8 + Bias)); | 
|  | 3924 | OS.PadToColumn(20 + 2 * Bias); | 
|  | 3925 | OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias)); | 
|  | 3926 | OS.PadToColumn(29 + 3 * Bias); | 
|  | 3927 | OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes)); | 
|  | 3928 | OS.PadToColumn(37 + 3 * Bias); | 
|  | 3929 | OS << getSymbolSectionNdx(Parser.Obj, Sym, | 
|  | 3930 | this->dumper()->dynamic_symbols().begin()); | 
|  | 3931 | OS.PadToColumn(41 + 3 * Bias); | 
|  | 3932 | OS << SymName << "\n"; | 
|  | 3933 | } | 
|  | 3934 | } | 
|  | 3935 | } | 
|  | 3936 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 3937 | template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 3938 | const Elf_Ehdr *e = Obj->getHeader(); | 
|  | 3939 | { | 
|  | 3940 | DictScope D(W, "ElfHeader"); | 
|  | 3941 | { | 
|  | 3942 | DictScope D(W, "Ident"); | 
|  | 3943 | W.printBinary("Magic", makeArrayRef(e->e_ident).slice(ELF::EI_MAG0, 4)); | 
|  | 3944 | W.printEnum("Class", e->e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass)); | 
|  | 3945 | W.printEnum("DataEncoding", e->e_ident[ELF::EI_DATA], | 
|  | 3946 | makeArrayRef(ElfDataEncoding)); | 
|  | 3947 | W.printNumber("FileVersion", e->e_ident[ELF::EI_VERSION]); | 
|  | 3948 |  | 
| Konstantin Zhuravlyov | 121125f | 2017-10-02 20:49:58 +0000 | [diff] [blame] | 3949 | auto OSABI = makeArrayRef(ElfOSABI); | 
|  | 3950 | if (e->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH && | 
|  | 3951 | e->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) { | 
|  | 3952 | switch (e->e_machine) { | 
|  | 3953 | case ELF::EM_AMDGPU: | 
|  | 3954 | OSABI = makeArrayRef(AMDGPUElfOSABI); | 
|  | 3955 | break; | 
|  | 3956 | case ELF::EM_ARM: | 
|  | 3957 | OSABI = makeArrayRef(ARMElfOSABI); | 
|  | 3958 | break; | 
|  | 3959 | case ELF::EM_TI_C6000: | 
|  | 3960 | OSABI = makeArrayRef(C6000ElfOSABI); | 
|  | 3961 | break; | 
|  | 3962 | } | 
|  | 3963 | } | 
|  | 3964 | W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI], OSABI); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 3965 | W.printNumber("ABIVersion", e->e_ident[ELF::EI_ABIVERSION]); | 
|  | 3966 | W.printBinary("Unused", makeArrayRef(e->e_ident).slice(ELF::EI_PAD)); | 
|  | 3967 | } | 
|  | 3968 |  | 
|  | 3969 | W.printEnum("Type", e->e_type, makeArrayRef(ElfObjectFileType)); | 
|  | 3970 | W.printEnum("Machine", e->e_machine, makeArrayRef(ElfMachineType)); | 
|  | 3971 | W.printNumber("Version", e->e_version); | 
|  | 3972 | W.printHex("Entry", e->e_entry); | 
|  | 3973 | W.printHex("ProgramHeaderOffset", e->e_phoff); | 
|  | 3974 | W.printHex("SectionHeaderOffset", e->e_shoff); | 
|  | 3975 | if (e->e_machine == EM_MIPS) | 
|  | 3976 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderMipsFlags), | 
|  | 3977 | unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI), | 
|  | 3978 | unsigned(ELF::EF_MIPS_MACH)); | 
| Konstantin Zhuravlyov | aa0835a | 2017-10-05 16:19:18 +0000 | [diff] [blame] | 3979 | else if (e->e_machine == EM_AMDGPU) | 
|  | 3980 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags), | 
| Konstantin Zhuravlyov | 9122a63 | 2018-02-16 22:33:59 +0000 | [diff] [blame] | 3981 | unsigned(ELF::EF_AMDGPU_MACH)); | 
| Alex Bradbury | bb89b2b | 2017-10-03 08:41:59 +0000 | [diff] [blame] | 3982 | else if (e->e_machine == EM_RISCV) | 
|  | 3983 | W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags)); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 3984 | else | 
|  | 3985 | W.printFlags("Flags", e->e_flags); | 
|  | 3986 | W.printNumber("HeaderSize", e->e_ehsize); | 
|  | 3987 | W.printNumber("ProgramHeaderEntrySize", e->e_phentsize); | 
|  | 3988 | W.printNumber("ProgramHeaderCount", e->e_phnum); | 
|  | 3989 | W.printNumber("SectionHeaderEntrySize", e->e_shentsize); | 
| George Rimar | 6fdac3b | 2018-07-18 08:19:58 +0000 | [diff] [blame] | 3990 | W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj)); | 
|  | 3991 | W.printString("StringTableSectionIndex", getSectionHeaderTableIndexString(Obj)); | 
| Hemant Kulkarni | d8a985e | 2016-02-10 20:40:55 +0000 | [diff] [blame] | 3992 | } | 
|  | 3993 | } | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 3994 |  | 
|  | 3995 | template <class ELFT> | 
|  | 3996 | void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) { | 
|  | 3997 | DictScope Lists(W, "Groups"); | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 3998 | std::vector<GroupSection> V = getGroups<ELFT>(Obj); | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 3999 | DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V); | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 4000 | for (const GroupSection &G : V) { | 
|  | 4001 | DictScope D(W, "Group"); | 
|  | 4002 | W.printNumber("Name", G.Name, G.ShName); | 
|  | 4003 | W.printNumber("Index", G.Index); | 
| Alexander Shaposhnikov | 8febe3d | 2018-03-12 22:40:09 +0000 | [diff] [blame] | 4004 | W.printNumber("Link", G.Link); | 
|  | 4005 | W.printNumber("Info", G.Info); | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 4006 | W.printHex("Type", getGroupType(G.Type), G.Type); | 
|  | 4007 | W.startLine() << "Signature: " << G.Signature << "\n"; | 
|  | 4008 |  | 
|  | 4009 | ListScope L(W, "Section(s) in group"); | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 4010 | for (const GroupMember &GM : G.Members) { | 
|  | 4011 | const GroupSection *MainGroup = Map[GM.Index]; | 
|  | 4012 | if (MainGroup != &G) { | 
|  | 4013 | W.flush(); | 
|  | 4014 | errs() << "Error: " << GM.Name << " (" << GM.Index | 
|  | 4015 | << ") in a group " + G.Name + " (" << G.Index | 
|  | 4016 | << ") is already in a group " + MainGroup->Name + " (" | 
|  | 4017 | << MainGroup->Index << ")\n"; | 
|  | 4018 | errs().flush(); | 
|  | 4019 | continue; | 
|  | 4020 | } | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 4021 | W.startLine() << GM.Name << " (" << GM.Index << ")\n"; | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 4022 | } | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 4023 | } | 
| George Rimar | ea39eed | 2017-09-14 07:32:52 +0000 | [diff] [blame] | 4024 |  | 
|  | 4025 | if (V.empty()) | 
| Hemant Kulkarni | 206ba84 | 2016-03-09 19:16:13 +0000 | [diff] [blame] | 4026 | W.startLine() << "There are no group sections in the file.\n"; | 
|  | 4027 | } | 
| George Rimar | 762abff6 | 2017-09-16 14:29:51 +0000 | [diff] [blame] | 4028 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4029 | template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) { | 
|  | 4030 | ListScope D(W, "Relocations"); | 
|  | 4031 |  | 
|  | 4032 | int SectionNumber = -1; | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 4033 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4034 | ++SectionNumber; | 
|  | 4035 |  | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 4036 | if (Sec.sh_type != ELF::SHT_REL && | 
|  | 4037 | Sec.sh_type != ELF::SHT_RELA && | 
|  | 4038 | Sec.sh_type != ELF::SHT_RELR && | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 4039 | Sec.sh_type != ELF::SHT_ANDROID_REL && | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 4040 | Sec.sh_type != ELF::SHT_ANDROID_RELA && | 
|  | 4041 | Sec.sh_type != ELF::SHT_ANDROID_RELR) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4042 | continue; | 
|  | 4043 |  | 
|  | 4044 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 4045 |  | 
|  | 4046 | W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; | 
|  | 4047 | W.indent(); | 
|  | 4048 |  | 
|  | 4049 | printRelocations(&Sec, Obj); | 
|  | 4050 |  | 
|  | 4051 | W.unindent(); | 
|  | 4052 | W.startLine() << "}\n"; | 
|  | 4053 | } | 
|  | 4054 | } | 
|  | 4055 |  | 
|  | 4056 | template <class ELFT> | 
|  | 4057 | void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { | 
|  | 4058 | const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); | 
|  | 4059 |  | 
|  | 4060 | switch (Sec->sh_type) { | 
|  | 4061 | case ELF::SHT_REL: | 
| Rafael Espindola | 354680a | 2016-11-03 19:07:15 +0000 | [diff] [blame] | 4062 | for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4063 | Elf_Rela Rela; | 
|  | 4064 | Rela.r_offset = R.r_offset; | 
|  | 4065 | Rela.r_info = R.r_info; | 
|  | 4066 | Rela.r_addend = 0; | 
|  | 4067 | printRelocation(Obj, Rela, SymTab); | 
|  | 4068 | } | 
|  | 4069 | break; | 
|  | 4070 | case ELF::SHT_RELA: | 
| Rafael Espindola | 354680a | 2016-11-03 19:07:15 +0000 | [diff] [blame] | 4071 | for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4072 | printRelocation(Obj, R, SymTab); | 
|  | 4073 | break; | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 4074 | case ELF::SHT_RELR: | 
|  | 4075 | case ELF::SHT_ANDROID_RELR: { | 
|  | 4076 | Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); | 
|  | 4077 | if (opts::RawRelr) { | 
|  | 4078 | for (const Elf_Relr &R : Relrs) | 
|  | 4079 | W.startLine() << W.hex(R) << "\n"; | 
|  | 4080 | } else { | 
|  | 4081 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | 
|  | 4082 | for (const Elf_Rela &R : RelrRelas) | 
|  | 4083 | printRelocation(Obj, R, SymTab); | 
|  | 4084 | } | 
|  | 4085 | break; | 
|  | 4086 | } | 
| Peter Collingbourne | 689e6c05 | 2017-10-25 03:37:12 +0000 | [diff] [blame] | 4087 | case ELF::SHT_ANDROID_REL: | 
|  | 4088 | case ELF::SHT_ANDROID_RELA: | 
|  | 4089 | for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec))) | 
|  | 4090 | printRelocation(Obj, R, SymTab); | 
|  | 4091 | break; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4092 | } | 
|  | 4093 | } | 
|  | 4094 |  | 
|  | 4095 | template <class ELFT> | 
|  | 4096 | void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel, | 
|  | 4097 | const Elf_Shdr *SymTab) { | 
|  | 4098 | SmallString<32> RelocName; | 
|  | 4099 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | 
|  | 4100 | StringRef TargetName; | 
| Rafael Espindola | ed1395a | 2016-11-03 18:05:33 +0000 | [diff] [blame] | 4101 | const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab)); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4102 | if (Sym && Sym->getType() == ELF::STT_SECTION) { | 
|  | 4103 | const Elf_Shdr *Sec = unwrapOrError( | 
|  | 4104 | Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); | 
|  | 4105 | TargetName = unwrapOrError(Obj->getSectionName(Sec)); | 
|  | 4106 | } else if (Sym) { | 
|  | 4107 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); | 
|  | 4108 | TargetName = unwrapOrError(Sym->getName(StrTable)); | 
|  | 4109 | } | 
|  | 4110 |  | 
|  | 4111 | if (opts::ExpandRelocs) { | 
|  | 4112 | DictScope Group(W, "Relocation"); | 
|  | 4113 | W.printHex("Offset", Rel.r_offset); | 
|  | 4114 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 4115 | W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-", | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4116 | Rel.getSymbol(Obj->isMips64EL())); | 
|  | 4117 | W.printHex("Addend", Rel.r_addend); | 
|  | 4118 | } else { | 
|  | 4119 | raw_ostream &OS = W.startLine(); | 
|  | 4120 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 4121 | << (!TargetName.empty() ? TargetName : "-") << " " | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4122 | << W.hex(Rel.r_addend) << "\n"; | 
|  | 4123 | } | 
|  | 4124 | } | 
|  | 4125 |  | 
|  | 4126 | template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { | 
|  | 4127 | ListScope SectionsD(W, "Sections"); | 
|  | 4128 |  | 
|  | 4129 | int SectionIndex = -1; | 
| Rafael Espindola | 25be8c8 | 2016-11-02 14:10:57 +0000 | [diff] [blame] | 4130 | for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4131 | ++SectionIndex; | 
|  | 4132 |  | 
|  | 4133 | StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); | 
|  | 4134 |  | 
|  | 4135 | DictScope SectionD(W, "Section"); | 
|  | 4136 | W.printNumber("Index", SectionIndex); | 
|  | 4137 | W.printNumber("Name", Name, Sec.sh_name); | 
| Rafael Espindola | 3ba2573 | 2017-05-02 14:04:52 +0000 | [diff] [blame] | 4138 | W.printHex( | 
|  | 4139 | "Type", | 
|  | 4140 | object::getELFSectionTypeName(Obj->getHeader()->e_machine, Sec.sh_type), | 
|  | 4141 | Sec.sh_type); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4142 | std::vector<EnumEntry<unsigned>> SectionFlags(std::begin(ElfSectionFlags), | 
|  | 4143 | std::end(ElfSectionFlags)); | 
|  | 4144 | switch (Obj->getHeader()->e_machine) { | 
| Prakhar Bahuguna | 52a7dd7 | 2016-12-15 07:59:08 +0000 | [diff] [blame] | 4145 | case EM_ARM: | 
|  | 4146 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), | 
|  | 4147 | std::end(ElfARMSectionFlags)); | 
|  | 4148 | break; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4149 | case EM_HEXAGON: | 
|  | 4150 | SectionFlags.insert(SectionFlags.end(), | 
|  | 4151 | std::begin(ElfHexagonSectionFlags), | 
|  | 4152 | std::end(ElfHexagonSectionFlags)); | 
|  | 4153 | break; | 
|  | 4154 | case EM_MIPS: | 
|  | 4155 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags), | 
|  | 4156 | std::end(ElfMipsSectionFlags)); | 
|  | 4157 | break; | 
|  | 4158 | case EM_X86_64: | 
|  | 4159 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags), | 
|  | 4160 | std::end(ElfX86_64SectionFlags)); | 
|  | 4161 | break; | 
| George Rimar | c13c59a | 2016-05-21 10:16:58 +0000 | [diff] [blame] | 4162 | case EM_XCORE: | 
|  | 4163 | SectionFlags.insert(SectionFlags.end(), std::begin(ElfXCoreSectionFlags), | 
|  | 4164 | std::end(ElfXCoreSectionFlags)); | 
|  | 4165 | break; | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4166 | default: | 
|  | 4167 | // Nothing to do. | 
|  | 4168 | break; | 
|  | 4169 | } | 
|  | 4170 | W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags)); | 
|  | 4171 | W.printHex("Address", Sec.sh_addr); | 
|  | 4172 | W.printHex("Offset", Sec.sh_offset); | 
|  | 4173 | W.printNumber("Size", Sec.sh_size); | 
|  | 4174 | W.printNumber("Link", Sec.sh_link); | 
|  | 4175 | W.printNumber("Info", Sec.sh_info); | 
|  | 4176 | W.printNumber("AddressAlignment", Sec.sh_addralign); | 
|  | 4177 | W.printNumber("EntrySize", Sec.sh_entsize); | 
|  | 4178 |  | 
|  | 4179 | if (opts::SectionRelocations) { | 
|  | 4180 | ListScope D(W, "Relocations"); | 
|  | 4181 | printRelocations(&Sec, Obj); | 
|  | 4182 | } | 
|  | 4183 |  | 
|  | 4184 | if (opts::SectionSymbols) { | 
|  | 4185 | ListScope D(W, "Symbols"); | 
|  | 4186 | const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec(); | 
|  | 4187 | StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); | 
|  | 4188 |  | 
| Rafael Espindola | 9ea6834 | 2016-11-03 13:43:30 +0000 | [diff] [blame] | 4189 | for (const Elf_Sym &Sym : unwrapOrError(Obj->symbols(Symtab))) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4190 | const Elf_Shdr *SymSec = unwrapOrError( | 
|  | 4191 | Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable())); | 
|  | 4192 | if (SymSec == &Sec) | 
| Rafael Espindola | 9ea6834 | 2016-11-03 13:43:30 +0000 | [diff] [blame] | 4193 | printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(), | 
|  | 4194 | StrTable, false); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4195 | } | 
|  | 4196 | } | 
|  | 4197 |  | 
|  | 4198 | if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { | 
|  | 4199 | ArrayRef<uint8_t> Data = unwrapOrError(Obj->getSectionContents(&Sec)); | 
|  | 4200 | W.printBinaryBlock("SectionData", | 
|  | 4201 | StringRef((const char *)Data.data(), Data.size())); | 
|  | 4202 | } | 
|  | 4203 | } | 
|  | 4204 | } | 
|  | 4205 |  | 
|  | 4206 | template <class ELFT> | 
|  | 4207 | void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, | 
|  | 4208 | const Elf_Sym *First, StringRef StrTable, | 
|  | 4209 | bool IsDynamic) { | 
|  | 4210 | unsigned SectionIndex = 0; | 
|  | 4211 | StringRef SectionName; | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 4212 | this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4213 | std::string FullSymbolName = | 
|  | 4214 | this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); | 
|  | 4215 | unsigned char SymbolType = Symbol->getType(); | 
|  | 4216 |  | 
|  | 4217 | DictScope D(W, "Symbol"); | 
|  | 4218 | W.printNumber("Name", FullSymbolName, Symbol->st_name); | 
|  | 4219 | W.printHex("Value", Symbol->st_value); | 
|  | 4220 | W.printNumber("Size", Symbol->st_size); | 
|  | 4221 | W.printEnum("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); | 
|  | 4222 | if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && | 
|  | 4223 | SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) | 
|  | 4224 | W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); | 
|  | 4225 | else | 
|  | 4226 | W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); | 
| Simon Atanasyan | b7807a0 | 2016-03-24 16:10:37 +0000 | [diff] [blame] | 4227 | if (Symbol->st_other == 0) | 
|  | 4228 | // Usually st_other flag is zero. Do not pollute the output | 
|  | 4229 | // by flags enumeration in that case. | 
|  | 4230 | W.printNumber("Other", 0); | 
|  | 4231 | else { | 
|  | 4232 | std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags), | 
|  | 4233 | std::end(ElfSymOtherFlags)); | 
|  | 4234 | if (Obj->getHeader()->e_machine == EM_MIPS) { | 
|  | 4235 | // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16 | 
|  | 4236 | // flag overlapped with other ST_MIPS_xxx flags. So consider both | 
|  | 4237 | // cases separately. | 
|  | 4238 | if ((Symbol->st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) | 
|  | 4239 | SymOtherFlags.insert(SymOtherFlags.end(), | 
|  | 4240 | std::begin(ElfMips16SymOtherFlags), | 
|  | 4241 | std::end(ElfMips16SymOtherFlags)); | 
|  | 4242 | else | 
|  | 4243 | SymOtherFlags.insert(SymOtherFlags.end(), | 
|  | 4244 | std::begin(ElfMipsSymOtherFlags), | 
|  | 4245 | std::end(ElfMipsSymOtherFlags)); | 
|  | 4246 | } | 
|  | 4247 | W.printFlags("Other", Symbol->st_other, makeArrayRef(SymOtherFlags), 0x3u); | 
|  | 4248 | } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4249 | W.printHex("Section", SectionName, SectionIndex); | 
|  | 4250 | } | 
|  | 4251 |  | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4252 | template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) { | 
|  | 4253 | ListScope Group(W, "Symbols"); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 4254 | this->dumper()->printSymbolsHelper(false); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4255 | } | 
|  | 4256 |  | 
|  | 4257 | template <class ELFT> | 
|  | 4258 | void LLVMStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { | 
|  | 4259 | ListScope Group(W, "DynamicSymbols"); | 
| Hemant Kulkarni | a11fbe1 | 2016-03-21 17:18:23 +0000 | [diff] [blame] | 4260 | this->dumper()->printSymbolsHelper(true); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4261 | } | 
|  | 4262 |  | 
|  | 4263 | template <class ELFT> | 
|  | 4264 | void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) { | 
|  | 4265 | const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); | 
|  | 4266 | const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 4267 | const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4268 | const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); | 
|  | 4269 | if (DynRelRegion.Size && DynRelaRegion.Size) | 
|  | 4270 | report_fatal_error("There are both REL and RELA dynamic relocations"); | 
|  | 4271 | W.startLine() << "Dynamic Relocations {\n"; | 
|  | 4272 | W.indent(); | 
|  | 4273 | if (DynRelaRegion.Size > 0) | 
|  | 4274 | for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) | 
|  | 4275 | printDynamicRelocation(Obj, Rela); | 
|  | 4276 | else | 
|  | 4277 | for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { | 
|  | 4278 | Elf_Rela Rela; | 
|  | 4279 | Rela.r_offset = Rel.r_offset; | 
|  | 4280 | Rela.r_info = Rel.r_info; | 
|  | 4281 | Rela.r_addend = 0; | 
|  | 4282 | printDynamicRelocation(Obj, Rela); | 
|  | 4283 | } | 
| Jake Ehrlich | 0f440d8 | 2018-06-28 21:07:34 +0000 | [diff] [blame] | 4284 | if (DynRelrRegion.Size > 0) { | 
|  | 4285 | Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); | 
|  | 4286 | std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); | 
|  | 4287 | for (const Elf_Rela &Rela : RelrRelas) | 
|  | 4288 | printDynamicRelocation(Obj, Rela); | 
|  | 4289 | } | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4290 | if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 4291 | for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>()) | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4292 | printDynamicRelocation(Obj, Rela); | 
|  | 4293 | else | 
| Rafael Espindola | aafcf75 | 2016-04-05 14:47:22 +0000 | [diff] [blame] | 4294 | for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) { | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4295 | Elf_Rela Rela; | 
|  | 4296 | Rela.r_offset = Rel.r_offset; | 
|  | 4297 | Rela.r_info = Rel.r_info; | 
|  | 4298 | Rela.r_addend = 0; | 
|  | 4299 | printDynamicRelocation(Obj, Rela); | 
|  | 4300 | } | 
|  | 4301 | W.unindent(); | 
|  | 4302 | W.startLine() << "}\n"; | 
|  | 4303 | } | 
|  | 4304 |  | 
|  | 4305 | template <class ELFT> | 
|  | 4306 | void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { | 
|  | 4307 | SmallString<32> RelocName; | 
|  | 4308 | Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); | 
|  | 4309 | StringRef SymbolName; | 
|  | 4310 | uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); | 
|  | 4311 | const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; | 
|  | 4312 | SymbolName = | 
|  | 4313 | unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); | 
|  | 4314 | if (opts::ExpandRelocs) { | 
|  | 4315 | DictScope Group(W, "Relocation"); | 
|  | 4316 | W.printHex("Offset", Rel.r_offset); | 
|  | 4317 | W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 4318 | W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4319 | W.printHex("Addend", Rel.r_addend); | 
|  | 4320 | } else { | 
|  | 4321 | raw_ostream &OS = W.startLine(); | 
|  | 4322 | OS << W.hex(Rel.r_offset) << " " << RelocName << " " | 
| Eugene Zelenko | 416e059 | 2017-06-09 21:41:54 +0000 | [diff] [blame] | 4323 | << (!SymbolName.empty() ? SymbolName : "-") << " " | 
| Hemant Kulkarni | c030f23 | 2016-03-15 17:25:31 +0000 | [diff] [blame] | 4324 | << W.hex(Rel.r_addend) << "\n"; | 
|  | 4325 | } | 
|  | 4326 | } | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 4327 |  | 
|  | 4328 | template <class ELFT> | 
|  | 4329 | void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { | 
|  | 4330 | ListScope L(W, "ProgramHeaders"); | 
|  | 4331 |  | 
| Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 4332 | for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { | 
| Hemant Kulkarni | 966b3ac | 2016-03-25 16:04:48 +0000 | [diff] [blame] | 4333 | DictScope P(W, "ProgramHeader"); | 
|  | 4334 | W.printHex("Type", | 
|  | 4335 | getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), | 
|  | 4336 | Phdr.p_type); | 
|  | 4337 | W.printHex("Offset", Phdr.p_offset); | 
|  | 4338 | W.printHex("VirtualAddress", Phdr.p_vaddr); | 
|  | 4339 | W.printHex("PhysicalAddress", Phdr.p_paddr); | 
|  | 4340 | W.printNumber("FileSize", Phdr.p_filesz); | 
|  | 4341 | W.printNumber("MemSize", Phdr.p_memsz); | 
|  | 4342 | W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags)); | 
|  | 4343 | W.printNumber("Alignment", Phdr.p_align); | 
|  | 4344 | } | 
|  | 4345 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 4346 |  | 
| Hemant Kulkarni | 9b1b7f0 | 2016-04-11 17:15:30 +0000 | [diff] [blame] | 4347 | template <class ELFT> | 
|  | 4348 | void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { | 
|  | 4349 | W.startLine() << "Hash Histogram not implemented!\n"; | 
|  | 4350 | } | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 4351 |  | 
|  | 4352 | template <class ELFT> | 
| Michael J. Spencer | ae6eeae | 2018-06-02 16:33:01 +0000 | [diff] [blame] | 4353 | void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) { | 
|  | 4354 | ListScope L(W, "CGProfile"); | 
|  | 4355 | if (!this->dumper()->getDotCGProfileSec()) | 
|  | 4356 | return; | 
|  | 4357 | auto CGProfile = | 
|  | 4358 | unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>( | 
|  | 4359 | this->dumper()->getDotCGProfileSec())); | 
|  | 4360 | for (const Elf_CGProfile &CGPE : CGProfile) { | 
|  | 4361 | DictScope D(W, "CGProfileEntry"); | 
|  | 4362 | W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), | 
|  | 4363 | CGPE.cgp_from); | 
|  | 4364 | W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), | 
|  | 4365 | CGPE.cgp_to); | 
|  | 4366 | W.printNumber("Weight", CGPE.cgp_weight); | 
|  | 4367 | } | 
|  | 4368 | } | 
|  | 4369 |  | 
|  | 4370 | template <class ELFT> | 
| Peter Collingbourne | 3e22733 | 2018-07-17 22:17:18 +0000 | [diff] [blame] | 4371 | void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) { | 
|  | 4372 | ListScope L(W, "Addrsig"); | 
|  | 4373 | if (!this->dumper()->getDotAddrsigSec()) | 
|  | 4374 | return; | 
|  | 4375 | ArrayRef<uint8_t> Contents = unwrapOrError( | 
|  | 4376 | Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); | 
|  | 4377 | const uint8_t *Cur = Contents.begin(); | 
|  | 4378 | const uint8_t *End = Contents.end(); | 
|  | 4379 | while (Cur != End) { | 
|  | 4380 | unsigned Size; | 
|  | 4381 | const char *Err; | 
|  | 4382 | uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); | 
|  | 4383 | if (Err) | 
|  | 4384 | reportError(Err); | 
|  | 4385 | W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), | 
|  | 4386 | SymIndex); | 
|  | 4387 | Cur += Size; | 
|  | 4388 | } | 
|  | 4389 | } | 
|  | 4390 |  | 
|  | 4391 | template <class ELFT> | 
| Saleem Abdulrasool | 6a40544 | 2016-08-30 18:52:02 +0000 | [diff] [blame] | 4392 | void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { | 
|  | 4393 | W.startLine() << "printNotes not implemented!\n"; | 
|  | 4394 | } | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 4395 |  | 
|  | 4396 | template <class ELFT> | 
| Saleem Abdulrasool | b36fbbc | 2018-01-30 16:29:29 +0000 | [diff] [blame] | 4397 | void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) { | 
|  | 4398 | ListScope L(W, "LinkerOptions"); | 
|  | 4399 |  | 
|  | 4400 | for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) { | 
|  | 4401 | if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS) | 
|  | 4402 | continue; | 
|  | 4403 |  | 
|  | 4404 | ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr)); | 
|  | 4405 | for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) { | 
|  | 4406 | StringRef Key = StringRef(reinterpret_cast<const char *>(P)); | 
|  | 4407 | StringRef Value = | 
|  | 4408 | StringRef(reinterpret_cast<const char *>(P) + Key.size() + 1); | 
|  | 4409 |  | 
|  | 4410 | W.printString(Key, Value); | 
|  | 4411 |  | 
|  | 4412 | P = P + Key.size() + Value.size() + 2; | 
|  | 4413 | } | 
|  | 4414 | } | 
|  | 4415 | } | 
|  | 4416 |  | 
|  | 4417 | template <class ELFT> | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 4418 | void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) { | 
|  | 4419 | auto PrintEntry = [&](const Elf_Addr *E) { | 
|  | 4420 | W.printHex("Address", Parser.getGotAddress(E)); | 
|  | 4421 | W.printNumber("Access", Parser.getGotOffset(E)); | 
|  | 4422 | W.printHex("Initial", *E); | 
|  | 4423 | }; | 
|  | 4424 |  | 
|  | 4425 | DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT"); | 
|  | 4426 |  | 
|  | 4427 | W.printHex("Canonical gp value", Parser.getGp()); | 
|  | 4428 | { | 
|  | 4429 | ListScope RS(W, "Reserved entries"); | 
|  | 4430 | { | 
|  | 4431 | DictScope D(W, "Entry"); | 
|  | 4432 | PrintEntry(Parser.getGotLazyResolver()); | 
|  | 4433 | W.printString("Purpose", StringRef("Lazy resolver")); | 
|  | 4434 | } | 
|  | 4435 |  | 
|  | 4436 | if (Parser.getGotModulePointer()) { | 
|  | 4437 | DictScope D(W, "Entry"); | 
|  | 4438 | PrintEntry(Parser.getGotModulePointer()); | 
|  | 4439 | W.printString("Purpose", StringRef("Module pointer (GNU extension)")); | 
|  | 4440 | } | 
|  | 4441 | } | 
|  | 4442 | { | 
|  | 4443 | ListScope LS(W, "Local entries"); | 
|  | 4444 | for (auto &E : Parser.getLocalEntries()) { | 
|  | 4445 | DictScope D(W, "Entry"); | 
|  | 4446 | PrintEntry(&E); | 
|  | 4447 | } | 
|  | 4448 | } | 
|  | 4449 |  | 
|  | 4450 | if (Parser.IsStatic) | 
|  | 4451 | return; | 
|  | 4452 |  | 
|  | 4453 | { | 
|  | 4454 | ListScope GS(W, "Global entries"); | 
|  | 4455 | for (auto &E : Parser.getGlobalEntries()) { | 
|  | 4456 | DictScope D(W, "Entry"); | 
|  | 4457 |  | 
|  | 4458 | PrintEntry(&E); | 
|  | 4459 |  | 
|  | 4460 | const Elf_Sym *Sym = Parser.getGotSym(&E); | 
|  | 4461 | W.printHex("Value", Sym->st_value); | 
|  | 4462 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | 
|  | 4463 |  | 
|  | 4464 | unsigned SectionIndex = 0; | 
|  | 4465 | StringRef SectionName; | 
|  | 4466 | this->dumper()->getSectionNameIndex( | 
|  | 4467 | Sym, this->dumper()->dynamic_symbols().begin(), SectionName, | 
|  | 4468 | SectionIndex); | 
|  | 4469 | W.printHex("Section", SectionName, SectionIndex); | 
|  | 4470 |  | 
|  | 4471 | std::string SymName = this->dumper()->getFullSymbolName( | 
|  | 4472 | Sym, this->dumper()->getDynamicStringTable(), true); | 
|  | 4473 | W.printNumber("Name", SymName, Sym->st_name); | 
|  | 4474 | } | 
|  | 4475 | } | 
|  | 4476 |  | 
|  | 4477 | W.printNumber("Number of TLS and multi-GOT entries", | 
| Simon Atanasyan | 4e945b6 | 2017-12-21 10:46:20 +0000 | [diff] [blame] | 4478 | uint64_t(Parser.getOtherEntries().size())); | 
| Simon Atanasyan | 62d3259 | 2017-12-21 10:26:02 +0000 | [diff] [blame] | 4479 | } | 
|  | 4480 |  | 
|  | 4481 | template <class ELFT> | 
|  | 4482 | void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) { | 
|  | 4483 | auto PrintEntry = [&](const Elf_Addr *E) { | 
|  | 4484 | W.printHex("Address", Parser.getPltAddress(E)); | 
|  | 4485 | W.printHex("Initial", *E); | 
|  | 4486 | }; | 
|  | 4487 |  | 
|  | 4488 | DictScope GS(W, "PLT GOT"); | 
|  | 4489 |  | 
|  | 4490 | { | 
|  | 4491 | ListScope RS(W, "Reserved entries"); | 
|  | 4492 | { | 
|  | 4493 | DictScope D(W, "Entry"); | 
|  | 4494 | PrintEntry(Parser.getPltLazyResolver()); | 
|  | 4495 | W.printString("Purpose", StringRef("PLT lazy resolver")); | 
|  | 4496 | } | 
|  | 4497 |  | 
|  | 4498 | if (auto E = Parser.getPltModulePointer()) { | 
|  | 4499 | DictScope D(W, "Entry"); | 
|  | 4500 | PrintEntry(E); | 
|  | 4501 | W.printString("Purpose", StringRef("Module pointer")); | 
|  | 4502 | } | 
|  | 4503 | } | 
|  | 4504 | { | 
|  | 4505 | ListScope LS(W, "Entries"); | 
|  | 4506 | for (auto &E : Parser.getPltEntries()) { | 
|  | 4507 | DictScope D(W, "Entry"); | 
|  | 4508 | PrintEntry(&E); | 
|  | 4509 |  | 
|  | 4510 | const Elf_Sym *Sym = Parser.getPltSym(&E); | 
|  | 4511 | W.printHex("Value", Sym->st_value); | 
|  | 4512 | W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); | 
|  | 4513 |  | 
|  | 4514 | unsigned SectionIndex = 0; | 
|  | 4515 | StringRef SectionName; | 
|  | 4516 | this->dumper()->getSectionNameIndex( | 
|  | 4517 | Sym, this->dumper()->dynamic_symbols().begin(), SectionName, | 
|  | 4518 | SectionIndex); | 
|  | 4519 | W.printHex("Section", SectionName, SectionIndex); | 
|  | 4520 |  | 
|  | 4521 | std::string SymName = | 
|  | 4522 | this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true); | 
|  | 4523 | W.printNumber("Name", SymName, Sym->st_name); | 
|  | 4524 | } | 
|  | 4525 | } | 
|  | 4526 | } |