llvm-readobj.cpp revision 148ee4f224be6448834bf039807c70bb1a7c78f5
1//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// 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// This program is a utility that works like traditional Unix "readelf", 11// except that it can handle any type of object file recognized by lib/Object. 12// 13// It makes use of the generic ObjectFile interface. 14// 15// Caution: This utility is new, experimental, unsupported, and incomplete. 16// 17//===----------------------------------------------------------------------===// 18 19#include "llvm/ADT/Triple.h" 20#include "llvm/Analysis/Verifier.h" 21#include "llvm/Object/ELF.h" 22#include "llvm/Object/ObjectFile.h" 23#include "llvm/Support/CommandLine.h" 24#include "llvm/Support/Debug.h" 25#include "llvm/Support/Format.h" 26#include "llvm/Support/FormattedStream.h" 27#include "llvm/Support/PrettyStackTrace.h" 28#include "llvm/Support/Signals.h" 29 30using namespace llvm; 31using namespace llvm::object; 32 33static cl::opt<std::string> 34InputFilename(cl::Positional, cl::desc("<input object>"), cl::init("")); 35 36static void dumpSymbolHeader() { 37 outs() << format(" %-32s", (const char*)"Name") 38 << format(" %-4s", (const char*)"Type") 39 << format(" %-16s", (const char*)"Address") 40 << format(" %-16s", (const char*)"Size") 41 << format(" %-16s", (const char*)"FileOffset") 42 << format(" %-26s", (const char*)"Flags") 43 << "\n"; 44} 45 46static const char *getTypeStr(SymbolRef::Type Type) { 47 switch (Type) { 48 case SymbolRef::ST_Unknown: return "?"; 49 case SymbolRef::ST_Data: return "DATA"; 50 case SymbolRef::ST_Debug: return "DBG"; 51 case SymbolRef::ST_File: return "FILE"; 52 case SymbolRef::ST_Function: return "FUNC"; 53 case SymbolRef::ST_Other: return "-"; 54 } 55 return "INV"; 56} 57 58static std::string getSymbolFlagStr(uint32_t Flags) { 59 std::string result; 60 if (Flags & SymbolRef::SF_Undefined) 61 result += "undef,"; 62 if (Flags & SymbolRef::SF_Global) 63 result += "global,"; 64 if (Flags & SymbolRef::SF_Weak) 65 result += "weak,"; 66 if (Flags & SymbolRef::SF_Absolute) 67 result += "absolute,"; 68 if (Flags & SymbolRef::SF_ThreadLocal) 69 result += "threadlocal,"; 70 if (Flags & SymbolRef::SF_Common) 71 result += "common,"; 72 if (Flags & SymbolRef::SF_FormatSpecific) 73 result += "formatspecific,"; 74 75 // Remove trailing comma 76 if (result.size() > 0) { 77 result.erase(result.size() - 1); 78 } 79 return result; 80} 81 82static void checkError(error_code ec, const char *msg) { 83 if (ec) 84 report_fatal_error(std::string(msg) + ": " + ec.message()); 85} 86 87static void 88dumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { 89 StringRef Name; 90 SymbolRef::Type Type; 91 uint32_t Flags; 92 uint64_t Address; 93 uint64_t Size; 94 uint64_t FileOffset; 95 checkError(Sym.getName(Name), "SymbolRef.getName() failed"); 96 checkError(Sym.getAddress(Address), "SymbolRef.getAddress() failed"); 97 checkError(Sym.getSize(Size), "SymbolRef.getSize() failed"); 98 checkError(Sym.getFileOffset(FileOffset), 99 "SymbolRef.getFileOffset() failed"); 100 checkError(Sym.getType(Type), "SymbolRef.getType() failed"); 101 checkError(Sym.getFlags(Flags), "SymbolRef.getFlags() failed"); 102 std::string FullName = Name; 103 104 // If this is a dynamic symbol from an ELF object, append 105 // the symbol's version to the name. 106 if (IsDynamic && obj->isELF()) { 107 StringRef Version; 108 bool IsDefault; 109 GetELFSymbolVersion(obj, Sym, Version, IsDefault); 110 if (!Version.empty()) { 111 FullName += (IsDefault ? "@@" : "@"); 112 FullName += Version; 113 } 114 } 115 116 // format() can't handle StringRefs 117 outs() << format(" %-32s", FullName.c_str()) 118 << format(" %-4s", getTypeStr(Type)) 119 << format(" %16" PRIx64, Address) 120 << format(" %16" PRIx64, Size) 121 << format(" %16" PRIx64, FileOffset) 122 << " " << getSymbolFlagStr(Flags) 123 << "\n"; 124} 125 126// Iterate through the normal symbols in the ObjectFile 127static void dumpSymbols(const ObjectFile *obj) { 128 error_code ec; 129 uint32_t count = 0; 130 outs() << "Symbols:\n"; 131 dumpSymbolHeader(); 132 symbol_iterator it = obj->begin_symbols(); 133 symbol_iterator ie = obj->end_symbols(); 134 while (it != ie) { 135 dumpSymbol(*it, obj, false); 136 it.increment(ec); 137 if (ec) 138 report_fatal_error("Symbol iteration failed"); 139 ++count; 140 } 141 outs() << " Total: " << count << "\n\n"; 142} 143 144// Iterate through the dynamic symbols in the ObjectFile. 145static void dumpDynamicSymbols(const ObjectFile *obj) { 146 error_code ec; 147 uint32_t count = 0; 148 outs() << "Dynamic Symbols:\n"; 149 dumpSymbolHeader(); 150 symbol_iterator it = obj->begin_dynamic_symbols(); 151 symbol_iterator ie = obj->end_dynamic_symbols(); 152 while (it != ie) { 153 dumpSymbol(*it, obj, true); 154 it.increment(ec); 155 if (ec) 156 report_fatal_error("Symbol iteration failed"); 157 ++count; 158 } 159 outs() << " Total: " << count << "\n\n"; 160} 161 162static void dumpLibrary(const LibraryRef &lib) { 163 StringRef path; 164 lib.getPath(path); 165 outs() << " " << path << "\n"; 166} 167 168// Iterate through needed libraries 169static void dumpLibrariesNeeded(const ObjectFile *obj) { 170 error_code ec; 171 uint32_t count = 0; 172 library_iterator it = obj->begin_libraries_needed(); 173 library_iterator ie = obj->end_libraries_needed(); 174 outs() << "Libraries needed:\n"; 175 while (it != ie) { 176 dumpLibrary(*it); 177 it.increment(ec); 178 if (ec) 179 report_fatal_error("Needed libraries iteration failed"); 180 ++count; 181 } 182 outs() << " Total: " << count << "\n\n"; 183} 184 185static void dumpHeaders(const ObjectFile *obj) { 186 outs() << "File Format : " << obj->getFileFormatName() << "\n"; 187 outs() << "Arch : " 188 << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) 189 << "\n"; 190 outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n"; 191 outs() << "Load Name : " << obj->getLoadName() << "\n"; 192 outs() << "\n"; 193} 194 195int main(int argc, char** argv) { 196 error_code ec; 197 sys::PrintStackTraceOnErrorSignal(); 198 PrettyStackTraceProgram X(argc, argv); 199 200 cl::ParseCommandLineOptions(argc, argv, 201 "LLVM Object Reader\n"); 202 203 if (InputFilename.empty()) { 204 errs() << "Please specify an input filename\n"; 205 return 1; 206 } 207 208 // Open the object file 209 OwningPtr<MemoryBuffer> File; 210 if (MemoryBuffer::getFile(InputFilename, File)) { 211 errs() << InputFilename << ": Open failed\n"; 212 return 1; 213 } 214 215 ObjectFile *obj = ObjectFile::createObjectFile(File.take()); 216 if (!obj) { 217 errs() << InputFilename << ": Object type not recognized\n"; 218 } 219 220 dumpHeaders(obj); 221 dumpSymbols(obj); 222 dumpDynamicSymbols(obj); 223 dumpLibrariesNeeded(obj); 224 return 0; 225} 226 227