//===- llvm-readobj/ELF.cpp - ELF Specific Dumper -------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm-readobj.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Format.h" namespace llvm { using namespace object; using namespace ELF; const char *getTypeString(uint64_t Type) { switch (Type) { case DT_BIND_NOW: return "(BIND_NOW)"; case DT_DEBUG: return "(DEBUG)"; case DT_FINI: return "(FINI)"; case DT_FINI_ARRAY: return "(FINI_ARRAY)"; case DT_FINI_ARRAYSZ: return "(FINI_ARRAYSZ)"; case DT_FLAGS: return "(FLAGS)"; case DT_HASH: return "(HASH)"; case DT_INIT: return "(INIT)"; case DT_INIT_ARRAY: return "(INIT_ARRAY)"; case DT_INIT_ARRAYSZ: return "(INIT_ARRAYSZ)"; case DT_PREINIT_ARRAY: return "(PREINIT_ARRAY)"; case DT_PREINIT_ARRAYSZ: return "(PREINIT_ARRAYSZ)"; case DT_JMPREL: return "(JMPREL)"; case DT_NEEDED: return "(NEEDED)"; case DT_NULL: return "(NULL)"; case DT_PLTGOT: return "(PLTGOT)"; case DT_PLTREL: return "(PLTREL)"; case DT_PLTRELSZ: return "(PLTRELSZ)"; case DT_REL: return "(REL)"; case DT_RELA: return "(RELA)"; case DT_RELENT: return "(RELENT)"; case DT_RELSZ: return "(RELSZ)"; case DT_RELAENT: return "(RELAENT)"; case DT_RELASZ: return "(RELASZ)"; case DT_RPATH: return "(RPATH)"; case DT_RUNPATH: return "(RUNPATH)"; case DT_SONAME: return "(SONAME)"; case DT_STRSZ: return "(STRSZ)"; case DT_STRTAB: return "(STRTAB)"; case DT_SYMBOLIC: return "(SYMBOLIC)"; case DT_SYMENT: return "(SYMENT)"; case DT_SYMTAB: return "(SYMTAB)"; case DT_TEXTREL: return "(TEXTREL)"; default: return "unknown"; } } template void printValue(const ELFObjectFile *O, uint64_t Type, uint64_t Value, bool Is64, raw_ostream &OS) { switch (Type) { case DT_PLTREL: if (Value == DT_REL) { OS << "REL"; break; } else if (Value == DT_RELA) { OS << "RELA"; break; } // Fallthrough. case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: case DT_RELA: case DT_INIT: case DT_FINI: case DT_REL: case DT_JMPREL: case DT_INIT_ARRAY: case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: case DT_DEBUG: case DT_NULL: OS << format("0x%" PRIx64, Value); break; case DT_PLTRELSZ: case DT_RELASZ: case DT_RELAENT: case DT_STRSZ: case DT_SYMENT: case DT_RELSZ: case DT_RELENT: case DT_INIT_ARRAYSZ: case DT_FINI_ARRAYSZ: case DT_PREINIT_ARRAYSZ: OS << Value << " (bytes)"; break; case DT_NEEDED: OS << "Shared library: [" << O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]"; break; case DT_SONAME: OS << "Library soname: [" << O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]"; break; } } template ErrorOr dumpDynamicTable(const ELFObjectFile *O, raw_ostream &OS) { typedef ELFObjectFile ELFO; typedef typename ELFO::Elf_Dyn_iterator EDI; EDI Start = O->begin_dynamic_table(), End = O->end_dynamic_table(true); if (Start == End) return error_code::success(); ptrdiff_t Total = std::distance(Start, End); OS << "Dynamic section contains " << Total << " entries\n"; bool Is64 = O->getBytesInAddress() == 8; OS << " Tag" << (Is64 ? " " : " ") << "Type" << " " << "Name/Value\n"; for (; Start != End; ++Start) { OS << " " << format(Is64 ? "0x%016" PRIx64 : "0x%08" PRIx64, Start->getTag()) << " " << format("%-21s", getTypeString(Start->getTag())); printValue(O, Start->getTag(), Start->getVal(), Is64, OS); OS << "\n"; } OS << " Total: " << Total << "\n\n"; return error_code::success(); } ErrorOr dumpELFDynamicTable(ObjectFile *O, raw_ostream &OS) { // Little-endian 32-bit if (const ELFObjectFile > *ELFObj = dyn_cast > >(O)) return dumpDynamicTable(ELFObj, OS); // Big-endian 32-bit if (const ELFObjectFile > *ELFObj = dyn_cast > >(O)) return dumpDynamicTable(ELFObj, OS); // Little-endian 64-bit if (const ELFObjectFile > *ELFObj = dyn_cast > >(O)) return dumpDynamicTable(ELFObj, OS); // Big-endian 64-bit if (const ELFObjectFile > *ELFObj = dyn_cast > >(O)) return dumpDynamicTable(ELFObj, OS); return error_code(object_error::invalid_file_type); } } // end namespace llvm