1 //===-- ELFDump.cpp - ELF-specific dumper -----------------------*- C++ -*-===// 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 11 /// This file implements the ELF-specific dumper for llvm-objdump. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm-objdump.h" 16 #include "llvm/Object/ELFObjectFile.h" 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 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> 55 void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { 56 auto ProgramHeaderOrError = Elf->program_headers(); 57 if (!ProgramHeaderOrError) 58 report_error(Filename, ProgramHeaderOrError.takeError()); 59 60 auto DynamicEntriesOrError = Elf->dynamicEntries(); 61 if (!DynamicEntriesOrError) 62 report_error(Filename, DynamicEntriesOrError.takeError()); 63 64 outs() << "Dynamic Section:\n"; 65 for (const auto &Dyn : *DynamicEntriesOrError) { 66 if (Dyn.d_tag == ELF::DT_NULL) 67 continue; 68 69 StringRef Str = StringRef(Elf->getDynamicTagAsString(Dyn.d_tag)); 70 71 if (Str.empty()) { 72 std::string HexStr = utohexstr(static_cast<uint64_t>(Dyn.d_tag), true); 73 outs() << format(" 0x%-19s", HexStr.c_str()); 74 } else { 75 // We use "-21" in order to match GNU objdump's output. 76 outs() << format(" %-21s", Str.data()); 77 } 78 79 const char *Fmt = 80 ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; 81 if (Dyn.d_tag == ELF::DT_NEEDED) { 82 Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); 83 if (StrTabOrErr) { 84 const char *Data = StrTabOrErr.get().data(); 85 outs() << (Data + Dyn.d_un.d_val) << "\n"; 86 continue; 87 } 88 warn(errorToErrorCode(StrTabOrErr.takeError()).message()); 89 consumeError(StrTabOrErr.takeError()); 90 } 91 outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); 92 } 93 } 94 95 template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { 96 typedef ELFFile<ELFT> ELFO; 97 outs() << "Program Header:\n"; 98 auto ProgramHeaderOrError = o->program_headers(); 99 if (!ProgramHeaderOrError) 100 report_fatal_error( 101 errorToErrorCode(ProgramHeaderOrError.takeError()).message()); 102 for (const typename ELFO::Elf_Phdr &Phdr : *ProgramHeaderOrError) { 103 switch (Phdr.p_type) { 104 case ELF::PT_DYNAMIC: 105 outs() << " DYNAMIC "; 106 break; 107 case ELF::PT_GNU_EH_FRAME: 108 outs() << "EH_FRAME "; 109 break; 110 case ELF::PT_GNU_RELRO: 111 outs() << " RELRO "; 112 break; 113 case ELF::PT_GNU_STACK: 114 outs() << " STACK "; 115 break; 116 case ELF::PT_INTERP: 117 outs() << " INTERP "; 118 break; 119 case ELF::PT_LOAD: 120 outs() << " LOAD "; 121 break; 122 case ELF::PT_NOTE: 123 outs() << " NOTE "; 124 break; 125 case ELF::PT_OPENBSD_BOOTDATA: 126 outs() << " OPENBSD_BOOTDATA "; 127 break; 128 case ELF::PT_OPENBSD_RANDOMIZE: 129 outs() << " OPENBSD_RANDOMIZE "; 130 break; 131 case ELF::PT_OPENBSD_WXNEEDED: 132 outs() << " OPENBSD_WXNEEDED "; 133 break; 134 case ELF::PT_PHDR: 135 outs() << " PHDR "; 136 break; 137 case ELF::PT_TLS: 138 outs() << " TLS "; 139 break; 140 default: 141 outs() << " UNKNOWN "; 142 } 143 144 const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; 145 146 outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr " 147 << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr " 148 << format(Fmt, (uint64_t)Phdr.p_paddr) 149 << format("align 2**%u\n", 150 countTrailingZeros<uint64_t>(Phdr.p_align)) 151 << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz) 152 << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags " 153 << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-") 154 << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-") 155 << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n"; 156 } 157 outs() << "\n"; 158 } 159 160 void llvm::printELFFileHeader(const object::ObjectFile *Obj) { 161 if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) 162 printProgramHeaders(ELFObj->getELFFile()); 163 else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) 164 printProgramHeaders(ELFObj->getELFFile()); 165 else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) 166 printProgramHeaders(ELFObj->getELFFile()); 167 else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) 168 printProgramHeaders(ELFObj->getELFFile()); 169 } 170 171 void llvm::printELFDynamicSection(const object::ObjectFile *Obj) { 172 if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) 173 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); 174 else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) 175 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); 176 else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) 177 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); 178 else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) 179 printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); 180 } 181