diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp new file mode 100644 index 0000000..3be1289 --- /dev/null +++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -0,0 +1,218 @@ +//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that works like traditional Unix "readelf", +// except that it can handle any type of object file recognized by lib/Object. +// +// It makes use of the generic ObjectFile interface. +// +// Caution: This utility is new, experimental, unsupported, and incomplete. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELF.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; +using namespace llvm::object; + +static cl::opt<std::string> +InputFilename(cl::Positional, cl::desc("<input object>"), cl::init("")); + +void DumpSymbolHeader() { + outs() << format(" %-32s", (const char*)"Name") + << format(" %-4s", (const char*)"Type") + << format(" %-16s", (const char*)"Address") + << format(" %-16s", (const char*)"Size") + << format(" %-16s", (const char*)"FileOffset") + << format(" %-26s", (const char*)"Flags") + << "\n"; +} + +const char *GetTypeStr(SymbolRef::Type Type) { + switch (Type) { + case SymbolRef::ST_Unknown: return "?"; + case SymbolRef::ST_Data: return "DATA"; + case SymbolRef::ST_Debug: return "DBG"; + case SymbolRef::ST_File: return "FILE"; + case SymbolRef::ST_Function: return "FUNC"; + case SymbolRef::ST_Other: return "-"; + } + return "INV"; +} + +std::string GetFlagStr(uint32_t Flags) { + std::string result; + if (Flags & SymbolRef::SF_Undefined) + result += "undef,"; + if (Flags & SymbolRef::SF_Global) + result += "global,"; + if (Flags & SymbolRef::SF_Weak) + result += "weak,"; + if (Flags & SymbolRef::SF_Absolute) + result += "absolute,"; + if (Flags & SymbolRef::SF_ThreadLocal) + result += "threadlocal,"; + if (Flags & SymbolRef::SF_Common) + result += "common,"; + if (Flags & SymbolRef::SF_FormatSpecific) + result += "formatspecific,"; + + // Remove trailing comma + if (result.size() > 0) { + result.erase(result.size() - 1); + } + return result; +} + +void DumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { + StringRef Name; + SymbolRef::Type Type; + uint32_t Flags; + uint64_t Address; + uint64_t Size; + uint64_t FileOffset; + Sym.getName(Name); + Sym.getAddress(Address); + Sym.getSize(Size); + Sym.getFileOffset(FileOffset); + Sym.getType(Type); + Sym.getFlags(Flags); + std::string FullName = Name; + + // If this is a dynamic symbol from an ELF object, append + // the symbol's version to the name. + if (IsDynamic && obj->isELF()) { + StringRef Version; + bool IsDefault; + GetELFSymbolVersion(obj, Sym, Version, IsDefault); + if (!Version.empty()) { + FullName += (IsDefault ? "@@" : "@"); + FullName += Version; + } + } + + // format() can't handle StringRefs + outs() << format(" %-32s", FullName.c_str()) + << format(" %-4s", GetTypeStr(Type)) + << format(" %16" PRIx64, Address) + << format(" %16" PRIx64, Size) + << format(" %16" PRIx64, FileOffset) + << " " << GetFlagStr(Flags) + << "\n"; +} + + +// Iterate through the normal symbols in the ObjectFile +void DumpSymbols(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + outs() << "Symbols:\n"; + symbol_iterator it = obj->begin_symbols(); + symbol_iterator ie = obj->end_symbols(); + while (it != ie) { + DumpSymbol(*it, obj, false); + it.increment(ec); + if (ec) + report_fatal_error("Symbol iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +// Iterate through the dynamic symbols in the ObjectFile. +void DumpDynamicSymbols(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + outs() << "Dynamic Symbols:\n"; + symbol_iterator it = obj->begin_dynamic_symbols(); + symbol_iterator ie = obj->end_dynamic_symbols(); + while (it != ie) { + DumpSymbol(*it, obj, true); + it.increment(ec); + if (ec) + report_fatal_error("Symbol iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +void DumpLibrary(const LibraryRef &lib) { + StringRef path; + lib.getPath(path); + outs() << " " << path << "\n"; +} + +// Iterate through needed libraries +void DumpLibrariesNeeded(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + library_iterator it = obj->begin_libraries_needed(); + library_iterator ie = obj->end_libraries_needed(); + outs() << "Libraries needed:\n"; + while (it != ie) { + DumpLibrary(*it); + it.increment(ec); + if (ec) + report_fatal_error("Needed libraries iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +void DumpHeaders(const ObjectFile *obj) { + outs() << "File Format : " << obj->getFileFormatName() << "\n"; + outs() << "Arch : " + << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) + << "\n"; + outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n"; + outs() << "Load Name : " << obj->getLoadName() << "\n"; + outs() << "\n"; +} + +int main(int argc, char** argv) { + error_code ec; + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + cl::ParseCommandLineOptions(argc, argv, + "LLVM Object Reader\n"); + + if (InputFilename.empty()) { + errs() << "Please specify an input filename\n"; + return 1; + } + + // Open the object file + OwningPtr<MemoryBuffer> File; + if (MemoryBuffer::getFile(InputFilename, File)) { + errs() << InputFilename << ": Open failed\n"; + return 1; + } + + ObjectFile *obj = ObjectFile::createObjectFile(File.take()); + if (!obj) { + errs() << InputFilename << ": Object type not recognized\n"; + } + + DumpHeaders(obj); + DumpSymbols(obj); + DumpDynamicSymbols(obj); + DumpLibrariesNeeded(obj); + return 0; +} + |