// dumps out a plethora of information about an object file depending on the
// flags.
//
+// The flags and output of this program should be near identical to those of
+// binutils objdump.
+//
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
SymbolTable("t", cl::desc("Display the symbol table"));
static cl::opt<bool>
-MachO("macho", cl::desc("Use MachO specific object file parser"));
+MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
static cl::alias
-MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO));
+MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachOOpt));
cl::opt<std::string>
llvm::TripleName("triple", cl::desc("Target triple to disassemble for, "
UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
cl::aliasopt(UnwindInfo));
+static cl::opt<bool>
+PrivateHeaders("private-headers",
+ cl::desc("Display format specific file headers"));
+
+static cl::alias
+PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
+ cl::aliasopt(PrivateHeaders));
+
static StringRef ToolName;
bool llvm::error(error_code ec) {
return a_addr < b_addr;
}
+StringRef
+getSectionFinalSegmentName(const MachOObjectFileBase *MachO, DataRefImpl DR) {
+ if (const MachOObjectFileLE *O = dyn_cast<MachOObjectFileLE>(MachO))
+ return O->getSectionFinalSegmentName(DR);
+ const MachOObjectFileBE *O = dyn_cast<MachOObjectFileBE>(MachO);
+ return O->getSectionFinalSegmentName(DR);
+}
+
static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
const Target *TheTarget = getTarget(Obj);
// getTarget() will have already issued a diagnostic if necessary, so
if (!error(i->containsSymbol(*si, contains)) && contains) {
uint64_t Address;
if (error(si->getAddress(Address))) break;
+ if (Address == UnknownAddressOrSize) continue;
Address -= SectionAddr;
StringRef Name;
// Sort relocations by address.
std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
+ StringRef SegmentName = "";
+ if (const MachOObjectFileBase *MachO =
+ dyn_cast<const MachOObjectFileBase>(Obj)) {
+ DataRefImpl DR = i->getRawDataRefImpl();
+ SegmentName = getSectionFinalSegmentName(MachO, DR);
+ }
StringRef name;
if (error(i->getName(name))) break;
- outs() << "Disassembly of section " << name << ':';
+ outs() << "Disassembly of section ";
+ if (!SegmentName.empty())
+ outs() << SegmentName << ",";
+ outs() << name << ':';
// If the section has no symbols just insert a dummy one and disassemble
// the whole section.
if (error(si->isBSS(BSS))) return;
std::string Type = (std::string(Text ? "TEXT " : "") +
(Data ? "DATA " : "") + (BSS ? "BSS" : ""));
- outs() << format("%3d %-13s %09" PRIx64 " %017" PRIx64 " %s\n",
+ outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n",
i, Name.str().c_str(), Size, Address, Type.c_str());
++i;
}
StringRef Name;
StringRef Contents;
uint64_t BaseAddr;
+ bool BSS;
if (error(si->getName(Name))) continue;
if (error(si->getContents(Contents))) continue;
if (error(si->getAddress(BaseAddr))) continue;
+ if (error(si->isBSS(BSS))) continue;
outs() << "Contents of section " << Name << ":\n";
+ if (BSS) {
+ outs() << format("<skipping contents of bss section at [%04" PRIx64
+ ", %04" PRIx64 ")>\n", BaseAddr,
+ BaseAddr + Contents.size());
+ continue;
+ }
// Dump out the content as hex and printable ascii characters.
for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) {
// Print ascii.
outs() << " ";
for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
- if (std::isprint(Contents[addr + i] & 0xFF))
+ if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
outs() << Contents[addr + i];
else
outs() << ".";
else if (Type == SymbolRef::ST_Function)
FileFunc = 'F';
- outs() << format("%08" PRIx64, Address) << " "
+ const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
+ "%08" PRIx64;
+
+ outs() << format(Fmt, Address) << " "
<< GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
<< (Weak ? 'w' : ' ') // Weak?
<< ' ' // Constructor. Not supported yet.
else if (Section == o->end_sections())
outs() << "*UND*";
else {
+ if (const MachOObjectFileBase *MachO =
+ dyn_cast<const MachOObjectFileBase>(o)) {
+ DataRefImpl DR = Section->getRawDataRefImpl();
+ StringRef SegmentName = getSectionFinalSegmentName(MachO, DR);
+ outs() << SegmentName << ",";
+ }
StringRef SectionName;
if (error(Section->getName(SectionName)))
SectionName = "";
PrintSymbolTable(o);
if (UnwindInfo)
PrintUnwindInfo(o);
+ if (PrivateHeaders && o->isELF())
+ printELFFileHeader(o);
}
/// @brief Dump each object file in \a a;
return;
}
- if (MachO && Disassemble) {
+ if (MachOOpt && Disassemble) {
DisassembleInputMachO(file);
return;
}
&& !SectionHeaders
&& !SectionContents
&& !SymbolTable
- && !UnwindInfo) {
+ && !UnwindInfo
+ && !PrivateHeaders) {
cl::PrintHelpMessage();
return 2;
}