Home | History | Annotate | Download | only in llvm-objdump
      1 //===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This program is a utility that works like binutils "objdump", that is, it
     11 // dumps out a plethora of information about an object file depending on the
     12 // flags.
     13 //
     14 // The flags and output of this program should be near identical to those of
     15 // binutils objdump.
     16 //
     17 //===----------------------------------------------------------------------===//
     18 
     19 #include "llvm-objdump.h"
     20 #include "llvm/ADT/STLExtras.h"
     21 #include "llvm/ADT/StringExtras.h"
     22 #include "llvm/ADT/Triple.h"
     23 #include "llvm/MC/MCAnalysis/MCAtom.h"
     24 #include "llvm/MC/MCAnalysis/MCFunction.h"
     25 #include "llvm/MC/MCAnalysis/MCModule.h"
     26 #include "llvm/MC/MCAnalysis/MCModuleYAML.h"
     27 #include "llvm/MC/MCAsmInfo.h"
     28 #include "llvm/MC/MCContext.h"
     29 #include "llvm/MC/MCDisassembler.h"
     30 #include "llvm/MC/MCInst.h"
     31 #include "llvm/MC/MCInstPrinter.h"
     32 #include "llvm/MC/MCInstrAnalysis.h"
     33 #include "llvm/MC/MCInstrInfo.h"
     34 #include "llvm/MC/MCObjectDisassembler.h"
     35 #include "llvm/MC/MCObjectFileInfo.h"
     36 #include "llvm/MC/MCObjectSymbolizer.h"
     37 #include "llvm/MC/MCRegisterInfo.h"
     38 #include "llvm/MC/MCRelocationInfo.h"
     39 #include "llvm/MC/MCSubtargetInfo.h"
     40 #include "llvm/Object/Archive.h"
     41 #include "llvm/Object/COFF.h"
     42 #include "llvm/Object/MachO.h"
     43 #include "llvm/Object/ObjectFile.h"
     44 #include "llvm/Support/Casting.h"
     45 #include "llvm/Support/CommandLine.h"
     46 #include "llvm/Support/Debug.h"
     47 #include "llvm/Support/FileSystem.h"
     48 #include "llvm/Support/Format.h"
     49 #include "llvm/Support/GraphWriter.h"
     50 #include "llvm/Support/Host.h"
     51 #include "llvm/Support/ManagedStatic.h"
     52 #include "llvm/Support/MemoryBuffer.h"
     53 #include "llvm/Support/MemoryObject.h"
     54 #include "llvm/Support/PrettyStackTrace.h"
     55 #include "llvm/Support/Signals.h"
     56 #include "llvm/Support/SourceMgr.h"
     57 #include "llvm/Support/TargetRegistry.h"
     58 #include "llvm/Support/TargetSelect.h"
     59 #include "llvm/Support/raw_ostream.h"
     60 #include <algorithm>
     61 #include <cctype>
     62 #include <cstring>
     63 #include <system_error>
     64 
     65 using namespace llvm;
     66 using namespace object;
     67 
     68 static cl::list<std::string>
     69 InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
     70 
     71 static cl::opt<bool>
     72 Disassemble("disassemble",
     73   cl::desc("Display assembler mnemonics for the machine instructions"));
     74 static cl::alias
     75 Disassembled("d", cl::desc("Alias for --disassemble"),
     76              cl::aliasopt(Disassemble));
     77 
     78 static cl::opt<bool>
     79 Relocations("r", cl::desc("Display the relocation entries in the file"));
     80 
     81 static cl::opt<bool>
     82 SectionContents("s", cl::desc("Display the content of each section"));
     83 
     84 static cl::opt<bool>
     85 SymbolTable("t", cl::desc("Display the symbol table"));
     86 
     87 static cl::opt<bool>
     88 MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
     89 static cl::alias
     90 MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachOOpt));
     91 
     92 cl::opt<std::string>
     93 llvm::TripleName("triple", cl::desc("Target triple to disassemble for, "
     94                                     "see -version for available targets"));
     95 
     96 cl::opt<std::string>
     97 llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
     98                                 "see -version for available targets"));
     99 
    100 static cl::opt<bool>
    101 SectionHeaders("section-headers", cl::desc("Display summaries of the headers "
    102                                            "for each section."));
    103 static cl::alias
    104 SectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
    105                     cl::aliasopt(SectionHeaders));
    106 static cl::alias
    107 SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
    108                       cl::aliasopt(SectionHeaders));
    109 
    110 static cl::list<std::string>
    111 MAttrs("mattr",
    112   cl::CommaSeparated,
    113   cl::desc("Target specific attributes"),
    114   cl::value_desc("a1,+a2,-a3,..."));
    115 
    116 static cl::opt<bool>
    117 NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling instructions, "
    118                                            "do not print the instruction bytes."));
    119 
    120 static cl::opt<bool>
    121 UnwindInfo("unwind-info", cl::desc("Display unwind information"));
    122 
    123 static cl::alias
    124 UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
    125                 cl::aliasopt(UnwindInfo));
    126 
    127 static cl::opt<bool>
    128 PrivateHeaders("private-headers",
    129                cl::desc("Display format specific file headers"));
    130 
    131 static cl::alias
    132 PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
    133                     cl::aliasopt(PrivateHeaders));
    134 
    135 static cl::opt<bool>
    136 Symbolize("symbolize", cl::desc("When disassembling instructions, "
    137                                 "try to symbolize operands."));
    138 
    139 static cl::opt<bool>
    140 CFG("cfg", cl::desc("Create a CFG for every function found in the object"
    141                       " and write it to a graphviz file"));
    142 
    143 // FIXME: Does it make sense to have a dedicated tool for yaml cfg output?
    144 static cl::opt<std::string>
    145 YAMLCFG("yaml-cfg",
    146         cl::desc("Create a CFG and write it as a YAML MCModule."),
    147         cl::value_desc("yaml output file"));
    148 
    149 static StringRef ToolName;
    150 
    151 bool llvm::error(std::error_code EC) {
    152   if (!EC)
    153     return false;
    154 
    155   outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
    156   outs().flush();
    157   return true;
    158 }
    159 
    160 static const Target *getTarget(const ObjectFile *Obj = nullptr) {
    161   // Figure out the target triple.
    162   llvm::Triple TheTriple("unknown-unknown-unknown");
    163   if (TripleName.empty()) {
    164     if (Obj) {
    165       TheTriple.setArch(Triple::ArchType(Obj->getArch()));
    166       // TheTriple defaults to ELF, and COFF doesn't have an environment:
    167       // the best we can do here is indicate that it is mach-o.
    168       if (Obj->isMachO())
    169         TheTriple.setObjectFormat(Triple::MachO);
    170 
    171       if (Obj->isCOFF()) {
    172         const auto COFFObj = dyn_cast<COFFObjectFile>(Obj);
    173         if (COFFObj->getArch() == Triple::thumb)
    174           TheTriple.setTriple("thumbv7-windows");
    175       }
    176     }
    177   } else
    178     TheTriple.setTriple(Triple::normalize(TripleName));
    179 
    180   // Get the target specific parser.
    181   std::string Error;
    182   const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
    183                                                          Error);
    184   if (!TheTarget) {
    185     errs() << ToolName << ": " << Error;
    186     return nullptr;
    187   }
    188 
    189   // Update the triple name and return the found target.
    190   TripleName = TheTriple.getTriple();
    191   return TheTarget;
    192 }
    193 
    194 // Write a graphviz file for the CFG inside an MCFunction.
    195 // FIXME: Use GraphWriter
    196 static void emitDOTFile(const char *FileName, const MCFunction &f,
    197                         MCInstPrinter *IP) {
    198   // Start a new dot file.
    199   std::string Error;
    200   raw_fd_ostream Out(FileName, Error, sys::fs::F_Text);
    201   if (!Error.empty()) {
    202     errs() << "llvm-objdump: warning: " << Error << '\n';
    203     return;
    204   }
    205 
    206   Out << "digraph \"" << f.getName() << "\" {\n";
    207   Out << "graph [ rankdir = \"LR\" ];\n";
    208   for (MCFunction::const_iterator i = f.begin(), e = f.end(); i != e; ++i) {
    209     // Only print blocks that have predecessors.
    210     bool hasPreds = (*i)->pred_begin() != (*i)->pred_end();
    211 
    212     if (!hasPreds && i != f.begin())
    213       continue;
    214 
    215     Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\"<a>";
    216     // Print instructions.
    217     for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie;
    218         ++ii) {
    219       if (ii != 0) // Not the first line, start a new row.
    220         Out << '|';
    221       if (ii + 1 == ie) // Last line, add an end id.
    222         Out << "<o>";
    223 
    224       // Escape special chars and print the instruction in mnemonic form.
    225       std::string Str;
    226       raw_string_ostream OS(Str);
    227       IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, "");
    228       Out << DOT::EscapeString(OS.str());
    229     }
    230     Out << "\" shape=\"record\" ];\n";
    231 
    232     // Add edges.
    233     for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(),
    234         se = (*i)->succ_end(); si != se; ++si)
    235       Out << (*i)->getInsts()->getBeginAddr() << ":o -> "
    236           << (*si)->getInsts()->getBeginAddr() << ":a\n";
    237   }
    238   Out << "}\n";
    239 }
    240 
    241 void llvm::DumpBytes(StringRef bytes) {
    242   static const char hex_rep[] = "0123456789abcdef";
    243   // FIXME: The real way to do this is to figure out the longest instruction
    244   //        and align to that size before printing. I'll fix this when I get
    245   //        around to outputting relocations.
    246   // 15 is the longest x86 instruction
    247   // 3 is for the hex rep of a byte + a space.
    248   // 1 is for the null terminator.
    249   enum { OutputSize = (15 * 3) + 1 };
    250   char output[OutputSize];
    251 
    252   assert(bytes.size() <= 15
    253     && "DumpBytes only supports instructions of up to 15 bytes");
    254   memset(output, ' ', sizeof(output));
    255   unsigned index = 0;
    256   for (StringRef::iterator i = bytes.begin(),
    257                            e = bytes.end(); i != e; ++i) {
    258     output[index] = hex_rep[(*i & 0xF0) >> 4];
    259     output[index + 1] = hex_rep[*i & 0xF];
    260     index += 3;
    261   }
    262 
    263   output[sizeof(output) - 1] = 0;
    264   outs() << output;
    265 }
    266 
    267 bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
    268   uint64_t a_addr, b_addr;
    269   if (error(a.getOffset(a_addr))) return false;
    270   if (error(b.getOffset(b_addr))) return false;
    271   return a_addr < b_addr;
    272 }
    273 
    274 static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
    275   const Target *TheTarget = getTarget(Obj);
    276   // getTarget() will have already issued a diagnostic if necessary, so
    277   // just bail here if it failed.
    278   if (!TheTarget)
    279     return;
    280 
    281   // Package up features to be passed to target/subtarget
    282   std::string FeaturesStr;
    283   if (MAttrs.size()) {
    284     SubtargetFeatures Features;
    285     for (unsigned i = 0; i != MAttrs.size(); ++i)
    286       Features.AddFeature(MAttrs[i]);
    287     FeaturesStr = Features.getString();
    288   }
    289 
    290   std::unique_ptr<const MCRegisterInfo> MRI(
    291       TheTarget->createMCRegInfo(TripleName));
    292   if (!MRI) {
    293     errs() << "error: no register info for target " << TripleName << "\n";
    294     return;
    295   }
    296 
    297   // Set up disassembler.
    298   std::unique_ptr<const MCAsmInfo> AsmInfo(
    299       TheTarget->createMCAsmInfo(*MRI, TripleName));
    300   if (!AsmInfo) {
    301     errs() << "error: no assembly info for target " << TripleName << "\n";
    302     return;
    303   }
    304 
    305   std::unique_ptr<const MCSubtargetInfo> STI(
    306       TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
    307   if (!STI) {
    308     errs() << "error: no subtarget info for target " << TripleName << "\n";
    309     return;
    310   }
    311 
    312   std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
    313   if (!MII) {
    314     errs() << "error: no instruction info for target " << TripleName << "\n";
    315     return;
    316   }
    317 
    318   std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
    319   MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
    320 
    321   std::unique_ptr<MCDisassembler> DisAsm(
    322     TheTarget->createMCDisassembler(*STI, Ctx));
    323 
    324   if (!DisAsm) {
    325     errs() << "error: no disassembler for target " << TripleName << "\n";
    326     return;
    327   }
    328 
    329 
    330   if (Symbolize) {
    331     std::unique_ptr<MCRelocationInfo> RelInfo(
    332         TheTarget->createMCRelocationInfo(TripleName, Ctx));
    333     if (RelInfo) {
    334       std::unique_ptr<MCSymbolizer> Symzer(
    335         MCObjectSymbolizer::createObjectSymbolizer(Ctx, std::move(RelInfo),
    336                                                    Obj));
    337       if (Symzer)
    338         DisAsm->setSymbolizer(std::move(Symzer));
    339     }
    340   }
    341 
    342   std::unique_ptr<const MCInstrAnalysis> MIA(
    343       TheTarget->createMCInstrAnalysis(MII.get()));
    344 
    345   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
    346   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
    347       AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
    348   if (!IP) {
    349     errs() << "error: no instruction printer for target " << TripleName
    350       << '\n';
    351     return;
    352   }
    353 
    354   if (CFG || !YAMLCFG.empty()) {
    355     std::unique_ptr<MCObjectDisassembler> OD(
    356         new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
    357     std::unique_ptr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
    358     for (MCModule::const_atom_iterator AI = Mod->atom_begin(),
    359                                        AE = Mod->atom_end();
    360                                        AI != AE; ++AI) {
    361       outs() << "Atom " << (*AI)->getName() << ": \n";
    362       if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI)) {
    363         for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end();
    364              II != IE;
    365              ++II) {
    366           IP->printInst(&II->Inst, outs(), "");
    367           outs() << "\n";
    368         }
    369       }
    370     }
    371     if (CFG) {
    372       for (MCModule::const_func_iterator FI = Mod->func_begin(),
    373                                          FE = Mod->func_end();
    374                                          FI != FE; ++FI) {
    375         static int filenum = 0;
    376         emitDOTFile((Twine((*FI)->getName()) + "_" +
    377                      utostr(filenum) + ".dot").str().c_str(),
    378                       **FI, IP.get());
    379         ++filenum;
    380       }
    381     }
    382     if (!YAMLCFG.empty()) {
    383       std::string Error;
    384       raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error, sys::fs::F_Text);
    385       if (!Error.empty()) {
    386         errs() << ToolName << ": warning: " << Error << '\n';
    387         return;
    388       }
    389       mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI);
    390     }
    391   }
    392 
    393   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ":  " :
    394                                                  "\t\t\t%08" PRIx64 ":  ";
    395 
    396   // Create a mapping, RelocSecs = SectionRelocMap[S], where sections
    397   // in RelocSecs contain the relocations for section S.
    398   std::error_code EC;
    399   std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
    400   for (const SectionRef &Section : Obj->sections()) {
    401     section_iterator Sec2 = Section.getRelocatedSection();
    402     if (Sec2 != Obj->section_end())
    403       SectionRelocMap[*Sec2].push_back(Section);
    404   }
    405 
    406   for (const SectionRef &Section : Obj->sections()) {
    407     bool Text;
    408     if (error(Section.isText(Text)))
    409       break;
    410     if (!Text)
    411       continue;
    412 
    413     uint64_t SectionAddr;
    414     if (error(Section.getAddress(SectionAddr)))
    415       break;
    416 
    417     uint64_t SectSize;
    418     if (error(Section.getSize(SectSize)))
    419       break;
    420 
    421     // Make a list of all the symbols in this section.
    422     std::vector<std::pair<uint64_t, StringRef>> Symbols;
    423     for (const SymbolRef &Symbol : Obj->symbols()) {
    424       bool contains;
    425       if (!error(Section.containsSymbol(Symbol, contains)) && contains) {
    426         uint64_t Address;
    427         if (error(Symbol.getAddress(Address)))
    428           break;
    429         if (Address == UnknownAddressOrSize)
    430           continue;
    431         Address -= SectionAddr;
    432         if (Address >= SectSize)
    433           continue;
    434 
    435         StringRef Name;
    436         if (error(Symbol.getName(Name)))
    437           break;
    438         Symbols.push_back(std::make_pair(Address, Name));
    439       }
    440     }
    441 
    442     // Sort the symbols by address, just in case they didn't come in that way.
    443     array_pod_sort(Symbols.begin(), Symbols.end());
    444 
    445     // Make a list of all the relocations for this section.
    446     std::vector<RelocationRef> Rels;
    447     if (InlineRelocs) {
    448       for (const SectionRef &RelocSec : SectionRelocMap[Section]) {
    449         for (const RelocationRef &Reloc : RelocSec.relocations()) {
    450           Rels.push_back(Reloc);
    451         }
    452       }
    453     }
    454 
    455     // Sort relocations by address.
    456     std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
    457 
    458     StringRef SegmentName = "";
    459     if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {
    460       DataRefImpl DR = Section.getRawDataRefImpl();
    461       SegmentName = MachO->getSectionFinalSegmentName(DR);
    462     }
    463     StringRef name;
    464     if (error(Section.getName(name)))
    465       break;
    466     outs() << "Disassembly of section ";
    467     if (!SegmentName.empty())
    468       outs() << SegmentName << ",";
    469     outs() << name << ':';
    470 
    471     // If the section has no symbols just insert a dummy one and disassemble
    472     // the whole section.
    473     if (Symbols.empty())
    474       Symbols.push_back(std::make_pair(0, name));
    475 
    476 
    477     SmallString<40> Comments;
    478     raw_svector_ostream CommentStream(Comments);
    479 
    480     StringRef Bytes;
    481     if (error(Section.getContents(Bytes)))
    482       break;
    483     StringRefMemoryObject memoryObject(Bytes, SectionAddr);
    484     uint64_t Size;
    485     uint64_t Index;
    486 
    487     std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();
    488     std::vector<RelocationRef>::const_iterator rel_end = Rels.end();
    489     // Disassemble symbol by symbol.
    490     for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
    491       uint64_t Start = Symbols[si].first;
    492       uint64_t End;
    493       // The end is either the size of the section or the beginning of the next
    494       // symbol.
    495       if (si == se - 1)
    496         End = SectSize;
    497       // Make sure this symbol takes up space.
    498       else if (Symbols[si + 1].first != Start)
    499         End = Symbols[si + 1].first - 1;
    500       else
    501         // This symbol has the same address as the next symbol. Skip it.
    502         continue;
    503 
    504       outs() << '\n' << Symbols[si].second << ":\n";
    505 
    506 #ifndef NDEBUG
    507       raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
    508 #else
    509       raw_ostream &DebugOut = nulls();
    510 #endif
    511 
    512       for (Index = Start; Index < End; Index += Size) {
    513         MCInst Inst;
    514 
    515         if (DisAsm->getInstruction(Inst, Size, memoryObject,
    516                                    SectionAddr + Index,
    517                                    DebugOut, CommentStream)) {
    518           outs() << format("%8" PRIx64 ":", SectionAddr + Index);
    519           if (!NoShowRawInsn) {
    520             outs() << "\t";
    521             DumpBytes(StringRef(Bytes.data() + Index, Size));
    522           }
    523           IP->printInst(&Inst, outs(), "");
    524           outs() << CommentStream.str();
    525           Comments.clear();
    526           outs() << "\n";
    527         } else {
    528           errs() << ToolName << ": warning: invalid instruction encoding\n";
    529           if (Size == 0)
    530             Size = 1; // skip illegible bytes
    531         }
    532 
    533         // Print relocation for instruction.
    534         while (rel_cur != rel_end) {
    535           bool hidden = false;
    536           uint64_t addr;
    537           SmallString<16> name;
    538           SmallString<32> val;
    539 
    540           // If this relocation is hidden, skip it.
    541           if (error(rel_cur->getHidden(hidden))) goto skip_print_rel;
    542           if (hidden) goto skip_print_rel;
    543 
    544           if (error(rel_cur->getOffset(addr))) goto skip_print_rel;
    545           // Stop when rel_cur's address is past the current instruction.
    546           if (addr >= Index + Size) break;
    547           if (error(rel_cur->getTypeName(name))) goto skip_print_rel;
    548           if (error(rel_cur->getValueString(val))) goto skip_print_rel;
    549 
    550           outs() << format(Fmt.data(), SectionAddr + addr) << name
    551                  << "\t" << val << "\n";
    552 
    553         skip_print_rel:
    554           ++rel_cur;
    555         }
    556       }
    557     }
    558   }
    559 }
    560 
    561 static void PrintRelocations(const ObjectFile *Obj) {
    562   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
    563                                                  "%08" PRIx64;
    564   for (const SectionRef &Section : Obj->sections()) {
    565     if (Section.relocation_begin() == Section.relocation_end())
    566       continue;
    567     StringRef secname;
    568     if (error(Section.getName(secname)))
    569       continue;
    570     outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
    571     for (const RelocationRef &Reloc : Section.relocations()) {
    572       bool hidden;
    573       uint64_t address;
    574       SmallString<32> relocname;
    575       SmallString<32> valuestr;
    576       if (error(Reloc.getHidden(hidden)))
    577         continue;
    578       if (hidden)
    579         continue;
    580       if (error(Reloc.getTypeName(relocname)))
    581         continue;
    582       if (error(Reloc.getOffset(address)))
    583         continue;
    584       if (error(Reloc.getValueString(valuestr)))
    585         continue;
    586       outs() << format(Fmt.data(), address) << " " << relocname << " "
    587              << valuestr << "\n";
    588     }
    589     outs() << "\n";
    590   }
    591 }
    592 
    593 static void PrintSectionHeaders(const ObjectFile *Obj) {
    594   outs() << "Sections:\n"
    595             "Idx Name          Size      Address          Type\n";
    596   unsigned i = 0;
    597   for (const SectionRef &Section : Obj->sections()) {
    598     StringRef Name;
    599     if (error(Section.getName(Name)))
    600       return;
    601     uint64_t Address;
    602     if (error(Section.getAddress(Address)))
    603       return;
    604     uint64_t Size;
    605     if (error(Section.getSize(Size)))
    606       return;
    607     bool Text, Data, BSS;
    608     if (error(Section.isText(Text)))
    609       return;
    610     if (error(Section.isData(Data)))
    611       return;
    612     if (error(Section.isBSS(BSS)))
    613       return;
    614     std::string Type = (std::string(Text ? "TEXT " : "") +
    615                         (Data ? "DATA " : "") + (BSS ? "BSS" : ""));
    616     outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
    617                      Name.str().c_str(), Size, Address, Type.c_str());
    618     ++i;
    619   }
    620 }
    621 
    622 static void PrintSectionContents(const ObjectFile *Obj) {
    623   std::error_code EC;
    624   for (const SectionRef &Section : Obj->sections()) {
    625     StringRef Name;
    626     StringRef Contents;
    627     uint64_t BaseAddr;
    628     bool BSS;
    629     if (error(Section.getName(Name)))
    630       continue;
    631     if (error(Section.getContents(Contents)))
    632       continue;
    633     if (error(Section.getAddress(BaseAddr)))
    634       continue;
    635     if (error(Section.isBSS(BSS)))
    636       continue;
    637 
    638     outs() << "Contents of section " << Name << ":\n";
    639     if (BSS) {
    640       outs() << format("<skipping contents of bss section at [%04" PRIx64
    641                        ", %04" PRIx64 ")>\n", BaseAddr,
    642                        BaseAddr + Contents.size());
    643       continue;
    644     }
    645 
    646     // Dump out the content as hex and printable ascii characters.
    647     for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) {
    648       outs() << format(" %04" PRIx64 " ", BaseAddr + addr);
    649       // Dump line of hex.
    650       for (std::size_t i = 0; i < 16; ++i) {
    651         if (i != 0 && i % 4 == 0)
    652           outs() << ' ';
    653         if (addr + i < end)
    654           outs() << hexdigit((Contents[addr + i] >> 4) & 0xF, true)
    655                  << hexdigit(Contents[addr + i] & 0xF, true);
    656         else
    657           outs() << "  ";
    658       }
    659       // Print ascii.
    660       outs() << "  ";
    661       for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
    662         if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
    663           outs() << Contents[addr + i];
    664         else
    665           outs() << ".";
    666       }
    667       outs() << "\n";
    668     }
    669   }
    670 }
    671 
    672 static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
    673   const coff_file_header *header;
    674   if (error(coff->getHeader(header)))
    675     return;
    676 
    677   for (unsigned SI = 0, SE = header->NumberOfSymbols; SI != SE; ++SI) {
    678     const coff_symbol *Symbol;
    679     StringRef Name;
    680     if (error(coff->getSymbol(SI, Symbol)))
    681       return;
    682 
    683     if (error(coff->getSymbolName(Symbol, Name)))
    684       return;
    685 
    686     outs() << "[" << format("%2d", SI) << "]"
    687            << "(sec " << format("%2d", int(Symbol->SectionNumber)) << ")"
    688            << "(fl 0x00)" // Flag bits, which COFF doesn't have.
    689            << "(ty " << format("%3x", unsigned(Symbol->Type)) << ")"
    690            << "(scl " << format("%3x", unsigned(Symbol->StorageClass)) << ") "
    691            << "(nx " << unsigned(Symbol->NumberOfAuxSymbols) << ") "
    692            << "0x" << format("%08x", unsigned(Symbol->Value)) << " "
    693            << Name << "\n";
    694 
    695     for (unsigned AI = 0, AE = Symbol->NumberOfAuxSymbols; AI < AE; ++AI, ++SI) {
    696       if (Symbol->isSectionDefinition()) {
    697         const coff_aux_section_definition *asd;
    698         if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
    699           return;
    700 
    701         outs() << "AUX "
    702                << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
    703                          , unsigned(asd->Length)
    704                          , unsigned(asd->NumberOfRelocations)
    705                          , unsigned(asd->NumberOfLinenumbers)
    706                          , unsigned(asd->CheckSum))
    707                << format("assoc %d comdat %d\n"
    708                          , unsigned(asd->Number)
    709                          , unsigned(asd->Selection));
    710       } else if (Symbol->isFileRecord()) {
    711         const coff_aux_file *AF;
    712         if (error(coff->getAuxSymbol<coff_aux_file>(SI + 1, AF)))
    713           return;
    714 
    715         StringRef Name(AF->FileName,
    716                        Symbol->NumberOfAuxSymbols * COFF::SymbolSize);
    717         outs() << "AUX " << Name.rtrim(StringRef("\0", 1))  << '\n';
    718 
    719         SI = SI + Symbol->NumberOfAuxSymbols;
    720         break;
    721       } else {
    722         outs() << "AUX Unknown\n";
    723       }
    724     }
    725   }
    726 }
    727 
    728 static void PrintSymbolTable(const ObjectFile *o) {
    729   outs() << "SYMBOL TABLE:\n";
    730 
    731   if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
    732     PrintCOFFSymbolTable(coff);
    733     return;
    734   }
    735   for (const SymbolRef &Symbol : o->symbols()) {
    736     StringRef Name;
    737     uint64_t Address;
    738     SymbolRef::Type Type;
    739     uint64_t Size;
    740     uint32_t Flags = Symbol.getFlags();
    741     section_iterator Section = o->section_end();
    742     if (error(Symbol.getName(Name)))
    743       continue;
    744     if (error(Symbol.getAddress(Address)))
    745       continue;
    746     if (error(Symbol.getType(Type)))
    747       continue;
    748     if (error(Symbol.getSize(Size)))
    749       continue;
    750     if (error(Symbol.getSection(Section)))
    751       continue;
    752 
    753     bool Global = Flags & SymbolRef::SF_Global;
    754     bool Weak = Flags & SymbolRef::SF_Weak;
    755     bool Absolute = Flags & SymbolRef::SF_Absolute;
    756 
    757     if (Address == UnknownAddressOrSize)
    758       Address = 0;
    759     if (Size == UnknownAddressOrSize)
    760       Size = 0;
    761     char GlobLoc = ' ';
    762     if (Type != SymbolRef::ST_Unknown)
    763       GlobLoc = Global ? 'g' : 'l';
    764     char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
    765                  ? 'd' : ' ';
    766     char FileFunc = ' ';
    767     if (Type == SymbolRef::ST_File)
    768       FileFunc = 'f';
    769     else if (Type == SymbolRef::ST_Function)
    770       FileFunc = 'F';
    771 
    772     const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
    773                                                    "%08" PRIx64;
    774 
    775     outs() << format(Fmt, Address) << " "
    776            << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
    777            << (Weak ? 'w' : ' ') // Weak?
    778            << ' ' // Constructor. Not supported yet.
    779            << ' ' // Warning. Not supported yet.
    780            << ' ' // Indirect reference to another symbol.
    781            << Debug // Debugging (d) or dynamic (D) symbol.
    782            << FileFunc // Name of function (F), file (f) or object (O).
    783            << ' ';
    784     if (Absolute) {
    785       outs() << "*ABS*";
    786     } else if (Section == o->section_end()) {
    787       outs() << "*UND*";
    788     } else {
    789       if (const MachOObjectFile *MachO =
    790           dyn_cast<const MachOObjectFile>(o)) {
    791         DataRefImpl DR = Section->getRawDataRefImpl();
    792         StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
    793         outs() << SegmentName << ",";
    794       }
    795       StringRef SectionName;
    796       if (error(Section->getName(SectionName)))
    797         SectionName = "";
    798       outs() << SectionName;
    799     }
    800     outs() << '\t'
    801            << format("%08" PRIx64 " ", Size)
    802            << Name
    803            << '\n';
    804   }
    805 }
    806 
    807 static void PrintUnwindInfo(const ObjectFile *o) {
    808   outs() << "Unwind info:\n\n";
    809 
    810   if (const COFFObjectFile *coff = dyn_cast<COFFObjectFile>(o)) {
    811     printCOFFUnwindInfo(coff);
    812   } else {
    813     // TODO: Extract DWARF dump tool to objdump.
    814     errs() << "This operation is only currently supported "
    815               "for COFF object files.\n";
    816     return;
    817   }
    818 }
    819 
    820 static void printPrivateFileHeader(const ObjectFile *o) {
    821   if (o->isELF()) {
    822     printELFFileHeader(o);
    823   } else if (o->isCOFF()) {
    824     printCOFFFileHeader(o);
    825   }
    826 }
    827 
    828 static void DumpObject(const ObjectFile *o) {
    829   outs() << '\n';
    830   outs() << o->getFileName()
    831          << ":\tfile format " << o->getFileFormatName() << "\n\n";
    832 
    833   if (Disassemble)
    834     DisassembleObject(o, Relocations);
    835   if (Relocations && !Disassemble)
    836     PrintRelocations(o);
    837   if (SectionHeaders)
    838     PrintSectionHeaders(o);
    839   if (SectionContents)
    840     PrintSectionContents(o);
    841   if (SymbolTable)
    842     PrintSymbolTable(o);
    843   if (UnwindInfo)
    844     PrintUnwindInfo(o);
    845   if (PrivateHeaders)
    846     printPrivateFileHeader(o);
    847 }
    848 
    849 /// @brief Dump each object file in \a a;
    850 static void DumpArchive(const Archive *a) {
    851   for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
    852        ++i) {
    853     ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
    854     if (std::error_code EC = ChildOrErr.getError()) {
    855       // Ignore non-object files.
    856       if (EC != object_error::invalid_file_type)
    857         errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message()
    858                << ".\n";
    859       continue;
    860     }
    861     if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
    862       DumpObject(o);
    863     else
    864       errs() << ToolName << ": '" << a->getFileName() << "': "
    865               << "Unrecognized file type.\n";
    866   }
    867 }
    868 
    869 /// @brief Open file and figure out how to dump it.
    870 static void DumpInput(StringRef file) {
    871   // If file isn't stdin, check that it exists.
    872   if (file != "-" && !sys::fs::exists(file)) {
    873     errs() << ToolName << ": '" << file << "': " << "No such file\n";
    874     return;
    875   }
    876 
    877   if (MachOOpt && Disassemble) {
    878     DisassembleInputMachO(file);
    879     return;
    880   }
    881 
    882   // Attempt to open the binary.
    883   ErrorOr<Binary *> BinaryOrErr = createBinary(file);
    884   if (std::error_code EC = BinaryOrErr.getError()) {
    885     errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n";
    886     return;
    887   }
    888   std::unique_ptr<Binary> binary(BinaryOrErr.get());
    889 
    890   if (Archive *a = dyn_cast<Archive>(binary.get()))
    891     DumpArchive(a);
    892   else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get()))
    893     DumpObject(o);
    894   else
    895     errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n";
    896 }
    897 
    898 int main(int argc, char **argv) {
    899   // Print a stack trace if we signal out.
    900   sys::PrintStackTraceOnErrorSignal();
    901   PrettyStackTraceProgram X(argc, argv);
    902   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
    903 
    904   // Initialize targets and assembly printers/parsers.
    905   llvm::InitializeAllTargetInfos();
    906   llvm::InitializeAllTargetMCs();
    907   llvm::InitializeAllAsmParsers();
    908   llvm::InitializeAllDisassemblers();
    909 
    910   // Register the target printer for --version.
    911   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
    912 
    913   cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n");
    914   TripleName = Triple::normalize(TripleName);
    915 
    916   ToolName = argv[0];
    917 
    918   // Defaults to a.out if no filenames specified.
    919   if (InputFilenames.size() == 0)
    920     InputFilenames.push_back("a.out");
    921 
    922   if (!Disassemble
    923       && !Relocations
    924       && !SectionHeaders
    925       && !SectionContents
    926       && !SymbolTable
    927       && !UnwindInfo
    928       && !PrivateHeaders) {
    929     cl::PrintHelpMessage();
    930     return 2;
    931   }
    932 
    933   std::for_each(InputFilenames.begin(), InputFilenames.end(),
    934                 DumpInput);
    935 
    936   return 0;
    937 }
    938