//
//===----------------------------------------------------------------------===//
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Format.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
using namespace llvm;
using namespace llvm::object;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input object>"), cl::init(""));
-void DumpSymbolHeader() {
+static void dumpSymbolHeader() {
outs() << format(" %-32s", (const char*)"Name")
<< format(" %-4s", (const char*)"Type")
<< format(" %-16s", (const char*)"Address")
<< "\n";
}
-const char *GetTypeStr(SymbolRef::Type Type) {
+static void dumpSectionHeader() {
+ outs() << format(" %-24s", (const char*)"Name")
+ << format(" %-16s", (const char*)"Address")
+ << format(" %-16s", (const char*)"Size")
+ << format(" %-8s", (const char*)"Align")
+ << format(" %-26s", (const char*)"Flags")
+ << "\n";
+}
+
+static const char *getTypeStr(SymbolRef::Type Type) {
switch (Type) {
case SymbolRef::ST_Unknown: return "?";
case SymbolRef::ST_Data: return "DATA";
return "INV";
}
-std::string GetFlagStr(uint32_t Flags) {
+static std::string getSymbolFlagStr(uint32_t Flags) {
std::string result;
if (Flags & SymbolRef::SF_Undefined)
result += "undef,";
return result;
}
-void DumpSymbol(const SymbolRef &sym) {
- 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);
-
- // format() can't handle StringRefs
- outs() << format(" %-32s", Name.str().c_str())
- << format(" %-4s", GetTypeStr(Type))
- << format(" %16"PRIx64, Address)
- << format(" %16"PRIx64, Size)
- << format(" %16"PRIx64, FileOffset)
- << " " << GetFlagStr(Flags)
- << "\n";
+static void checkError(error_code ec, const char *msg) {
+ if (ec)
+ report_fatal_error(std::string(msg) + ": " + ec.message());
}
+static std::string getSectionFlagStr(const SectionRef &Section) {
+ const struct {
+ error_code (SectionRef::*MemF)(bool &) const;
+ const char *FlagStr, *ErrorStr;
+ } Work[] =
+ {{ &SectionRef::isText, "text,", "Section.isText() failed" },
+ { &SectionRef::isData, "data,", "Section.isData() failed" },
+ { &SectionRef::isBSS, "bss,", "Section.isBSS() failed" },
+ { &SectionRef::isRequiredForExecution, "required,",
+ "Section.isRequiredForExecution() failed" },
+ { &SectionRef::isVirtual, "virtual,", "Section.isVirtual() failed" },
+ { &SectionRef::isZeroInit, "zeroinit,", "Section.isZeroInit() failed" },
+ { &SectionRef::isReadOnlyData, "rodata,",
+ "Section.isReadOnlyData() failed" }};
-// 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);
- it.increment(ec);
- if (ec)
- report_fatal_error("Symbol iteration failed");
- ++count;
+ std::string result;
+ for (uint32_t I = 0; I < sizeof(Work)/sizeof(*Work); ++I) {
+ bool B;
+ checkError((Section.*Work[I].MemF)(B), Work[I].ErrorStr);
+ if (B)
+ result += Work[I].FlagStr;
}
- outs() << " Total: " << count << "\n\n";
+
+ // Remove trailing comma
+ if (result.size() > 0) {
+ result.erase(result.size() - 1);
+ }
+ return result;
}
-// 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);
- it.increment(ec);
- if (ec)
- report_fatal_error("Symbol iteration failed");
- ++count;
+static 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;
+ checkError(Sym.getName(Name), "SymbolRef.getName() failed");
+ checkError(Sym.getAddress(Address), "SymbolRef.getAddress() failed");
+ checkError(Sym.getSize(Size), "SymbolRef.getSize() failed");
+ checkError(Sym.getFileOffset(FileOffset),
+ "SymbolRef.getFileOffset() failed");
+ checkError(Sym.getType(Type), "SymbolRef.getType() failed");
+ checkError(Sym.getFlags(Flags), "SymbolRef.getFlags() failed");
+ 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;
+ }
}
- outs() << " Total: " << count << "\n\n";
+
+ // 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)
+ << " " << getSymbolFlagStr(Flags)
+ << "\n";
+}
+
+static void dumpStaticSymbol(const SymbolRef &Sym, const ObjectFile *obj) {
+ return dumpSymbol(Sym, obj, false);
}
-void DumpLibrary(const LibraryRef &lib) {
+static void dumpDynamicSymbol(const SymbolRef &Sym, const ObjectFile *obj) {
+ return dumpSymbol(Sym, obj, true);
+}
+
+static void dumpSection(const SectionRef &Section, const ObjectFile *obj) {
+ StringRef Name;
+ checkError(Section.getName(Name), "SectionRef::getName() failed");
+ uint64_t Addr, Size, Align;
+ checkError(Section.getAddress(Addr), "SectionRef::getAddress() failed");
+ checkError(Section.getSize(Size), "SectionRef::getSize() failed");
+ checkError(Section.getAlignment(Align), "SectionRef::getAlignment() failed");
+ outs() << format(" %-24s", std::string(Name).c_str())
+ << format(" %16" PRIx64, Addr)
+ << format(" %16" PRIx64, Size)
+ << format(" %8" PRIx64, Align)
+ << " " << getSectionFlagStr(Section)
+ << "\n";
+}
+
+static void dumpLibrary(const LibraryRef &lib, const ObjectFile *obj) {
StringRef path;
lib.getPath(path);
outs() << " " << path << "\n";
}
-// Iterate through needed libraries
-void DumpLibrariesNeeded(const ObjectFile *obj) {
+template<typename Iterator, typename Func>
+static void dump(const ObjectFile *obj, Func f, Iterator begin, Iterator end,
+ const char *errStr) {
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";
+ Iterator it = begin, ie = end;
while (it != ie) {
- DumpLibrary(*it);
+ f(*it, obj);
it.increment(ec);
if (ec)
- report_fatal_error("Needed libraries iteration failed");
+ report_fatal_error(errStr);
++count;
}
outs() << " Total: " << count << "\n\n";
}
-void DumpHeaders(const ObjectFile *obj) {
+static void dumpHeaders(const ObjectFile *obj) {
outs() << "File Format : " << obj->getFileFormatName() << "\n";
outs() << "Arch : "
<< Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch())
errs() << InputFilename << ": Object type not recognized\n";
}
- DumpHeaders(obj);
- DumpSymbols(obj);
- DumpDynamicSymbols(obj);
- DumpLibrariesNeeded(obj);
+ dumpHeaders(obj);
+
+ outs() << "Symbols:\n";
+ dumpSymbolHeader();
+ dump(obj, dumpStaticSymbol, obj->begin_symbols(), obj->end_symbols(),
+ "Symbol iteration failed");
+
+ outs() << "Dynamic Symbols:\n";
+ dumpSymbolHeader();
+ dump(obj, dumpDynamicSymbol, obj->begin_dynamic_symbols(),
+ obj->end_dynamic_symbols(), "Symbol iteration failed");
+
+ outs() << "Sections:\n";
+ dumpSectionHeader();
+ dump(obj, &dumpSection, obj->begin_sections(), obj->end_sections(),
+ "Section iteration failed");
+
+ outs() << "Libraries needed:\n";
+ dump(obj, &dumpLibrary, obj->begin_libraries_needed(),
+ obj->end_libraries_needed(), "Needed libraries iteration failed");
+
return 0;
}