192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//
392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//                     The LLVM Compiler Infrastructure
492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//
592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer// This file is distributed under the University of Illinois Open Source
692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer// License. See LICENSE.TXT for details.
792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//
892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//===----------------------------------------------------------------------===//
992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//
1092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer// This program is a utility that works like binutils "objdump", that is, it
1192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer// dumps out a plethora of information about an object file depending on the
1292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer// flags.
1392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//
14dd3aa9eab2b40ea1573a5482472bbb89e6f1038dMichael J. Spencer// The flags and output of this program should be near identical to those of
15dd3aa9eab2b40ea1573a5482472bbb89e6f1038dMichael J. Spencer// binutils objdump.
16dd3aa9eab2b40ea1573a5482472bbb89e6f1038dMichael J. Spencer//
1792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer//===----------------------------------------------------------------------===//
1892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
190b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer#include "llvm-objdump.h"
20f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/ADT/STLExtras.h"
211e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer#include "llvm/ADT/StringExtras.h"
2292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/ADT/Triple.h"
23cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/MC/MCAnalysis/MCAtom.h"
24cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/MC/MCAnalysis/MCFunction.h"
25cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/MC/MCAnalysis/MCModule.h"
26cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/MC/MCAnalysis/MCModuleYAML.h"
2792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/MC/MCAsmInfo.h"
282c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCContext.h"
2992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/MC/MCDisassembler.h"
3092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/MC/MCInst.h"
3192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/MC/MCInstPrinter.h"
32ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha#include "llvm/MC/MCInstrAnalysis.h"
3317463b3ef1a3d39b10619254f12e806c8c43f9e7Craig Topper#include "llvm/MC/MCInstrInfo.h"
34ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha#include "llvm/MC/MCObjectDisassembler.h"
352c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCObjectFileInfo.h"
362c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCObjectSymbolizer.h"
37c6449b636f4984be88f128d0375c056ad05e7e8fJim Grosbach#include "llvm/MC/MCRegisterInfo.h"
382c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha#include "llvm/MC/MCRelocationInfo.h"
39ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha#include "llvm/MC/MCSubtargetInfo.h"
40f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/Object/Archive.h"
41f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/Object/COFF.h"
42cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola#include "llvm/Object/MachO.h"
43f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/Object/ObjectFile.h"
4427781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer#include "llvm/Support/Casting.h"
4592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/CommandLine.h"
4692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/Debug.h"
4727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer#include "llvm/Support/FileSystem.h"
4892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/Format.h"
49853b0fd623491ef7dafeed20ee15897e3b95d82cBenjamin Kramer#include "llvm/Support/GraphWriter.h"
5092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/Host.h"
5192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/ManagedStatic.h"
5292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/MemoryBuffer.h"
5392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/MemoryObject.h"
5492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/PrettyStackTrace.h"
5592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/Signals.h"
5692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/SourceMgr.h"
573e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
583e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetSelect.h"
5992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include "llvm/Support/raw_ostream.h"
6092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include <algorithm>
6181bbdfda82a3e5528d979b2cc150e9c7e0fa4427Benjamin Kramer#include <cctype>
6292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer#include <cstring>
63cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <system_error>
64171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha
6592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencerusing namespace llvm;
6692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencerusing namespace object;
6792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
680b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic cl::list<std::string>
690b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin KramerInputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
7092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
710b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic cl::opt<bool>
720b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin KramerDisassemble("disassemble",
730b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer  cl::desc("Display assembler mnemonics for the machine instructions"));
740b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic cl::alias
750b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin KramerDisassembled("d", cl::desc("Alias for --disassemble"),
760b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer             cl::aliasopt(Disassemble));
7792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
780b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic cl::opt<bool>
7927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. SpencerRelocations("r", cl::desc("Display the relocation entries in the file"));
8027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
8127781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencerstatic cl::opt<bool>
821e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. SpencerSectionContents("s", cl::desc("Display the content of each section"));
831e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer
841e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencerstatic cl::opt<bool>
8522ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. SpencerSymbolTable("t", cl::desc("Display the symbol table"));
8622ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer
8722ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencerstatic cl::opt<bool>
88cef81b37c77978cd4dddb4a5ad13564793ded155Rafael EspindolaMachOOpt("macho", cl::desc("Use MachO specific object file parser"));
890b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic cl::alias
90cef81b37c77978cd4dddb4a5ad13564793ded155Rafael EspindolaMachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachOOpt));
91685a2501b20baf688f6cc087f4b92bbafcd8028eBenjamin Kramer
920b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramercl::opt<std::string>
930b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerllvm::TripleName("triple", cl::desc("Target triple to disassemble for, "
940b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer                                    "see -version for available targets"));
9592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
960b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramercl::opt<std::string>
970b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerllvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
980b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer                                "see -version for available targets"));
9992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
100023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewyckystatic cl::opt<bool>
101023bb15beaac3744ce3a5d1f750d6e32829c7130Nick LewyckySectionHeaders("section-headers", cl::desc("Display summaries of the headers "
102023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky                                           "for each section."));
103023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewyckystatic cl::alias
104023bb15beaac3744ce3a5d1f750d6e32829c7130Nick LewyckySectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
105023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky                    cl::aliasopt(SectionHeaders));
106023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewyckystatic cl::alias
107023bb15beaac3744ce3a5d1f750d6e32829c7130Nick LewyckySectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
108023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky                      cl::aliasopt(SectionHeaders));
109023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky
110fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carterstatic cl::list<std::string>
111fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack CarterMAttrs("mattr",
112fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  cl::CommaSeparated,
113fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  cl::desc("Target specific attributes"),
114fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  cl::value_desc("a1,+a2,-a3,..."));
115fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter
1168b9da530e3637fd4afb33f80673178dcc74397f0Eli Benderskystatic cl::opt<bool>
1178b9da530e3637fd4afb33f80673178dcc74397f0Eli BenderskyNoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling instructions, "
1188b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky                                           "do not print the instruction bytes."));
1198b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky
120eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic cl::opt<bool>
121eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. SpencerUnwindInfo("unwind-info", cl::desc("Display unwind information"));
122eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer
123eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic cl::alias
124eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. SpencerUnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
125eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer                cl::aliasopt(UnwindInfo));
126eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer
127b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencerstatic cl::opt<bool>
128b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. SpencerPrivateHeaders("private-headers",
129b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer               cl::desc("Display format specific file headers"));
130b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer
131b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencerstatic cl::alias
132b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. SpencerPrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
133b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer                    cl::aliasopt(PrivateHeaders));
134b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer
1352c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougachastatic cl::opt<bool>
1362c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed BougachaSymbolize("symbolize", cl::desc("When disassembling instructions, "
1372c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                "try to symbolize operands."));
1382c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
139ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougachastatic cl::opt<bool>
140ef99356dfebb96f6f90efb912c2877214bad060eAhmed BougachaCFG("cfg", cl::desc("Create a CFG for every function found in the object"
141ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha                      " and write it to a graphviz file"));
142ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
143171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha// FIXME: Does it make sense to have a dedicated tool for yaml cfg output?
144171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougachastatic cl::opt<std::string>
145171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed BougachaYAMLCFG("yaml-cfg",
146171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        cl::desc("Create a CFG and write it as a YAML MCModule."),
147171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        cl::value_desc("yaml output file"));
148171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha
1490b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramerstatic StringRef ToolName;
15025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
151cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool llvm::error(std::error_code EC) {
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (!EC)
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
15425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
1560b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer  outs().flush();
1570b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer  return true;
15892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer}
15992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic const Target *getTarget(const ObjectFile *Obj = nullptr) {
16192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // Figure out the target triple.
1629ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  llvm::Triple TheTriple("unknown-unknown-unknown");
163d11699d3c057129d0716fa548c67d1f62837f6b6Michael J. Spencer  if (TripleName.empty()) {
1642c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    if (Obj) {
1659ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      TheTriple.setArch(Triple::ArchType(Obj->getArch()));
1662c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      // TheTriple defaults to ELF, and COFF doesn't have an environment:
1672c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      // the best we can do here is indicate that it is mach-o.
1682c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      if (Obj->isMachO())
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        TheTriple.setObjectFormat(Triple::MachO);
170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
171dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (Obj->isCOFF()) {
172dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        const auto COFFObj = dyn_cast<COFFObjectFile>(Obj);
173dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (COFFObj->getArch() == Triple::thumb)
174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          TheTriple.setTriple("thumbv7-windows");
175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      }
1762c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    }
177d11699d3c057129d0716fa548c67d1f62837f6b6Michael J. Spencer  } else
1789ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    TheTriple.setTriple(Triple::normalize(TripleName));
17992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
18092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // Get the target specific parser.
18192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  std::string Error;
1829ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
1839ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby                                                         Error);
1849ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  if (!TheTarget) {
1859ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    errs() << ToolName << ": " << Error;
186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
1879ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  }
1889ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby
1899ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  // Update the triple name and return the found target.
1909ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  TripleName = TheTriple.getTriple();
1919ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  return TheTarget;
19292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer}
19392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
194ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha// Write a graphviz file for the CFG inside an MCFunction.
195171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha// FIXME: Use GraphWriter
196ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougachastatic void emitDOTFile(const char *FileName, const MCFunction &f,
197ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha                        MCInstPrinter *IP) {
198ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  // Start a new dot file.
199ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  std::string Error;
20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  raw_fd_ostream Out(FileName, Error, sys::fs::F_Text);
201ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  if (!Error.empty()) {
202ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    errs() << "llvm-objdump: warning: " << Error << '\n';
203ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    return;
204ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  }
205ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
206ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  Out << "digraph \"" << f.getName() << "\" {\n";
207ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  Out << "graph [ rankdir = \"LR\" ];\n";
208ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  for (MCFunction::const_iterator i = f.begin(), e = f.end(); i != e; ++i) {
209ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    // Only print blocks that have predecessors.
210ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    bool hasPreds = (*i)->pred_begin() != (*i)->pred_end();
211ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
212ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    if (!hasPreds && i != f.begin())
213ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      continue;
214ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
215ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\"<a>";
216ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    // Print instructions.
217ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie;
218ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        ++ii) {
219ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      if (ii != 0) // Not the first line, start a new row.
220ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        Out << '|';
221ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      if (ii + 1 == ie) // Last line, add an end id.
222ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        Out << "<o>";
223ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
224ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      // Escape special chars and print the instruction in mnemonic form.
225ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      std::string Str;
226ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      raw_string_ostream OS(Str);
227ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, "");
228ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      Out << DOT::EscapeString(OS.str());
229ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    }
230ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    Out << "\" shape=\"record\" ];\n";
231ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
232ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    // Add edges.
233ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(),
234ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        se = (*i)->succ_end(); si != se; ++si)
235ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      Out << (*i)->getInsts()->getBeginAddr() << ":o -> "
236ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha          << (*si)->getInsts()->getBeginAddr() << ":a\n";
237ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  }
238ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  Out << "}\n";
239ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha}
2402d24e2a396a1d211baaeedf32148a3b657240170David Blaikie
2410b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramervoid llvm::DumpBytes(StringRef bytes) {
2420b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer  static const char hex_rep[] = "0123456789abcdef";
24392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // FIXME: The real way to do this is to figure out the longest instruction
24492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  //        and align to that size before printing. I'll fix this when I get
24592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  //        around to outputting relocations.
24692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // 15 is the longest x86 instruction
24792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // 3 is for the hex rep of a byte + a space.
24892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // 1 is for the null terminator.
24992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  enum { OutputSize = (15 * 3) + 1 };
25092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  char output[OutputSize];
25192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
25292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  assert(bytes.size() <= 15
25392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    && "DumpBytes only supports instructions of up to 15 bytes");
25492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  memset(output, ' ', sizeof(output));
25592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  unsigned index = 0;
25692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  for (StringRef::iterator i = bytes.begin(),
25792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer                           e = bytes.end(); i != e; ++i) {
25892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    output[index] = hex_rep[(*i & 0xF0) >> 4];
25992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    output[index + 1] = hex_rep[*i & 0xF];
26092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    index += 3;
26192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  }
26292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
26392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  output[sizeof(output) - 1] = 0;
26492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  outs() << output;
26592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer}
26692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
267eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerbool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
268942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer  uint64_t a_addr, b_addr;
269956ca7265c697107708468b7e1b2fd21f4185baeRafael Espindola  if (error(a.getOffset(a_addr))) return false;
270956ca7265c697107708468b7e1b2fd21f4185baeRafael Espindola  if (error(b.getOffset(b_addr))) return false;
271942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer  return a_addr < b_addr;
272942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer}
273942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
274942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencerstatic void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
2753f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  const Target *TheTarget = getTarget(Obj);
2763f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  // getTarget() will have already issued a diagnostic if necessary, so
2773f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  // just bail here if it failed.
2783f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  if (!TheTarget)
27992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    return;
28092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
281fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  // Package up features to be passed to target/subtarget
282fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  std::string FeaturesStr;
283fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  if (MAttrs.size()) {
284fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter    SubtargetFeatures Features;
285fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter    for (unsigned i = 0; i != MAttrs.size(); ++i)
286fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter      Features.AddFeature(MAttrs[i]);
287fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter    FeaturesStr = Features.getString();
288fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter  }
289fd6d1651551d5a08b3cf0fcafed5e91a40b8e317Jack Carter
29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<const MCRegisterInfo> MRI(
29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      TheTarget->createMCRegInfo(TripleName));
29227a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  if (!MRI) {
29327a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    errs() << "error: no register info for target " << TripleName << "\n";
29427a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    return;
29527a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
29627a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
29727a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  // Set up disassembler.
29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<const MCAsmInfo> AsmInfo(
29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      TheTarget->createMCAsmInfo(*MRI, TripleName));
30027a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  if (!AsmInfo) {
30127a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    errs() << "error: no assembly info for target " << TripleName << "\n";
30227a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    return;
30327a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
30427a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<const MCSubtargetInfo> STI(
30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
30727a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  if (!STI) {
30827a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    errs() << "error: no subtarget info for target " << TripleName << "\n";
30927a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    return;
31027a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
31127a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
3132c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  if (!MII) {
3142c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    errs() << "error: no instruction info for target " << TripleName << "\n";
3152c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    return;
3162c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  }
3172c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
318dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
319dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
320dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
321dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  std::unique_ptr<MCDisassembler> DisAsm(
322dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    TheTarget->createMCDisassembler(*STI, Ctx));
323dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
32427a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  if (!DisAsm) {
32527a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    errs() << "error: no disassembler for target " << TripleName << "\n";
32627a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    return;
32727a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
32827a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
3292c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
3302c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  if (Symbolize) {
33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::unique_ptr<MCRelocationInfo> RelInfo(
332dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        TheTarget->createMCRelocationInfo(TripleName, Ctx));
3332c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    if (RelInfo) {
33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      std::unique_ptr<MCSymbolizer> Symzer(
335dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        MCObjectSymbolizer::createObjectSymbolizer(Ctx, std::move(RelInfo),
336dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                   Obj));
3372c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha      if (Symzer)
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        DisAsm->setSymbolizer(std::move(Symzer));
3392c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    }
34027a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
34127a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<const MCInstrAnalysis> MIA(
34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      TheTarget->createMCInstrAnalysis(MII.get()));
344ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
34527a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
34727a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha      AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
34827a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  if (!IP) {
34927a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    errs() << "error: no instruction printer for target " << TripleName
35027a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha      << '\n';
35127a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha    return;
35227a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha  }
35327a33ad5ce3a6ca9a5d7546b41d96e975b1e9305Ahmed Bougacha
354171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha  if (CFG || !YAMLCFG.empty()) {
35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::unique_ptr<MCObjectDisassembler> OD(
35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::unique_ptr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
358ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    for (MCModule::const_atom_iterator AI = Mod->atom_begin(),
359ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha                                       AE = Mod->atom_end();
360ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha                                       AI != AE; ++AI) {
361ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      outs() << "Atom " << (*AI)->getName() << ": \n";
362ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI)) {
363ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end();
364ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha             II != IE;
365ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha             ++II) {
366ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha          IP->printInst(&II->Inst, outs(), "");
367ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha          outs() << "\n";
368ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha        }
369ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha      }
370ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    }
371171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha    if (CFG) {
372171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      for (MCModule::const_func_iterator FI = Mod->func_begin(),
373171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha                                         FE = Mod->func_end();
374171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha                                         FI != FE; ++FI) {
375171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        static int filenum = 0;
376171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        emitDOTFile((Twine((*FI)->getName()) + "_" +
377171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha                     utostr(filenum) + ".dot").str().c_str(),
378171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha                      **FI, IP.get());
379171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        ++filenum;
380171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      }
381171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha    }
382171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha    if (!YAMLCFG.empty()) {
383171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      std::string Error;
38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error, sys::fs::F_Text);
385171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      if (!Error.empty()) {
3867413b54c897c9a7bd04e7b918128d0279be9a126Ahmed Bougacha        errs() << ToolName << ": warning: " << Error << '\n';
387171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha        return;
388171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      }
389171ac8ca175bec5bc0bff8b3006850f70e0569c9Ahmed Bougacha      mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI);
390ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha    }
391ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha  }
392ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ":  " :
39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                 "\t\t\t%08" PRIx64 ":  ";
39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
39636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Create a mapping, RelocSecs = SectionRelocMap[S], where sections
39736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // in RelocSecs contain the relocations for section S.
398cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code EC;
39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
40036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
40136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    section_iterator Sec2 = Section.getRelocatedSection();
40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Sec2 != Obj->section_end())
40336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      SectionRelocMap[*Sec2].push_back(Section);
40436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
405ef99356dfebb96f6f90efb912c2877214bad060eAhmed Bougacha
40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool Text;
40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.isText(Text)))
40936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      break;
41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (!Text)
41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
41225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
413942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    uint64_t SectionAddr;
41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getAddress(SectionAddr)))
41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      break;
41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t SectSize;
41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getSize(SectSize)))
41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      break;
420942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
421739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    // Make a list of all the symbols in this section.
42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::vector<std::pair<uint64_t, StringRef>> Symbols;
42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const SymbolRef &Symbol : Obj->symbols()) {
424739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer      bool contains;
42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (!error(Section.containsSymbol(Symbol, contains)) && contains) {
426739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer        uint64_t Address;
42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (error(Symbol.getAddress(Address)))
42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          break;
42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (Address == UnknownAddressOrSize)
43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          continue;
431aab219110994cc4d848fae5f50166a2f70ccc812Cameron Zwarich        Address -= SectionAddr;
43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (Address >= SectSize)
43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          continue;
434aab219110994cc4d848fae5f50166a2f70ccc812Cameron Zwarich
435739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer        StringRef Name;
43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (error(Symbol.getName(Name)))
43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          break;
438739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer        Symbols.push_back(std::make_pair(Address, Name));
439739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer      }
440739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    }
441739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
442739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    // Sort the symbols by address, just in case they didn't come in that way.
443739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    array_pod_sort(Symbols.begin(), Symbols.end());
444739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
445942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    // Make a list of all the relocations for this section.
446942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    std::vector<RelocationRef> Rels;
447942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    if (InlineRelocs) {
44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      for (const SectionRef &RelocSec : SectionRelocMap[Section]) {
44936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        for (const RelocationRef &Reloc : RelocSec.relocations()) {
45036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          Rels.push_back(Reloc);
45136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }
452942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer      }
453942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    }
454942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
455942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    // Sort relocations by address.
456942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
457942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
458cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola    StringRef SegmentName = "";
45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {
46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      DataRefImpl DR = Section.getRawDataRefImpl();
461fd7aa38e304a09fa0ef51b85b773b649b7e58c5eRafael Espindola      SegmentName = MachO->getSectionFinalSegmentName(DR);
462cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola    }
46325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    StringRef name;
46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getName(name)))
46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      break;
466cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola    outs() << "Disassembly of section ";
467cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola    if (!SegmentName.empty())
468cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola      outs() << SegmentName << ",";
469cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola    outs() << name << ':';
470739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
471739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    // If the section has no symbols just insert a dummy one and disassemble
472739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    // the whole section.
473739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    if (Symbols.empty())
474739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer      Symbols.push_back(std::make_pair(0, name));
47592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
4762c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
4772c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    SmallString<40> Comments;
4782c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    raw_svector_ostream CommentStream(Comments);
4792c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
48025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    StringRef Bytes;
48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getContents(Bytes)))
48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      break;
4832c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha    StringRefMemoryObject memoryObject(Bytes, SectionAddr);
48492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    uint64_t Size;
48592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    uint64_t Index;
486739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
487942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();
488942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    std::vector<RelocationRef>::const_iterator rel_end = Rels.end();
489739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    // Disassemble symbol by symbol.
490739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer    for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
491739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer      uint64_t Start = Symbols[si].first;
492178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      uint64_t End;
493178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      // The end is either the size of the section or the beginning of the next
494178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      // symbol.
495178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      if (si == se - 1)
496178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer        End = SectSize;
497178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      // Make sure this symbol takes up space.
498178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      else if (Symbols[si + 1].first != Start)
499178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer        End = Symbols[si + 1].first - 1;
500178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer      else
501178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer        // This symbol has the same address as the next symbol. Skip it.
502178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer        continue;
503178dbd44187e23e7e3f3ba17b00c89c819070296Michael J. Spencer
504739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer      outs() << '\n' << Symbols[si].second << ":\n";
505739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
506739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer#ifndef NDEBUG
50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
508739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer#else
50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      raw_ostream &DebugOut = nulls();
510739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer#endif
511739b65bf85cf7221b8a615e83dee11ec729e2649Benjamin Kramer
5120b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer      for (Index = Start; Index < End; Index += Size) {
5130b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer        MCInst Inst;
5140b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer
5152c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha        if (DisAsm->getInstruction(Inst, Size, memoryObject,
5162c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                   SectionAddr + Index,
5172c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha                                   DebugOut, CommentStream)) {
5188b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky          outs() << format("%8" PRIx64 ":", SectionAddr + Index);
5198b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky          if (!NoShowRawInsn) {
5208b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky            outs() << "\t";
5218b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky            DumpBytes(StringRef(Bytes.data() + Index, Size));
5228b9da530e3637fd4afb33f80673178dcc74397f0Eli Bendersky          }
5230b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer          IP->printInst(&Inst, outs(), "");
5242c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha          outs() << CommentStream.str();
5252c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha          Comments.clear();
5260b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer          outs() << "\n";
5270b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer        } else {
5280b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer          errs() << ToolName << ": warning: invalid instruction encoding\n";
5290b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer          if (Size == 0)
5300b8b771e9f2f251460a6f200c45efe9d55640d60Benjamin Kramer            Size = 1; // skip illegible bytes
531685a2501b20baf688f6cc087f4b92bbafcd8028eBenjamin Kramer        }
532942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
533942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer        // Print relocation for instruction.
534942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer        while (rel_cur != rel_end) {
5350685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson          bool hidden = false;
536942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          uint64_t addr;
537942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          SmallString<16> name;
538942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          SmallString<32> val;
5390685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson
5400685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson          // If this relocation is hidden, skip it.
5410685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson          if (error(rel_cur->getHidden(hidden))) goto skip_print_rel;
5420685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson          if (hidden) goto skip_print_rel;
5430685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson
544956ca7265c697107708468b7e1b2fd21f4185baeRafael Espindola          if (error(rel_cur->getOffset(addr))) goto skip_print_rel;
545942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          // Stop when rel_cur's address is past the current instruction.
54634749ce4df9636188782c652dc9dc9c73d4bce11Owen Anderson          if (addr >= Index + Size) break;
547942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          if (error(rel_cur->getTypeName(name))) goto skip_print_rel;
548942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          if (error(rel_cur->getValueString(val))) goto skip_print_rel;
549942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
55036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          outs() << format(Fmt.data(), SectionAddr + addr) << name
55151cf8661637c114e4b4f178bd2677a6bb246be0dBenjamin Kramer                 << "\t" << val << "\n";
552942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer
553942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer        skip_print_rel:
554942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer          ++rel_cur;
555942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer        }
556685a2501b20baf688f6cc087f4b92bbafcd8028eBenjamin Kramer      }
55792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    }
55892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  }
55992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer}
56092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
56136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void PrintRelocations(const ObjectFile *Obj) {
56236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
56336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                 "%08" PRIx64;
56436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
56536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Section.relocation_begin() == Section.relocation_end())
56627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      continue;
56727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    StringRef secname;
56836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getName(secname)))
56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
57027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
57136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (const RelocationRef &Reloc : Section.relocations()) {
5720685e94895f26f96aa1032696e3150dd00aad1f3Owen Anderson      bool hidden;
57327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      uint64_t address;
57427781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      SmallString<32> relocname;
57527781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      SmallString<32> valuestr;
57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Reloc.getHidden(hidden)))
57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        continue;
57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (hidden)
57936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        continue;
58036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Reloc.getTypeName(relocname)))
58136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        continue;
58236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Reloc.getOffset(address)))
58336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        continue;
58436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Reloc.getValueString(valuestr)))
58536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        continue;
58636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << format(Fmt.data(), address) << " " << relocname << " "
58736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines             << valuestr << "\n";
58827781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    }
58927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    outs() << "\n";
59027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  }
59127781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer}
59227781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
59336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void PrintSectionHeaders(const ObjectFile *Obj) {
594023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky  outs() << "Sections:\n"
595023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky            "Idx Name          Size      Address          Type\n";
596023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky  unsigned i = 0;
59736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
598023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    StringRef Name;
59936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getName(Name)))
60036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
601023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    uint64_t Address;
60236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getAddress(Address)))
60336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
604023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    uint64_t Size;
60536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getSize(Size)))
60636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
607023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    bool Text, Data, BSS;
60836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.isText(Text)))
60936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
61036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.isData(Data)))
61136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
61236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.isBSS(BSS)))
61336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
614023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    std::string Type = (std::string(Text ? "TEXT " : "") +
61514a5f468d6b18b7637821e13e56fe56dd79d7cafMichael J. Spencer                        (Data ? "DATA " : "") + (BSS ? "BSS" : ""));
61636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
61736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                     Name.str().c_str(), Size, Address, Type.c_str());
618023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    ++i;
619023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky  }
620023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky}
621023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky
62236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void PrintSectionContents(const ObjectFile *Obj) {
623cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code EC;
62436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
6251e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    StringRef Name;
6261e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    StringRef Contents;
6271e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    uint64_t BaseAddr;
6280eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov    bool BSS;
62936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getName(Name)))
63036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
63136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getContents(Contents)))
63236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
63336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.getAddress(BaseAddr)))
63436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
63536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Section.isBSS(BSS)))
63636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
6371e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer
6381e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    outs() << "Contents of section " << Name << ":\n";
6390eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov    if (BSS) {
6400eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov      outs() << format("<skipping contents of bss section at [%04" PRIx64
6410eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov                       ", %04" PRIx64 ")>\n", BaseAddr,
6420eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov                       BaseAddr + Contents.size());
6430eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov      continue;
6440eaa6f675cafb2bb1b6a6210797c1d7b3da3ff9fAlexey Samsonov    }
6451e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer
6461e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    // Dump out the content as hex and printable ascii characters.
6471e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) {
64851cf8661637c114e4b4f178bd2677a6bb246be0dBenjamin Kramer      outs() << format(" %04" PRIx64 " ", BaseAddr + addr);
6491e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      // Dump line of hex.
6501e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      for (std::size_t i = 0; i < 16; ++i) {
6511e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer        if (i != 0 && i % 4 == 0)
6521e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer          outs() << ' ';
6531e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer        if (addr + i < end)
6541e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer          outs() << hexdigit((Contents[addr + i] >> 4) & 0xF, true)
6551e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer                 << hexdigit(Contents[addr + i] & 0xF, true);
6561e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer        else
6571e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer          outs() << "  ";
6581e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      }
6591e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      // Print ascii.
6601e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      outs() << "  ";
6611e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
66287d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei        if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
6631e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer          outs() << Contents[addr + i];
6641e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer        else
6651e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer          outs() << ".";
6661e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      }
6671e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer      outs() << "\n";
6681e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    }
6691e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer  }
6701e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer}
6711e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer
67222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencerstatic void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
67322ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  const coff_file_header *header;
674dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (error(coff->getHeader(header)))
675dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return;
676dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
677dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  for (unsigned SI = 0, SE = header->NumberOfSymbols; SI != SE; ++SI) {
678dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const coff_symbol *Symbol;
679dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    StringRef Name;
680dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (error(coff->getSymbol(SI, Symbol)))
681dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return;
682dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
683dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (error(coff->getSymbolName(Symbol, Name)))
684dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return;
685dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
686dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    outs() << "[" << format("%2d", SI) << "]"
687dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "(sec " << format("%2d", int(Symbol->SectionNumber)) << ")"
688dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "(fl 0x00)" // Flag bits, which COFF doesn't have.
689dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "(ty " << format("%3x", unsigned(Symbol->Type)) << ")"
690dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "(scl " << format("%3x", unsigned(Symbol->StorageClass)) << ") "
691dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "(nx " << unsigned(Symbol->NumberOfAuxSymbols) << ") "
692dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << "0x" << format("%08x", unsigned(Symbol->Value)) << " "
693dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines           << Name << "\n";
694dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
695dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (unsigned AI = 0, AE = Symbol->NumberOfAuxSymbols; AI < AE; ++AI, ++SI) {
696dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (Symbol->isSectionDefinition()) {
69722ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer        const coff_aux_section_definition *asd;
698dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
69922ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer          return;
700dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
70122ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer        outs() << "AUX "
70222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer               << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
70322ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->Length)
70422ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->NumberOfRelocations)
70522ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->NumberOfLinenumbers)
70622ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->CheckSum))
70722ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer               << format("assoc %d comdat %d\n"
70822ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->Number)
70922ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer                         , unsigned(asd->Selection));
710dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      } else if (Symbol->isFileRecord()) {
711dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        const coff_aux_file *AF;
712dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (error(coff->getAuxSymbol<coff_aux_file>(SI + 1, AF)))
713dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          return;
714dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
715dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        StringRef Name(AF->FileName,
716dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       Symbol->NumberOfAuxSymbols * COFF::SymbolSize);
717dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        outs() << "AUX " << Name.rtrim(StringRef("\0", 1))  << '\n';
718dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
719dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        SI = SI + Symbol->NumberOfAuxSymbols;
720dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        break;
721dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      } else {
72222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer        outs() << "AUX Unknown\n";
723dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      }
72422ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer    }
72522ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  }
72622ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer}
72722ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer
72822ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencerstatic void PrintSymbolTable(const ObjectFile *o) {
72922ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  outs() << "SYMBOL TABLE:\n";
73022ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer
73136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
73222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer    PrintCOFFSymbolTable(coff);
73336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
73436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
73536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SymbolRef &Symbol : o->symbols()) {
73636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    StringRef Name;
73736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t Address;
73836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    SymbolRef::Type Type;
73936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t Size;
74036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t Flags = Symbol.getFlags();
74136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    section_iterator Section = o->section_end();
74236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Symbol.getName(Name)))
74336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
74436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Symbol.getAddress(Address)))
74536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
74636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Symbol.getType(Type)))
74736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
74836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Symbol.getSize(Size)))
74936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
75036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (error(Symbol.getSection(Section)))
75136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
75236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
75336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool Global = Flags & SymbolRef::SF_Global;
75436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool Weak = Flags & SymbolRef::SF_Weak;
75536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool Absolute = Flags & SymbolRef::SF_Absolute;
75636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
75736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Address == UnknownAddressOrSize)
75836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Address = 0;
75936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Size == UnknownAddressOrSize)
76036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Size = 0;
76136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    char GlobLoc = ' ';
76236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Type != SymbolRef::ST_Unknown)
76336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      GlobLoc = Global ? 'g' : 'l';
76436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
76536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                 ? 'd' : ' ';
76636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    char FileFunc = ' ';
76736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Type == SymbolRef::ST_File)
76836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      FileFunc = 'f';
76936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    else if (Type == SymbolRef::ST_Function)
77036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      FileFunc = 'F';
77136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
77236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
77336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                   "%08" PRIx64;
77436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
77536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    outs() << format(Fmt, Address) << " "
77636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
77736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << (Weak ? 'w' : ' ') // Weak?
77836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << ' ' // Constructor. Not supported yet.
77936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << ' ' // Warning. Not supported yet.
78036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << ' ' // Indirect reference to another symbol.
78136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << Debug // Debugging (d) or dynamic (D) symbol.
78236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << FileFunc // Name of function (F), file (f) or object (O).
78336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << ' ';
78436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Absolute) {
78536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << "*ABS*";
78636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (Section == o->section_end()) {
78736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << "*UND*";
78836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else {
78936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (const MachOObjectFile *MachO =
79036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          dyn_cast<const MachOObjectFile>(o)) {
79136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        DataRefImpl DR = Section->getRawDataRefImpl();
79236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
79336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        outs() << SegmentName << ",";
79422ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer      }
79536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      StringRef SectionName;
79636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (error(Section->getName(SectionName)))
79736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        SectionName = "";
79836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      outs() << SectionName;
79922ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer    }
80036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    outs() << '\t'
80136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << format("%08" PRIx64 " ", Size)
80236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << Name
80336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           << '\n';
80422ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  }
80522ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer}
80622ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer
807eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencerstatic void PrintUnwindInfo(const ObjectFile *o) {
808eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer  outs() << "Unwind info:\n\n";
809eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer
810eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer  if (const COFFObjectFile *coff = dyn_cast<COFFObjectFile>(o)) {
811eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer    printCOFFUnwindInfo(coff);
812eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer  } else {
813eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer    // TODO: Extract DWARF dump tool to objdump.
814eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer    errs() << "This operation is only currently supported "
815eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer              "for COFF object files.\n";
816eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer    return;
817eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer  }
818eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer}
819eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer
820a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamastatic void printPrivateFileHeader(const ObjectFile *o) {
821a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama  if (o->isELF()) {
822a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama    printELFFileHeader(o);
823a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama  } else if (o->isCOFF()) {
824a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama    printCOFFFileHeader(o);
825a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama  }
826a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama}
827a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama
82827781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencerstatic void DumpObject(const ObjectFile *o) {
8291e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer  outs() << '\n';
8301e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer  outs() << o->getFileName()
8311e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer         << ":\tfile format " << o->getFileFormatName() << "\n\n";
8321e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer
83327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  if (Disassemble)
834942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer    DisassembleObject(o, Relocations);
835942eb009114ef9a2e95e236790faa7a3c04bc2baMichael J. Spencer  if (Relocations && !Disassemble)
83627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    PrintRelocations(o);
837023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky  if (SectionHeaders)
838023bb15beaac3744ce3a5d1f750d6e32829c7130Nick Lewycky    PrintSectionHeaders(o);
8391e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer  if (SectionContents)
8401e8ba3fa21326de4ef5bf908f6bfbf2852e04794Michael J. Spencer    PrintSectionContents(o);
84122ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  if (SymbolTable)
84222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer    PrintSymbolTable(o);
843eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer  if (UnwindInfo)
844eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer    PrintUnwindInfo(o);
845a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama  if (PrivateHeaders)
846a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama    printPrivateFileHeader(o);
84727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer}
84827781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
84927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer/// @brief Dump each object file in \a a;
85027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencerstatic void DumpArchive(const Archive *a) {
85136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
85236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines       ++i) {
853cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
854cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (std::error_code EC = ChildOrErr.getError()) {
855f81285c0c507908b429a2c4cbd0683d624d375f9Michael J. Spencer      // Ignore non-object files.
85636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (EC != object_error::invalid_file_type)
85736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message()
858f81285c0c507908b429a2c4cbd0683d624d375f9Michael J. Spencer               << ".\n";
85927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      continue;
86027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    }
861cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
86227781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      DumpObject(o);
86327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    else
86427781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer      errs() << ToolName << ": '" << a->getFileName() << "': "
86527781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer              << "Unrecognized file type.\n";
86627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  }
86727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer}
86827781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
86927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer/// @brief Open file and figure out how to dump it.
87027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencerstatic void DumpInput(StringRef file) {
87127781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  // If file isn't stdin, check that it exists.
87227781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  if (file != "-" && !sys::fs::exists(file)) {
87327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    errs() << ToolName << ": '" << file << "': " << "No such file\n";
87427781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    return;
87527781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  }
87627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
877cef81b37c77978cd4dddb4a5ad13564793ded155Rafael Espindola  if (MachOOpt && Disassemble) {
87827781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    DisassembleInputMachO(file);
87927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    return;
88027781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  }
88127781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
88227781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  // Attempt to open the binary.
88336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ErrorOr<Binary *> BinaryOrErr = createBinary(file);
884cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (std::error_code EC = BinaryOrErr.getError()) {
88536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n";
88627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    return;
88727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  }
88836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<Binary> binary(BinaryOrErr.get());
88927781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
8903f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  if (Archive *a = dyn_cast<Archive>(binary.get()))
89127781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    DumpArchive(a);
8923f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get()))
89327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    DumpObject(o);
8943f5d1a2396915ebff20ce4f5d668ee5c839d1d91Jim Grosbach  else
89527781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer    errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n";
89627781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer}
89727781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer
89892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencerint main(int argc, char **argv) {
89992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // Print a stack trace if we signal out.
90092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  sys::PrintStackTraceOnErrorSignal();
90192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  PrettyStackTraceProgram X(argc, argv);
90292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
90392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
90492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // Initialize targets and assembly printers/parsers.
90592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  llvm::InitializeAllTargetInfos();
906e78085a3c03de648a481e9751c3094c517bd7123Evan Cheng  llvm::InitializeAllTargetMCs();
90792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  llvm::InitializeAllAsmParsers();
90892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  llvm::InitializeAllDisassemblers();
90992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
910ff204963cbcd7c68d59f3bba5bfa2797ea0cebaePete Cooper  // Register the target printer for --version.
911ff204963cbcd7c68d59f3bba5bfa2797ea0cebaePete Cooper  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
912ff204963cbcd7c68d59f3bba5bfa2797ea0cebaePete Cooper
91392e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n");
91492e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  TripleName = Triple::normalize(TripleName);
91592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
91692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  ToolName = argv[0];
91792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
91892e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  // Defaults to a.out if no filenames specified.
91992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  if (InputFilenames.size() == 0)
92092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    InputFilenames.push_back("a.out");
92192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
92222ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer  if (!Disassemble
92322ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer      && !Relocations
92422ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer      && !SectionHeaders
92522ff0f33dbfe99d7308658f07986c1014ea5aff2Michael J. Spencer      && !SectionContents
926eef7b6219ebe5d0ded0be4adb3003055fa8a63c4Michael J. Spencer      && !SymbolTable
927b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer      && !UnwindInfo
928b2c064c6954c9bfa49b7a7e3223df5e7849464c0Michael J. Spencer      && !PrivateHeaders) {
92992e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    cl::PrintHelpMessage();
93092e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer    return 2;
93192e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  }
93292e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
93327781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer  std::for_each(InputFilenames.begin(), InputFilenames.end(),
93427781b78e111a1d276dd3cd604b0cdfa662f1f4eMichael J. Spencer                DumpInput);
93592e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer
93692e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer  return 0;
93792e1deb05182c116bf39bec5f4df3769b5abc7f4Michael J. Spencer}
938