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