llvm-readobj.cpp revision ee37b6e4cd53b8e2412c522eeab4e39b434f00c6
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/Object/ObjectFile.h" 20#include "llvm/Analysis/Verifier.h" 21#include "llvm/ADT/Triple.h" 22#include "llvm/Support/Format.h" 23#include "llvm/Support/CommandLine.h" 24#include "llvm/Support/PrettyStackTrace.h" 25#include "llvm/Support/Debug.h" 26#include "llvm/Support/Signals.h" 27#include "llvm/Support/FormattedStream.h" 28 29using namespace llvm; 30using namespace llvm::object; 31 32static cl::opt<std::string> 33InputFilename(cl::Positional, cl::desc("<input object>"), cl::init("")); 34 35void DumpSymbolHeader() { 36 outs() << format(" %-32s", (const char*)"Name") 37 << format(" %-4s", (const char*)"Type") 38 << format(" %-16s", (const char*)"Address") 39 << format(" %-16s", (const char*)"Size") 40 << format(" %-16s", (const char*)"FileOffset") 41 << format(" %-26s", (const char*)"Flags") 42 << "\n"; 43} 44 45const char *GetTypeStr(SymbolRef::Type Type) { 46 switch (Type) { 47 case SymbolRef::ST_Unknown: return "?"; 48 case SymbolRef::ST_Data: return "DATA"; 49 case SymbolRef::ST_Debug: return "DBG"; 50 case SymbolRef::ST_File: return "FILE"; 51 case SymbolRef::ST_Function: return "FUNC"; 52 case SymbolRef::ST_Other: return "-"; 53 } 54 return "INV"; 55} 56 57std::string GetFlagStr(uint32_t Flags) { 58 std::string result; 59 if (Flags & SymbolRef::SF_Undefined) 60 result += "undef,"; 61 if (Flags & SymbolRef::SF_Global) 62 result += "global,"; 63 if (Flags & SymbolRef::SF_Weak) 64 result += "weak,"; 65 if (Flags & SymbolRef::SF_Absolute) 66 result += "absolute,"; 67 if (Flags & SymbolRef::SF_ThreadLocal) 68 result += "threadlocal,"; 69 if (Flags & SymbolRef::SF_Common) 70 result += "common,"; 71 if (Flags & SymbolRef::SF_FormatSpecific) 72 result += "formatspecific,"; 73 74 // Remove trailing comma 75 if (result.size() > 0) { 76 result.erase(result.size() - 1); 77 } 78 return result; 79} 80 81void DumpSymbol(const SymbolRef &sym) { 82 StringRef Name; 83 SymbolRef::Type Type; 84 uint32_t Flags; 85 uint64_t Address; 86 uint64_t Size; 87 uint64_t FileOffset; 88 sym.getName(Name); 89 sym.getAddress(Address); 90 sym.getSize(Size); 91 sym.getFileOffset(FileOffset); 92 sym.getType(Type); 93 sym.getFlags(Flags); 94 95 // format() can't handle StringRefs 96 outs() << format(" %-32s", Name.str().c_str()) 97 << format(" %-4s", GetTypeStr(Type)) 98 << format(" %16"PRIx64, Address) 99 << format(" %16"PRIx64, Size) 100 << format(" %16"PRIx64, FileOffset) 101 << " " << GetFlagStr(Flags) 102 << "\n"; 103} 104 105 106// Iterate through the normal symbols in the ObjectFile 107void DumpSymbols(const ObjectFile *obj) { 108 error_code ec; 109 uint32_t count = 0; 110 outs() << "Symbols:\n"; 111 symbol_iterator it = obj->begin_symbols(); 112 symbol_iterator ie = obj->end_symbols(); 113 while (it != ie) { 114 DumpSymbol(*it); 115 it.increment(ec); 116 if (ec) 117 report_fatal_error("Symbol iteration failed"); 118 ++count; 119 } 120 outs() << " Total: " << count << "\n\n"; 121} 122 123// Iterate through the dynamic symbols in the ObjectFile. 124void DumpDynamicSymbols(const ObjectFile *obj) { 125 error_code ec; 126 uint32_t count = 0; 127 outs() << "Dynamic Symbols:\n"; 128 symbol_iterator it = obj->begin_dynamic_symbols(); 129 symbol_iterator ie = obj->end_dynamic_symbols(); 130 while (it != ie) { 131 DumpSymbol(*it); 132 it.increment(ec); 133 if (ec) 134 report_fatal_error("Symbol iteration failed"); 135 ++count; 136 } 137 outs() << " Total: " << count << "\n\n"; 138} 139 140void DumpLibrary(const LibraryRef &lib) { 141 StringRef path; 142 lib.getPath(path); 143 outs() << " " << path << "\n"; 144} 145 146// Iterate through needed libraries 147void DumpLibrariesNeeded(const ObjectFile *obj) { 148 error_code ec; 149 uint32_t count = 0; 150 library_iterator it = obj->begin_libraries_needed(); 151 library_iterator ie = obj->end_libraries_needed(); 152 outs() << "Libraries needed:\n"; 153 while (it != ie) { 154 DumpLibrary(*it); 155 it.increment(ec); 156 if (ec) 157 report_fatal_error("Needed libraries iteration failed"); 158 ++count; 159 } 160 outs() << " Total: " << count << "\n\n"; 161} 162 163void DumpHeaders(const ObjectFile *obj) { 164 outs() << "File Format : " << obj->getFileFormatName() << "\n"; 165 outs() << "Arch : " 166 << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) 167 << "\n"; 168 outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n"; 169 outs() << "Load Name : " << obj->getLoadName() << "\n"; 170 outs() << "\n"; 171} 172 173int main(int argc, char** argv) { 174 error_code ec; 175 sys::PrintStackTraceOnErrorSignal(); 176 PrettyStackTraceProgram X(argc, argv); 177 178 cl::ParseCommandLineOptions(argc, argv, 179 "LLVM Object Reader\n"); 180 181 if (InputFilename.empty()) { 182 errs() << "Please specify an input filename\n"; 183 return 1; 184 } 185 186 // Open the object file 187 OwningPtr<MemoryBuffer> File; 188 if (MemoryBuffer::getFile(InputFilename, File)) { 189 errs() << InputFilename << ": Open failed\n"; 190 return 1; 191 } 192 193 ObjectFile *obj = ObjectFile::createObjectFile(File.take()); 194 if (!obj) { 195 errs() << InputFilename << ": Object type not recognized\n"; 196 } 197 198 DumpHeaders(obj); 199 DumpSymbols(obj); 200 DumpDynamicSymbols(obj); 201 DumpLibrariesNeeded(obj); 202 return 0; 203} 204 205