#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
static cl::list<std::string>
InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
-static cl::opt<bool>
-Disassemble("disassemble",
+cl::opt<bool>
+llvm::Disassemble("disassemble",
cl::desc("Display assembler mnemonics for the machine instructions"));
static cl::alias
Disassembled("d", cl::desc("Alias for --disassemble"),
cl::aliasopt(Disassemble));
-static cl::opt<bool>
-Relocations("r", cl::desc("Display the relocation entries in the file"));
+cl::opt<bool>
+llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
-static cl::opt<bool>
-SectionContents("s", cl::desc("Display the content of each section"));
+cl::opt<bool>
+llvm::SectionContents("s", cl::desc("Display the content of each section"));
-static cl::opt<bool>
-SymbolTable("t", cl::desc("Display the symbol table"));
+cl::opt<bool>
+llvm::SymbolTable("t", cl::desc("Display the symbol table"));
-static cl::opt<bool>
-ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));
+cl::opt<bool>
+llvm::ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));
-static cl::opt<bool>
-Rebase("rebase", cl::desc("Display mach-o rebasing info"));
+cl::opt<bool>
+llvm::Rebase("rebase", cl::desc("Display mach-o rebasing info"));
+
+cl::opt<bool>
+llvm::Bind("bind", cl::desc("Display mach-o binding info"));
+
+cl::opt<bool>
+llvm::LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info"));
+
+cl::opt<bool>
+llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info"));
static cl::opt<bool>
MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
cl::init(""));
cl::opt<std::string>
-llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
+llvm::ArchName("arch-name", cl::desc("Target arch to disassemble for, "
"see -version for available targets"));
-static cl::opt<bool>
-SectionHeaders("section-headers", cl::desc("Display summaries of the headers "
- "for each section."));
+cl::opt<bool>
+llvm::SectionHeaders("section-headers", cl::desc("Display summaries of the "
+ "headers for each section."));
static cl::alias
SectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
cl::desc("Target specific attributes"),
cl::value_desc("a1,+a2,-a3,..."));
-static cl::opt<bool>
-NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling instructions, "
- "do not print the instruction bytes."));
+cl::opt<bool>
+llvm::NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling "
+ "instructions, do not print "
+ "the instruction bytes."));
-static cl::opt<bool>
-UnwindInfo("unwind-info", cl::desc("Display unwind information"));
+cl::opt<bool>
+llvm::UnwindInfo("unwind-info", cl::desc("Display unwind information"));
static cl::alias
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"));
+cl::opt<bool>
+llvm::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;
+static int ReturnValue = EXIT_SUCCESS;
bool llvm::error(std::error_code EC) {
if (!EC)
outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
outs().flush();
+ ReturnValue = EXIT_FAILURE;
return true;
}
return TheTarget;
}
-void llvm::DumpBytes(StringRef bytes) {
+void llvm::DumpBytes(ArrayRef<uint8_t> bytes) {
static const char hex_rep[] = "0123456789abcdef";
- // FIXME: The real way to do this is to figure out the longest instruction
- // and align to that size before printing. I'll fix this when I get
- // around to outputting relocations.
- // 15 is the longest x86 instruction
- // 3 is for the hex rep of a byte + a space.
- // 1 is for the null terminator.
- enum { OutputSize = (15 * 3) + 1 };
- char output[OutputSize];
-
- assert(bytes.size() <= 15
- && "DumpBytes only supports instructions of up to 15 bytes");
- memset(output, ' ', sizeof(output));
- unsigned index = 0;
- for (StringRef::iterator i = bytes.begin(),
- e = bytes.end(); i != e; ++i) {
- output[index] = hex_rep[(*i & 0xF0) >> 4];
- output[index + 1] = hex_rep[*i & 0xF];
- index += 3;
+ SmallString<64> output;
+
+ for (char i: bytes) {
+ output.push_back(hex_rep[(i & 0xF0) >> 4]);
+ output.push_back(hex_rep[i & 0xF]);
+ output.push_back(' ');
}
- output[sizeof(output) - 1] = 0;
- outs() << output;
+ outs() << output.c_str();
}
bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
+ Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
if (!IP) {
errs() << "error: no instruction printer for target " << TripleName
<< '\n';
}
for (const SectionRef &Section : Obj->sections()) {
- bool Text;
- if (error(Section.isText(Text)))
- break;
- if (!Text)
+ if (!Section.isText() || Section.isVirtual())
continue;
- uint64_t SectionAddr;
- if (error(Section.getAddress(SectionAddr)))
- break;
-
- uint64_t SectSize;
- if (error(Section.getSize(SectSize)))
- break;
+ uint64_t SectionAddr = Section.getAddress();
+ uint64_t SectSize = Section.getSize();
+ if (!SectSize)
+ continue;
// Make a list of all the symbols in this section.
std::vector<std::pair<uint64_t, StringRef>> Symbols;
for (const SymbolRef &Symbol : Obj->symbols()) {
- bool contains;
- if (!error(Section.containsSymbol(Symbol, contains)) && contains) {
+ if (Section.containsSymbol(Symbol)) {
uint64_t Address;
if (error(Symbol.getAddress(Address)))
break;
SmallString<40> Comments;
raw_svector_ostream CommentStream(Comments);
- StringRef Bytes;
- if (error(Section.getContents(Bytes)))
+ StringRef BytesStr;
+ if (error(Section.getContents(BytesStr)))
break;
- StringRefMemoryObject memoryObject(Bytes, SectionAddr);
+ ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
+ BytesStr.size());
+
uint64_t Size;
uint64_t Index;
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
- if (DisAsm->getInstruction(Inst, Size, memoryObject,
- SectionAddr + Index,
- DebugOut, CommentStream)) {
+ if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
+ SectionAddr + Index, DebugOut,
+ CommentStream)) {
outs() << format("%8" PRIx64 ":", SectionAddr + Index);
if (!NoShowRawInsn) {
outs() << "\t";
- DumpBytes(StringRef(Bytes.data() + Index, Size));
+ DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
}
- IP->printInst(&Inst, outs(), "");
+ IP->printInst(&Inst, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
outs() << "\n";
}
}
-static void PrintRelocations(const ObjectFile *Obj) {
+void llvm::PrintRelocations(const ObjectFile *Obj) {
StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
"%08" PRIx64;
// Regular objdump doesn't print relocations in non-relocatable object
}
}
-static void PrintSectionHeaders(const ObjectFile *Obj) {
+void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
unsigned i = 0;
StringRef Name;
if (error(Section.getName(Name)))
return;
- uint64_t Address;
- if (error(Section.getAddress(Address)))
- return;
- uint64_t Size;
- if (error(Section.getSize(Size)))
- return;
- bool Text, Data, BSS;
- if (error(Section.isText(Text)))
- return;
- if (error(Section.isData(Data)))
- return;
- if (error(Section.isBSS(BSS)))
- return;
+ uint64_t Address = Section.getAddress();
+ uint64_t Size = Section.getSize();
+ bool Text = Section.isText();
+ bool Data = Section.isData();
+ bool BSS = Section.isBSS();
std::string Type = (std::string(Text ? "TEXT " : "") +
(Data ? "DATA " : "") + (BSS ? "BSS" : ""));
outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
}
}
-static void PrintSectionContents(const ObjectFile *Obj) {
+void llvm::PrintSectionContents(const ObjectFile *Obj) {
std::error_code EC;
for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
StringRef Contents;
- uint64_t BaseAddr;
- bool BSS;
if (error(Section.getName(Name)))
continue;
- if (error(Section.getAddress(BaseAddr)))
- continue;
- if (error(Section.isBSS(BSS)))
+ uint64_t BaseAddr = Section.getAddress();
+ uint64_t Size = Section.getSize();
+ if (!Size)
continue;
outs() << "Contents of section " << Name << ":\n";
- if (BSS) {
- uint64_t Size;
- if (error(Section.getSize(Size)))
- continue;
+ if (Section.isBSS()) {
outs() << format("<skipping contents of bss section at [%04" PRIx64
", %04" PRIx64 ")>\n",
BaseAddr, BaseAddr + Size);
if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
return;
+ int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
+
outs() << "AUX "
<< format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
, unsigned(asd->Length)
, unsigned(asd->NumberOfLinenumbers)
, unsigned(asd->CheckSum))
<< format("assoc %d comdat %d\n"
- , unsigned(asd->Number)
+ , unsigned(AuxNumber)
, unsigned(asd->Selection));
} else if (Symbol->isFileRecord()) {
const char *FileName;
}
}
-static void PrintSymbolTable(const ObjectFile *o) {
+void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << "SYMBOL TABLE:\n";
if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
bool Global = Flags & SymbolRef::SF_Global;
bool Weak = Flags & SymbolRef::SF_Weak;
bool Absolute = Flags & SymbolRef::SF_Absolute;
-
+ bool Common = Flags & SymbolRef::SF_Common;
+ bool Hidden = Flags & SymbolRef::SF_Hidden;
+
+ if (Common) {
+ uint32_t Alignment;
+ if (error(Symbol.getAlignment(Alignment)))
+ Alignment = 0;
+ Address = Size;
+ Size = Alignment;
+ }
if (Address == UnknownAddressOrSize)
Address = 0;
if (Size == UnknownAddressOrSize)
<< ' ';
if (Absolute) {
outs() << "*ABS*";
+ } else if (Common) {
+ outs() << "*COM*";
} else if (Section == o->section_end()) {
outs() << "*UND*";
} else {
outs() << SectionName;
}
outs() << '\t'
- << format("%08" PRIx64 " ", Size)
- << Name
+ << format("%08" PRIx64 " ", Size);
+ if (Hidden) {
+ outs() << ".hidden ";
+ }
+ outs() << Name
<< '\n';
}
}
}
}
-static void printExportsTrie(const ObjectFile *o) {
+void llvm::printExportsTrie(const ObjectFile *o) {
outs() << "Exports trie:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOExportsTrie(MachO);
}
}
-static void printRebaseTable(const ObjectFile *o) {
+void llvm::printRebaseTable(const ObjectFile *o) {
outs() << "Rebase table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachORebaseTable(MachO);
}
}
+void llvm::printBindTable(const ObjectFile *o) {
+ outs() << "Bind table:\n";
+ if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachOBindTable(MachO);
+ else {
+ errs() << "This operation is only currently supported "
+ "for Mach-O executable files.\n";
+ return;
+ }
+}
+
+void llvm::printLazyBindTable(const ObjectFile *o) {
+ outs() << "Lazy bind table:\n";
+ if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachOLazyBindTable(MachO);
+ else {
+ errs() << "This operation is only currently supported "
+ "for Mach-O executable files.\n";
+ return;
+ }
+}
+
+void llvm::printWeakBindTable(const ObjectFile *o) {
+ outs() << "Weak bind table:\n";
+ if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachOWeakBindTable(MachO);
+ else {
+ errs() << "This operation is only currently supported "
+ "for Mach-O executable files.\n";
+ return;
+ }
+}
static void printPrivateFileHeader(const ObjectFile *o) {
if (o->isELF()) {
printExportsTrie(o);
if (Rebase)
printRebaseTable(o);
+ if (Bind)
+ printBindTable(o);
+ if (LazyBind)
+ printLazyBindTable(o);
+ if (WeakBind)
+ printWeakBindTable(o);
}
/// @brief Dump each object file in \a a;
return;
}
- if (MachOOpt && Disassemble) {
- DisassembleInputMachO(file);
+ // If we are using the Mach-O specific object file parser, then let it parse
+ // the file and process the command line options. So the -arch flags can
+ // be used to select specific slices, etc.
+ if (MachOOpt) {
+ ParseInputMachO(file);
return;
}
&& !UnwindInfo
&& !PrivateHeaders
&& !ExportsTrie
- && !Rebase) {
+ && !Rebase
+ && !Bind
+ && !LazyBind
+ && !WeakBind
+ && !(UniversalHeaders && MachOOpt)
+ && !(ArchiveHeaders && MachOOpt)
+ && !(IndirectSymbols && MachOOpt)
+ && !(DataInCode && MachOOpt)
+ && !(LinkOptHints && MachOOpt)
+ && !(InfoPlist && MachOOpt)
+ && !(DylibsUsed && MachOOpt)
+ && !(DylibId && MachOOpt)
+ && !(ObjcMetaData && MachOOpt)
+ && !(DumpSections.size() != 0 && MachOOpt)) {
cl::PrintHelpMessage();
return 2;
}
std::for_each(InputFilenames.begin(), InputFilenames.end(),
DumpInput);
- return 0;
+ return ReturnValue;
}