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