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/Object/ELF.h" 21#include "llvm/Analysis/Verifier.h" 22#include "llvm/ADT/Triple.h" 23#include "llvm/Support/Format.h" 24#include "llvm/Support/CommandLine.h" 25#include "llvm/Support/PrettyStackTrace.h" 26#include "llvm/Support/Debug.h" 27#include "llvm/Support/Signals.h" 28#include "llvm/Support/FormattedStream.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 36void 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 46const 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 58std::string GetFlagStr(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 82void DumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { 83 StringRef Name; 84 SymbolRef::Type Type; 85 uint32_t Flags; 86 uint64_t Address; 87 uint64_t Size; 88 uint64_t FileOffset; 89 Sym.getName(Name); 90 Sym.getAddress(Address); 91 Sym.getSize(Size); 92 Sym.getFileOffset(FileOffset); 93 Sym.getType(Type); 94 Sym.getFlags(Flags); 95 std::string FullName = Name; 96 97 // If this is a dynamic symbol from an ELF object, append 98 // the symbol's version to the name. 99 if (IsDynamic && obj->isELF()) { 100 StringRef Version; 101 bool IsDefault; 102 GetELFSymbolVersion(obj, Sym, Version, IsDefault); 103 if (!Version.empty()) { 104 FullName += (IsDefault ? "@@" : "@"); 105 FullName += Version; 106 } 107 } 108 109 // format() can't handle StringRefs 110 outs() << format(" %-32s", FullName.c_str()) 111 << format(" %-4s", GetTypeStr(Type)) 112 << format(" %16" PRIx64, Address) 113 << format(" %16" PRIx64, Size) 114 << format(" %16" PRIx64, FileOffset) 115 << " " << GetFlagStr(Flags) 116 << "\n"; 117} 118 119 120// Iterate through the normal symbols in the ObjectFile 121void DumpSymbols(const ObjectFile *obj) { 122 error_code ec; 123 uint32_t count = 0; 124 outs() << "Symbols:\n"; 125 symbol_iterator it = obj->begin_symbols(); 126 symbol_iterator ie = obj->end_symbols(); 127 while (it != ie) { 128 DumpSymbol(*it, obj, false); 129 it.increment(ec); 130 if (ec) 131 report_fatal_error("Symbol iteration failed"); 132 ++count; 133 } 134 outs() << " Total: " << count << "\n\n"; 135} 136 137// Iterate through the dynamic symbols in the ObjectFile. 138void DumpDynamicSymbols(const ObjectFile *obj) { 139 error_code ec; 140 uint32_t count = 0; 141 outs() << "Dynamic Symbols:\n"; 142 symbol_iterator it = obj->begin_dynamic_symbols(); 143 symbol_iterator ie = obj->end_dynamic_symbols(); 144 while (it != ie) { 145 DumpSymbol(*it, obj, true); 146 it.increment(ec); 147 if (ec) 148 report_fatal_error("Symbol iteration failed"); 149 ++count; 150 } 151 outs() << " Total: " << count << "\n\n"; 152} 153 154void DumpLibrary(const LibraryRef &lib) { 155 StringRef path; 156 lib.getPath(path); 157 outs() << " " << path << "\n"; 158} 159 160// Iterate through needed libraries 161void DumpLibrariesNeeded(const ObjectFile *obj) { 162 error_code ec; 163 uint32_t count = 0; 164 library_iterator it = obj->begin_libraries_needed(); 165 library_iterator ie = obj->end_libraries_needed(); 166 outs() << "Libraries needed:\n"; 167 while (it != ie) { 168 DumpLibrary(*it); 169 it.increment(ec); 170 if (ec) 171 report_fatal_error("Needed libraries iteration failed"); 172 ++count; 173 } 174 outs() << " Total: " << count << "\n\n"; 175} 176 177void DumpHeaders(const ObjectFile *obj) { 178 outs() << "File Format : " << obj->getFileFormatName() << "\n"; 179 outs() << "Arch : " 180 << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) 181 << "\n"; 182 outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n"; 183 outs() << "Load Name : " << obj->getLoadName() << "\n"; 184 outs() << "\n"; 185} 186 187int main(int argc, char** argv) { 188 error_code ec; 189 sys::PrintStackTraceOnErrorSignal(); 190 PrettyStackTraceProgram X(argc, argv); 191 192 cl::ParseCommandLineOptions(argc, argv, 193 "LLVM Object Reader\n"); 194 195 if (InputFilename.empty()) { 196 errs() << "Please specify an input filename\n"; 197 return 1; 198 } 199 200 // Open the object file 201 OwningPtr<MemoryBuffer> File; 202 if (MemoryBuffer::getFile(InputFilename, File)) { 203 errs() << InputFilename << ": Open failed\n"; 204 return 1; 205 } 206 207 ObjectFile *obj = ObjectFile::createObjectFile(File.take()); 208 if (!obj) { 209 errs() << InputFilename << ": Object type not recognized\n"; 210 } 211 212 DumpHeaders(obj); 213 DumpSymbols(obj); 214 DumpDynamicSymbols(obj); 215 DumpLibrariesNeeded(obj); 216 return 0; 217} 218 219