blob: 3b293a75f08596df69f0f2260048cef4cf1872f2 [file] [log] [blame]
Michael J. Spencer209565db2013-01-06 03:56:49 +00001//===-- ELFDump.cpp - ELF-specific dumper -----------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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. Spencer209565db2013-01-06 03:56:49 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// This file implements the ELF-specific dumper for llvm-objdump.
Michael J. Spencer209565db2013-01-06 03:56:49 +000011///
12//===----------------------------------------------------------------------===//
13
14#include "llvm-objdump.h"
George Rimarc1964882019-01-18 11:33:26 +000015#include "llvm/Demangle/Demangle.h"
Michael J. Spencer126973b2013-08-08 22:27:13 +000016#include "llvm/Object/ELFObjectFile.h"
Michael J. Spencer209565db2013-01-06 03:56:49 +000017#include "llvm/Support/Format.h"
18#include "llvm/Support/MathExtras.h"
19#include "llvm/Support/raw_ostream.h"
20
21using namespace llvm;
22using namespace llvm::object;
23
Paul Semel0913dcd2018-07-25 11:09:20 +000024template <class ELFT>
25Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) {
Paul Semel0913dcd2018-07-25 11:09:20 +000026 auto DynamicEntriesOrError = Elf->dynamicEntries();
27 if (!DynamicEntriesOrError)
28 return DynamicEntriesOrError.takeError();
29
Fangrui Song454a7bb2019-04-07 08:28:56 +000030 for (const typename ELFT::Dyn &Dyn : *DynamicEntriesOrError) {
Paul Semel0913dcd2018-07-25 11:09:20 +000031 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 Song454a7bb2019-04-07 08:28:56 +000044 for (const typename ELFT::Shdr &Sec : *SectionsOrError) {
Paul Semel0913dcd2018-07-25 11:09:20 +000045 if (Sec.sh_type == ELF::SHT_DYNSYM)
46 return Elf->getStringTableForSymtab(Sec);
47 }
48
49 return createError("dynamic string table not found");
50}
51
52template <class ELFT>
George Rimarc1964882019-01-18 11:33:26 +000053static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
54 const RelocationRef &RelRef,
55 SmallVectorImpl<char> &Result) {
George Rimarc1964882019-01-18 11:33:26 +000056 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 Song454a7bb2019-04-07 08:28:56 +000087 const typename ELFT::Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl());
George Rimarc1964882019-01-18 11:33:26 +000088 if (Sym->getType() == ELF::STT_SECTION) {
89 Expected<section_iterator> SymSI = SI->getSection();
90 if (!SymSI)
91 return errorToErrorCode(SymSI.takeError());
Fangrui Song454a7bb2019-04-07 08:28:56 +000092 const typename ELFT::Shdr *SymSec =
93 Obj->getSection((*SymSI)->getRawDataRefImpl());
George Rimarc1964882019-01-18 11:33:26 +000094 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
118std::error_code
119llvm::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
132template <class ELFT>
George Rimar87fa2e62019-01-28 14:11:35 +0000133static 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
150uint64_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
161template <class ELFT>
Paul Semel0913dcd2018-07-25 11:09:20 +0000162void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) {
Fangrui Songe7834bd2019-04-07 08:19:55 +0000163 ArrayRef<typename ELFT::Dyn> DynamicEntries =
164 unwrapOrError(Elf->dynamicEntries(), Filename);
Paul Semel0913dcd2018-07-25 11:09:20 +0000165 outs() << "Dynamic Section:\n";
Fangrui Songe7834bd2019-04-07 08:19:55 +0000166 for (const typename ELFT::Dyn &Dyn : DynamicEntries) {
Paul Semel0913dcd2018-07-25 11:09:20 +0000167 if (Dyn.d_tag == ELF::DT_NULL)
168 continue;
169
Xing GUOb2858782019-03-02 04:20:28 +0000170 std::string Str = Elf->getDynamicTagAsString(Dyn.d_tag);
171 outs() << format(" %-21s", Str.c_str());
Paul Semel0913dcd2018-07-25 11:09:20 +0000172
173 const char *Fmt =
174 ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n";
Xing GUOd78164a2019-02-27 16:37:15 +0000175 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 Semel0913dcd2018-07-25 11:09:20 +0000178 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. Spencer126973b2013-08-08 22:27:13 +0000191template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
Michael J. Spencer209565db2013-01-06 03:56:49 +0000192 outs() << "Program Header:\n";
Rafael Espindola6a494972016-11-03 17:28:33 +0000193 auto ProgramHeaderOrError = o->program_headers();
Davide Italiano6cf09262016-11-16 05:10:28 +0000194 if (!ProgramHeaderOrError)
195 report_fatal_error(
196 errorToErrorCode(ProgramHeaderOrError.takeError()).message());
Fangrui Song454a7bb2019-04-07 08:28:56 +0000197 for (const typename ELFT::Phdr &Phdr : *ProgramHeaderOrError) {
Rafael Espindola073624b2015-07-20 13:35:33 +0000198 switch (Phdr.p_type) {
Ed Maste178a4e52016-12-24 14:53:45 +0000199 case ELF::PT_DYNAMIC:
200 outs() << " DYNAMIC ";
Michael J. Spencer209565db2013-01-06 03:56:49 +0000201 break;
202 case ELF::PT_GNU_EH_FRAME:
203 outs() << "EH_FRAME ";
204 break;
Davide Italianocad19272017-01-16 22:58:26 +0000205 case ELF::PT_GNU_RELRO:
206 outs() << " RELRO ";
207 break;
Ed Maste178a4e52016-12-24 14:53:45 +0000208 case ELF::PT_GNU_STACK:
209 outs() << " STACK ";
210 break;
Michael J. Spencer1366a612013-02-20 20:18:10 +0000211 case ELF::PT_INTERP:
212 outs() << " INTERP ";
213 break;
Ed Maste178a4e52016-12-24 14:53:45 +0000214 case ELF::PT_LOAD:
215 outs() << " LOAD ";
Michael J. Spencer1366a612013-02-20 20:18:10 +0000216 break;
Davide Italianoeb9ad982017-01-16 23:13:46 +0000217 case ELF::PT_NOTE:
218 outs() << " NOTE ";
219 break;
Davide Italiano6cc726e2017-01-16 22:01:41 +0000220 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. Spencered820952013-02-21 02:21:29 +0000229 case ELF::PT_PHDR:
230 outs() << " PHDR ";
231 break;
Shankar Easwarane0bdc942013-02-27 17:57:17 +0000232 case ELF::PT_TLS:
233 outs() << " TLS ";
234 break;
Michael J. Spencer209565db2013-01-06 03:56:49 +0000235 default:
236 outs() << " UNKNOWN ";
237 }
238
Michael J. Spencer1a791612013-01-15 07:44:25 +0000239 const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";
Michael J. Spencer6acf8142013-01-06 05:23:59 +0000240
Rafael Espindola073624b2015-07-20 13:35:33 +0000241 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. Spencer209565db2013-01-06 03:56:49 +0000251 }
252 outs() << "\n";
253}
254
Xing GUO56d651d2019-02-25 13:13:19 +0000255template <class ELFT>
256void printSymbolVersionDependency(ArrayRef<uint8_t> Contents,
257 StringRef StrTab) {
Xing GUO56d651d2019-02-25 13:13:19 +0000258 outs() << "Version References:\n";
259
260 const uint8_t *Buf = Contents.data();
261 while (Buf) {
Fangrui Song454a7bb2019-04-07 08:28:56 +0000262 auto *Verneed = reinterpret_cast<const typename ELFT::Verneed *>(Buf);
Xing GUO56d651d2019-02-25 13:13:19 +0000263 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 Song454a7bb2019-04-07 08:28:56 +0000268 auto *Vernaux = reinterpret_cast<const typename ELFT::Vernaux *>(BufAux);
Xing GUO56d651d2019-02-25 13:13:19 +0000269 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
280template <class ELFT>
Xing GUO85b50a72019-02-26 13:06:16 +0000281void 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
317template <class ELFT>
Xing GUO56d651d2019-02-25 13:13:19 +0000318void printSymbolVersionInfo(const ELFFile<ELFT> *Elf, StringRef FileName) {
Fangrui Songe7834bd2019-04-07 08:19:55 +0000319 ArrayRef<typename ELFT::Shdr> Sections =
320 unwrapOrError(Elf->sections(), FileName);
321 for (const typename ELFT::Shdr &Shdr : Sections) {
Xing GUO85b50a72019-02-26 13:06:16 +0000322 if (Shdr.sh_type != ELF::SHT_GNU_verneed &&
323 Shdr.sh_type != ELF::SHT_GNU_verdef)
Xing GUO56d651d2019-02-25 13:13:19 +0000324 continue;
325
Fangrui Songe7834bd2019-04-07 08:19:55 +0000326 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 GUO56d651d2019-02-25 13:13:19 +0000331
Xing GUO85b50a72019-02-26 13:06:16 +0000332 if (Shdr.sh_type == ELF::SHT_GNU_verneed)
Fangrui Songe7834bd2019-04-07 08:19:55 +0000333 printSymbolVersionDependency<ELFT>(Contents, StrTab);
Xing GUO85b50a72019-02-26 13:06:16 +0000334 else
Fangrui Songe7834bd2019-04-07 08:19:55 +0000335 printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
Xing GUO56d651d2019-02-25 13:13:19 +0000336 }
337}
338
Michael J. Spencer209565db2013-01-06 03:56:49 +0000339void llvm::printELFFileHeader(const object::ObjectFile *Obj) {
Xing GUOcc0829f2018-11-15 11:51:13 +0000340 if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
Michael J. Spencer126973b2013-08-08 22:27:13 +0000341 printProgramHeaders(ELFObj->getELFFile());
Xing GUOcc0829f2018-11-15 11:51:13 +0000342 else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
Michael J. Spencer126973b2013-08-08 22:27:13 +0000343 printProgramHeaders(ELFObj->getELFFile());
Xing GUOcc0829f2018-11-15 11:51:13 +0000344 else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
Michael J. Spencer126973b2013-08-08 22:27:13 +0000345 printProgramHeaders(ELFObj->getELFFile());
Xing GUOcc0829f2018-11-15 11:51:13 +0000346 else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
Michael J. Spencer126973b2013-08-08 22:27:13 +0000347 printProgramHeaders(ELFObj->getELFFile());
Michael J. Spencer209565db2013-01-06 03:56:49 +0000348}
Paul Semel0913dcd2018-07-25 11:09:20 +0000349
350void llvm::printELFDynamicSection(const object::ObjectFile *Obj) {
Xing GUOcc0829f2018-11-15 11:51:13 +0000351 if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
Paul Semel0913dcd2018-07-25 11:09:20 +0000352 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
Xing GUOcc0829f2018-11-15 11:51:13 +0000353 else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
Paul Semel0913dcd2018-07-25 11:09:20 +0000354 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
Xing GUOcc0829f2018-11-15 11:51:13 +0000355 else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
Paul Semel0913dcd2018-07-25 11:09:20 +0000356 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
Xing GUOcc0829f2018-11-15 11:51:13 +0000357 else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
Paul Semel0913dcd2018-07-25 11:09:20 +0000358 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
359}
Xing GUO56d651d2019-02-25 13:13:19 +0000360
361void 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}