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