+ outs() << "\n";
+ }
+ }
+}
+
+static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
+ for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
+ ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
+ StringRef Name;
+ if (error(Symbol.getError()))
+ return;
+
+ if (error(coff->getSymbolName(*Symbol, Name)))
+ return;
+
+ outs() << "[" << format("%2d", SI) << "]"
+ << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
+ << "(fl 0x00)" // Flag bits, which COFF doesn't have.
+ << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
+ << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
+ << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
+ << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
+ << Name << "\n";
+
+ for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
+ if (Symbol->isSectionDefinition()) {
+ const coff_aux_section_definition *asd;
+ 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->NumberOfRelocations)
+ , unsigned(asd->NumberOfLinenumbers)
+ , unsigned(asd->CheckSum))
+ << format("assoc %d comdat %d\n"
+ , unsigned(AuxNumber)
+ , unsigned(asd->Selection));
+ } else if (Symbol->isFileRecord()) {
+ const char *FileName;
+ if (error(coff->getAuxSymbol<char>(SI + 1, FileName)))
+ return;
+
+ StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
+ coff->getSymbolTableEntrySize());
+ outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
+
+ SI = SI + Symbol->getNumberOfAuxSymbols();
+ break;
+ } else {
+ outs() << "AUX Unknown\n";
+ }
+ }
+ }
+}
+
+void llvm::PrintSymbolTable(const ObjectFile *o) {
+ outs() << "SYMBOL TABLE:\n";
+
+ if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
+ PrintCOFFSymbolTable(coff);
+ return;
+ }
+ for (const SymbolRef &Symbol : o->symbols()) {
+ StringRef Name;
+ uint64_t Address;
+ SymbolRef::Type Type;
+ uint64_t Size;
+ uint32_t Flags = Symbol.getFlags();
+ section_iterator Section = o->section_end();
+ if (error(Symbol.getName(Name)))
+ continue;
+ if (error(Symbol.getAddress(Address)))
+ continue;
+ if (error(Symbol.getType(Type)))
+ continue;
+ if (error(Symbol.getSize(Size)))
+ continue;
+ if (error(Symbol.getSection(Section)))
+ continue;
+
+ bool Global = Flags & SymbolRef::SF_Global;
+ bool Weak = Flags & SymbolRef::SF_Weak;
+ bool Absolute = Flags & SymbolRef::SF_Absolute;
+ bool Common = Flags & SymbolRef::SF_Common;
+
+ if (Common) {
+ uint32_t Alignment;
+ if (error(Symbol.getAlignment(Alignment)))
+ Alignment = 0;
+ Address = Size;
+ Size = Alignment;
+ }
+ if (Address == UnknownAddressOrSize)
+ Address = 0;
+ if (Size == UnknownAddressOrSize)
+ Size = 0;
+ char GlobLoc = ' ';
+ if (Type != SymbolRef::ST_Unknown)
+ GlobLoc = Global ? 'g' : 'l';
+ char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
+ ? 'd' : ' ';
+ char FileFunc = ' ';
+ if (Type == SymbolRef::ST_File)
+ FileFunc = 'f';
+ else if (Type == SymbolRef::ST_Function)
+ FileFunc = 'F';
+
+ 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.
+ << ' ' // Warning. Not supported yet.
+ << ' ' // Indirect reference to another symbol.
+ << Debug // Debugging (d) or dynamic (D) symbol.
+ << FileFunc // Name of function (F), file (f) or object (O).
+ << ' ';
+ if (Absolute) {
+ outs() << "*ABS*";
+ } else if (Common) {
+ outs() << "*COM*";
+ } else if (Section == o->section_end()) {
+ outs() << "*UND*";
+ } else {
+ if (const MachOObjectFile *MachO =
+ dyn_cast<const MachOObjectFile>(o)) {
+ DataRefImpl DR = Section->getRawDataRefImpl();
+ StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
+ outs() << SegmentName << ",";
+ }
+ StringRef SectionName;
+ if (error(Section->getName(SectionName)))
+ SectionName = "";
+ outs() << SectionName;
+ }
+ outs() << '\t'
+ << format("%08" PRIx64 " ", Size)
+ << Name
+ << '\n';
+ }
+}
+
+static void PrintUnwindInfo(const ObjectFile *o) {
+ outs() << "Unwind info:\n\n";
+
+ if (const COFFObjectFile *coff = dyn_cast<COFFObjectFile>(o)) {
+ printCOFFUnwindInfo(coff);
+ } else if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachOUnwindInfo(MachO);
+ else {
+ // TODO: Extract DWARF dump tool to objdump.
+ errs() << "This operation is only currently supported "
+ "for COFF and MachO object files.\n";
+ return;
+ }
+}
+
+void llvm::printExportsTrie(const ObjectFile *o) {
+ outs() << "Exports trie:\n";
+ if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachOExportsTrie(MachO);
+ else {
+ errs() << "This operation is only currently supported "
+ "for Mach-O executable files.\n";
+ return;
+ }
+}
+
+void llvm::printRebaseTable(const ObjectFile *o) {
+ outs() << "Rebase table:\n";
+ if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+ printMachORebaseTable(MachO);
+ else {
+ errs() << "This operation is only currently supported "
+ "for Mach-O executable files.\n";
+ return;
+ }
+}
+
+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()) {
+ printELFFileHeader(o);
+ } else if (o->isCOFF()) {
+ printCOFFFileHeader(o);
+ } else if (o->isMachO()) {
+ printMachOFileHeader(o);
+ }
+}
+
+static void DumpObject(const ObjectFile *o) {
+ outs() << '\n';
+ outs() << o->getFileName()
+ << ":\tfile format " << o->getFileFormatName() << "\n\n";
+
+ if (Disassemble)
+ DisassembleObject(o, Relocations);
+ if (Relocations && !Disassemble)
+ PrintRelocations(o);
+ if (SectionHeaders)
+ PrintSectionHeaders(o);
+ if (SectionContents)
+ PrintSectionContents(o);
+ if (SymbolTable)
+ PrintSymbolTable(o);
+ if (UnwindInfo)
+ PrintUnwindInfo(o);
+ if (PrivateHeaders)
+ printPrivateFileHeader(o);
+ if (ExportsTrie)
+ 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;
+static void DumpArchive(const Archive *a) {
+ for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
+ ++i) {
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
+ if (std::error_code EC = ChildOrErr.getError()) {
+ // Ignore non-object files.
+ if (EC != object_error::invalid_file_type)
+ errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message()
+ << ".\n";
+ continue;