Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 1 | //===-- ELFDump.cpp - ELF-specific dumper -----------------------*- C++ -*-===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 10 | /// This file implements the ELF-specific dumper for llvm-objdump. |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 11 | /// |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "llvm-objdump.h" |
George Rimar | c196488 | 2019-01-18 11:33:26 +0000 | [diff] [blame] | 15 | #include "llvm/Demangle/Demangle.h" |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 16 | #include "llvm/Object/ELFObjectFile.h" |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 17 | #include "llvm/Support/Format.h" |
| 18 | #include "llvm/Support/MathExtras.h" |
| 19 | #include "llvm/Support/raw_ostream.h" |
| 20 | |
| 21 | using namespace llvm; |
| 22 | using namespace llvm::object; |
| 23 | |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 24 | template <class ELFT> |
| 25 | Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) { |
| 26 | typedef ELFFile<ELFT> ELFO; |
| 27 | |
| 28 | auto DynamicEntriesOrError = Elf->dynamicEntries(); |
| 29 | if (!DynamicEntriesOrError) |
| 30 | return DynamicEntriesOrError.takeError(); |
| 31 | |
| 32 | for (const typename ELFO::Elf_Dyn &Dyn : *DynamicEntriesOrError) { |
| 33 | if (Dyn.d_tag == ELF::DT_STRTAB) { |
| 34 | auto MappedAddrOrError = Elf->toMappedAddr(Dyn.getPtr()); |
| 35 | if (!MappedAddrOrError) |
| 36 | consumeError(MappedAddrOrError.takeError()); |
| 37 | return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError)); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | // If the dynamic segment is not present, we fall back on the sections. |
| 42 | auto SectionsOrError = Elf->sections(); |
| 43 | if (!SectionsOrError) |
| 44 | return SectionsOrError.takeError(); |
| 45 | |
| 46 | for (const typename ELFO::Elf_Shdr &Sec : *SectionsOrError) { |
| 47 | if (Sec.sh_type == ELF::SHT_DYNSYM) |
| 48 | return Elf->getStringTableForSymtab(Sec); |
| 49 | } |
| 50 | |
| 51 | return createError("dynamic string table not found"); |
| 52 | } |
| 53 | |
| 54 | template <class ELFT> |
George Rimar | c196488 | 2019-01-18 11:33:26 +0000 | [diff] [blame] | 55 | static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, |
| 56 | const RelocationRef &RelRef, |
| 57 | SmallVectorImpl<char> &Result) { |
| 58 | typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; |
| 59 | typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; |
| 60 | typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela; |
| 61 | |
| 62 | const ELFFile<ELFT> &EF = *Obj->getELFFile(); |
| 63 | DataRefImpl Rel = RelRef.getRawDataRefImpl(); |
| 64 | auto SecOrErr = EF.getSection(Rel.d.a); |
| 65 | if (!SecOrErr) |
| 66 | return errorToErrorCode(SecOrErr.takeError()); |
| 67 | |
| 68 | int64_t Addend = 0; |
| 69 | // If there is no Symbol associated with the relocation, we set the undef |
| 70 | // boolean value to 'true'. This will prevent us from calling functions that |
| 71 | // requires the relocation to be associated with a symbol. |
| 72 | // |
| 73 | // In SHT_REL case we would need to read the addend from section data. |
| 74 | // GNU objdump does not do that and we just follow for simplicity atm. |
| 75 | bool Undef = false; |
| 76 | if ((*SecOrErr)->sh_type == ELF::SHT_RELA) { |
| 77 | const Elf_Rela *ERela = Obj->getRela(Rel); |
| 78 | Addend = ERela->r_addend; |
| 79 | Undef = ERela->getSymbol(false) == 0; |
| 80 | } else if ((*SecOrErr)->sh_type != ELF::SHT_REL) { |
| 81 | return object_error::parse_failed; |
| 82 | } |
| 83 | |
| 84 | // Default scheme is to print Target, as well as "+ <addend>" for nonzero |
| 85 | // addend. Should be acceptable for all normal purposes. |
| 86 | std::string FmtBuf; |
| 87 | raw_string_ostream Fmt(FmtBuf); |
| 88 | |
| 89 | if (!Undef) { |
| 90 | symbol_iterator SI = RelRef.getSymbol(); |
| 91 | const Elf_Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl()); |
| 92 | if (Sym->getType() == ELF::STT_SECTION) { |
| 93 | Expected<section_iterator> SymSI = SI->getSection(); |
| 94 | if (!SymSI) |
| 95 | return errorToErrorCode(SymSI.takeError()); |
| 96 | const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); |
| 97 | auto SecName = EF.getSectionName(SymSec); |
| 98 | if (!SecName) |
| 99 | return errorToErrorCode(SecName.takeError()); |
| 100 | Fmt << *SecName; |
| 101 | } else { |
| 102 | Expected<StringRef> SymName = SI->getName(); |
| 103 | if (!SymName) |
| 104 | return errorToErrorCode(SymName.takeError()); |
| 105 | if (Demangle) |
| 106 | Fmt << demangle(*SymName); |
| 107 | else |
| 108 | Fmt << *SymName; |
| 109 | } |
| 110 | } else { |
| 111 | Fmt << "*ABS*"; |
| 112 | } |
| 113 | |
| 114 | if (Addend != 0) |
| 115 | Fmt << (Addend < 0 ? "" : "+") << Addend; |
| 116 | Fmt.flush(); |
| 117 | Result.append(FmtBuf.begin(), FmtBuf.end()); |
| 118 | return std::error_code(); |
| 119 | } |
| 120 | |
| 121 | std::error_code |
| 122 | llvm::getELFRelocationValueString(const ELFObjectFileBase *Obj, |
| 123 | const RelocationRef &Rel, |
| 124 | SmallVectorImpl<char> &Result) { |
| 125 | if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj)) |
| 126 | return getRelocationValueString(ELF32LE, Rel, Result); |
| 127 | if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj)) |
| 128 | return getRelocationValueString(ELF64LE, Rel, Result); |
| 129 | if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj)) |
| 130 | return getRelocationValueString(ELF32BE, Rel, Result); |
| 131 | auto *ELF64BE = cast<ELF64BEObjectFile>(Obj); |
| 132 | return getRelocationValueString(ELF64BE, Rel, Result); |
| 133 | } |
| 134 | |
| 135 | template <class ELFT> |
George Rimar | 87fa2e6 | 2019-01-28 14:11:35 +0000 | [diff] [blame] | 136 | static uint64_t getSectionLMA(const ELFFile<ELFT> *Obj, |
| 137 | const object::ELFSectionRef &Sec) { |
| 138 | auto PhdrRangeOrErr = Obj->program_headers(); |
| 139 | if (!PhdrRangeOrErr) |
| 140 | report_fatal_error(errorToErrorCode(PhdrRangeOrErr.takeError()).message()); |
| 141 | |
| 142 | // Search for a PT_LOAD segment containing the requested section. Use this |
| 143 | // segment's p_addr to calculate the section's LMA. |
| 144 | for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *PhdrRangeOrErr) |
| 145 | if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_vaddr <= Sec.getAddress()) && |
| 146 | (Phdr.p_vaddr + Phdr.p_memsz > Sec.getAddress())) |
| 147 | return Sec.getAddress() - Phdr.p_vaddr + Phdr.p_paddr; |
| 148 | |
| 149 | // Return section's VMA if it isn't in a PT_LOAD segment. |
| 150 | return Sec.getAddress(); |
| 151 | } |
| 152 | |
| 153 | uint64_t llvm::getELFSectionLMA(const object::ELFSectionRef &Sec) { |
| 154 | if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Sec.getObject())) |
| 155 | return getSectionLMA(ELFObj->getELFFile(), Sec); |
| 156 | else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Sec.getObject())) |
| 157 | return getSectionLMA(ELFObj->getELFFile(), Sec); |
| 158 | else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Sec.getObject())) |
| 159 | return getSectionLMA(ELFObj->getELFFile(), Sec); |
| 160 | const auto *ELFObj = cast<ELF64BEObjectFile>(Sec.getObject()); |
| 161 | return getSectionLMA(ELFObj->getELFFile(), Sec); |
| 162 | } |
| 163 | |
| 164 | template <class ELFT> |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 165 | void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 166 | ArrayRef<typename ELFT::Dyn> DynamicEntries = |
| 167 | unwrapOrError(Elf->dynamicEntries(), Filename); |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 168 | outs() << "Dynamic Section:\n"; |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 169 | for (const typename ELFT::Dyn &Dyn : DynamicEntries) { |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 170 | if (Dyn.d_tag == ELF::DT_NULL) |
| 171 | continue; |
| 172 | |
Xing GUO | b285878 | 2019-03-02 04:20:28 +0000 | [diff] [blame] | 173 | std::string Str = Elf->getDynamicTagAsString(Dyn.d_tag); |
| 174 | outs() << format(" %-21s", Str.c_str()); |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 175 | |
| 176 | const char *Fmt = |
| 177 | ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; |
Xing GUO | d78164a | 2019-02-27 16:37:15 +0000 | [diff] [blame] | 178 | if (Dyn.d_tag == ELF::DT_NEEDED || Dyn.d_tag == ELF::DT_RPATH || |
| 179 | Dyn.d_tag == ELF::DT_RUNPATH || Dyn.d_tag == ELF::DT_SONAME || |
| 180 | Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER) { |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 181 | Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); |
| 182 | if (StrTabOrErr) { |
| 183 | const char *Data = StrTabOrErr.get().data(); |
| 184 | outs() << (Data + Dyn.d_un.d_val) << "\n"; |
| 185 | continue; |
| 186 | } |
| 187 | warn(errorToErrorCode(StrTabOrErr.takeError()).message()); |
| 188 | consumeError(StrTabOrErr.takeError()); |
| 189 | } |
| 190 | outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); |
| 191 | } |
| 192 | } |
| 193 | |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 194 | template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { |
| 195 | typedef ELFFile<ELFT> ELFO; |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 196 | outs() << "Program Header:\n"; |
Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 197 | auto ProgramHeaderOrError = o->program_headers(); |
Davide Italiano | 6cf0926 | 2016-11-16 05:10:28 +0000 | [diff] [blame] | 198 | if (!ProgramHeaderOrError) |
| 199 | report_fatal_error( |
| 200 | errorToErrorCode(ProgramHeaderOrError.takeError()).message()); |
Rafael Espindola | 6a49497 | 2016-11-03 17:28:33 +0000 | [diff] [blame] | 201 | for (const typename ELFO::Elf_Phdr &Phdr : *ProgramHeaderOrError) { |
Rafael Espindola | 073624b | 2015-07-20 13:35:33 +0000 | [diff] [blame] | 202 | switch (Phdr.p_type) { |
Ed Maste | 178a4e5 | 2016-12-24 14:53:45 +0000 | [diff] [blame] | 203 | case ELF::PT_DYNAMIC: |
| 204 | outs() << " DYNAMIC "; |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 205 | break; |
| 206 | case ELF::PT_GNU_EH_FRAME: |
| 207 | outs() << "EH_FRAME "; |
| 208 | break; |
Davide Italiano | cad1927 | 2017-01-16 22:58:26 +0000 | [diff] [blame] | 209 | case ELF::PT_GNU_RELRO: |
| 210 | outs() << " RELRO "; |
| 211 | break; |
Ed Maste | 178a4e5 | 2016-12-24 14:53:45 +0000 | [diff] [blame] | 212 | case ELF::PT_GNU_STACK: |
| 213 | outs() << " STACK "; |
| 214 | break; |
Michael J. Spencer | 1366a61 | 2013-02-20 20:18:10 +0000 | [diff] [blame] | 215 | case ELF::PT_INTERP: |
| 216 | outs() << " INTERP "; |
| 217 | break; |
Ed Maste | 178a4e5 | 2016-12-24 14:53:45 +0000 | [diff] [blame] | 218 | case ELF::PT_LOAD: |
| 219 | outs() << " LOAD "; |
Michael J. Spencer | 1366a61 | 2013-02-20 20:18:10 +0000 | [diff] [blame] | 220 | break; |
Davide Italiano | eb9ad98 | 2017-01-16 23:13:46 +0000 | [diff] [blame] | 221 | case ELF::PT_NOTE: |
| 222 | outs() << " NOTE "; |
| 223 | break; |
Davide Italiano | 6cc726e | 2017-01-16 22:01:41 +0000 | [diff] [blame] | 224 | case ELF::PT_OPENBSD_BOOTDATA: |
| 225 | outs() << " OPENBSD_BOOTDATA "; |
| 226 | break; |
| 227 | case ELF::PT_OPENBSD_RANDOMIZE: |
| 228 | outs() << " OPENBSD_RANDOMIZE "; |
| 229 | break; |
| 230 | case ELF::PT_OPENBSD_WXNEEDED: |
| 231 | outs() << " OPENBSD_WXNEEDED "; |
| 232 | break; |
Michael J. Spencer | ed82095 | 2013-02-21 02:21:29 +0000 | [diff] [blame] | 233 | case ELF::PT_PHDR: |
| 234 | outs() << " PHDR "; |
| 235 | break; |
Shankar Easwaran | e0bdc94 | 2013-02-27 17:57:17 +0000 | [diff] [blame] | 236 | case ELF::PT_TLS: |
| 237 | outs() << " TLS "; |
| 238 | break; |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 239 | default: |
| 240 | outs() << " UNKNOWN "; |
| 241 | } |
| 242 | |
Michael J. Spencer | 1a79161 | 2013-01-15 07:44:25 +0000 | [diff] [blame] | 243 | const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; |
Michael J. Spencer | 6acf814 | 2013-01-06 05:23:59 +0000 | [diff] [blame] | 244 | |
Rafael Espindola | 073624b | 2015-07-20 13:35:33 +0000 | [diff] [blame] | 245 | outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr " |
| 246 | << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr " |
| 247 | << format(Fmt, (uint64_t)Phdr.p_paddr) |
| 248 | << format("align 2**%u\n", |
| 249 | countTrailingZeros<uint64_t>(Phdr.p_align)) |
| 250 | << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz) |
| 251 | << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags " |
| 252 | << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-") |
| 253 | << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-") |
| 254 | << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n"; |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 255 | } |
| 256 | outs() << "\n"; |
| 257 | } |
| 258 | |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 259 | template <class ELFT> |
| 260 | void printSymbolVersionDependency(ArrayRef<uint8_t> Contents, |
| 261 | StringRef StrTab) { |
| 262 | typedef ELFFile<ELFT> ELFO; |
| 263 | typedef typename ELFO::Elf_Verneed Elf_Verneed; |
| 264 | typedef typename ELFO::Elf_Vernaux Elf_Vernaux; |
| 265 | |
| 266 | outs() << "Version References:\n"; |
| 267 | |
| 268 | const uint8_t *Buf = Contents.data(); |
| 269 | while (Buf) { |
| 270 | const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); |
| 271 | outs() << " required from " |
| 272 | << StringRef(StrTab.drop_front(Verneed->vn_file).data()) << ":\n"; |
| 273 | |
| 274 | const uint8_t *BufAux = Buf + Verneed->vn_aux; |
| 275 | while (BufAux) { |
| 276 | const Elf_Vernaux *Vernaux = |
| 277 | reinterpret_cast<const Elf_Vernaux *>(BufAux); |
| 278 | outs() << " " |
| 279 | << format("0x%08" PRIx32 " ", (uint32_t)Vernaux->vna_hash) |
| 280 | << format("0x%02" PRIx16 " ", (uint16_t)Vernaux->vna_flags) |
| 281 | << format("%02" PRIu16 " ", (uint16_t)Vernaux->vna_other) |
| 282 | << StringRef(StrTab.drop_front(Vernaux->vna_name).data()) << '\n'; |
| 283 | BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; |
| 284 | } |
| 285 | Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | template <class ELFT> |
Xing GUO | 85b50a7 | 2019-02-26 13:06:16 +0000 | [diff] [blame] | 290 | void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, |
| 291 | ArrayRef<uint8_t> Contents, |
| 292 | StringRef StrTab) { |
| 293 | typedef ELFFile<ELFT> ELFO; |
| 294 | typedef typename ELFO::Elf_Verdef Elf_Verdef; |
| 295 | typedef typename ELFO::Elf_Verdaux Elf_Verdaux; |
| 296 | |
| 297 | outs() << "Version definitions:\n"; |
| 298 | |
| 299 | const uint8_t *Buf = Contents.data(); |
| 300 | uint32_t VerdefIndex = 1; |
| 301 | // sh_info contains the number of entries in the SHT_GNU_verdef section. To |
| 302 | // make the index column have consistent width, we should insert blank spaces |
| 303 | // according to sh_info. |
| 304 | uint16_t VerdefIndexWidth = std::to_string(Shdr.sh_info).size(); |
| 305 | while (Buf) { |
| 306 | const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); |
| 307 | outs() << format_decimal(VerdefIndex++, VerdefIndexWidth) << " " |
| 308 | << format("0x%02" PRIx16 " ", (uint16_t)Verdef->vd_flags) |
| 309 | << format("0x%08" PRIx32 " ", (uint32_t)Verdef->vd_hash); |
| 310 | |
| 311 | const uint8_t *BufAux = Buf + Verdef->vd_aux; |
| 312 | uint16_t VerdauxIndex = 0; |
| 313 | while (BufAux) { |
| 314 | const Elf_Verdaux *Verdaux = |
| 315 | reinterpret_cast<const Elf_Verdaux *>(BufAux); |
| 316 | if (VerdauxIndex) |
| 317 | outs() << std::string(VerdefIndexWidth + 17, ' '); |
| 318 | outs() << StringRef(StrTab.drop_front(Verdaux->vda_name).data()) << '\n'; |
| 319 | BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; |
| 320 | ++VerdauxIndex; |
| 321 | } |
| 322 | Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | template <class ELFT> |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 327 | void printSymbolVersionInfo(const ELFFile<ELFT> *Elf, StringRef FileName) { |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 328 | ArrayRef<typename ELFT::Shdr> Sections = |
| 329 | unwrapOrError(Elf->sections(), FileName); |
| 330 | for (const typename ELFT::Shdr &Shdr : Sections) { |
Xing GUO | 85b50a7 | 2019-02-26 13:06:16 +0000 | [diff] [blame] | 331 | if (Shdr.sh_type != ELF::SHT_GNU_verneed && |
| 332 | Shdr.sh_type != ELF::SHT_GNU_verdef) |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 333 | continue; |
| 334 | |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 335 | ArrayRef<uint8_t> Contents = |
| 336 | unwrapOrError(Elf->getSectionContents(&Shdr), FileName); |
| 337 | const typename ELFT::Shdr *StrTabSec = |
| 338 | unwrapOrError(Elf->getSection(Shdr.sh_link), FileName); |
| 339 | StringRef StrTab = unwrapOrError(Elf->getStringTable(StrTabSec), FileName); |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 340 | |
Xing GUO | 85b50a7 | 2019-02-26 13:06:16 +0000 | [diff] [blame] | 341 | if (Shdr.sh_type == ELF::SHT_GNU_verneed) |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 342 | printSymbolVersionDependency<ELFT>(Contents, StrTab); |
Xing GUO | 85b50a7 | 2019-02-26 13:06:16 +0000 | [diff] [blame] | 343 | else |
Fangrui Song | e7834bd | 2019-04-07 08:19:55 +0000 | [diff] [blame^] | 344 | printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab); |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 345 | } |
| 346 | } |
| 347 | |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 348 | void llvm::printELFFileHeader(const object::ObjectFile *Obj) { |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 349 | if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 350 | printProgramHeaders(ELFObj->getELFFile()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 351 | else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 352 | printProgramHeaders(ELFObj->getELFFile()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 353 | else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 354 | printProgramHeaders(ELFObj->getELFFile()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 355 | else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) |
Michael J. Spencer | 126973b | 2013-08-08 22:27:13 +0000 | [diff] [blame] | 356 | printProgramHeaders(ELFObj->getELFFile()); |
Michael J. Spencer | 209565db | 2013-01-06 03:56:49 +0000 | [diff] [blame] | 357 | } |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 358 | |
| 359 | void llvm::printELFDynamicSection(const object::ObjectFile *Obj) { |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 360 | if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 361 | printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 362 | else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 363 | printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 364 | else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 365 | printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); |
Xing GUO | cc0829f | 2018-11-15 11:51:13 +0000 | [diff] [blame] | 366 | else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) |
Paul Semel | 0913dcd | 2018-07-25 11:09:20 +0000 | [diff] [blame] | 367 | printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); |
| 368 | } |
Xing GUO | 56d651d | 2019-02-25 13:13:19 +0000 | [diff] [blame] | 369 | |
| 370 | void llvm::printELFSymbolVersionInfo(const object::ObjectFile *Obj) { |
| 371 | if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) |
| 372 | printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); |
| 373 | else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) |
| 374 | printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); |
| 375 | else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) |
| 376 | printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); |
| 377 | else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) |
| 378 | printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); |
| 379 | } |