xref: /netbsd-src/external/apache2/llvm/dist/llvm/tools/llvm-objdump/llvm-objdump.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This program is a utility that works like binutils "objdump", that is, it
107330f729Sjoerg // dumps out a plethora of information about an object file depending on the
117330f729Sjoerg // flags.
127330f729Sjoerg //
137330f729Sjoerg // The flags and output of this program should be near identical to those of
147330f729Sjoerg // binutils objdump.
157330f729Sjoerg //
167330f729Sjoerg //===----------------------------------------------------------------------===//
177330f729Sjoerg 
187330f729Sjoerg #include "llvm-objdump.h"
19*82d56013Sjoerg #include "COFFDump.h"
20*82d56013Sjoerg #include "ELFDump.h"
21*82d56013Sjoerg #include "MachODump.h"
22*82d56013Sjoerg #include "ObjdumpOptID.h"
23*82d56013Sjoerg #include "SourcePrinter.h"
24*82d56013Sjoerg #include "WasmDump.h"
25*82d56013Sjoerg #include "XCOFFDump.h"
26*82d56013Sjoerg #include "llvm/ADT/IndexedMap.h"
277330f729Sjoerg #include "llvm/ADT/Optional.h"
287330f729Sjoerg #include "llvm/ADT/STLExtras.h"
297330f729Sjoerg #include "llvm/ADT/SetOperations.h"
30*82d56013Sjoerg #include "llvm/ADT/SmallSet.h"
317330f729Sjoerg #include "llvm/ADT/StringExtras.h"
327330f729Sjoerg #include "llvm/ADT/StringSet.h"
337330f729Sjoerg #include "llvm/ADT/Triple.h"
34*82d56013Sjoerg #include "llvm/ADT/Twine.h"
357330f729Sjoerg #include "llvm/DebugInfo/DWARF/DWARFContext.h"
367330f729Sjoerg #include "llvm/DebugInfo/Symbolize/Symbolize.h"
377330f729Sjoerg #include "llvm/Demangle/Demangle.h"
387330f729Sjoerg #include "llvm/MC/MCAsmInfo.h"
397330f729Sjoerg #include "llvm/MC/MCContext.h"
407330f729Sjoerg #include "llvm/MC/MCDisassembler/MCDisassembler.h"
417330f729Sjoerg #include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
427330f729Sjoerg #include "llvm/MC/MCInst.h"
437330f729Sjoerg #include "llvm/MC/MCInstPrinter.h"
447330f729Sjoerg #include "llvm/MC/MCInstrAnalysis.h"
457330f729Sjoerg #include "llvm/MC/MCInstrInfo.h"
467330f729Sjoerg #include "llvm/MC/MCObjectFileInfo.h"
477330f729Sjoerg #include "llvm/MC/MCRegisterInfo.h"
487330f729Sjoerg #include "llvm/MC/MCSubtargetInfo.h"
497330f729Sjoerg #include "llvm/MC/MCTargetOptions.h"
507330f729Sjoerg #include "llvm/Object/Archive.h"
517330f729Sjoerg #include "llvm/Object/COFF.h"
527330f729Sjoerg #include "llvm/Object/COFFImportFile.h"
537330f729Sjoerg #include "llvm/Object/ELFObjectFile.h"
54*82d56013Sjoerg #include "llvm/Object/FaultMapParser.h"
557330f729Sjoerg #include "llvm/Object/MachO.h"
567330f729Sjoerg #include "llvm/Object/MachOUniversal.h"
577330f729Sjoerg #include "llvm/Object/ObjectFile.h"
587330f729Sjoerg #include "llvm/Object/Wasm.h"
59*82d56013Sjoerg #include "llvm/Option/Arg.h"
60*82d56013Sjoerg #include "llvm/Option/ArgList.h"
61*82d56013Sjoerg #include "llvm/Option/Option.h"
627330f729Sjoerg #include "llvm/Support/Casting.h"
637330f729Sjoerg #include "llvm/Support/Debug.h"
647330f729Sjoerg #include "llvm/Support/Errc.h"
657330f729Sjoerg #include "llvm/Support/FileSystem.h"
667330f729Sjoerg #include "llvm/Support/Format.h"
677330f729Sjoerg #include "llvm/Support/FormatVariadic.h"
687330f729Sjoerg #include "llvm/Support/GraphWriter.h"
697330f729Sjoerg #include "llvm/Support/Host.h"
707330f729Sjoerg #include "llvm/Support/InitLLVM.h"
717330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
727330f729Sjoerg #include "llvm/Support/SourceMgr.h"
737330f729Sjoerg #include "llvm/Support/StringSaver.h"
747330f729Sjoerg #include "llvm/Support/TargetRegistry.h"
757330f729Sjoerg #include "llvm/Support/TargetSelect.h"
767330f729Sjoerg #include "llvm/Support/WithColor.h"
777330f729Sjoerg #include "llvm/Support/raw_ostream.h"
787330f729Sjoerg #include <algorithm>
797330f729Sjoerg #include <cctype>
807330f729Sjoerg #include <cstring>
817330f729Sjoerg #include <system_error>
827330f729Sjoerg #include <unordered_map>
837330f729Sjoerg #include <utility>
847330f729Sjoerg 
85*82d56013Sjoerg using namespace llvm;
867330f729Sjoerg using namespace llvm::object;
87*82d56013Sjoerg using namespace llvm::objdump;
88*82d56013Sjoerg using namespace llvm::opt;
897330f729Sjoerg 
90*82d56013Sjoerg namespace {
917330f729Sjoerg 
92*82d56013Sjoerg class CommonOptTable : public opt::OptTable {
93*82d56013Sjoerg public:
CommonOptTable(ArrayRef<Info> OptionInfos,const char * Usage,const char * Description)94*82d56013Sjoerg   CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage,
95*82d56013Sjoerg                  const char *Description)
96*82d56013Sjoerg       : OptTable(OptionInfos), Usage(Usage), Description(Description) {
97*82d56013Sjoerg     setGroupedShortOptions(true);
98*82d56013Sjoerg   }
997330f729Sjoerg 
printHelp(StringRef Argv0,bool ShowHidden=false) const100*82d56013Sjoerg   void printHelp(StringRef Argv0, bool ShowHidden = false) const {
101*82d56013Sjoerg     Argv0 = sys::path::filename(Argv0);
102*82d56013Sjoerg     PrintHelp(outs(), (Argv0 + Usage).str().c_str(), Description, ShowHidden,
103*82d56013Sjoerg               ShowHidden);
104*82d56013Sjoerg     // TODO Replace this with OptTable API once it adds extrahelp support.
105*82d56013Sjoerg     outs() << "\nPass @FILE as argument to read options from FILE.\n";
106*82d56013Sjoerg   }
1077330f729Sjoerg 
108*82d56013Sjoerg private:
109*82d56013Sjoerg   const char *Usage;
110*82d56013Sjoerg   const char *Description;
111*82d56013Sjoerg };
1127330f729Sjoerg 
113*82d56013Sjoerg // ObjdumpOptID is in ObjdumpOptID.h
1147330f729Sjoerg 
115*82d56013Sjoerg #define PREFIX(NAME, VALUE) const char *const OBJDUMP_##NAME[] = VALUE;
116*82d56013Sjoerg #include "ObjdumpOpts.inc"
117*82d56013Sjoerg #undef PREFIX
1187330f729Sjoerg 
119*82d56013Sjoerg static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
120*82d56013Sjoerg #define OBJDUMP_nullptr nullptr
121*82d56013Sjoerg #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
122*82d56013Sjoerg                HELPTEXT, METAVAR, VALUES)                                      \
123*82d56013Sjoerg   {OBJDUMP_##PREFIX, NAME,         HELPTEXT,                                   \
124*82d56013Sjoerg    METAVAR,          OBJDUMP_##ID, opt::Option::KIND##Class,                   \
125*82d56013Sjoerg    PARAM,            FLAGS,        OBJDUMP_##GROUP,                            \
126*82d56013Sjoerg    OBJDUMP_##ALIAS,  ALIASARGS,    VALUES},
127*82d56013Sjoerg #include "ObjdumpOpts.inc"
128*82d56013Sjoerg #undef OPTION
129*82d56013Sjoerg #undef OBJDUMP_nullptr
130*82d56013Sjoerg };
1317330f729Sjoerg 
132*82d56013Sjoerg class ObjdumpOptTable : public CommonOptTable {
133*82d56013Sjoerg public:
ObjdumpOptTable()134*82d56013Sjoerg   ObjdumpOptTable()
135*82d56013Sjoerg       : CommonOptTable(ObjdumpInfoTable, " [options] <input object files>",
136*82d56013Sjoerg                        "llvm object file dumper") {}
137*82d56013Sjoerg };
1387330f729Sjoerg 
139*82d56013Sjoerg enum OtoolOptID {
140*82d56013Sjoerg   OTOOL_INVALID = 0, // This is not an option ID.
141*82d56013Sjoerg #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
142*82d56013Sjoerg                HELPTEXT, METAVAR, VALUES)                                      \
143*82d56013Sjoerg   OTOOL_##ID,
144*82d56013Sjoerg #include "OtoolOpts.inc"
145*82d56013Sjoerg #undef OPTION
146*82d56013Sjoerg };
1477330f729Sjoerg 
148*82d56013Sjoerg #define PREFIX(NAME, VALUE) const char *const OTOOL_##NAME[] = VALUE;
149*82d56013Sjoerg #include "OtoolOpts.inc"
150*82d56013Sjoerg #undef PREFIX
1517330f729Sjoerg 
152*82d56013Sjoerg static constexpr opt::OptTable::Info OtoolInfoTable[] = {
153*82d56013Sjoerg #define OTOOL_nullptr nullptr
154*82d56013Sjoerg #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
155*82d56013Sjoerg                HELPTEXT, METAVAR, VALUES)                                      \
156*82d56013Sjoerg   {OTOOL_##PREFIX, NAME,       HELPTEXT,                                       \
157*82d56013Sjoerg    METAVAR,        OTOOL_##ID, opt::Option::KIND##Class,                       \
158*82d56013Sjoerg    PARAM,          FLAGS,      OTOOL_##GROUP,                                  \
159*82d56013Sjoerg    OTOOL_##ALIAS,  ALIASARGS,  VALUES},
160*82d56013Sjoerg #include "OtoolOpts.inc"
161*82d56013Sjoerg #undef OPTION
162*82d56013Sjoerg #undef OTOOL_nullptr
163*82d56013Sjoerg };
1647330f729Sjoerg 
165*82d56013Sjoerg class OtoolOptTable : public CommonOptTable {
166*82d56013Sjoerg public:
OtoolOptTable()167*82d56013Sjoerg   OtoolOptTable()
168*82d56013Sjoerg       : CommonOptTable(OtoolInfoTable, " [option...] [file...]",
169*82d56013Sjoerg                        "Mach-O object file displaying tool") {}
170*82d56013Sjoerg };
1717330f729Sjoerg 
172*82d56013Sjoerg } // namespace
1737330f729Sjoerg 
174*82d56013Sjoerg #define DEBUG_TYPE "objdump"
1757330f729Sjoerg 
176*82d56013Sjoerg static uint64_t AdjustVMA;
177*82d56013Sjoerg static bool AllHeaders;
178*82d56013Sjoerg static std::string ArchName;
179*82d56013Sjoerg bool objdump::ArchiveHeaders;
180*82d56013Sjoerg bool objdump::Demangle;
181*82d56013Sjoerg bool objdump::Disassemble;
182*82d56013Sjoerg bool objdump::DisassembleAll;
183*82d56013Sjoerg bool objdump::SymbolDescription;
184*82d56013Sjoerg static std::vector<std::string> DisassembleSymbols;
185*82d56013Sjoerg static bool DisassembleZeroes;
186*82d56013Sjoerg static std::vector<std::string> DisassemblerOptions;
187*82d56013Sjoerg DIDumpType objdump::DwarfDumpType;
188*82d56013Sjoerg static bool DynamicRelocations;
189*82d56013Sjoerg static bool FaultMapSection;
190*82d56013Sjoerg static bool FileHeaders;
191*82d56013Sjoerg bool objdump::SectionContents;
192*82d56013Sjoerg static std::vector<std::string> InputFilenames;
193*82d56013Sjoerg bool objdump::PrintLines;
194*82d56013Sjoerg static bool MachOOpt;
195*82d56013Sjoerg std::string objdump::MCPU;
196*82d56013Sjoerg std::vector<std::string> objdump::MAttrs;
197*82d56013Sjoerg bool objdump::ShowRawInsn;
198*82d56013Sjoerg bool objdump::LeadingAddr;
199*82d56013Sjoerg static bool RawClangAST;
200*82d56013Sjoerg bool objdump::Relocations;
201*82d56013Sjoerg bool objdump::PrintImmHex;
202*82d56013Sjoerg bool objdump::PrivateHeaders;
203*82d56013Sjoerg std::vector<std::string> objdump::FilterSections;
204*82d56013Sjoerg bool objdump::SectionHeaders;
205*82d56013Sjoerg static bool ShowLMA;
206*82d56013Sjoerg bool objdump::PrintSource;
2077330f729Sjoerg 
208*82d56013Sjoerg static uint64_t StartAddress;
209*82d56013Sjoerg static bool HasStartAddressFlag;
210*82d56013Sjoerg static uint64_t StopAddress = UINT64_MAX;
211*82d56013Sjoerg static bool HasStopAddressFlag;
2127330f729Sjoerg 
213*82d56013Sjoerg bool objdump::SymbolTable;
214*82d56013Sjoerg static bool SymbolizeOperands;
215*82d56013Sjoerg static bool DynamicSymbolTable;
216*82d56013Sjoerg std::string objdump::TripleName;
217*82d56013Sjoerg bool objdump::UnwindInfo;
218*82d56013Sjoerg static bool Wide;
219*82d56013Sjoerg std::string objdump::Prefix;
220*82d56013Sjoerg uint32_t objdump::PrefixStrip;
2217330f729Sjoerg 
222*82d56013Sjoerg DebugVarsFormat objdump::DbgVariables = DVDisabled;
2237330f729Sjoerg 
224*82d56013Sjoerg int objdump::DbgIndent = 40;
2257330f729Sjoerg 
226*82d56013Sjoerg static StringSet<> DisasmSymbolSet;
227*82d56013Sjoerg StringSet<> objdump::FoundSectionSet;
2287330f729Sjoerg static StringRef ToolName;
2297330f729Sjoerg 
2307330f729Sjoerg namespace {
2317330f729Sjoerg struct FilterResult {
2327330f729Sjoerg   // True if the section should not be skipped.
2337330f729Sjoerg   bool Keep;
2347330f729Sjoerg 
2357330f729Sjoerg   // True if the index counter should be incremented, even if the section should
2367330f729Sjoerg   // be skipped. For example, sections may be skipped if they are not included
2377330f729Sjoerg   // in the --section flag, but we still want those to count toward the section
2387330f729Sjoerg   // count.
2397330f729Sjoerg   bool IncrementIndex;
2407330f729Sjoerg };
2417330f729Sjoerg } // namespace
2427330f729Sjoerg 
checkSectionFilter(object::SectionRef S)2437330f729Sjoerg static FilterResult checkSectionFilter(object::SectionRef S) {
2447330f729Sjoerg   if (FilterSections.empty())
2457330f729Sjoerg     return {/*Keep=*/true, /*IncrementIndex=*/true};
2467330f729Sjoerg 
2477330f729Sjoerg   Expected<StringRef> SecNameOrErr = S.getName();
2487330f729Sjoerg   if (!SecNameOrErr) {
2497330f729Sjoerg     consumeError(SecNameOrErr.takeError());
2507330f729Sjoerg     return {/*Keep=*/false, /*IncrementIndex=*/false};
2517330f729Sjoerg   }
2527330f729Sjoerg   StringRef SecName = *SecNameOrErr;
2537330f729Sjoerg 
2547330f729Sjoerg   // StringSet does not allow empty key so avoid adding sections with
2557330f729Sjoerg   // no name (such as the section with index 0) here.
2567330f729Sjoerg   if (!SecName.empty())
2577330f729Sjoerg     FoundSectionSet.insert(SecName);
2587330f729Sjoerg 
2597330f729Sjoerg   // Only show the section if it's in the FilterSections list, but always
2607330f729Sjoerg   // increment so the indexing is stable.
2617330f729Sjoerg   return {/*Keep=*/is_contained(FilterSections, SecName),
2627330f729Sjoerg           /*IncrementIndex=*/true};
2637330f729Sjoerg }
2647330f729Sjoerg 
ToolSectionFilter(object::ObjectFile const & O,uint64_t * Idx)265*82d56013Sjoerg SectionFilter objdump::ToolSectionFilter(object::ObjectFile const &O,
266*82d56013Sjoerg                                          uint64_t *Idx) {
2677330f729Sjoerg   // Start at UINT64_MAX so that the first index returned after an increment is
2687330f729Sjoerg   // zero (after the unsigned wrap).
2697330f729Sjoerg   if (Idx)
2707330f729Sjoerg     *Idx = UINT64_MAX;
2717330f729Sjoerg   return SectionFilter(
2727330f729Sjoerg       [Idx](object::SectionRef S) {
2737330f729Sjoerg         FilterResult Result = checkSectionFilter(S);
2747330f729Sjoerg         if (Idx != nullptr && Result.IncrementIndex)
2757330f729Sjoerg           *Idx += 1;
2767330f729Sjoerg         return Result.Keep;
2777330f729Sjoerg       },
2787330f729Sjoerg       O);
2797330f729Sjoerg }
2807330f729Sjoerg 
getFileNameForError(const object::Archive::Child & C,unsigned Index)281*82d56013Sjoerg std::string objdump::getFileNameForError(const object::Archive::Child &C,
2827330f729Sjoerg                                          unsigned Index) {
2837330f729Sjoerg   Expected<StringRef> NameOrErr = C.getName();
2847330f729Sjoerg   if (NameOrErr)
285*82d56013Sjoerg     return std::string(NameOrErr.get());
2867330f729Sjoerg   // If we have an error getting the name then we print the index of the archive
2877330f729Sjoerg   // member. Since we are already in an error state, we just ignore this error.
2887330f729Sjoerg   consumeError(NameOrErr.takeError());
2897330f729Sjoerg   return "<file index: " + std::to_string(Index) + ">";
2907330f729Sjoerg }
2917330f729Sjoerg 
reportWarning(const Twine & Message,StringRef File)292*82d56013Sjoerg void objdump::reportWarning(const Twine &Message, StringRef File) {
2937330f729Sjoerg   // Output order between errs() and outs() matters especially for archive
2947330f729Sjoerg   // files where the output is per member object.
2957330f729Sjoerg   outs().flush();
2967330f729Sjoerg   WithColor::warning(errs(), ToolName)
2977330f729Sjoerg       << "'" << File << "': " << Message << "\n";
2987330f729Sjoerg }
2997330f729Sjoerg 
reportError(StringRef File,const Twine & Message)300*82d56013Sjoerg LLVM_ATTRIBUTE_NORETURN void objdump::reportError(StringRef File,
301*82d56013Sjoerg                                                   const Twine &Message) {
302*82d56013Sjoerg   outs().flush();
3037330f729Sjoerg   WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n";
3047330f729Sjoerg   exit(1);
3057330f729Sjoerg }
3067330f729Sjoerg 
reportError(Error E,StringRef FileName,StringRef ArchiveName,StringRef ArchitectureName)307*82d56013Sjoerg LLVM_ATTRIBUTE_NORETURN void objdump::reportError(Error E, StringRef FileName,
3087330f729Sjoerg                                                   StringRef ArchiveName,
3097330f729Sjoerg                                                   StringRef ArchitectureName) {
3107330f729Sjoerg   assert(E);
311*82d56013Sjoerg   outs().flush();
3127330f729Sjoerg   WithColor::error(errs(), ToolName);
3137330f729Sjoerg   if (ArchiveName != "")
3147330f729Sjoerg     errs() << ArchiveName << "(" << FileName << ")";
3157330f729Sjoerg   else
3167330f729Sjoerg     errs() << "'" << FileName << "'";
3177330f729Sjoerg   if (!ArchitectureName.empty())
3187330f729Sjoerg     errs() << " (for architecture " << ArchitectureName << ")";
319*82d56013Sjoerg   errs() << ": ";
320*82d56013Sjoerg   logAllUnhandledErrors(std::move(E), errs());
3217330f729Sjoerg   exit(1);
3227330f729Sjoerg }
3237330f729Sjoerg 
reportCmdLineWarning(const Twine & Message)324*82d56013Sjoerg static void reportCmdLineWarning(const Twine &Message) {
3257330f729Sjoerg   WithColor::warning(errs(), ToolName) << Message << "\n";
3267330f729Sjoerg }
3277330f729Sjoerg 
reportCmdLineError(const Twine & Message)328*82d56013Sjoerg LLVM_ATTRIBUTE_NORETURN static void reportCmdLineError(const Twine &Message) {
3297330f729Sjoerg   WithColor::error(errs(), ToolName) << Message << "\n";
3307330f729Sjoerg   exit(1);
3317330f729Sjoerg }
3327330f729Sjoerg 
warnOnNoMatchForSections()3337330f729Sjoerg static void warnOnNoMatchForSections() {
3347330f729Sjoerg   SetVector<StringRef> MissingSections;
3357330f729Sjoerg   for (StringRef S : FilterSections) {
3367330f729Sjoerg     if (FoundSectionSet.count(S))
3377330f729Sjoerg       return;
3387330f729Sjoerg     // User may specify a unnamed section. Don't warn for it.
3397330f729Sjoerg     if (!S.empty())
3407330f729Sjoerg       MissingSections.insert(S);
3417330f729Sjoerg   }
3427330f729Sjoerg 
3437330f729Sjoerg   // Warn only if no section in FilterSections is matched.
3447330f729Sjoerg   for (StringRef S : MissingSections)
3457330f729Sjoerg     reportCmdLineWarning("section '" + S +
3467330f729Sjoerg                          "' mentioned in a -j/--section option, but not "
3477330f729Sjoerg                          "found in any input file");
3487330f729Sjoerg }
3497330f729Sjoerg 
getTarget(const ObjectFile * Obj)3507330f729Sjoerg static const Target *getTarget(const ObjectFile *Obj) {
3517330f729Sjoerg   // Figure out the target triple.
3527330f729Sjoerg   Triple TheTriple("unknown-unknown-unknown");
3537330f729Sjoerg   if (TripleName.empty()) {
3547330f729Sjoerg     TheTriple = Obj->makeTriple();
3557330f729Sjoerg   } else {
3567330f729Sjoerg     TheTriple.setTriple(Triple::normalize(TripleName));
3577330f729Sjoerg     auto Arch = Obj->getArch();
3587330f729Sjoerg     if (Arch == Triple::arm || Arch == Triple::armeb)
3597330f729Sjoerg       Obj->setARMSubArch(TheTriple);
3607330f729Sjoerg   }
3617330f729Sjoerg 
3627330f729Sjoerg   // Get the target specific parser.
3637330f729Sjoerg   std::string Error;
3647330f729Sjoerg   const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
3657330f729Sjoerg                                                          Error);
3667330f729Sjoerg   if (!TheTarget)
3677330f729Sjoerg     reportError(Obj->getFileName(), "can't find target: " + Error);
3687330f729Sjoerg 
3697330f729Sjoerg   // Update the triple name and return the found target.
3707330f729Sjoerg   TripleName = TheTriple.getTriple();
3717330f729Sjoerg   return TheTarget;
3727330f729Sjoerg }
3737330f729Sjoerg 
isRelocAddressLess(RelocationRef A,RelocationRef B)374*82d56013Sjoerg bool objdump::isRelocAddressLess(RelocationRef A, RelocationRef B) {
3757330f729Sjoerg   return A.getOffset() < B.getOffset();
3767330f729Sjoerg }
3777330f729Sjoerg 
getRelocationValueString(const RelocationRef & Rel,SmallVectorImpl<char> & Result)3787330f729Sjoerg static Error getRelocationValueString(const RelocationRef &Rel,
3797330f729Sjoerg                                       SmallVectorImpl<char> &Result) {
3807330f729Sjoerg   const ObjectFile *Obj = Rel.getObject();
3817330f729Sjoerg   if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))
3827330f729Sjoerg     return getELFRelocationValueString(ELF, Rel, Result);
3837330f729Sjoerg   if (auto *COFF = dyn_cast<COFFObjectFile>(Obj))
3847330f729Sjoerg     return getCOFFRelocationValueString(COFF, Rel, Result);
3857330f729Sjoerg   if (auto *Wasm = dyn_cast<WasmObjectFile>(Obj))
3867330f729Sjoerg     return getWasmRelocationValueString(Wasm, Rel, Result);
3877330f729Sjoerg   if (auto *MachO = dyn_cast<MachOObjectFile>(Obj))
3887330f729Sjoerg     return getMachORelocationValueString(MachO, Rel, Result);
389*82d56013Sjoerg   if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Obj))
390*82d56013Sjoerg     return getXCOFFRelocationValueString(XCOFF, Rel, Result);
3917330f729Sjoerg   llvm_unreachable("unknown object file format");
3927330f729Sjoerg }
3937330f729Sjoerg 
3947330f729Sjoerg /// Indicates whether this relocation should hidden when listing
3957330f729Sjoerg /// relocations, usually because it is the trailing part of a multipart
3967330f729Sjoerg /// relocation that will be printed as part of the leading relocation.
getHidden(RelocationRef RelRef)3977330f729Sjoerg static bool getHidden(RelocationRef RelRef) {
3987330f729Sjoerg   auto *MachO = dyn_cast<MachOObjectFile>(RelRef.getObject());
3997330f729Sjoerg   if (!MachO)
4007330f729Sjoerg     return false;
4017330f729Sjoerg 
4027330f729Sjoerg   unsigned Arch = MachO->getArch();
4037330f729Sjoerg   DataRefImpl Rel = RelRef.getRawDataRefImpl();
4047330f729Sjoerg   uint64_t Type = MachO->getRelocationType(Rel);
4057330f729Sjoerg 
4067330f729Sjoerg   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
4077330f729Sjoerg   // is always hidden.
4087330f729Sjoerg   if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc)
4097330f729Sjoerg     return Type == MachO::GENERIC_RELOC_PAIR;
4107330f729Sjoerg 
4117330f729Sjoerg   if (Arch == Triple::x86_64) {
4127330f729Sjoerg     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
4137330f729Sjoerg     // an X86_64_RELOC_SUBTRACTOR.
4147330f729Sjoerg     if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
4157330f729Sjoerg       DataRefImpl RelPrev = Rel;
4167330f729Sjoerg       RelPrev.d.a--;
4177330f729Sjoerg       uint64_t PrevType = MachO->getRelocationType(RelPrev);
4187330f729Sjoerg       if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
4197330f729Sjoerg         return true;
4207330f729Sjoerg     }
4217330f729Sjoerg   }
4227330f729Sjoerg 
4237330f729Sjoerg   return false;
4247330f729Sjoerg }
4257330f729Sjoerg 
4267330f729Sjoerg namespace {
4277330f729Sjoerg 
428*82d56013Sjoerg /// Get the column at which we want to start printing the instruction
429*82d56013Sjoerg /// disassembly, taking into account anything which appears to the left of it.
getInstStartColumn(const MCSubtargetInfo & STI)430*82d56013Sjoerg unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
431*82d56013Sjoerg   return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
4327330f729Sjoerg }
4337330f729Sjoerg 
isAArch64Elf(const ObjectFile * Obj)4347330f729Sjoerg static bool isAArch64Elf(const ObjectFile *Obj) {
4357330f729Sjoerg   const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
4367330f729Sjoerg   return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
4377330f729Sjoerg }
4387330f729Sjoerg 
isArmElf(const ObjectFile * Obj)4397330f729Sjoerg static bool isArmElf(const ObjectFile *Obj) {
4407330f729Sjoerg   const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
4417330f729Sjoerg   return Elf && Elf->getEMachine() == ELF::EM_ARM;
4427330f729Sjoerg }
4437330f729Sjoerg 
hasMappingSymbols(const ObjectFile * Obj)4447330f729Sjoerg static bool hasMappingSymbols(const ObjectFile *Obj) {
4457330f729Sjoerg   return isArmElf(Obj) || isAArch64Elf(Obj);
4467330f729Sjoerg }
4477330f729Sjoerg 
printRelocation(formatted_raw_ostream & OS,StringRef FileName,const RelocationRef & Rel,uint64_t Address,bool Is64Bits)448*82d56013Sjoerg static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
449*82d56013Sjoerg                             const RelocationRef &Rel, uint64_t Address,
450*82d56013Sjoerg                             bool Is64Bits) {
4517330f729Sjoerg   StringRef Fmt = Is64Bits ? "\t\t%016" PRIx64 ":  " : "\t\t\t%08" PRIx64 ":  ";
4527330f729Sjoerg   SmallString<16> Name;
4537330f729Sjoerg   SmallString<32> Val;
4547330f729Sjoerg   Rel.getTypeName(Name);
4557330f729Sjoerg   if (Error E = getRelocationValueString(Rel, Val))
4567330f729Sjoerg     reportError(std::move(E), FileName);
457*82d56013Sjoerg   OS << format(Fmt.data(), Address) << Name << "\t" << Val;
4587330f729Sjoerg }
4597330f729Sjoerg 
4607330f729Sjoerg class PrettyPrinter {
4617330f729Sjoerg public:
4627330f729Sjoerg   virtual ~PrettyPrinter() = default;
463*82d56013Sjoerg   virtual void
printInst(MCInstPrinter & IP,const MCInst * MI,ArrayRef<uint8_t> Bytes,object::SectionedAddress Address,formatted_raw_ostream & OS,StringRef Annot,MCSubtargetInfo const & STI,SourcePrinter * SP,StringRef ObjectFilename,std::vector<RelocationRef> * Rels,LiveVariablePrinter & LVP)464*82d56013Sjoerg   printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
465*82d56013Sjoerg             object::SectionedAddress Address, formatted_raw_ostream &OS,
466*82d56013Sjoerg             StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
467*82d56013Sjoerg             StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
468*82d56013Sjoerg             LiveVariablePrinter &LVP) {
4697330f729Sjoerg     if (SP && (PrintSource || PrintLines))
470*82d56013Sjoerg       SP->printSourceLine(OS, Address, ObjectFilename, LVP);
471*82d56013Sjoerg     LVP.printBetweenInsts(OS, false);
4727330f729Sjoerg 
4737330f729Sjoerg     size_t Start = OS.tell();
474*82d56013Sjoerg     if (LeadingAddr)
4757330f729Sjoerg       OS << format("%8" PRIx64 ":", Address.Address);
476*82d56013Sjoerg     if (ShowRawInsn) {
4777330f729Sjoerg       OS << ' ';
4787330f729Sjoerg       dumpBytes(Bytes, OS);
4797330f729Sjoerg     }
4807330f729Sjoerg 
4817330f729Sjoerg     // The output of printInst starts with a tab. Print some spaces so that
4827330f729Sjoerg     // the tab has 1 column and advances to the target tab stop.
483*82d56013Sjoerg     unsigned TabStop = getInstStartColumn(STI);
4847330f729Sjoerg     unsigned Column = OS.tell() - Start;
4857330f729Sjoerg     OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
4867330f729Sjoerg 
487*82d56013Sjoerg     if (MI) {
488*82d56013Sjoerg       // See MCInstPrinter::printInst. On targets where a PC relative immediate
489*82d56013Sjoerg       // is relative to the next instruction and the length of a MCInst is
490*82d56013Sjoerg       // difficult to measure (x86), this is the address of the next
491*82d56013Sjoerg       // instruction.
492*82d56013Sjoerg       uint64_t Addr =
493*82d56013Sjoerg           Address.Address + (STI.getTargetTriple().isX86() ? Bytes.size() : 0);
494*82d56013Sjoerg       IP.printInst(MI, Addr, "", STI, OS);
495*82d56013Sjoerg     } else
4967330f729Sjoerg       OS << "\t<unknown>";
4977330f729Sjoerg   }
4987330f729Sjoerg };
4997330f729Sjoerg PrettyPrinter PrettyPrinterInst;
5007330f729Sjoerg 
5017330f729Sjoerg class HexagonPrettyPrinter : public PrettyPrinter {
5027330f729Sjoerg public:
printLead(ArrayRef<uint8_t> Bytes,uint64_t Address,formatted_raw_ostream & OS)5037330f729Sjoerg   void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
504*82d56013Sjoerg                  formatted_raw_ostream &OS) {
5057330f729Sjoerg     uint32_t opcode =
5067330f729Sjoerg       (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
507*82d56013Sjoerg     if (LeadingAddr)
5087330f729Sjoerg       OS << format("%8" PRIx64 ":", Address);
509*82d56013Sjoerg     if (ShowRawInsn) {
5107330f729Sjoerg       OS << "\t";
5117330f729Sjoerg       dumpBytes(Bytes.slice(0, 4), OS);
5127330f729Sjoerg       OS << format("\t%08" PRIx32, opcode);
5137330f729Sjoerg     }
5147330f729Sjoerg   }
printInst(MCInstPrinter & IP,const MCInst * MI,ArrayRef<uint8_t> Bytes,object::SectionedAddress Address,formatted_raw_ostream & OS,StringRef Annot,MCSubtargetInfo const & STI,SourcePrinter * SP,StringRef ObjectFilename,std::vector<RelocationRef> * Rels,LiveVariablePrinter & LVP)5157330f729Sjoerg   void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
516*82d56013Sjoerg                  object::SectionedAddress Address, formatted_raw_ostream &OS,
5177330f729Sjoerg                  StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
518*82d56013Sjoerg                  StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
519*82d56013Sjoerg                  LiveVariablePrinter &LVP) override {
5207330f729Sjoerg     if (SP && (PrintSource || PrintLines))
521*82d56013Sjoerg       SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
5227330f729Sjoerg     if (!MI) {
5237330f729Sjoerg       printLead(Bytes, Address.Address, OS);
5247330f729Sjoerg       OS << " <unknown>";
5257330f729Sjoerg       return;
5267330f729Sjoerg     }
5277330f729Sjoerg     std::string Buffer;
5287330f729Sjoerg     {
5297330f729Sjoerg       raw_string_ostream TempStream(Buffer);
530*82d56013Sjoerg       IP.printInst(MI, Address.Address, "", STI, TempStream);
5317330f729Sjoerg     }
5327330f729Sjoerg     StringRef Contents(Buffer);
5337330f729Sjoerg     // Split off bundle attributes
5347330f729Sjoerg     auto PacketBundle = Contents.rsplit('\n');
5357330f729Sjoerg     // Split off first instruction from the rest
5367330f729Sjoerg     auto HeadTail = PacketBundle.first.split('\n');
5377330f729Sjoerg     auto Preamble = " { ";
5387330f729Sjoerg     auto Separator = "";
5397330f729Sjoerg 
5407330f729Sjoerg     // Hexagon's packets require relocations to be inline rather than
5417330f729Sjoerg     // clustered at the end of the packet.
5427330f729Sjoerg     std::vector<RelocationRef>::const_iterator RelCur = Rels->begin();
5437330f729Sjoerg     std::vector<RelocationRef>::const_iterator RelEnd = Rels->end();
5447330f729Sjoerg     auto PrintReloc = [&]() -> void {
5457330f729Sjoerg       while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) {
5467330f729Sjoerg         if (RelCur->getOffset() == Address.Address) {
547*82d56013Sjoerg           printRelocation(OS, ObjectFilename, *RelCur, Address.Address, false);
5487330f729Sjoerg           return;
5497330f729Sjoerg         }
5507330f729Sjoerg         ++RelCur;
5517330f729Sjoerg       }
5527330f729Sjoerg     };
5537330f729Sjoerg 
5547330f729Sjoerg     while (!HeadTail.first.empty()) {
5557330f729Sjoerg       OS << Separator;
5567330f729Sjoerg       Separator = "\n";
5577330f729Sjoerg       if (SP && (PrintSource || PrintLines))
558*82d56013Sjoerg         SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
5597330f729Sjoerg       printLead(Bytes, Address.Address, OS);
5607330f729Sjoerg       OS << Preamble;
5617330f729Sjoerg       Preamble = "   ";
5627330f729Sjoerg       StringRef Inst;
5637330f729Sjoerg       auto Duplex = HeadTail.first.split('\v');
5647330f729Sjoerg       if (!Duplex.second.empty()) {
5657330f729Sjoerg         OS << Duplex.first;
5667330f729Sjoerg         OS << "; ";
5677330f729Sjoerg         Inst = Duplex.second;
5687330f729Sjoerg       }
5697330f729Sjoerg       else
5707330f729Sjoerg         Inst = HeadTail.first;
5717330f729Sjoerg       OS << Inst;
5727330f729Sjoerg       HeadTail = HeadTail.second.split('\n');
5737330f729Sjoerg       if (HeadTail.first.empty())
5747330f729Sjoerg         OS << " } " << PacketBundle.second;
5757330f729Sjoerg       PrintReloc();
5767330f729Sjoerg       Bytes = Bytes.slice(4);
5777330f729Sjoerg       Address.Address += 4;
5787330f729Sjoerg     }
5797330f729Sjoerg   }
5807330f729Sjoerg };
5817330f729Sjoerg HexagonPrettyPrinter HexagonPrettyPrinterInst;
5827330f729Sjoerg 
5837330f729Sjoerg class AMDGCNPrettyPrinter : public PrettyPrinter {
5847330f729Sjoerg public:
printInst(MCInstPrinter & IP,const MCInst * MI,ArrayRef<uint8_t> Bytes,object::SectionedAddress Address,formatted_raw_ostream & OS,StringRef Annot,MCSubtargetInfo const & STI,SourcePrinter * SP,StringRef ObjectFilename,std::vector<RelocationRef> * Rels,LiveVariablePrinter & LVP)5857330f729Sjoerg   void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
586*82d56013Sjoerg                  object::SectionedAddress Address, formatted_raw_ostream &OS,
5877330f729Sjoerg                  StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
588*82d56013Sjoerg                  StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
589*82d56013Sjoerg                  LiveVariablePrinter &LVP) override {
5907330f729Sjoerg     if (SP && (PrintSource || PrintLines))
591*82d56013Sjoerg       SP->printSourceLine(OS, Address, ObjectFilename, LVP);
5927330f729Sjoerg 
5937330f729Sjoerg     if (MI) {
5947330f729Sjoerg       SmallString<40> InstStr;
5957330f729Sjoerg       raw_svector_ostream IS(InstStr);
5967330f729Sjoerg 
597*82d56013Sjoerg       IP.printInst(MI, Address.Address, "", STI, IS);
5987330f729Sjoerg 
5997330f729Sjoerg       OS << left_justify(IS.str(), 60);
6007330f729Sjoerg     } else {
6017330f729Sjoerg       // an unrecognized encoding - this is probably data so represent it
6027330f729Sjoerg       // using the .long directive, or .byte directive if fewer than 4 bytes
6037330f729Sjoerg       // remaining
6047330f729Sjoerg       if (Bytes.size() >= 4) {
6057330f729Sjoerg         OS << format("\t.long 0x%08" PRIx32 " ",
6067330f729Sjoerg                      support::endian::read32<support::little>(Bytes.data()));
6077330f729Sjoerg         OS.indent(42);
6087330f729Sjoerg       } else {
6097330f729Sjoerg           OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
6107330f729Sjoerg           for (unsigned int i = 1; i < Bytes.size(); i++)
6117330f729Sjoerg             OS << format(", 0x%02" PRIx8, Bytes[i]);
6127330f729Sjoerg           OS.indent(55 - (6 * Bytes.size()));
6137330f729Sjoerg       }
6147330f729Sjoerg     }
6157330f729Sjoerg 
6167330f729Sjoerg     OS << format("// %012" PRIX64 ":", Address.Address);
6177330f729Sjoerg     if (Bytes.size() >= 4) {
6187330f729Sjoerg       // D should be casted to uint32_t here as it is passed by format to
6197330f729Sjoerg       // snprintf as vararg.
6207330f729Sjoerg       for (uint32_t D : makeArrayRef(
6217330f729Sjoerg                reinterpret_cast<const support::little32_t *>(Bytes.data()),
6227330f729Sjoerg                Bytes.size() / 4))
6237330f729Sjoerg         OS << format(" %08" PRIX32, D);
6247330f729Sjoerg     } else {
6257330f729Sjoerg       for (unsigned char B : Bytes)
6267330f729Sjoerg         OS << format(" %02" PRIX8, B);
6277330f729Sjoerg     }
6287330f729Sjoerg 
6297330f729Sjoerg     if (!Annot.empty())
6307330f729Sjoerg       OS << " // " << Annot;
6317330f729Sjoerg   }
6327330f729Sjoerg };
6337330f729Sjoerg AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
6347330f729Sjoerg 
6357330f729Sjoerg class BPFPrettyPrinter : public PrettyPrinter {
6367330f729Sjoerg public:
printInst(MCInstPrinter & IP,const MCInst * MI,ArrayRef<uint8_t> Bytes,object::SectionedAddress Address,formatted_raw_ostream & OS,StringRef Annot,MCSubtargetInfo const & STI,SourcePrinter * SP,StringRef ObjectFilename,std::vector<RelocationRef> * Rels,LiveVariablePrinter & LVP)6377330f729Sjoerg   void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
638*82d56013Sjoerg                  object::SectionedAddress Address, formatted_raw_ostream &OS,
6397330f729Sjoerg                  StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
640*82d56013Sjoerg                  StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
641*82d56013Sjoerg                  LiveVariablePrinter &LVP) override {
6427330f729Sjoerg     if (SP && (PrintSource || PrintLines))
643*82d56013Sjoerg       SP->printSourceLine(OS, Address, ObjectFilename, LVP);
644*82d56013Sjoerg     if (LeadingAddr)
6457330f729Sjoerg       OS << format("%8" PRId64 ":", Address.Address / 8);
646*82d56013Sjoerg     if (ShowRawInsn) {
6477330f729Sjoerg       OS << "\t";
6487330f729Sjoerg       dumpBytes(Bytes, OS);
6497330f729Sjoerg     }
6507330f729Sjoerg     if (MI)
651*82d56013Sjoerg       IP.printInst(MI, Address.Address, "", STI, OS);
6527330f729Sjoerg     else
6537330f729Sjoerg       OS << "\t<unknown>";
6547330f729Sjoerg   }
6557330f729Sjoerg };
6567330f729Sjoerg BPFPrettyPrinter BPFPrettyPrinterInst;
6577330f729Sjoerg 
selectPrettyPrinter(Triple const & Triple)6587330f729Sjoerg PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
6597330f729Sjoerg   switch(Triple.getArch()) {
6607330f729Sjoerg   default:
6617330f729Sjoerg     return PrettyPrinterInst;
6627330f729Sjoerg   case Triple::hexagon:
6637330f729Sjoerg     return HexagonPrettyPrinterInst;
6647330f729Sjoerg   case Triple::amdgcn:
6657330f729Sjoerg     return AMDGCNPrettyPrinterInst;
6667330f729Sjoerg   case Triple::bpfel:
6677330f729Sjoerg   case Triple::bpfeb:
6687330f729Sjoerg     return BPFPrettyPrinterInst;
6697330f729Sjoerg   }
6707330f729Sjoerg }
6717330f729Sjoerg }
6727330f729Sjoerg 
getElfSymbolType(const ObjectFile * Obj,const SymbolRef & Sym)6737330f729Sjoerg static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) {
6747330f729Sjoerg   assert(Obj->isELF());
6757330f729Sjoerg   if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
676*82d56013Sjoerg     return unwrapOrError(Elf32LEObj->getSymbol(Sym.getRawDataRefImpl()),
677*82d56013Sjoerg                          Obj->getFileName())
678*82d56013Sjoerg         ->getType();
6797330f729Sjoerg   if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
680*82d56013Sjoerg     return unwrapOrError(Elf64LEObj->getSymbol(Sym.getRawDataRefImpl()),
681*82d56013Sjoerg                          Obj->getFileName())
682*82d56013Sjoerg         ->getType();
6837330f729Sjoerg   if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
684*82d56013Sjoerg     return unwrapOrError(Elf32BEObj->getSymbol(Sym.getRawDataRefImpl()),
685*82d56013Sjoerg                          Obj->getFileName())
686*82d56013Sjoerg         ->getType();
6877330f729Sjoerg   if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj))
688*82d56013Sjoerg     return unwrapOrError(Elf64BEObj->getSymbol(Sym.getRawDataRefImpl()),
689*82d56013Sjoerg                          Obj->getFileName())
690*82d56013Sjoerg         ->getType();
6917330f729Sjoerg   llvm_unreachable("Unsupported binary format");
6927330f729Sjoerg }
6937330f729Sjoerg 
6947330f729Sjoerg template <class ELFT> static void
addDynamicElfSymbols(const ELFObjectFile<ELFT> * Obj,std::map<SectionRef,SectionSymbolsTy> & AllSymbols)6957330f729Sjoerg addDynamicElfSymbols(const ELFObjectFile<ELFT> *Obj,
6967330f729Sjoerg                      std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
6977330f729Sjoerg   for (auto Symbol : Obj->getDynamicSymbolIterators()) {
6987330f729Sjoerg     uint8_t SymbolType = Symbol.getELFType();
6997330f729Sjoerg     if (SymbolType == ELF::STT_SECTION)
7007330f729Sjoerg       continue;
7017330f729Sjoerg 
7027330f729Sjoerg     uint64_t Address = unwrapOrError(Symbol.getAddress(), Obj->getFileName());
7037330f729Sjoerg     // ELFSymbolRef::getAddress() returns size instead of value for common
7047330f729Sjoerg     // symbols which is not desirable for disassembly output. Overriding.
7057330f729Sjoerg     if (SymbolType == ELF::STT_COMMON)
706*82d56013Sjoerg       Address = unwrapOrError(Obj->getSymbol(Symbol.getRawDataRefImpl()),
707*82d56013Sjoerg                               Obj->getFileName())
708*82d56013Sjoerg                     ->st_value;
7097330f729Sjoerg 
7107330f729Sjoerg     StringRef Name = unwrapOrError(Symbol.getName(), Obj->getFileName());
7117330f729Sjoerg     if (Name.empty())
7127330f729Sjoerg       continue;
7137330f729Sjoerg 
7147330f729Sjoerg     section_iterator SecI =
7157330f729Sjoerg         unwrapOrError(Symbol.getSection(), Obj->getFileName());
7167330f729Sjoerg     if (SecI == Obj->section_end())
7177330f729Sjoerg       continue;
7187330f729Sjoerg 
7197330f729Sjoerg     AllSymbols[*SecI].emplace_back(Address, Name, SymbolType);
7207330f729Sjoerg   }
7217330f729Sjoerg }
7227330f729Sjoerg 
7237330f729Sjoerg static void
addDynamicElfSymbols(const ObjectFile * Obj,std::map<SectionRef,SectionSymbolsTy> & AllSymbols)7247330f729Sjoerg addDynamicElfSymbols(const ObjectFile *Obj,
7257330f729Sjoerg                      std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
7267330f729Sjoerg   assert(Obj->isELF());
7277330f729Sjoerg   if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
7287330f729Sjoerg     addDynamicElfSymbols(Elf32LEObj, AllSymbols);
7297330f729Sjoerg   else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
7307330f729Sjoerg     addDynamicElfSymbols(Elf64LEObj, AllSymbols);
7317330f729Sjoerg   else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
7327330f729Sjoerg     addDynamicElfSymbols(Elf32BEObj, AllSymbols);
7337330f729Sjoerg   else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj))
7347330f729Sjoerg     addDynamicElfSymbols(Elf64BEObj, AllSymbols);
7357330f729Sjoerg   else
7367330f729Sjoerg     llvm_unreachable("Unsupported binary format");
7377330f729Sjoerg }
7387330f729Sjoerg 
addPltEntries(const ObjectFile * Obj,std::map<SectionRef,SectionSymbolsTy> & AllSymbols,StringSaver & Saver)7397330f729Sjoerg static void addPltEntries(const ObjectFile *Obj,
7407330f729Sjoerg                           std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
7417330f729Sjoerg                           StringSaver &Saver) {
7427330f729Sjoerg   Optional<SectionRef> Plt = None;
7437330f729Sjoerg   for (const SectionRef &Section : Obj->sections()) {
7447330f729Sjoerg     Expected<StringRef> SecNameOrErr = Section.getName();
7457330f729Sjoerg     if (!SecNameOrErr) {
7467330f729Sjoerg       consumeError(SecNameOrErr.takeError());
7477330f729Sjoerg       continue;
7487330f729Sjoerg     }
7497330f729Sjoerg     if (*SecNameOrErr == ".plt")
7507330f729Sjoerg       Plt = Section;
7517330f729Sjoerg   }
7527330f729Sjoerg   if (!Plt)
7537330f729Sjoerg     return;
7547330f729Sjoerg   if (auto *ElfObj = dyn_cast<ELFObjectFileBase>(Obj)) {
7557330f729Sjoerg     for (auto PltEntry : ElfObj->getPltAddresses()) {
756*82d56013Sjoerg       if (PltEntry.first) {
757*82d56013Sjoerg         SymbolRef Symbol(*PltEntry.first, ElfObj);
7587330f729Sjoerg         uint8_t SymbolType = getElfSymbolType(Obj, Symbol);
759*82d56013Sjoerg         if (Expected<StringRef> NameOrErr = Symbol.getName()) {
760*82d56013Sjoerg           if (!NameOrErr->empty())
7617330f729Sjoerg             AllSymbols[*Plt].emplace_back(
762*82d56013Sjoerg                 PltEntry.second, Saver.save((*NameOrErr + "@plt").str()),
763*82d56013Sjoerg                 SymbolType);
764*82d56013Sjoerg           continue;
765*82d56013Sjoerg         } else {
766*82d56013Sjoerg           // The warning has been reported in disassembleObject().
767*82d56013Sjoerg           consumeError(NameOrErr.takeError());
768*82d56013Sjoerg         }
769*82d56013Sjoerg       }
770*82d56013Sjoerg       reportWarning("PLT entry at 0x" + Twine::utohexstr(PltEntry.second) +
771*82d56013Sjoerg                         " references an invalid symbol",
772*82d56013Sjoerg                     Obj->getFileName());
7737330f729Sjoerg     }
7747330f729Sjoerg   }
7757330f729Sjoerg }
7767330f729Sjoerg 
7777330f729Sjoerg // Normally the disassembly output will skip blocks of zeroes. This function
7787330f729Sjoerg // returns the number of zero bytes that can be skipped when dumping the
7797330f729Sjoerg // disassembly of the instructions in Buf.
countSkippableZeroBytes(ArrayRef<uint8_t> Buf)7807330f729Sjoerg static size_t countSkippableZeroBytes(ArrayRef<uint8_t> Buf) {
7817330f729Sjoerg   // Find the number of leading zeroes.
7827330f729Sjoerg   size_t N = 0;
7837330f729Sjoerg   while (N < Buf.size() && !Buf[N])
7847330f729Sjoerg     ++N;
7857330f729Sjoerg 
7867330f729Sjoerg   // We may want to skip blocks of zero bytes, but unless we see
7877330f729Sjoerg   // at least 8 of them in a row.
7887330f729Sjoerg   if (N < 8)
7897330f729Sjoerg     return 0;
7907330f729Sjoerg 
7917330f729Sjoerg   // We skip zeroes in multiples of 4 because do not want to truncate an
7927330f729Sjoerg   // instruction if it starts with a zero byte.
7937330f729Sjoerg   return N & ~0x3;
7947330f729Sjoerg }
7957330f729Sjoerg 
7967330f729Sjoerg // Returns a map from sections to their relocations.
7977330f729Sjoerg static std::map<SectionRef, std::vector<RelocationRef>>
getRelocsMap(object::ObjectFile const & Obj)7987330f729Sjoerg getRelocsMap(object::ObjectFile const &Obj) {
7997330f729Sjoerg   std::map<SectionRef, std::vector<RelocationRef>> Ret;
8007330f729Sjoerg   uint64_t I = (uint64_t)-1;
8017330f729Sjoerg   for (SectionRef Sec : Obj.sections()) {
8027330f729Sjoerg     ++I;
8037330f729Sjoerg     Expected<section_iterator> RelocatedOrErr = Sec.getRelocatedSection();
8047330f729Sjoerg     if (!RelocatedOrErr)
8057330f729Sjoerg       reportError(Obj.getFileName(),
8067330f729Sjoerg                   "section (" + Twine(I) +
8077330f729Sjoerg                       "): failed to get a relocated section: " +
8087330f729Sjoerg                       toString(RelocatedOrErr.takeError()));
8097330f729Sjoerg 
8107330f729Sjoerg     section_iterator Relocated = *RelocatedOrErr;
8117330f729Sjoerg     if (Relocated == Obj.section_end() || !checkSectionFilter(*Relocated).Keep)
8127330f729Sjoerg       continue;
8137330f729Sjoerg     std::vector<RelocationRef> &V = Ret[*Relocated];
814*82d56013Sjoerg     append_range(V, Sec.relocations());
8157330f729Sjoerg     // Sort relocations by address.
8167330f729Sjoerg     llvm::stable_sort(V, isRelocAddressLess);
8177330f729Sjoerg   }
8187330f729Sjoerg   return Ret;
8197330f729Sjoerg }
8207330f729Sjoerg 
8217330f729Sjoerg // Used for --adjust-vma to check if address should be adjusted by the
8227330f729Sjoerg // specified value for a given section.
8237330f729Sjoerg // For ELF we do not adjust non-allocatable sections like debug ones,
8247330f729Sjoerg // because they are not loadable.
8257330f729Sjoerg // TODO: implement for other file formats.
shouldAdjustVA(const SectionRef & Section)8267330f729Sjoerg static bool shouldAdjustVA(const SectionRef &Section) {
8277330f729Sjoerg   const ObjectFile *Obj = Section.getObject();
828*82d56013Sjoerg   if (Obj->isELF())
8297330f729Sjoerg     return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;
8307330f729Sjoerg   return false;
8317330f729Sjoerg }
8327330f729Sjoerg 
8337330f729Sjoerg 
8347330f729Sjoerg typedef std::pair<uint64_t, char> MappingSymbolPair;
getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,uint64_t Address)8357330f729Sjoerg static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
8367330f729Sjoerg                                  uint64_t Address) {
8377330f729Sjoerg   auto It =
8387330f729Sjoerg       partition_point(MappingSymbols, [Address](const MappingSymbolPair &Val) {
8397330f729Sjoerg         return Val.first <= Address;
8407330f729Sjoerg       });
8417330f729Sjoerg   // Return zero for any address before the first mapping symbol; this means
8427330f729Sjoerg   // we should use the default disassembly mode, depending on the target.
8437330f729Sjoerg   if (It == MappingSymbols.begin())
8447330f729Sjoerg     return '\x00';
8457330f729Sjoerg   return (It - 1)->second;
8467330f729Sjoerg }
8477330f729Sjoerg 
dumpARMELFData(uint64_t SectionAddr,uint64_t Index,uint64_t End,const ObjectFile * Obj,ArrayRef<uint8_t> Bytes,ArrayRef<MappingSymbolPair> MappingSymbols,raw_ostream & OS)848*82d56013Sjoerg static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,
849*82d56013Sjoerg                                uint64_t End, const ObjectFile *Obj,
850*82d56013Sjoerg                                ArrayRef<uint8_t> Bytes,
851*82d56013Sjoerg                                ArrayRef<MappingSymbolPair> MappingSymbols,
852*82d56013Sjoerg                                raw_ostream &OS) {
8537330f729Sjoerg   support::endianness Endian =
8547330f729Sjoerg       Obj->isLittleEndian() ? support::little : support::big;
855*82d56013Sjoerg   OS << format("%8" PRIx64 ":\t", SectionAddr + Index);
8567330f729Sjoerg   if (Index + 4 <= End) {
857*82d56013Sjoerg     dumpBytes(Bytes.slice(Index, 4), OS);
858*82d56013Sjoerg     OS << "\t.word\t"
859*82d56013Sjoerg            << format_hex(support::endian::read32(Bytes.data() + Index, Endian),
860*82d56013Sjoerg                          10);
861*82d56013Sjoerg     return 4;
8627330f729Sjoerg   }
863*82d56013Sjoerg   if (Index + 2 <= End) {
864*82d56013Sjoerg     dumpBytes(Bytes.slice(Index, 2), OS);
865*82d56013Sjoerg     OS << "\t\t.short\t"
866*82d56013Sjoerg            << format_hex(support::endian::read16(Bytes.data() + Index, Endian),
867*82d56013Sjoerg                          6);
868*82d56013Sjoerg     return 2;
8697330f729Sjoerg   }
870*82d56013Sjoerg   dumpBytes(Bytes.slice(Index, 1), OS);
871*82d56013Sjoerg   OS << "\t\t.byte\t" << format_hex(Bytes[0], 4);
872*82d56013Sjoerg   return 1;
8737330f729Sjoerg }
8747330f729Sjoerg 
dumpELFData(uint64_t SectionAddr,uint64_t Index,uint64_t End,ArrayRef<uint8_t> Bytes)8757330f729Sjoerg static void dumpELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
8767330f729Sjoerg                         ArrayRef<uint8_t> Bytes) {
8777330f729Sjoerg   // print out data up to 8 bytes at a time in hex and ascii
8787330f729Sjoerg   uint8_t AsciiData[9] = {'\0'};
8797330f729Sjoerg   uint8_t Byte;
8807330f729Sjoerg   int NumBytes = 0;
8817330f729Sjoerg 
8827330f729Sjoerg   for (; Index < End; ++Index) {
8837330f729Sjoerg     if (NumBytes == 0)
8847330f729Sjoerg       outs() << format("%8" PRIx64 ":", SectionAddr + Index);
8857330f729Sjoerg     Byte = Bytes.slice(Index)[0];
8867330f729Sjoerg     outs() << format(" %02x", Byte);
8877330f729Sjoerg     AsciiData[NumBytes] = isPrint(Byte) ? Byte : '.';
8887330f729Sjoerg 
8897330f729Sjoerg     uint8_t IndentOffset = 0;
8907330f729Sjoerg     NumBytes++;
8917330f729Sjoerg     if (Index == End - 1 || NumBytes > 8) {
8927330f729Sjoerg       // Indent the space for less than 8 bytes data.
8937330f729Sjoerg       // 2 spaces for byte and one for space between bytes
8947330f729Sjoerg       IndentOffset = 3 * (8 - NumBytes);
8957330f729Sjoerg       for (int Excess = NumBytes; Excess < 8; Excess++)
8967330f729Sjoerg         AsciiData[Excess] = '\0';
8977330f729Sjoerg       NumBytes = 8;
8987330f729Sjoerg     }
8997330f729Sjoerg     if (NumBytes == 8) {
9007330f729Sjoerg       AsciiData[8] = '\0';
9017330f729Sjoerg       outs() << std::string(IndentOffset, ' ') << "         ";
9027330f729Sjoerg       outs() << reinterpret_cast<char *>(AsciiData);
9037330f729Sjoerg       outs() << '\n';
9047330f729Sjoerg       NumBytes = 0;
9057330f729Sjoerg     }
9067330f729Sjoerg   }
9077330f729Sjoerg }
9087330f729Sjoerg 
createSymbolInfo(const ObjectFile * Obj,const SymbolRef & Symbol)909*82d56013Sjoerg SymbolInfoTy objdump::createSymbolInfo(const ObjectFile *Obj,
910*82d56013Sjoerg                                        const SymbolRef &Symbol) {
911*82d56013Sjoerg   const StringRef FileName = Obj->getFileName();
912*82d56013Sjoerg   const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
913*82d56013Sjoerg   const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
914*82d56013Sjoerg 
915*82d56013Sjoerg   if (Obj->isXCOFF() && SymbolDescription) {
916*82d56013Sjoerg     const auto *XCOFFObj = cast<XCOFFObjectFile>(Obj);
917*82d56013Sjoerg     DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();
918*82d56013Sjoerg 
919*82d56013Sjoerg     const uint32_t SymbolIndex = XCOFFObj->getSymbolIndex(SymbolDRI.p);
920*82d56013Sjoerg     Optional<XCOFF::StorageMappingClass> Smc =
921*82d56013Sjoerg         getXCOFFSymbolCsectSMC(XCOFFObj, Symbol);
922*82d56013Sjoerg     return SymbolInfoTy(Addr, Name, Smc, SymbolIndex,
923*82d56013Sjoerg                         isLabel(XCOFFObj, Symbol));
924*82d56013Sjoerg   } else
925*82d56013Sjoerg     return SymbolInfoTy(Addr, Name,
926*82d56013Sjoerg                         Obj->isELF() ? getElfSymbolType(Obj, Symbol)
927*82d56013Sjoerg                                      : (uint8_t)ELF::STT_NOTYPE);
928*82d56013Sjoerg }
929*82d56013Sjoerg 
createDummySymbolInfo(const ObjectFile * Obj,const uint64_t Addr,StringRef & Name,uint8_t Type)930*82d56013Sjoerg static SymbolInfoTy createDummySymbolInfo(const ObjectFile *Obj,
931*82d56013Sjoerg                                           const uint64_t Addr, StringRef &Name,
932*82d56013Sjoerg                                           uint8_t Type) {
933*82d56013Sjoerg   if (Obj->isXCOFF() && SymbolDescription)
934*82d56013Sjoerg     return SymbolInfoTy(Addr, Name, None, None, false);
935*82d56013Sjoerg   else
936*82d56013Sjoerg     return SymbolInfoTy(Addr, Name, Type);
937*82d56013Sjoerg }
938*82d56013Sjoerg 
939*82d56013Sjoerg static void
collectLocalBranchTargets(ArrayRef<uint8_t> Bytes,const MCInstrAnalysis * MIA,MCDisassembler * DisAsm,MCInstPrinter * IP,const MCSubtargetInfo * STI,uint64_t SectionAddr,uint64_t Start,uint64_t End,std::unordered_map<uint64_t,std::string> & Labels)940*82d56013Sjoerg collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA,
941*82d56013Sjoerg                           MCDisassembler *DisAsm, MCInstPrinter *IP,
942*82d56013Sjoerg                           const MCSubtargetInfo *STI, uint64_t SectionAddr,
943*82d56013Sjoerg                           uint64_t Start, uint64_t End,
944*82d56013Sjoerg                           std::unordered_map<uint64_t, std::string> &Labels) {
945*82d56013Sjoerg   // So far only supports X86.
946*82d56013Sjoerg   if (!STI->getTargetTriple().isX86())
947*82d56013Sjoerg     return;
948*82d56013Sjoerg 
949*82d56013Sjoerg   Labels.clear();
950*82d56013Sjoerg   unsigned LabelCount = 0;
951*82d56013Sjoerg   Start += SectionAddr;
952*82d56013Sjoerg   End += SectionAddr;
953*82d56013Sjoerg   uint64_t Index = Start;
954*82d56013Sjoerg   while (Index < End) {
955*82d56013Sjoerg     // Disassemble a real instruction and record function-local branch labels.
956*82d56013Sjoerg     MCInst Inst;
957*82d56013Sjoerg     uint64_t Size;
958*82d56013Sjoerg     bool Disassembled = DisAsm->getInstruction(
959*82d56013Sjoerg         Inst, Size, Bytes.slice(Index - SectionAddr), Index, nulls());
960*82d56013Sjoerg     if (Size == 0)
961*82d56013Sjoerg       Size = 1;
962*82d56013Sjoerg 
963*82d56013Sjoerg     if (Disassembled && MIA) {
964*82d56013Sjoerg       uint64_t Target;
965*82d56013Sjoerg       bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
966*82d56013Sjoerg       if (TargetKnown && (Target >= Start && Target < End) &&
967*82d56013Sjoerg           !Labels.count(Target))
968*82d56013Sjoerg         Labels[Target] = ("L" + Twine(LabelCount++)).str();
969*82d56013Sjoerg     }
970*82d56013Sjoerg 
971*82d56013Sjoerg     Index += Size;
972*82d56013Sjoerg   }
973*82d56013Sjoerg }
974*82d56013Sjoerg 
975*82d56013Sjoerg // Create an MCSymbolizer for the target and add it to the MCDisassembler.
976*82d56013Sjoerg // This is currently only used on AMDGPU, and assumes the format of the
977*82d56013Sjoerg // void * argument passed to AMDGPU's createMCSymbolizer.
addSymbolizer(MCContext & Ctx,const Target * Target,StringRef TripleName,MCDisassembler * DisAsm,uint64_t SectionAddr,ArrayRef<uint8_t> Bytes,SectionSymbolsTy & Symbols,std::vector<std::unique_ptr<std::string>> & SynthesizedLabelNames)978*82d56013Sjoerg static void addSymbolizer(
979*82d56013Sjoerg     MCContext &Ctx, const Target *Target, StringRef TripleName,
980*82d56013Sjoerg     MCDisassembler *DisAsm, uint64_t SectionAddr, ArrayRef<uint8_t> Bytes,
981*82d56013Sjoerg     SectionSymbolsTy &Symbols,
982*82d56013Sjoerg     std::vector<std::unique_ptr<std::string>> &SynthesizedLabelNames) {
983*82d56013Sjoerg 
984*82d56013Sjoerg   std::unique_ptr<MCRelocationInfo> RelInfo(
985*82d56013Sjoerg       Target->createMCRelocationInfo(TripleName, Ctx));
986*82d56013Sjoerg   if (!RelInfo)
987*82d56013Sjoerg     return;
988*82d56013Sjoerg   std::unique_ptr<MCSymbolizer> Symbolizer(Target->createMCSymbolizer(
989*82d56013Sjoerg       TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
990*82d56013Sjoerg   MCSymbolizer *SymbolizerPtr = &*Symbolizer;
991*82d56013Sjoerg   DisAsm->setSymbolizer(std::move(Symbolizer));
992*82d56013Sjoerg 
993*82d56013Sjoerg   if (!SymbolizeOperands)
994*82d56013Sjoerg     return;
995*82d56013Sjoerg 
996*82d56013Sjoerg   // Synthesize labels referenced by branch instructions by
997*82d56013Sjoerg   // disassembling, discarding the output, and collecting the referenced
998*82d56013Sjoerg   // addresses from the symbolizer.
999*82d56013Sjoerg   for (size_t Index = 0; Index != Bytes.size();) {
1000*82d56013Sjoerg     MCInst Inst;
1001*82d56013Sjoerg     uint64_t Size;
1002*82d56013Sjoerg     DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), SectionAddr + Index,
1003*82d56013Sjoerg                            nulls());
1004*82d56013Sjoerg     if (Size == 0)
1005*82d56013Sjoerg       Size = 1;
1006*82d56013Sjoerg     Index += Size;
1007*82d56013Sjoerg   }
1008*82d56013Sjoerg   ArrayRef<uint64_t> LabelAddrsRef = SymbolizerPtr->getReferencedAddresses();
1009*82d56013Sjoerg   // Copy and sort to remove duplicates.
1010*82d56013Sjoerg   std::vector<uint64_t> LabelAddrs;
1011*82d56013Sjoerg   LabelAddrs.insert(LabelAddrs.end(), LabelAddrsRef.begin(),
1012*82d56013Sjoerg                     LabelAddrsRef.end());
1013*82d56013Sjoerg   llvm::sort(LabelAddrs);
1014*82d56013Sjoerg   LabelAddrs.resize(std::unique(LabelAddrs.begin(), LabelAddrs.end()) -
1015*82d56013Sjoerg                     LabelAddrs.begin());
1016*82d56013Sjoerg   // Add the labels.
1017*82d56013Sjoerg   for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) {
1018*82d56013Sjoerg     auto Name = std::make_unique<std::string>();
1019*82d56013Sjoerg     *Name = (Twine("L") + Twine(LabelNum)).str();
1020*82d56013Sjoerg     SynthesizedLabelNames.push_back(std::move(Name));
1021*82d56013Sjoerg     Symbols.push_back(SymbolInfoTy(
1022*82d56013Sjoerg         LabelAddrs[LabelNum], *SynthesizedLabelNames.back(), ELF::STT_NOTYPE));
1023*82d56013Sjoerg   }
1024*82d56013Sjoerg   llvm::stable_sort(Symbols);
1025*82d56013Sjoerg   // Recreate the symbolizer with the new symbols list.
1026*82d56013Sjoerg   RelInfo.reset(Target->createMCRelocationInfo(TripleName, Ctx));
1027*82d56013Sjoerg   Symbolizer.reset(Target->createMCSymbolizer(
1028*82d56013Sjoerg       TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
1029*82d56013Sjoerg   DisAsm->setSymbolizer(std::move(Symbolizer));
1030*82d56013Sjoerg }
1031*82d56013Sjoerg 
getSegmentName(const MachOObjectFile * MachO,const SectionRef & Section)1032*82d56013Sjoerg static StringRef getSegmentName(const MachOObjectFile *MachO,
1033*82d56013Sjoerg                                 const SectionRef &Section) {
1034*82d56013Sjoerg   if (MachO) {
1035*82d56013Sjoerg     DataRefImpl DR = Section.getRawDataRefImpl();
1036*82d56013Sjoerg     StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
1037*82d56013Sjoerg     return SegmentName;
1038*82d56013Sjoerg   }
1039*82d56013Sjoerg   return "";
1040*82d56013Sjoerg }
1041*82d56013Sjoerg 
disassembleObject(const Target * TheTarget,const ObjectFile * Obj,MCContext & Ctx,MCDisassembler * PrimaryDisAsm,MCDisassembler * SecondaryDisAsm,const MCInstrAnalysis * MIA,MCInstPrinter * IP,const MCSubtargetInfo * PrimarySTI,const MCSubtargetInfo * SecondarySTI,PrettyPrinter & PIP,SourcePrinter & SP,bool InlineRelocs)10427330f729Sjoerg static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
10437330f729Sjoerg                               MCContext &Ctx, MCDisassembler *PrimaryDisAsm,
10447330f729Sjoerg                               MCDisassembler *SecondaryDisAsm,
10457330f729Sjoerg                               const MCInstrAnalysis *MIA, MCInstPrinter *IP,
10467330f729Sjoerg                               const MCSubtargetInfo *PrimarySTI,
10477330f729Sjoerg                               const MCSubtargetInfo *SecondarySTI,
10487330f729Sjoerg                               PrettyPrinter &PIP,
10497330f729Sjoerg                               SourcePrinter &SP, bool InlineRelocs) {
10507330f729Sjoerg   const MCSubtargetInfo *STI = PrimarySTI;
10517330f729Sjoerg   MCDisassembler *DisAsm = PrimaryDisAsm;
10527330f729Sjoerg   bool PrimaryIsThumb = false;
10537330f729Sjoerg   if (isArmElf(Obj))
10547330f729Sjoerg     PrimaryIsThumb = STI->checkFeatures("+thumb-mode");
10557330f729Sjoerg 
10567330f729Sjoerg   std::map<SectionRef, std::vector<RelocationRef>> RelocMap;
10577330f729Sjoerg   if (InlineRelocs)
10587330f729Sjoerg     RelocMap = getRelocsMap(*Obj);
10597330f729Sjoerg   bool Is64Bits = Obj->getBytesInAddress() > 4;
10607330f729Sjoerg 
10617330f729Sjoerg   // Create a mapping from virtual address to symbol name.  This is used to
10627330f729Sjoerg   // pretty print the symbols while disassembling.
10637330f729Sjoerg   std::map<SectionRef, SectionSymbolsTy> AllSymbols;
10647330f729Sjoerg   SectionSymbolsTy AbsoluteSymbols;
10657330f729Sjoerg   const StringRef FileName = Obj->getFileName();
1066*82d56013Sjoerg   const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj);
10677330f729Sjoerg   for (const SymbolRef &Symbol : Obj->symbols()) {
1068*82d56013Sjoerg     Expected<StringRef> NameOrErr = Symbol.getName();
1069*82d56013Sjoerg     if (!NameOrErr) {
1070*82d56013Sjoerg       reportWarning(toString(NameOrErr.takeError()), FileName);
1071*82d56013Sjoerg       continue;
1072*82d56013Sjoerg     }
1073*82d56013Sjoerg     if (NameOrErr->empty() && !(Obj->isXCOFF() && SymbolDescription))
10747330f729Sjoerg       continue;
10757330f729Sjoerg 
1076*82d56013Sjoerg     if (Obj->isELF() && getElfSymbolType(Obj, Symbol) == ELF::STT_SECTION)
1077*82d56013Sjoerg       continue;
1078*82d56013Sjoerg 
1079*82d56013Sjoerg     if (MachO) {
1080*82d56013Sjoerg       // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special
1081*82d56013Sjoerg       // symbols that support MachO header introspection. They do not bind to
1082*82d56013Sjoerg       // code locations and are irrelevant for disassembly.
1083*82d56013Sjoerg       if (NameOrErr->startswith("__mh_") && NameOrErr->endswith("_header"))
1084*82d56013Sjoerg         continue;
1085*82d56013Sjoerg       // Don't ask a Mach-O STAB symbol for its section unless you know that
1086*82d56013Sjoerg       // STAB symbol's section field refers to a valid section index. Otherwise
1087*82d56013Sjoerg       // the symbol may error trying to load a section that does not exist.
1088*82d56013Sjoerg       DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1089*82d56013Sjoerg       uint8_t NType = (MachO->is64Bit() ?
1090*82d56013Sjoerg                        MachO->getSymbol64TableEntry(SymDRI).n_type:
1091*82d56013Sjoerg                        MachO->getSymbolTableEntry(SymDRI).n_type);
1092*82d56013Sjoerg       if (NType & MachO::N_STAB)
10937330f729Sjoerg         continue;
10947330f729Sjoerg     }
10957330f729Sjoerg 
10967330f729Sjoerg     section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
10977330f729Sjoerg     if (SecI != Obj->section_end())
1098*82d56013Sjoerg       AllSymbols[*SecI].push_back(createSymbolInfo(Obj, Symbol));
10997330f729Sjoerg     else
1100*82d56013Sjoerg       AbsoluteSymbols.push_back(createSymbolInfo(Obj, Symbol));
11017330f729Sjoerg   }
1102*82d56013Sjoerg 
11037330f729Sjoerg   if (AllSymbols.empty() && Obj->isELF())
11047330f729Sjoerg     addDynamicElfSymbols(Obj, AllSymbols);
11057330f729Sjoerg 
11067330f729Sjoerg   BumpPtrAllocator A;
11077330f729Sjoerg   StringSaver Saver(A);
11087330f729Sjoerg   addPltEntries(Obj, AllSymbols, Saver);
11097330f729Sjoerg 
1110*82d56013Sjoerg   // Create a mapping from virtual address to section. An empty section can
1111*82d56013Sjoerg   // cause more than one section at the same address. Sort such sections to be
1112*82d56013Sjoerg   // before same-addressed non-empty sections so that symbol lookups prefer the
1113*82d56013Sjoerg   // non-empty section.
11147330f729Sjoerg   std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;
11157330f729Sjoerg   for (SectionRef Sec : Obj->sections())
11167330f729Sjoerg     SectionAddresses.emplace_back(Sec.getAddress(), Sec);
1117*82d56013Sjoerg   llvm::stable_sort(SectionAddresses, [](const auto &LHS, const auto &RHS) {
1118*82d56013Sjoerg     if (LHS.first != RHS.first)
1119*82d56013Sjoerg       return LHS.first < RHS.first;
1120*82d56013Sjoerg     return LHS.second.getSize() < RHS.second.getSize();
1121*82d56013Sjoerg   });
11227330f729Sjoerg 
11237330f729Sjoerg   // Linked executables (.exe and .dll files) typically don't include a real
11247330f729Sjoerg   // symbol table but they might contain an export table.
11257330f729Sjoerg   if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {
11267330f729Sjoerg     for (const auto &ExportEntry : COFFObj->export_directories()) {
11277330f729Sjoerg       StringRef Name;
1128*82d56013Sjoerg       if (Error E = ExportEntry.getSymbolName(Name))
1129*82d56013Sjoerg         reportError(std::move(E), Obj->getFileName());
11307330f729Sjoerg       if (Name.empty())
11317330f729Sjoerg         continue;
11327330f729Sjoerg 
11337330f729Sjoerg       uint32_t RVA;
1134*82d56013Sjoerg       if (Error E = ExportEntry.getExportRVA(RVA))
1135*82d56013Sjoerg         reportError(std::move(E), Obj->getFileName());
11367330f729Sjoerg 
11377330f729Sjoerg       uint64_t VA = COFFObj->getImageBase() + RVA;
11387330f729Sjoerg       auto Sec = partition_point(
11397330f729Sjoerg           SectionAddresses, [VA](const std::pair<uint64_t, SectionRef> &O) {
11407330f729Sjoerg             return O.first <= VA;
11417330f729Sjoerg           });
11427330f729Sjoerg       if (Sec != SectionAddresses.begin()) {
11437330f729Sjoerg         --Sec;
11447330f729Sjoerg         AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE);
11457330f729Sjoerg       } else
11467330f729Sjoerg         AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE);
11477330f729Sjoerg     }
11487330f729Sjoerg   }
11497330f729Sjoerg 
11507330f729Sjoerg   // Sort all the symbols, this allows us to use a simple binary search to find
1151*82d56013Sjoerg   // Multiple symbols can have the same address. Use a stable sort to stabilize
1152*82d56013Sjoerg   // the output.
1153*82d56013Sjoerg   StringSet<> FoundDisasmSymbolSet;
11547330f729Sjoerg   for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
1155*82d56013Sjoerg     llvm::stable_sort(SecSyms.second);
1156*82d56013Sjoerg   llvm::stable_sort(AbsoluteSymbols);
1157*82d56013Sjoerg 
1158*82d56013Sjoerg   std::unique_ptr<DWARFContext> DICtx;
1159*82d56013Sjoerg   LiveVariablePrinter LVP(*Ctx.getRegisterInfo(), *STI);
1160*82d56013Sjoerg 
1161*82d56013Sjoerg   if (DbgVariables != DVDisabled) {
1162*82d56013Sjoerg     DICtx = DWARFContext::create(*Obj);
1163*82d56013Sjoerg     for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
1164*82d56013Sjoerg       LVP.addCompileUnit(CU->getUnitDIE(false));
1165*82d56013Sjoerg   }
1166*82d56013Sjoerg 
1167*82d56013Sjoerg   LLVM_DEBUG(LVP.dump());
11687330f729Sjoerg 
11697330f729Sjoerg   for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
11707330f729Sjoerg     if (FilterSections.empty() && !DisassembleAll &&
11717330f729Sjoerg         (!Section.isText() || Section.isVirtual()))
11727330f729Sjoerg       continue;
11737330f729Sjoerg 
11747330f729Sjoerg     uint64_t SectionAddr = Section.getAddress();
11757330f729Sjoerg     uint64_t SectSize = Section.getSize();
11767330f729Sjoerg     if (!SectSize)
11777330f729Sjoerg       continue;
11787330f729Sjoerg 
11797330f729Sjoerg     // Get the list of all the symbols in this section.
11807330f729Sjoerg     SectionSymbolsTy &Symbols = AllSymbols[Section];
11817330f729Sjoerg     std::vector<MappingSymbolPair> MappingSymbols;
11827330f729Sjoerg     if (hasMappingSymbols(Obj)) {
11837330f729Sjoerg       for (const auto &Symb : Symbols) {
1184*82d56013Sjoerg         uint64_t Address = Symb.Addr;
1185*82d56013Sjoerg         StringRef Name = Symb.Name;
11867330f729Sjoerg         if (Name.startswith("$d"))
11877330f729Sjoerg           MappingSymbols.emplace_back(Address - SectionAddr, 'd');
11887330f729Sjoerg         if (Name.startswith("$x"))
11897330f729Sjoerg           MappingSymbols.emplace_back(Address - SectionAddr, 'x');
11907330f729Sjoerg         if (Name.startswith("$a"))
11917330f729Sjoerg           MappingSymbols.emplace_back(Address - SectionAddr, 'a');
11927330f729Sjoerg         if (Name.startswith("$t"))
11937330f729Sjoerg           MappingSymbols.emplace_back(Address - SectionAddr, 't');
11947330f729Sjoerg       }
11957330f729Sjoerg     }
11967330f729Sjoerg 
11977330f729Sjoerg     llvm::sort(MappingSymbols);
11987330f729Sjoerg 
1199*82d56013Sjoerg     ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
1200*82d56013Sjoerg         unwrapOrError(Section.getContents(), Obj->getFileName()));
1201*82d56013Sjoerg 
1202*82d56013Sjoerg     std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;
12037330f729Sjoerg     if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
12047330f729Sjoerg       // AMDGPU disassembler uses symbolizer for printing labels
1205*82d56013Sjoerg       addSymbolizer(Ctx, TheTarget, TripleName, DisAsm, SectionAddr, Bytes,
1206*82d56013Sjoerg                     Symbols, SynthesizedLabelNames);
12077330f729Sjoerg     }
12087330f729Sjoerg 
1209*82d56013Sjoerg     StringRef SegmentName = getSegmentName(MachO, Section);
12107330f729Sjoerg     StringRef SectionName = unwrapOrError(Section.getName(), Obj->getFileName());
12117330f729Sjoerg     // If the section has no symbol at the start, just insert a dummy one.
1212*82d56013Sjoerg     if (Symbols.empty() || Symbols[0].Addr != 0) {
1213*82d56013Sjoerg       Symbols.insert(Symbols.begin(),
1214*82d56013Sjoerg                      createDummySymbolInfo(Obj, SectionAddr, SectionName,
1215*82d56013Sjoerg                                            Section.isText() ? ELF::STT_FUNC
1216*82d56013Sjoerg                                                             : ELF::STT_OBJECT));
12177330f729Sjoerg     }
12187330f729Sjoerg 
12197330f729Sjoerg     SmallString<40> Comments;
12207330f729Sjoerg     raw_svector_ostream CommentStream(Comments);
12217330f729Sjoerg 
12227330f729Sjoerg     uint64_t VMAAdjustment = 0;
12237330f729Sjoerg     if (shouldAdjustVA(Section))
12247330f729Sjoerg       VMAAdjustment = AdjustVMA;
12257330f729Sjoerg 
12267330f729Sjoerg     uint64_t Size;
12277330f729Sjoerg     uint64_t Index;
12287330f729Sjoerg     bool PrintedSection = false;
12297330f729Sjoerg     std::vector<RelocationRef> Rels = RelocMap[Section];
12307330f729Sjoerg     std::vector<RelocationRef>::const_iterator RelCur = Rels.begin();
12317330f729Sjoerg     std::vector<RelocationRef>::const_iterator RelEnd = Rels.end();
12327330f729Sjoerg     // Disassemble symbol by symbol.
12337330f729Sjoerg     for (unsigned SI = 0, SE = Symbols.size(); SI != SE; ++SI) {
1234*82d56013Sjoerg       std::string SymbolName = Symbols[SI].Name.str();
12357330f729Sjoerg       if (Demangle)
12367330f729Sjoerg         SymbolName = demangle(SymbolName);
12377330f729Sjoerg 
1238*82d56013Sjoerg       // Skip if --disassemble-symbols is not empty and the symbol is not in
12397330f729Sjoerg       // the list.
1240*82d56013Sjoerg       if (!DisasmSymbolSet.empty() && !DisasmSymbolSet.count(SymbolName))
12417330f729Sjoerg         continue;
12427330f729Sjoerg 
1243*82d56013Sjoerg       uint64_t Start = Symbols[SI].Addr;
12447330f729Sjoerg       if (Start < SectionAddr || StopAddress <= Start)
12457330f729Sjoerg         continue;
12467330f729Sjoerg       else
1247*82d56013Sjoerg         FoundDisasmSymbolSet.insert(SymbolName);
12487330f729Sjoerg 
12497330f729Sjoerg       // The end is the section end, the beginning of the next symbol, or
12507330f729Sjoerg       // --stop-address.
12517330f729Sjoerg       uint64_t End = std::min<uint64_t>(SectionAddr + SectSize, StopAddress);
12527330f729Sjoerg       if (SI + 1 < SE)
1253*82d56013Sjoerg         End = std::min(End, Symbols[SI + 1].Addr);
12547330f729Sjoerg       if (Start >= End || End <= StartAddress)
12557330f729Sjoerg         continue;
12567330f729Sjoerg       Start -= SectionAddr;
12577330f729Sjoerg       End -= SectionAddr;
12587330f729Sjoerg 
12597330f729Sjoerg       if (!PrintedSection) {
12607330f729Sjoerg         PrintedSection = true;
12617330f729Sjoerg         outs() << "\nDisassembly of section ";
12627330f729Sjoerg         if (!SegmentName.empty())
12637330f729Sjoerg           outs() << SegmentName << ",";
12647330f729Sjoerg         outs() << SectionName << ":\n";
12657330f729Sjoerg       }
12667330f729Sjoerg 
12677330f729Sjoerg       outs() << '\n';
1268*82d56013Sjoerg       if (LeadingAddr)
12697330f729Sjoerg         outs() << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
12707330f729Sjoerg                          SectionAddr + Start + VMAAdjustment);
1271*82d56013Sjoerg       if (Obj->isXCOFF() && SymbolDescription) {
1272*82d56013Sjoerg         outs() << getXCOFFSymbolDescription(Symbols[SI], SymbolName) << ":\n";
1273*82d56013Sjoerg       } else
1274*82d56013Sjoerg         outs() << '<' << SymbolName << ">:\n";
12757330f729Sjoerg 
12767330f729Sjoerg       // Don't print raw contents of a virtual section. A virtual section
12777330f729Sjoerg       // doesn't have any contents in the file.
12787330f729Sjoerg       if (Section.isVirtual()) {
12797330f729Sjoerg         outs() << "...\n";
12807330f729Sjoerg         continue;
12817330f729Sjoerg       }
12827330f729Sjoerg 
1283*82d56013Sjoerg       auto Status = DisAsm->onSymbolStart(Symbols[SI], Size,
1284*82d56013Sjoerg                                           Bytes.slice(Start, End - Start),
1285*82d56013Sjoerg                                           SectionAddr + Start, CommentStream);
1286*82d56013Sjoerg       // To have round trippable disassembly, we fall back to decoding the
1287*82d56013Sjoerg       // remaining bytes as instructions.
1288*82d56013Sjoerg       //
1289*82d56013Sjoerg       // If there is a failure, we disassemble the failed region as bytes before
1290*82d56013Sjoerg       // falling back. The target is expected to print nothing in this case.
1291*82d56013Sjoerg       //
1292*82d56013Sjoerg       // If there is Success or SoftFail i.e no 'real' failure, we go ahead by
1293*82d56013Sjoerg       // Size bytes before falling back.
1294*82d56013Sjoerg       // So if the entire symbol is 'eaten' by the target:
1295*82d56013Sjoerg       //   Start += Size  // Now Start = End and we will never decode as
1296*82d56013Sjoerg       //                  // instructions
1297*82d56013Sjoerg       //
1298*82d56013Sjoerg       // Right now, most targets return None i.e ignore to treat a symbol
1299*82d56013Sjoerg       // separately. But WebAssembly decodes preludes for some symbols.
1300*82d56013Sjoerg       //
1301*82d56013Sjoerg       if (Status.hasValue()) {
1302*82d56013Sjoerg         if (Status.getValue() == MCDisassembler::Fail) {
1303*82d56013Sjoerg           outs() << "// Error in decoding " << SymbolName
1304*82d56013Sjoerg                  << " : Decoding failed region as bytes.\n";
1305*82d56013Sjoerg           for (uint64_t I = 0; I < Size; ++I) {
1306*82d56013Sjoerg             outs() << "\t.byte\t " << format_hex(Bytes[I], 1, /*Upper=*/true)
1307*82d56013Sjoerg                    << "\n";
1308*82d56013Sjoerg           }
1309*82d56013Sjoerg         }
1310*82d56013Sjoerg       } else {
1311*82d56013Sjoerg         Size = 0;
1312*82d56013Sjoerg       }
13137330f729Sjoerg 
13147330f729Sjoerg       Start += Size;
13157330f729Sjoerg 
13167330f729Sjoerg       Index = Start;
13177330f729Sjoerg       if (SectionAddr < StartAddress)
13187330f729Sjoerg         Index = std::max<uint64_t>(Index, StartAddress - SectionAddr);
13197330f729Sjoerg 
13207330f729Sjoerg       // If there is a data/common symbol inside an ELF text section and we are
13217330f729Sjoerg       // only disassembling text (applicable all architectures), we are in a
13227330f729Sjoerg       // situation where we must print the data and not disassemble it.
13237330f729Sjoerg       if (Obj->isELF() && !DisassembleAll && Section.isText()) {
1324*82d56013Sjoerg         uint8_t SymTy = Symbols[SI].Type;
13257330f729Sjoerg         if (SymTy == ELF::STT_OBJECT || SymTy == ELF::STT_COMMON) {
13267330f729Sjoerg           dumpELFData(SectionAddr, Index, End, Bytes);
13277330f729Sjoerg           Index = End;
13287330f729Sjoerg         }
13297330f729Sjoerg       }
13307330f729Sjoerg 
13317330f729Sjoerg       bool CheckARMELFData = hasMappingSymbols(Obj) &&
1332*82d56013Sjoerg                              Symbols[SI].Type != ELF::STT_OBJECT &&
13337330f729Sjoerg                              !DisassembleAll;
1334*82d56013Sjoerg       bool DumpARMELFData = false;
1335*82d56013Sjoerg       formatted_raw_ostream FOS(outs());
1336*82d56013Sjoerg 
1337*82d56013Sjoerg       std::unordered_map<uint64_t, std::string> AllLabels;
1338*82d56013Sjoerg       if (SymbolizeOperands)
1339*82d56013Sjoerg         collectLocalBranchTargets(Bytes, MIA, DisAsm, IP, PrimarySTI,
1340*82d56013Sjoerg                                   SectionAddr, Index, End, AllLabels);
1341*82d56013Sjoerg 
13427330f729Sjoerg       while (Index < End) {
13437330f729Sjoerg         // ARM and AArch64 ELF binaries can interleave data and text in the
13447330f729Sjoerg         // same section. We rely on the markers introduced to understand what
13457330f729Sjoerg         // we need to dump. If the data marker is within a function, it is
13467330f729Sjoerg         // denoted as a word/short etc.
1347*82d56013Sjoerg         if (CheckARMELFData) {
1348*82d56013Sjoerg           char Kind = getMappingSymbolKind(MappingSymbols, Index);
1349*82d56013Sjoerg           DumpARMELFData = Kind == 'd';
1350*82d56013Sjoerg           if (SecondarySTI) {
1351*82d56013Sjoerg             if (Kind == 'a') {
1352*82d56013Sjoerg               STI = PrimaryIsThumb ? SecondarySTI : PrimarySTI;
1353*82d56013Sjoerg               DisAsm = PrimaryIsThumb ? SecondaryDisAsm : PrimaryDisAsm;
1354*82d56013Sjoerg             } else if (Kind == 't') {
1355*82d56013Sjoerg               STI = PrimaryIsThumb ? PrimarySTI : SecondarySTI;
1356*82d56013Sjoerg               DisAsm = PrimaryIsThumb ? PrimaryDisAsm : SecondaryDisAsm;
1357*82d56013Sjoerg             }
1358*82d56013Sjoerg           }
13597330f729Sjoerg         }
13607330f729Sjoerg 
1361*82d56013Sjoerg         if (DumpARMELFData) {
1362*82d56013Sjoerg           Size = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,
1363*82d56013Sjoerg                                 MappingSymbols, FOS);
1364*82d56013Sjoerg         } else {
13657330f729Sjoerg           // When -z or --disassemble-zeroes are given we always dissasemble
13667330f729Sjoerg           // them. Otherwise we might want to skip zero bytes we see.
13677330f729Sjoerg           if (!DisassembleZeroes) {
13687330f729Sjoerg             uint64_t MaxOffset = End - Index;
1369*82d56013Sjoerg             // For --reloc: print zero blocks patched by relocations, so that
13707330f729Sjoerg             // relocations can be shown in the dump.
13717330f729Sjoerg             if (RelCur != RelEnd)
13727330f729Sjoerg               MaxOffset = RelCur->getOffset() - Index;
13737330f729Sjoerg 
13747330f729Sjoerg             if (size_t N =
13757330f729Sjoerg                     countSkippableZeroBytes(Bytes.slice(Index, MaxOffset))) {
1376*82d56013Sjoerg               FOS << "\t\t..." << '\n';
13777330f729Sjoerg               Index += N;
13787330f729Sjoerg               continue;
13797330f729Sjoerg             }
13807330f729Sjoerg           }
13817330f729Sjoerg 
1382*82d56013Sjoerg           // Print local label if there's any.
1383*82d56013Sjoerg           auto Iter = AllLabels.find(SectionAddr + Index);
1384*82d56013Sjoerg           if (Iter != AllLabels.end())
1385*82d56013Sjoerg             FOS << "<" << Iter->second << ">:\n";
13867330f729Sjoerg 
13877330f729Sjoerg           // Disassemble a real instruction or a data when disassemble all is
13887330f729Sjoerg           // provided
13897330f729Sjoerg           MCInst Inst;
1390*82d56013Sjoerg           bool Disassembled =
1391*82d56013Sjoerg               DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
1392*82d56013Sjoerg                                      SectionAddr + Index, CommentStream);
13937330f729Sjoerg           if (Size == 0)
13947330f729Sjoerg             Size = 1;
13957330f729Sjoerg 
1396*82d56013Sjoerg           LVP.update({Index, Section.getIndex()},
1397*82d56013Sjoerg                      {Index + Size, Section.getIndex()}, Index + Size != End);
1398*82d56013Sjoerg 
1399*82d56013Sjoerg           PIP.printInst(
1400*82d56013Sjoerg               *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size),
1401*82d56013Sjoerg               {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
1402*82d56013Sjoerg               "", *STI, &SP, Obj->getFileName(), &Rels, LVP);
1403*82d56013Sjoerg           FOS << CommentStream.str();
14047330f729Sjoerg           Comments.clear();
14057330f729Sjoerg 
1406*82d56013Sjoerg           // If disassembly has failed, avoid analysing invalid/incomplete
1407*82d56013Sjoerg           // instruction information. Otherwise, try to resolve the target
1408*82d56013Sjoerg           // address (jump target or memory operand address) and print it on the
1409*82d56013Sjoerg           // right of the instruction.
1410*82d56013Sjoerg           if (Disassembled && MIA) {
14117330f729Sjoerg             uint64_t Target;
1412*82d56013Sjoerg             bool PrintTarget =
1413*82d56013Sjoerg                 MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target);
1414*82d56013Sjoerg             if (!PrintTarget)
1415*82d56013Sjoerg               if (Optional<uint64_t> MaybeTarget =
1416*82d56013Sjoerg                       MIA->evaluateMemoryOperandAddress(
1417*82d56013Sjoerg                           Inst, SectionAddr + Index, Size)) {
1418*82d56013Sjoerg                 Target = *MaybeTarget;
1419*82d56013Sjoerg                 PrintTarget = true;
1420*82d56013Sjoerg                 // Do not print real address when symbolizing.
1421*82d56013Sjoerg                 if (!SymbolizeOperands)
1422*82d56013Sjoerg                   FOS << "  # " << Twine::utohexstr(Target);
1423*82d56013Sjoerg               }
1424*82d56013Sjoerg             if (PrintTarget) {
14257330f729Sjoerg               // In a relocatable object, the target's section must reside in
14267330f729Sjoerg               // the same section as the call instruction or it is accessed
14277330f729Sjoerg               // through a relocation.
14287330f729Sjoerg               //
14297330f729Sjoerg               // In a non-relocatable object, the target may be in any section.
1430*82d56013Sjoerg               // In that case, locate the section(s) containing the target
1431*82d56013Sjoerg               // address and find the symbol in one of those, if possible.
14327330f729Sjoerg               //
14337330f729Sjoerg               // N.B. We don't walk the relocations in the relocatable case yet.
1434*82d56013Sjoerg               std::vector<const SectionSymbolsTy *> TargetSectionSymbols;
14357330f729Sjoerg               if (!Obj->isRelocatableObject()) {
1436*82d56013Sjoerg                 auto It = llvm::partition_point(
14377330f729Sjoerg                     SectionAddresses,
14387330f729Sjoerg                     [=](const std::pair<uint64_t, SectionRef> &O) {
14397330f729Sjoerg                       return O.first <= Target;
14407330f729Sjoerg                     });
1441*82d56013Sjoerg                 uint64_t TargetSecAddr = 0;
1442*82d56013Sjoerg                 while (It != SectionAddresses.begin()) {
14437330f729Sjoerg                   --It;
1444*82d56013Sjoerg                   if (TargetSecAddr == 0)
1445*82d56013Sjoerg                     TargetSecAddr = It->first;
1446*82d56013Sjoerg                   if (It->first != TargetSecAddr)
1447*82d56013Sjoerg                     break;
1448*82d56013Sjoerg                   TargetSectionSymbols.push_back(&AllSymbols[It->second]);
1449*82d56013Sjoerg                 }
14507330f729Sjoerg               } else {
1451*82d56013Sjoerg                 TargetSectionSymbols.push_back(&Symbols);
1452*82d56013Sjoerg               }
1453*82d56013Sjoerg               TargetSectionSymbols.push_back(&AbsoluteSymbols);
1454*82d56013Sjoerg 
1455*82d56013Sjoerg               // Find the last symbol in the first candidate section whose
1456*82d56013Sjoerg               // offset is less than or equal to the target. If there are no
1457*82d56013Sjoerg               // such symbols, try in the next section and so on, before finally
1458*82d56013Sjoerg               // using the nearest preceding absolute symbol (if any), if there
1459*82d56013Sjoerg               // are no other valid symbols.
1460*82d56013Sjoerg               const SymbolInfoTy *TargetSym = nullptr;
1461*82d56013Sjoerg               for (const SectionSymbolsTy *TargetSymbols :
1462*82d56013Sjoerg                    TargetSectionSymbols) {
1463*82d56013Sjoerg                 auto It = llvm::partition_point(
1464*82d56013Sjoerg                     *TargetSymbols,
1465*82d56013Sjoerg                     [=](const SymbolInfoTy &O) { return O.Addr <= Target; });
1466*82d56013Sjoerg                 if (It != TargetSymbols->begin()) {
1467*82d56013Sjoerg                   TargetSym = &*(It - 1);
1468*82d56013Sjoerg                   break;
14697330f729Sjoerg                 }
14707330f729Sjoerg               }
14717330f729Sjoerg 
1472*82d56013Sjoerg               // Print the labels corresponding to the target if there's any.
1473*82d56013Sjoerg               bool LabelAvailable = AllLabels.count(Target);
1474*82d56013Sjoerg               if (TargetSym != nullptr) {
1475*82d56013Sjoerg                 uint64_t TargetAddress = TargetSym->Addr;
14767330f729Sjoerg                 uint64_t Disp = Target - TargetAddress;
1477*82d56013Sjoerg                 std::string TargetName = TargetSym->Name.str();
1478*82d56013Sjoerg                 if (Demangle)
1479*82d56013Sjoerg                   TargetName = demangle(TargetName);
1480*82d56013Sjoerg 
1481*82d56013Sjoerg                 FOS << " <";
1482*82d56013Sjoerg                 if (!Disp) {
1483*82d56013Sjoerg                   // Always Print the binary symbol precisely corresponding to
1484*82d56013Sjoerg                   // the target address.
1485*82d56013Sjoerg                   FOS << TargetName;
1486*82d56013Sjoerg                 } else if (!LabelAvailable) {
1487*82d56013Sjoerg                   // Always Print the binary symbol plus an offset if there's no
1488*82d56013Sjoerg                   // local label corresponding to the target address.
1489*82d56013Sjoerg                   FOS << TargetName << "+0x" << Twine::utohexstr(Disp);
1490*82d56013Sjoerg                 } else {
1491*82d56013Sjoerg                   FOS << AllLabels[Target];
1492*82d56013Sjoerg                 }
1493*82d56013Sjoerg                 FOS << ">";
1494*82d56013Sjoerg               } else if (LabelAvailable) {
1495*82d56013Sjoerg                 FOS << " <" << AllLabels[Target] << ">";
14967330f729Sjoerg               }
14977330f729Sjoerg             }
14987330f729Sjoerg           }
1499*82d56013Sjoerg         }
1500*82d56013Sjoerg 
1501*82d56013Sjoerg         LVP.printAfterInst(FOS);
1502*82d56013Sjoerg         FOS << "\n";
15037330f729Sjoerg 
15047330f729Sjoerg         // Hexagon does this in pretty printer
15057330f729Sjoerg         if (Obj->getArch() != Triple::hexagon) {
1506*82d56013Sjoerg           // Print relocation for instruction and data.
15077330f729Sjoerg           while (RelCur != RelEnd) {
15087330f729Sjoerg             uint64_t Offset = RelCur->getOffset();
15097330f729Sjoerg             // If this relocation is hidden, skip it.
15107330f729Sjoerg             if (getHidden(*RelCur) || SectionAddr + Offset < StartAddress) {
15117330f729Sjoerg               ++RelCur;
15127330f729Sjoerg               continue;
15137330f729Sjoerg             }
15147330f729Sjoerg 
1515*82d56013Sjoerg             // Stop when RelCur's offset is past the disassembled
1516*82d56013Sjoerg             // instruction/data. Note that it's possible the disassembled data
1517*82d56013Sjoerg             // is not the complete data: we might see the relocation printed in
1518*82d56013Sjoerg             // the middle of the data, but this matches the binutils objdump
1519*82d56013Sjoerg             // output.
15207330f729Sjoerg             if (Offset >= Index + Size)
15217330f729Sjoerg               break;
15227330f729Sjoerg 
15237330f729Sjoerg             // When --adjust-vma is used, update the address printed.
15247330f729Sjoerg             if (RelCur->getSymbol() != Obj->symbol_end()) {
15257330f729Sjoerg               Expected<section_iterator> SymSI =
15267330f729Sjoerg                   RelCur->getSymbol()->getSection();
15277330f729Sjoerg               if (SymSI && *SymSI != Obj->section_end() &&
15287330f729Sjoerg                   shouldAdjustVA(**SymSI))
15297330f729Sjoerg                 Offset += AdjustVMA;
15307330f729Sjoerg             }
15317330f729Sjoerg 
1532*82d56013Sjoerg             printRelocation(FOS, Obj->getFileName(), *RelCur,
1533*82d56013Sjoerg                             SectionAddr + Offset, Is64Bits);
1534*82d56013Sjoerg             LVP.printAfterOtherLine(FOS, true);
15357330f729Sjoerg             ++RelCur;
15367330f729Sjoerg           }
15377330f729Sjoerg         }
15387330f729Sjoerg 
15397330f729Sjoerg         Index += Size;
15407330f729Sjoerg       }
15417330f729Sjoerg     }
15427330f729Sjoerg   }
1543*82d56013Sjoerg   StringSet<> MissingDisasmSymbolSet =
1544*82d56013Sjoerg       set_difference(DisasmSymbolSet, FoundDisasmSymbolSet);
1545*82d56013Sjoerg   for (StringRef Sym : MissingDisasmSymbolSet.keys())
1546*82d56013Sjoerg     reportWarning("failed to disassemble missing symbol " + Sym, FileName);
15477330f729Sjoerg }
15487330f729Sjoerg 
disassembleObject(const ObjectFile * Obj,bool InlineRelocs)15497330f729Sjoerg static void disassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
15507330f729Sjoerg   const Target *TheTarget = getTarget(Obj);
15517330f729Sjoerg 
15527330f729Sjoerg   // Package up features to be passed to target/subtarget
15537330f729Sjoerg   SubtargetFeatures Features = Obj->getFeatures();
15547330f729Sjoerg   if (!MAttrs.empty())
15557330f729Sjoerg     for (unsigned I = 0; I != MAttrs.size(); ++I)
15567330f729Sjoerg       Features.AddFeature(MAttrs[I]);
15577330f729Sjoerg 
15587330f729Sjoerg   std::unique_ptr<const MCRegisterInfo> MRI(
15597330f729Sjoerg       TheTarget->createMCRegInfo(TripleName));
15607330f729Sjoerg   if (!MRI)
15617330f729Sjoerg     reportError(Obj->getFileName(),
15627330f729Sjoerg                 "no register info for target " + TripleName);
15637330f729Sjoerg 
15647330f729Sjoerg   // Set up disassembler.
15657330f729Sjoerg   MCTargetOptions MCOptions;
15667330f729Sjoerg   std::unique_ptr<const MCAsmInfo> AsmInfo(
15677330f729Sjoerg       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
15687330f729Sjoerg   if (!AsmInfo)
15697330f729Sjoerg     reportError(Obj->getFileName(),
15707330f729Sjoerg                 "no assembly info for target " + TripleName);
1571*82d56013Sjoerg 
1572*82d56013Sjoerg   if (MCPU.empty())
1573*82d56013Sjoerg     MCPU = Obj->tryGetCPUName().getValueOr("").str();
1574*82d56013Sjoerg 
15757330f729Sjoerg   std::unique_ptr<const MCSubtargetInfo> STI(
15767330f729Sjoerg       TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
15777330f729Sjoerg   if (!STI)
15787330f729Sjoerg     reportError(Obj->getFileName(),
15797330f729Sjoerg                 "no subtarget info for target " + TripleName);
15807330f729Sjoerg   std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
15817330f729Sjoerg   if (!MII)
15827330f729Sjoerg     reportError(Obj->getFileName(),
15837330f729Sjoerg                 "no instruction info for target " + TripleName);
1584*82d56013Sjoerg   MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
15857330f729Sjoerg   // FIXME: for now initialize MCObjectFileInfo with default values
1586*82d56013Sjoerg   std::unique_ptr<MCObjectFileInfo> MOFI(
1587*82d56013Sjoerg       TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
1588*82d56013Sjoerg   Ctx.setObjectFileInfo(MOFI.get());
15897330f729Sjoerg 
15907330f729Sjoerg   std::unique_ptr<MCDisassembler> DisAsm(
15917330f729Sjoerg       TheTarget->createMCDisassembler(*STI, Ctx));
15927330f729Sjoerg   if (!DisAsm)
15937330f729Sjoerg     reportError(Obj->getFileName(), "no disassembler for target " + TripleName);
15947330f729Sjoerg 
15957330f729Sjoerg   // If we have an ARM object file, we need a second disassembler, because
15967330f729Sjoerg   // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
15977330f729Sjoerg   // We use mapping symbols to switch between the two assemblers, where
15987330f729Sjoerg   // appropriate.
15997330f729Sjoerg   std::unique_ptr<MCDisassembler> SecondaryDisAsm;
16007330f729Sjoerg   std::unique_ptr<const MCSubtargetInfo> SecondarySTI;
16017330f729Sjoerg   if (isArmElf(Obj) && !STI->checkFeatures("+mclass")) {
16027330f729Sjoerg     if (STI->checkFeatures("+thumb-mode"))
16037330f729Sjoerg       Features.AddFeature("-thumb-mode");
16047330f729Sjoerg     else
16057330f729Sjoerg       Features.AddFeature("+thumb-mode");
16067330f729Sjoerg     SecondarySTI.reset(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
16077330f729Sjoerg                                                         Features.getString()));
16087330f729Sjoerg     SecondaryDisAsm.reset(TheTarget->createMCDisassembler(*SecondarySTI, Ctx));
16097330f729Sjoerg   }
16107330f729Sjoerg 
16117330f729Sjoerg   std::unique_ptr<const MCInstrAnalysis> MIA(
16127330f729Sjoerg       TheTarget->createMCInstrAnalysis(MII.get()));
16137330f729Sjoerg 
16147330f729Sjoerg   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
16157330f729Sjoerg   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
16167330f729Sjoerg       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
16177330f729Sjoerg   if (!IP)
16187330f729Sjoerg     reportError(Obj->getFileName(),
16197330f729Sjoerg                 "no instruction printer for target " + TripleName);
16207330f729Sjoerg   IP->setPrintImmHex(PrintImmHex);
1621*82d56013Sjoerg   IP->setPrintBranchImmAsAddress(true);
1622*82d56013Sjoerg   IP->setSymbolizeOperands(SymbolizeOperands);
1623*82d56013Sjoerg   IP->setMCInstrAnalysis(MIA.get());
16247330f729Sjoerg 
16257330f729Sjoerg   PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
16267330f729Sjoerg   SourcePrinter SP(Obj, TheTarget->getName());
16277330f729Sjoerg 
16287330f729Sjoerg   for (StringRef Opt : DisassemblerOptions)
16297330f729Sjoerg     if (!IP->applyTargetSpecificCLOption(Opt))
16307330f729Sjoerg       reportError(Obj->getFileName(),
16317330f729Sjoerg                   "Unrecognized disassembler option: " + Opt);
16327330f729Sjoerg 
16337330f729Sjoerg   disassembleObject(TheTarget, Obj, Ctx, DisAsm.get(), SecondaryDisAsm.get(),
16347330f729Sjoerg                     MIA.get(), IP.get(), STI.get(), SecondarySTI.get(), PIP,
16357330f729Sjoerg                     SP, InlineRelocs);
16367330f729Sjoerg }
16377330f729Sjoerg 
printRelocations(const ObjectFile * Obj)1638*82d56013Sjoerg void objdump::printRelocations(const ObjectFile *Obj) {
16397330f729Sjoerg   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
16407330f729Sjoerg                                                  "%08" PRIx64;
16417330f729Sjoerg   // Regular objdump doesn't print relocations in non-relocatable object
16427330f729Sjoerg   // files.
16437330f729Sjoerg   if (!Obj->isRelocatableObject())
16447330f729Sjoerg     return;
16457330f729Sjoerg 
16467330f729Sjoerg   // Build a mapping from relocation target to a vector of relocation
16477330f729Sjoerg   // sections. Usually, there is an only one relocation section for
16487330f729Sjoerg   // each relocated section.
16497330f729Sjoerg   MapVector<SectionRef, std::vector<SectionRef>> SecToRelSec;
16507330f729Sjoerg   uint64_t Ndx;
16517330f729Sjoerg   for (const SectionRef &Section : ToolSectionFilter(*Obj, &Ndx)) {
16527330f729Sjoerg     if (Section.relocation_begin() == Section.relocation_end())
16537330f729Sjoerg       continue;
16547330f729Sjoerg     Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
16557330f729Sjoerg     if (!SecOrErr)
16567330f729Sjoerg       reportError(Obj->getFileName(),
16577330f729Sjoerg                   "section (" + Twine(Ndx) +
16587330f729Sjoerg                       "): unable to get a relocation target: " +
16597330f729Sjoerg                       toString(SecOrErr.takeError()));
16607330f729Sjoerg     SecToRelSec[**SecOrErr].push_back(Section);
16617330f729Sjoerg   }
16627330f729Sjoerg 
16637330f729Sjoerg   for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {
16647330f729Sjoerg     StringRef SecName = unwrapOrError(P.first.getName(), Obj->getFileName());
1665*82d56013Sjoerg     outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";
1666*82d56013Sjoerg     uint32_t OffsetPadding = (Obj->getBytesInAddress() > 4 ? 16 : 8);
1667*82d56013Sjoerg     uint32_t TypePadding = 24;
1668*82d56013Sjoerg     outs() << left_justify("OFFSET", OffsetPadding) << " "
1669*82d56013Sjoerg            << left_justify("TYPE", TypePadding) << " "
1670*82d56013Sjoerg            << "VALUE\n";
16717330f729Sjoerg 
16727330f729Sjoerg     for (SectionRef Section : P.second) {
16737330f729Sjoerg       for (const RelocationRef &Reloc : Section.relocations()) {
16747330f729Sjoerg         uint64_t Address = Reloc.getOffset();
16757330f729Sjoerg         SmallString<32> RelocName;
16767330f729Sjoerg         SmallString<32> ValueStr;
16777330f729Sjoerg         if (Address < StartAddress || Address > StopAddress || getHidden(Reloc))
16787330f729Sjoerg           continue;
16797330f729Sjoerg         Reloc.getTypeName(RelocName);
16807330f729Sjoerg         if (Error E = getRelocationValueString(Reloc, ValueStr))
16817330f729Sjoerg           reportError(std::move(E), Obj->getFileName());
16827330f729Sjoerg 
1683*82d56013Sjoerg         outs() << format(Fmt.data(), Address) << " "
1684*82d56013Sjoerg                << left_justify(RelocName, TypePadding) << " " << ValueStr
1685*82d56013Sjoerg                << "\n";
16867330f729Sjoerg       }
16877330f729Sjoerg     }
16887330f729Sjoerg   }
16897330f729Sjoerg }
16907330f729Sjoerg 
printDynamicRelocations(const ObjectFile * Obj)1691*82d56013Sjoerg void objdump::printDynamicRelocations(const ObjectFile *Obj) {
16927330f729Sjoerg   // For the moment, this option is for ELF only
16937330f729Sjoerg   if (!Obj->isELF())
16947330f729Sjoerg     return;
16957330f729Sjoerg 
16967330f729Sjoerg   const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
16977330f729Sjoerg   if (!Elf || Elf->getEType() != ELF::ET_DYN) {
16987330f729Sjoerg     reportError(Obj->getFileName(), "not a dynamic object");
16997330f729Sjoerg     return;
17007330f729Sjoerg   }
17017330f729Sjoerg 
17027330f729Sjoerg   std::vector<SectionRef> DynRelSec = Obj->dynamic_relocation_sections();
17037330f729Sjoerg   if (DynRelSec.empty())
17047330f729Sjoerg     return;
17057330f729Sjoerg 
17067330f729Sjoerg   outs() << "DYNAMIC RELOCATION RECORDS\n";
17077330f729Sjoerg   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
17087330f729Sjoerg   for (const SectionRef &Section : DynRelSec)
17097330f729Sjoerg     for (const RelocationRef &Reloc : Section.relocations()) {
17107330f729Sjoerg       uint64_t Address = Reloc.getOffset();
17117330f729Sjoerg       SmallString<32> RelocName;
17127330f729Sjoerg       SmallString<32> ValueStr;
17137330f729Sjoerg       Reloc.getTypeName(RelocName);
17147330f729Sjoerg       if (Error E = getRelocationValueString(Reloc, ValueStr))
17157330f729Sjoerg         reportError(std::move(E), Obj->getFileName());
17167330f729Sjoerg       outs() << format(Fmt.data(), Address) << " " << RelocName << " "
17177330f729Sjoerg              << ValueStr << "\n";
17187330f729Sjoerg     }
17197330f729Sjoerg }
17207330f729Sjoerg 
17217330f729Sjoerg // Returns true if we need to show LMA column when dumping section headers. We
17227330f729Sjoerg // show it only when the platform is ELF and either we have at least one section
17237330f729Sjoerg // whose VMA and LMA are different and/or when --show-lma flag is used.
shouldDisplayLMA(const ObjectFile * Obj)17247330f729Sjoerg static bool shouldDisplayLMA(const ObjectFile *Obj) {
17257330f729Sjoerg   if (!Obj->isELF())
17267330f729Sjoerg     return false;
17277330f729Sjoerg   for (const SectionRef &S : ToolSectionFilter(*Obj))
17287330f729Sjoerg     if (S.getAddress() != getELFSectionLMA(S))
17297330f729Sjoerg       return true;
17307330f729Sjoerg   return ShowLMA;
17317330f729Sjoerg }
17327330f729Sjoerg 
getMaxSectionNameWidth(const ObjectFile * Obj)17337330f729Sjoerg static size_t getMaxSectionNameWidth(const ObjectFile *Obj) {
17347330f729Sjoerg   // Default column width for names is 13 even if no names are that long.
17357330f729Sjoerg   size_t MaxWidth = 13;
17367330f729Sjoerg   for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
17377330f729Sjoerg     StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());
17387330f729Sjoerg     MaxWidth = std::max(MaxWidth, Name.size());
17397330f729Sjoerg   }
17407330f729Sjoerg   return MaxWidth;
17417330f729Sjoerg }
17427330f729Sjoerg 
printSectionHeaders(const ObjectFile * Obj)1743*82d56013Sjoerg void objdump::printSectionHeaders(const ObjectFile *Obj) {
17447330f729Sjoerg   size_t NameWidth = getMaxSectionNameWidth(Obj);
17457330f729Sjoerg   size_t AddressWidth = 2 * Obj->getBytesInAddress();
17467330f729Sjoerg   bool HasLMAColumn = shouldDisplayLMA(Obj);
1747*82d56013Sjoerg   outs() << "\nSections:\n";
17487330f729Sjoerg   if (HasLMAColumn)
1749*82d56013Sjoerg     outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
17507330f729Sjoerg            << left_justify("VMA", AddressWidth) << " "
17517330f729Sjoerg            << left_justify("LMA", AddressWidth) << " Type\n";
17527330f729Sjoerg   else
1753*82d56013Sjoerg     outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
17547330f729Sjoerg            << left_justify("VMA", AddressWidth) << " Type\n";
17557330f729Sjoerg 
17567330f729Sjoerg   uint64_t Idx;
17577330f729Sjoerg   for (const SectionRef &Section : ToolSectionFilter(*Obj, &Idx)) {
17587330f729Sjoerg     StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());
17597330f729Sjoerg     uint64_t VMA = Section.getAddress();
17607330f729Sjoerg     if (shouldAdjustVA(Section))
17617330f729Sjoerg       VMA += AdjustVMA;
17627330f729Sjoerg 
17637330f729Sjoerg     uint64_t Size = Section.getSize();
17647330f729Sjoerg 
17657330f729Sjoerg     std::string Type = Section.isText() ? "TEXT" : "";
17667330f729Sjoerg     if (Section.isData())
17677330f729Sjoerg       Type += Type.empty() ? "DATA" : " DATA";
17687330f729Sjoerg     if (Section.isBSS())
17697330f729Sjoerg       Type += Type.empty() ? "BSS" : " BSS";
17707330f729Sjoerg 
17717330f729Sjoerg     if (HasLMAColumn)
17727330f729Sjoerg       outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,
17737330f729Sjoerg                        Name.str().c_str(), Size)
17747330f729Sjoerg              << format_hex_no_prefix(VMA, AddressWidth) << " "
17757330f729Sjoerg              << format_hex_no_prefix(getELFSectionLMA(Section), AddressWidth)
17767330f729Sjoerg              << " " << Type << "\n";
17777330f729Sjoerg     else
17787330f729Sjoerg       outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,
17797330f729Sjoerg                        Name.str().c_str(), Size)
17807330f729Sjoerg              << format_hex_no_prefix(VMA, AddressWidth) << " " << Type << "\n";
17817330f729Sjoerg   }
17827330f729Sjoerg }
17837330f729Sjoerg 
printSectionContents(const ObjectFile * Obj)1784*82d56013Sjoerg void objdump::printSectionContents(const ObjectFile *Obj) {
1785*82d56013Sjoerg   const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj);
1786*82d56013Sjoerg 
17877330f729Sjoerg   for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
17887330f729Sjoerg     StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());
17897330f729Sjoerg     uint64_t BaseAddr = Section.getAddress();
17907330f729Sjoerg     uint64_t Size = Section.getSize();
17917330f729Sjoerg     if (!Size)
17927330f729Sjoerg       continue;
17937330f729Sjoerg 
1794*82d56013Sjoerg     outs() << "Contents of section ";
1795*82d56013Sjoerg     StringRef SegmentName = getSegmentName(MachO, Section);
1796*82d56013Sjoerg     if (!SegmentName.empty())
1797*82d56013Sjoerg       outs() << SegmentName << ",";
1798*82d56013Sjoerg     outs() << Name << ":\n";
17997330f729Sjoerg     if (Section.isBSS()) {
18007330f729Sjoerg       outs() << format("<skipping contents of bss section at [%04" PRIx64
18017330f729Sjoerg                        ", %04" PRIx64 ")>\n",
18027330f729Sjoerg                        BaseAddr, BaseAddr + Size);
18037330f729Sjoerg       continue;
18047330f729Sjoerg     }
18057330f729Sjoerg 
18067330f729Sjoerg     StringRef Contents = unwrapOrError(Section.getContents(), Obj->getFileName());
18077330f729Sjoerg 
18087330f729Sjoerg     // Dump out the content as hex and printable ascii characters.
18097330f729Sjoerg     for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {
18107330f729Sjoerg       outs() << format(" %04" PRIx64 " ", BaseAddr + Addr);
18117330f729Sjoerg       // Dump line of hex.
18127330f729Sjoerg       for (std::size_t I = 0; I < 16; ++I) {
18137330f729Sjoerg         if (I != 0 && I % 4 == 0)
18147330f729Sjoerg           outs() << ' ';
18157330f729Sjoerg         if (Addr + I < End)
18167330f729Sjoerg           outs() << hexdigit((Contents[Addr + I] >> 4) & 0xF, true)
18177330f729Sjoerg                  << hexdigit(Contents[Addr + I] & 0xF, true);
18187330f729Sjoerg         else
18197330f729Sjoerg           outs() << "  ";
18207330f729Sjoerg       }
18217330f729Sjoerg       // Print ascii.
18227330f729Sjoerg       outs() << "  ";
18237330f729Sjoerg       for (std::size_t I = 0; I < 16 && Addr + I < End; ++I) {
18247330f729Sjoerg         if (isPrint(static_cast<unsigned char>(Contents[Addr + I]) & 0xFF))
18257330f729Sjoerg           outs() << Contents[Addr + I];
18267330f729Sjoerg         else
18277330f729Sjoerg           outs() << ".";
18287330f729Sjoerg       }
18297330f729Sjoerg       outs() << "\n";
18307330f729Sjoerg     }
18317330f729Sjoerg   }
18327330f729Sjoerg }
18337330f729Sjoerg 
printSymbolTable(const ObjectFile * O,StringRef ArchiveName,StringRef ArchitectureName,bool DumpDynamic)1834*82d56013Sjoerg void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
1835*82d56013Sjoerg                                StringRef ArchitectureName, bool DumpDynamic) {
1836*82d56013Sjoerg   if (O->isCOFF() && !DumpDynamic) {
1837*82d56013Sjoerg     outs() << "\nSYMBOL TABLE:\n";
1838*82d56013Sjoerg     printCOFFSymbolTable(cast<const COFFObjectFile>(O));
18397330f729Sjoerg     return;
18407330f729Sjoerg   }
18417330f729Sjoerg 
18427330f729Sjoerg   const StringRef FileName = O->getFileName();
1843*82d56013Sjoerg 
1844*82d56013Sjoerg   if (!DumpDynamic) {
1845*82d56013Sjoerg     outs() << "\nSYMBOL TABLE:\n";
1846*82d56013Sjoerg     for (auto I = O->symbol_begin(); I != O->symbol_end(); ++I)
1847*82d56013Sjoerg       printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
1848*82d56013Sjoerg     return;
1849*82d56013Sjoerg   }
1850*82d56013Sjoerg 
1851*82d56013Sjoerg   outs() << "\nDYNAMIC SYMBOL TABLE:\n";
1852*82d56013Sjoerg   if (!O->isELF()) {
1853*82d56013Sjoerg     reportWarning(
1854*82d56013Sjoerg         "this operation is not currently supported for this file format",
1855*82d56013Sjoerg         FileName);
1856*82d56013Sjoerg     return;
1857*82d56013Sjoerg   }
1858*82d56013Sjoerg 
1859*82d56013Sjoerg   const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(O);
1860*82d56013Sjoerg   for (auto I = ELF->getDynamicSymbolIterators().begin();
1861*82d56013Sjoerg        I != ELF->getDynamicSymbolIterators().end(); ++I)
1862*82d56013Sjoerg     printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
1863*82d56013Sjoerg }
1864*82d56013Sjoerg 
printSymbol(const ObjectFile * O,const SymbolRef & Symbol,StringRef FileName,StringRef ArchiveName,StringRef ArchitectureName,bool DumpDynamic)1865*82d56013Sjoerg void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
1866*82d56013Sjoerg                           StringRef FileName, StringRef ArchiveName,
1867*82d56013Sjoerg                           StringRef ArchitectureName, bool DumpDynamic) {
1868*82d56013Sjoerg   const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
18697330f729Sjoerg   uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName, ArchiveName,
18707330f729Sjoerg                                    ArchitectureName);
18717330f729Sjoerg   if ((Address < StartAddress) || (Address > StopAddress))
1872*82d56013Sjoerg     return;
1873*82d56013Sjoerg   SymbolRef::Type Type =
1874*82d56013Sjoerg       unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName);
1875*82d56013Sjoerg   uint32_t Flags =
1876*82d56013Sjoerg       unwrapOrError(Symbol.getFlags(), FileName, ArchiveName, ArchitectureName);
1877*82d56013Sjoerg 
1878*82d56013Sjoerg   // Don't ask a Mach-O STAB symbol for its section unless you know that
1879*82d56013Sjoerg   // STAB symbol's section field refers to a valid section index. Otherwise
1880*82d56013Sjoerg   // the symbol may error trying to load a section that does not exist.
1881*82d56013Sjoerg   bool IsSTAB = false;
1882*82d56013Sjoerg   if (MachO) {
1883*82d56013Sjoerg     DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1884*82d56013Sjoerg     uint8_t NType =
1885*82d56013Sjoerg         (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
1886*82d56013Sjoerg                           : MachO->getSymbolTableEntry(SymDRI).n_type);
1887*82d56013Sjoerg     if (NType & MachO::N_STAB)
1888*82d56013Sjoerg       IsSTAB = true;
1889*82d56013Sjoerg   }
1890*82d56013Sjoerg   section_iterator Section = IsSTAB
1891*82d56013Sjoerg                                  ? O->section_end()
1892*82d56013Sjoerg                                  : unwrapOrError(Symbol.getSection(), FileName,
18937330f729Sjoerg                                                  ArchiveName, ArchitectureName);
1894*82d56013Sjoerg 
18957330f729Sjoerg   StringRef Name;
18967330f729Sjoerg   if (Type == SymbolRef::ST_Debug && Section != O->section_end()) {
18977330f729Sjoerg     if (Expected<StringRef> NameOrErr = Section->getName())
18987330f729Sjoerg       Name = *NameOrErr;
18997330f729Sjoerg     else
19007330f729Sjoerg       consumeError(NameOrErr.takeError());
19017330f729Sjoerg 
19027330f729Sjoerg   } else {
19037330f729Sjoerg     Name = unwrapOrError(Symbol.getName(), FileName, ArchiveName,
19047330f729Sjoerg                          ArchitectureName);
19057330f729Sjoerg   }
19067330f729Sjoerg 
19077330f729Sjoerg   bool Global = Flags & SymbolRef::SF_Global;
19087330f729Sjoerg   bool Weak = Flags & SymbolRef::SF_Weak;
19097330f729Sjoerg   bool Absolute = Flags & SymbolRef::SF_Absolute;
19107330f729Sjoerg   bool Common = Flags & SymbolRef::SF_Common;
19117330f729Sjoerg   bool Hidden = Flags & SymbolRef::SF_Hidden;
19127330f729Sjoerg 
19137330f729Sjoerg   char GlobLoc = ' ';
1914*82d56013Sjoerg   if ((Section != O->section_end() || Absolute) && !Weak)
19157330f729Sjoerg     GlobLoc = Global ? 'g' : 'l';
1916*82d56013Sjoerg   char IFunc = ' ';
1917*82d56013Sjoerg   if (O->isELF()) {
1918*82d56013Sjoerg     if (ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC)
1919*82d56013Sjoerg       IFunc = 'i';
1920*82d56013Sjoerg     if (ELFSymbolRef(Symbol).getBinding() == ELF::STB_GNU_UNIQUE)
1921*82d56013Sjoerg       GlobLoc = 'u';
1922*82d56013Sjoerg   }
1923*82d56013Sjoerg 
1924*82d56013Sjoerg   char Debug = ' ';
1925*82d56013Sjoerg   if (DumpDynamic)
1926*82d56013Sjoerg     Debug = 'D';
1927*82d56013Sjoerg   else if (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
1928*82d56013Sjoerg     Debug = 'd';
1929*82d56013Sjoerg 
19307330f729Sjoerg   char FileFunc = ' ';
19317330f729Sjoerg   if (Type == SymbolRef::ST_File)
19327330f729Sjoerg     FileFunc = 'f';
19337330f729Sjoerg   else if (Type == SymbolRef::ST_Function)
19347330f729Sjoerg     FileFunc = 'F';
19357330f729Sjoerg   else if (Type == SymbolRef::ST_Data)
19367330f729Sjoerg     FileFunc = 'O';
19377330f729Sjoerg 
1938*82d56013Sjoerg   const char *Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
19397330f729Sjoerg 
19407330f729Sjoerg   outs() << format(Fmt, Address) << " "
19417330f729Sjoerg          << GlobLoc            // Local -> 'l', Global -> 'g', Neither -> ' '
19427330f729Sjoerg          << (Weak ? 'w' : ' ') // Weak?
19437330f729Sjoerg          << ' '                // Constructor. Not supported yet.
19447330f729Sjoerg          << ' '                // Warning. Not supported yet.
1945*82d56013Sjoerg          << IFunc              // Indirect reference to another symbol.
19467330f729Sjoerg          << Debug              // Debugging (d) or dynamic (D) symbol.
19477330f729Sjoerg          << FileFunc           // Name of function (F), file (f) or object (O).
19487330f729Sjoerg          << ' ';
19497330f729Sjoerg   if (Absolute) {
19507330f729Sjoerg     outs() << "*ABS*";
19517330f729Sjoerg   } else if (Common) {
19527330f729Sjoerg     outs() << "*COM*";
19537330f729Sjoerg   } else if (Section == O->section_end()) {
19547330f729Sjoerg     outs() << "*UND*";
19557330f729Sjoerg   } else {
1956*82d56013Sjoerg     StringRef SegmentName = getSegmentName(MachO, *Section);
1957*82d56013Sjoerg     if (!SegmentName.empty())
19587330f729Sjoerg       outs() << SegmentName << ",";
1959*82d56013Sjoerg     StringRef SectionName = unwrapOrError(Section->getName(), FileName);
19607330f729Sjoerg     outs() << SectionName;
19617330f729Sjoerg   }
19627330f729Sjoerg 
1963*82d56013Sjoerg   if (Common || O->isELF()) {
19647330f729Sjoerg     uint64_t Val =
19657330f729Sjoerg         Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize();
1966*82d56013Sjoerg     outs() << '\t' << format(Fmt, Val);
19677330f729Sjoerg   }
19687330f729Sjoerg 
1969*82d56013Sjoerg   if (O->isELF()) {
19707330f729Sjoerg     uint8_t Other = ELFSymbolRef(Symbol).getOther();
19717330f729Sjoerg     switch (Other) {
19727330f729Sjoerg     case ELF::STV_DEFAULT:
19737330f729Sjoerg       break;
19747330f729Sjoerg     case ELF::STV_INTERNAL:
19757330f729Sjoerg       outs() << " .internal";
19767330f729Sjoerg       break;
19777330f729Sjoerg     case ELF::STV_HIDDEN:
19787330f729Sjoerg       outs() << " .hidden";
19797330f729Sjoerg       break;
19807330f729Sjoerg     case ELF::STV_PROTECTED:
19817330f729Sjoerg       outs() << " .protected";
19827330f729Sjoerg       break;
19837330f729Sjoerg     default:
19847330f729Sjoerg       outs() << format(" 0x%02x", Other);
19857330f729Sjoerg       break;
19867330f729Sjoerg     }
19877330f729Sjoerg   } else if (Hidden) {
19887330f729Sjoerg     outs() << " .hidden";
19897330f729Sjoerg   }
19907330f729Sjoerg 
19917330f729Sjoerg   if (Demangle)
1992*82d56013Sjoerg     outs() << ' ' << demangle(std::string(Name)) << '\n';
19937330f729Sjoerg   else
19947330f729Sjoerg     outs() << ' ' << Name << '\n';
19957330f729Sjoerg }
19967330f729Sjoerg 
printUnwindInfo(const ObjectFile * O)19977330f729Sjoerg static void printUnwindInfo(const ObjectFile *O) {
19987330f729Sjoerg   outs() << "Unwind info:\n\n";
19997330f729Sjoerg 
20007330f729Sjoerg   if (const COFFObjectFile *Coff = dyn_cast<COFFObjectFile>(O))
20017330f729Sjoerg     printCOFFUnwindInfo(Coff);
20027330f729Sjoerg   else if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O))
20037330f729Sjoerg     printMachOUnwindInfo(MachO);
20047330f729Sjoerg   else
20057330f729Sjoerg     // TODO: Extract DWARF dump tool to objdump.
20067330f729Sjoerg     WithColor::error(errs(), ToolName)
20077330f729Sjoerg         << "This operation is only currently supported "
20087330f729Sjoerg            "for COFF and MachO object files.\n";
20097330f729Sjoerg }
20107330f729Sjoerg 
20117330f729Sjoerg /// Dump the raw contents of the __clangast section so the output can be piped
20127330f729Sjoerg /// into llvm-bcanalyzer.
printRawClangAST(const ObjectFile * Obj)2013*82d56013Sjoerg static void printRawClangAST(const ObjectFile *Obj) {
20147330f729Sjoerg   if (outs().is_displayed()) {
20157330f729Sjoerg     WithColor::error(errs(), ToolName)
20167330f729Sjoerg         << "The -raw-clang-ast option will dump the raw binary contents of "
20177330f729Sjoerg            "the clang ast section.\n"
20187330f729Sjoerg            "Please redirect the output to a file or another program such as "
20197330f729Sjoerg            "llvm-bcanalyzer.\n";
20207330f729Sjoerg     return;
20217330f729Sjoerg   }
20227330f729Sjoerg 
20237330f729Sjoerg   StringRef ClangASTSectionName("__clangast");
2024*82d56013Sjoerg   if (Obj->isCOFF()) {
20257330f729Sjoerg     ClangASTSectionName = "clangast";
20267330f729Sjoerg   }
20277330f729Sjoerg 
20287330f729Sjoerg   Optional<object::SectionRef> ClangASTSection;
20297330f729Sjoerg   for (auto Sec : ToolSectionFilter(*Obj)) {
20307330f729Sjoerg     StringRef Name;
20317330f729Sjoerg     if (Expected<StringRef> NameOrErr = Sec.getName())
20327330f729Sjoerg       Name = *NameOrErr;
20337330f729Sjoerg     else
20347330f729Sjoerg       consumeError(NameOrErr.takeError());
20357330f729Sjoerg 
20367330f729Sjoerg     if (Name == ClangASTSectionName) {
20377330f729Sjoerg       ClangASTSection = Sec;
20387330f729Sjoerg       break;
20397330f729Sjoerg     }
20407330f729Sjoerg   }
20417330f729Sjoerg   if (!ClangASTSection)
20427330f729Sjoerg     return;
20437330f729Sjoerg 
20447330f729Sjoerg   StringRef ClangASTContents = unwrapOrError(
20457330f729Sjoerg       ClangASTSection.getValue().getContents(), Obj->getFileName());
20467330f729Sjoerg   outs().write(ClangASTContents.data(), ClangASTContents.size());
20477330f729Sjoerg }
20487330f729Sjoerg 
printFaultMaps(const ObjectFile * Obj)20497330f729Sjoerg static void printFaultMaps(const ObjectFile *Obj) {
20507330f729Sjoerg   StringRef FaultMapSectionName;
20517330f729Sjoerg 
2052*82d56013Sjoerg   if (Obj->isELF()) {
20537330f729Sjoerg     FaultMapSectionName = ".llvm_faultmaps";
2054*82d56013Sjoerg   } else if (Obj->isMachO()) {
20557330f729Sjoerg     FaultMapSectionName = "__llvm_faultmaps";
20567330f729Sjoerg   } else {
20577330f729Sjoerg     WithColor::error(errs(), ToolName)
20587330f729Sjoerg         << "This operation is only currently supported "
20597330f729Sjoerg            "for ELF and Mach-O executable files.\n";
20607330f729Sjoerg     return;
20617330f729Sjoerg   }
20627330f729Sjoerg 
20637330f729Sjoerg   Optional<object::SectionRef> FaultMapSection;
20647330f729Sjoerg 
20657330f729Sjoerg   for (auto Sec : ToolSectionFilter(*Obj)) {
20667330f729Sjoerg     StringRef Name;
20677330f729Sjoerg     if (Expected<StringRef> NameOrErr = Sec.getName())
20687330f729Sjoerg       Name = *NameOrErr;
20697330f729Sjoerg     else
20707330f729Sjoerg       consumeError(NameOrErr.takeError());
20717330f729Sjoerg 
20727330f729Sjoerg     if (Name == FaultMapSectionName) {
20737330f729Sjoerg       FaultMapSection = Sec;
20747330f729Sjoerg       break;
20757330f729Sjoerg     }
20767330f729Sjoerg   }
20777330f729Sjoerg 
20787330f729Sjoerg   outs() << "FaultMap table:\n";
20797330f729Sjoerg 
20807330f729Sjoerg   if (!FaultMapSection.hasValue()) {
20817330f729Sjoerg     outs() << "<not found>\n";
20827330f729Sjoerg     return;
20837330f729Sjoerg   }
20847330f729Sjoerg 
20857330f729Sjoerg   StringRef FaultMapContents =
20867330f729Sjoerg       unwrapOrError(FaultMapSection.getValue().getContents(), Obj->getFileName());
20877330f729Sjoerg   FaultMapParser FMP(FaultMapContents.bytes_begin(),
20887330f729Sjoerg                      FaultMapContents.bytes_end());
20897330f729Sjoerg 
20907330f729Sjoerg   outs() << FMP;
20917330f729Sjoerg }
20927330f729Sjoerg 
printPrivateFileHeaders(const ObjectFile * O,bool OnlyFirst)20937330f729Sjoerg static void printPrivateFileHeaders(const ObjectFile *O, bool OnlyFirst) {
20947330f729Sjoerg   if (O->isELF()) {
20957330f729Sjoerg     printELFFileHeader(O);
20967330f729Sjoerg     printELFDynamicSection(O);
20977330f729Sjoerg     printELFSymbolVersionInfo(O);
20987330f729Sjoerg     return;
20997330f729Sjoerg   }
21007330f729Sjoerg   if (O->isCOFF())
21017330f729Sjoerg     return printCOFFFileHeader(O);
21027330f729Sjoerg   if (O->isWasm())
21037330f729Sjoerg     return printWasmFileHeader(O);
21047330f729Sjoerg   if (O->isMachO()) {
21057330f729Sjoerg     printMachOFileHeader(O);
21067330f729Sjoerg     if (!OnlyFirst)
21077330f729Sjoerg       printMachOLoadCommands(O);
21087330f729Sjoerg     return;
21097330f729Sjoerg   }
21107330f729Sjoerg   reportError(O->getFileName(), "Invalid/Unsupported object file format");
21117330f729Sjoerg }
21127330f729Sjoerg 
printFileHeaders(const ObjectFile * O)21137330f729Sjoerg static void printFileHeaders(const ObjectFile *O) {
21147330f729Sjoerg   if (!O->isELF() && !O->isCOFF())
21157330f729Sjoerg     reportError(O->getFileName(), "Invalid/Unsupported object file format");
21167330f729Sjoerg 
21177330f729Sjoerg   Triple::ArchType AT = O->getArch();
21187330f729Sjoerg   outs() << "architecture: " << Triple::getArchTypeName(AT) << "\n";
21197330f729Sjoerg   uint64_t Address = unwrapOrError(O->getStartAddress(), O->getFileName());
21207330f729Sjoerg 
21217330f729Sjoerg   StringRef Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
21227330f729Sjoerg   outs() << "start address: "
2123*82d56013Sjoerg          << "0x" << format(Fmt.data(), Address) << "\n";
21247330f729Sjoerg }
21257330f729Sjoerg 
printArchiveChild(StringRef Filename,const Archive::Child & C)21267330f729Sjoerg static void printArchiveChild(StringRef Filename, const Archive::Child &C) {
21277330f729Sjoerg   Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
21287330f729Sjoerg   if (!ModeOrErr) {
21297330f729Sjoerg     WithColor::error(errs(), ToolName) << "ill-formed archive entry.\n";
21307330f729Sjoerg     consumeError(ModeOrErr.takeError());
21317330f729Sjoerg     return;
21327330f729Sjoerg   }
21337330f729Sjoerg   sys::fs::perms Mode = ModeOrErr.get();
21347330f729Sjoerg   outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
21357330f729Sjoerg   outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
21367330f729Sjoerg   outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
21377330f729Sjoerg   outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
21387330f729Sjoerg   outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
21397330f729Sjoerg   outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
21407330f729Sjoerg   outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
21417330f729Sjoerg   outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
21427330f729Sjoerg   outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
21437330f729Sjoerg 
21447330f729Sjoerg   outs() << " ";
21457330f729Sjoerg 
21467330f729Sjoerg   outs() << format("%d/%d %6" PRId64 " ", unwrapOrError(C.getUID(), Filename),
21477330f729Sjoerg                    unwrapOrError(C.getGID(), Filename),
21487330f729Sjoerg                    unwrapOrError(C.getRawSize(), Filename));
21497330f729Sjoerg 
21507330f729Sjoerg   StringRef RawLastModified = C.getRawLastModified();
21517330f729Sjoerg   unsigned Seconds;
21527330f729Sjoerg   if (RawLastModified.getAsInteger(10, Seconds))
21537330f729Sjoerg     outs() << "(date: \"" << RawLastModified
21547330f729Sjoerg            << "\" contains non-decimal chars) ";
21557330f729Sjoerg   else {
21567330f729Sjoerg     // Since ctime(3) returns a 26 character string of the form:
21577330f729Sjoerg     // "Sun Sep 16 01:03:52 1973\n\0"
21587330f729Sjoerg     // just print 24 characters.
21597330f729Sjoerg     time_t t = Seconds;
21607330f729Sjoerg     outs() << format("%.24s ", ctime(&t));
21617330f729Sjoerg   }
21627330f729Sjoerg 
21637330f729Sjoerg   StringRef Name = "";
21647330f729Sjoerg   Expected<StringRef> NameOrErr = C.getName();
21657330f729Sjoerg   if (!NameOrErr) {
21667330f729Sjoerg     consumeError(NameOrErr.takeError());
21677330f729Sjoerg     Name = unwrapOrError(C.getRawName(), Filename);
21687330f729Sjoerg   } else {
21697330f729Sjoerg     Name = NameOrErr.get();
21707330f729Sjoerg   }
21717330f729Sjoerg   outs() << Name << "\n";
21727330f729Sjoerg }
21737330f729Sjoerg 
21747330f729Sjoerg // For ELF only now.
shouldWarnForInvalidStartStopAddress(ObjectFile * Obj)21757330f729Sjoerg static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {
21767330f729Sjoerg   if (const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj)) {
21777330f729Sjoerg     if (Elf->getEType() != ELF::ET_REL)
21787330f729Sjoerg       return true;
21797330f729Sjoerg   }
21807330f729Sjoerg   return false;
21817330f729Sjoerg }
21827330f729Sjoerg 
checkForInvalidStartStopAddress(ObjectFile * Obj,uint64_t Start,uint64_t Stop)21837330f729Sjoerg static void checkForInvalidStartStopAddress(ObjectFile *Obj,
21847330f729Sjoerg                                             uint64_t Start, uint64_t Stop) {
21857330f729Sjoerg   if (!shouldWarnForInvalidStartStopAddress(Obj))
21867330f729Sjoerg     return;
21877330f729Sjoerg 
21887330f729Sjoerg   for (const SectionRef &Section : Obj->sections())
21897330f729Sjoerg     if (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC) {
21907330f729Sjoerg       uint64_t BaseAddr = Section.getAddress();
21917330f729Sjoerg       uint64_t Size = Section.getSize();
21927330f729Sjoerg       if ((Start < BaseAddr + Size) && Stop > BaseAddr)
21937330f729Sjoerg         return;
21947330f729Sjoerg     }
21957330f729Sjoerg 
2196*82d56013Sjoerg   if (!HasStartAddressFlag)
21977330f729Sjoerg     reportWarning("no section has address less than 0x" +
21987330f729Sjoerg                       Twine::utohexstr(Stop) + " specified by --stop-address",
21997330f729Sjoerg                   Obj->getFileName());
2200*82d56013Sjoerg   else if (!HasStopAddressFlag)
22017330f729Sjoerg     reportWarning("no section has address greater than or equal to 0x" +
22027330f729Sjoerg                       Twine::utohexstr(Start) + " specified by --start-address",
22037330f729Sjoerg                   Obj->getFileName());
22047330f729Sjoerg   else
22057330f729Sjoerg     reportWarning("no section overlaps the range [0x" +
22067330f729Sjoerg                       Twine::utohexstr(Start) + ",0x" + Twine::utohexstr(Stop) +
22077330f729Sjoerg                       ") specified by --start-address/--stop-address",
22087330f729Sjoerg                   Obj->getFileName());
22097330f729Sjoerg }
22107330f729Sjoerg 
dumpObject(ObjectFile * O,const Archive * A=nullptr,const Archive::Child * C=nullptr)22117330f729Sjoerg static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
22127330f729Sjoerg                        const Archive::Child *C = nullptr) {
22137330f729Sjoerg   // Avoid other output when using a raw option.
22147330f729Sjoerg   if (!RawClangAST) {
22157330f729Sjoerg     outs() << '\n';
22167330f729Sjoerg     if (A)
22177330f729Sjoerg       outs() << A->getFileName() << "(" << O->getFileName() << ")";
22187330f729Sjoerg     else
22197330f729Sjoerg       outs() << O->getFileName();
2220*82d56013Sjoerg     outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n";
22217330f729Sjoerg   }
22227330f729Sjoerg 
2223*82d56013Sjoerg   if (HasStartAddressFlag || HasStopAddressFlag)
22247330f729Sjoerg     checkForInvalidStartStopAddress(O, StartAddress, StopAddress);
22257330f729Sjoerg 
22267330f729Sjoerg   // Note: the order here matches GNU objdump for compatability.
22277330f729Sjoerg   StringRef ArchiveName = A ? A->getFileName() : "";
22287330f729Sjoerg   if (ArchiveHeaders && !MachOOpt && C)
22297330f729Sjoerg     printArchiveChild(ArchiveName, *C);
22307330f729Sjoerg   if (FileHeaders)
22317330f729Sjoerg     printFileHeaders(O);
22327330f729Sjoerg   if (PrivateHeaders || FirstPrivateHeader)
22337330f729Sjoerg     printPrivateFileHeaders(O, FirstPrivateHeader);
22347330f729Sjoerg   if (SectionHeaders)
22357330f729Sjoerg     printSectionHeaders(O);
22367330f729Sjoerg   if (SymbolTable)
22377330f729Sjoerg     printSymbolTable(O, ArchiveName);
2238*82d56013Sjoerg   if (DynamicSymbolTable)
2239*82d56013Sjoerg     printSymbolTable(O, ArchiveName, /*ArchitectureName=*/"",
2240*82d56013Sjoerg                      /*DumpDynamic=*/true);
22417330f729Sjoerg   if (DwarfDumpType != DIDT_Null) {
22427330f729Sjoerg     std::unique_ptr<DIContext> DICtx = DWARFContext::create(*O);
22437330f729Sjoerg     // Dump the complete DWARF structure.
22447330f729Sjoerg     DIDumpOptions DumpOpts;
22457330f729Sjoerg     DumpOpts.DumpType = DwarfDumpType;
22467330f729Sjoerg     DICtx->dump(outs(), DumpOpts);
22477330f729Sjoerg   }
22487330f729Sjoerg   if (Relocations && !Disassemble)
22497330f729Sjoerg     printRelocations(O);
22507330f729Sjoerg   if (DynamicRelocations)
22517330f729Sjoerg     printDynamicRelocations(O);
22527330f729Sjoerg   if (SectionContents)
22537330f729Sjoerg     printSectionContents(O);
22547330f729Sjoerg   if (Disassemble)
22557330f729Sjoerg     disassembleObject(O, Relocations);
22567330f729Sjoerg   if (UnwindInfo)
22577330f729Sjoerg     printUnwindInfo(O);
22587330f729Sjoerg 
22597330f729Sjoerg   // Mach-O specific options:
22607330f729Sjoerg   if (ExportsTrie)
22617330f729Sjoerg     printExportsTrie(O);
22627330f729Sjoerg   if (Rebase)
22637330f729Sjoerg     printRebaseTable(O);
22647330f729Sjoerg   if (Bind)
22657330f729Sjoerg     printBindTable(O);
22667330f729Sjoerg   if (LazyBind)
22677330f729Sjoerg     printLazyBindTable(O);
22687330f729Sjoerg   if (WeakBind)
22697330f729Sjoerg     printWeakBindTable(O);
22707330f729Sjoerg 
22717330f729Sjoerg   // Other special sections:
22727330f729Sjoerg   if (RawClangAST)
22737330f729Sjoerg     printRawClangAST(O);
22747330f729Sjoerg   if (FaultMapSection)
22757330f729Sjoerg     printFaultMaps(O);
22767330f729Sjoerg }
22777330f729Sjoerg 
dumpObject(const COFFImportFile * I,const Archive * A,const Archive::Child * C=nullptr)22787330f729Sjoerg static void dumpObject(const COFFImportFile *I, const Archive *A,
22797330f729Sjoerg                        const Archive::Child *C = nullptr) {
22807330f729Sjoerg   StringRef ArchiveName = A ? A->getFileName() : "";
22817330f729Sjoerg 
22827330f729Sjoerg   // Avoid other output when using a raw option.
22837330f729Sjoerg   if (!RawClangAST)
22847330f729Sjoerg     outs() << '\n'
22857330f729Sjoerg            << ArchiveName << "(" << I->getFileName() << ")"
22867330f729Sjoerg            << ":\tfile format COFF-import-file"
22877330f729Sjoerg            << "\n\n";
22887330f729Sjoerg 
22897330f729Sjoerg   if (ArchiveHeaders && !MachOOpt && C)
22907330f729Sjoerg     printArchiveChild(ArchiveName, *C);
22917330f729Sjoerg   if (SymbolTable)
22927330f729Sjoerg     printCOFFSymbolTable(I);
22937330f729Sjoerg }
22947330f729Sjoerg 
22957330f729Sjoerg /// Dump each object file in \a a;
dumpArchive(const Archive * A)22967330f729Sjoerg static void dumpArchive(const Archive *A) {
22977330f729Sjoerg   Error Err = Error::success();
22987330f729Sjoerg   unsigned I = -1;
22997330f729Sjoerg   for (auto &C : A->children(Err)) {
23007330f729Sjoerg     ++I;
23017330f729Sjoerg     Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
23027330f729Sjoerg     if (!ChildOrErr) {
23037330f729Sjoerg       if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
23047330f729Sjoerg         reportError(std::move(E), getFileNameForError(C, I), A->getFileName());
23057330f729Sjoerg       continue;
23067330f729Sjoerg     }
23077330f729Sjoerg     if (ObjectFile *O = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
23087330f729Sjoerg       dumpObject(O, A, &C);
23097330f729Sjoerg     else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))
23107330f729Sjoerg       dumpObject(I, A, &C);
23117330f729Sjoerg     else
23127330f729Sjoerg       reportError(errorCodeToError(object_error::invalid_file_type),
23137330f729Sjoerg                   A->getFileName());
23147330f729Sjoerg   }
23157330f729Sjoerg   if (Err)
23167330f729Sjoerg     reportError(std::move(Err), A->getFileName());
23177330f729Sjoerg }
23187330f729Sjoerg 
23197330f729Sjoerg /// Open file and figure out how to dump it.
dumpInput(StringRef file)23207330f729Sjoerg static void dumpInput(StringRef file) {
23217330f729Sjoerg   // If we are using the Mach-O specific object file parser, then let it parse
23227330f729Sjoerg   // the file and process the command line options.  So the -arch flags can
23237330f729Sjoerg   // be used to select specific slices, etc.
23247330f729Sjoerg   if (MachOOpt) {
23257330f729Sjoerg     parseInputMachO(file);
23267330f729Sjoerg     return;
23277330f729Sjoerg   }
23287330f729Sjoerg 
23297330f729Sjoerg   // Attempt to open the binary.
23307330f729Sjoerg   OwningBinary<Binary> OBinary = unwrapOrError(createBinary(file), file);
23317330f729Sjoerg   Binary &Binary = *OBinary.getBinary();
23327330f729Sjoerg 
23337330f729Sjoerg   if (Archive *A = dyn_cast<Archive>(&Binary))
23347330f729Sjoerg     dumpArchive(A);
23357330f729Sjoerg   else if (ObjectFile *O = dyn_cast<ObjectFile>(&Binary))
23367330f729Sjoerg     dumpObject(O);
23377330f729Sjoerg   else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Binary))
23387330f729Sjoerg     parseInputMachO(UB);
23397330f729Sjoerg   else
23407330f729Sjoerg     reportError(errorCodeToError(object_error::invalid_file_type), file);
23417330f729Sjoerg }
2342*82d56013Sjoerg 
2343*82d56013Sjoerg template <typename T>
parseIntArg(const llvm::opt::InputArgList & InputArgs,int ID,T & Value)2344*82d56013Sjoerg static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
2345*82d56013Sjoerg                         T &Value) {
2346*82d56013Sjoerg   if (const opt::Arg *A = InputArgs.getLastArg(ID)) {
2347*82d56013Sjoerg     StringRef V(A->getValue());
2348*82d56013Sjoerg     if (!llvm::to_integer(V, Value, 0)) {
2349*82d56013Sjoerg       reportCmdLineError(A->getSpelling() +
2350*82d56013Sjoerg                          ": expected a non-negative integer, but got '" + V +
2351*82d56013Sjoerg                          "'");
2352*82d56013Sjoerg     }
2353*82d56013Sjoerg   }
2354*82d56013Sjoerg }
2355*82d56013Sjoerg 
2356*82d56013Sjoerg static std::vector<std::string>
commaSeparatedValues(const llvm::opt::InputArgList & InputArgs,int ID)2357*82d56013Sjoerg commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
2358*82d56013Sjoerg   std::vector<std::string> Values;
2359*82d56013Sjoerg   for (StringRef Value : InputArgs.getAllArgValues(ID)) {
2360*82d56013Sjoerg     llvm::SmallVector<StringRef, 2> SplitValues;
2361*82d56013Sjoerg     llvm::SplitString(Value, SplitValues, ",");
2362*82d56013Sjoerg     for (StringRef SplitValue : SplitValues)
2363*82d56013Sjoerg       Values.push_back(SplitValue.str());
2364*82d56013Sjoerg   }
2365*82d56013Sjoerg   return Values;
2366*82d56013Sjoerg }
2367*82d56013Sjoerg 
parseOtoolOptions(const llvm::opt::InputArgList & InputArgs)2368*82d56013Sjoerg static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
2369*82d56013Sjoerg   MachOOpt = true;
2370*82d56013Sjoerg   FullLeadingAddr = true;
2371*82d56013Sjoerg   PrintImmHex = true;
2372*82d56013Sjoerg 
2373*82d56013Sjoerg   ArchName = InputArgs.getLastArgValue(OTOOL_arch).str();
2374*82d56013Sjoerg   LinkOptHints = InputArgs.hasArg(OTOOL_C);
2375*82d56013Sjoerg   if (InputArgs.hasArg(OTOOL_d))
2376*82d56013Sjoerg     FilterSections.push_back("__DATA,__data");
2377*82d56013Sjoerg   DylibId = InputArgs.hasArg(OTOOL_D);
2378*82d56013Sjoerg   UniversalHeaders = InputArgs.hasArg(OTOOL_f);
2379*82d56013Sjoerg   DataInCode = InputArgs.hasArg(OTOOL_G);
2380*82d56013Sjoerg   FirstPrivateHeader = InputArgs.hasArg(OTOOL_h);
2381*82d56013Sjoerg   IndirectSymbols = InputArgs.hasArg(OTOOL_I);
2382*82d56013Sjoerg   ShowRawInsn = InputArgs.hasArg(OTOOL_j);
2383*82d56013Sjoerg   PrivateHeaders = InputArgs.hasArg(OTOOL_l);
2384*82d56013Sjoerg   DylibsUsed = InputArgs.hasArg(OTOOL_L);
2385*82d56013Sjoerg   MCPU = InputArgs.getLastArgValue(OTOOL_mcpu_EQ).str();
2386*82d56013Sjoerg   ObjcMetaData = InputArgs.hasArg(OTOOL_o);
2387*82d56013Sjoerg   DisSymName = InputArgs.getLastArgValue(OTOOL_p).str();
2388*82d56013Sjoerg   InfoPlist = InputArgs.hasArg(OTOOL_P);
2389*82d56013Sjoerg   Relocations = InputArgs.hasArg(OTOOL_r);
2390*82d56013Sjoerg   if (const Arg *A = InputArgs.getLastArg(OTOOL_s)) {
2391*82d56013Sjoerg     auto Filter = (A->getValue(0) + StringRef(",") + A->getValue(1)).str();
2392*82d56013Sjoerg     FilterSections.push_back(Filter);
2393*82d56013Sjoerg   }
2394*82d56013Sjoerg   if (InputArgs.hasArg(OTOOL_t))
2395*82d56013Sjoerg     FilterSections.push_back("__TEXT,__text");
2396*82d56013Sjoerg   Verbose = InputArgs.hasArg(OTOOL_v) || InputArgs.hasArg(OTOOL_V) ||
2397*82d56013Sjoerg             InputArgs.hasArg(OTOOL_o);
2398*82d56013Sjoerg   SymbolicOperands = InputArgs.hasArg(OTOOL_V);
2399*82d56013Sjoerg   if (InputArgs.hasArg(OTOOL_x))
2400*82d56013Sjoerg     FilterSections.push_back(",__text");
2401*82d56013Sjoerg   LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X);
2402*82d56013Sjoerg 
2403*82d56013Sjoerg   InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);
2404*82d56013Sjoerg   if (InputFilenames.empty())
2405*82d56013Sjoerg     reportCmdLineError("no input file");
2406*82d56013Sjoerg 
2407*82d56013Sjoerg   for (const Arg *A : InputArgs) {
2408*82d56013Sjoerg     const Option &O = A->getOption();
2409*82d56013Sjoerg     if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {
2410*82d56013Sjoerg       reportCmdLineWarning(O.getPrefixedName() +
2411*82d56013Sjoerg                            " is obsolete and not implemented");
2412*82d56013Sjoerg     }
2413*82d56013Sjoerg   }
2414*82d56013Sjoerg }
2415*82d56013Sjoerg 
parseObjdumpOptions(const llvm::opt::InputArgList & InputArgs)2416*82d56013Sjoerg static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
2417*82d56013Sjoerg   parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA);
2418*82d56013Sjoerg   AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers);
2419*82d56013Sjoerg   ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str();
2420*82d56013Sjoerg   ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers);
2421*82d56013Sjoerg   Demangle = InputArgs.hasArg(OBJDUMP_demangle);
2422*82d56013Sjoerg   Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);
2423*82d56013Sjoerg   DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);
2424*82d56013Sjoerg   SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);
2425*82d56013Sjoerg   DisassembleSymbols =
2426*82d56013Sjoerg       commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
2427*82d56013Sjoerg   DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
2428*82d56013Sjoerg   if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) {
2429*82d56013Sjoerg     DwarfDumpType =
2430*82d56013Sjoerg         StringSwitch<DIDumpType>(A->getValue()).Case("frames", DIDT_DebugFrame);
2431*82d56013Sjoerg   }
2432*82d56013Sjoerg   DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc);
2433*82d56013Sjoerg   FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section);
2434*82d56013Sjoerg   FileHeaders = InputArgs.hasArg(OBJDUMP_file_headers);
2435*82d56013Sjoerg   SectionContents = InputArgs.hasArg(OBJDUMP_full_contents);
2436*82d56013Sjoerg   PrintLines = InputArgs.hasArg(OBJDUMP_line_numbers);
2437*82d56013Sjoerg   InputFilenames = InputArgs.getAllArgValues(OBJDUMP_INPUT);
2438*82d56013Sjoerg   MachOOpt = InputArgs.hasArg(OBJDUMP_macho);
2439*82d56013Sjoerg   MCPU = InputArgs.getLastArgValue(OBJDUMP_mcpu_EQ).str();
2440*82d56013Sjoerg   MAttrs = commaSeparatedValues(InputArgs, OBJDUMP_mattr_EQ);
2441*82d56013Sjoerg   ShowRawInsn = !InputArgs.hasArg(OBJDUMP_no_show_raw_insn);
2442*82d56013Sjoerg   LeadingAddr = !InputArgs.hasArg(OBJDUMP_no_leading_addr);
2443*82d56013Sjoerg   RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast);
2444*82d56013Sjoerg   Relocations = InputArgs.hasArg(OBJDUMP_reloc);
2445*82d56013Sjoerg   PrintImmHex =
2446*82d56013Sjoerg       InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, false);
2447*82d56013Sjoerg   PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers);
2448*82d56013Sjoerg   FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ);
2449*82d56013Sjoerg   SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers);
2450*82d56013Sjoerg   ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma);
2451*82d56013Sjoerg   PrintSource = InputArgs.hasArg(OBJDUMP_source);
2452*82d56013Sjoerg   parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress);
2453*82d56013Sjoerg   HasStartAddressFlag = InputArgs.hasArg(OBJDUMP_start_address_EQ);
2454*82d56013Sjoerg   parseIntArg(InputArgs, OBJDUMP_stop_address_EQ, StopAddress);
2455*82d56013Sjoerg   HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ);
2456*82d56013Sjoerg   SymbolTable = InputArgs.hasArg(OBJDUMP_syms);
2457*82d56013Sjoerg   SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands);
2458*82d56013Sjoerg   DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms);
2459*82d56013Sjoerg   TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str();
2460*82d56013Sjoerg   UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info);
2461*82d56013Sjoerg   Wide = InputArgs.hasArg(OBJDUMP_wide);
2462*82d56013Sjoerg   Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();
2463*82d56013Sjoerg   parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
2464*82d56013Sjoerg   if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
2465*82d56013Sjoerg     DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
2466*82d56013Sjoerg                        .Case("ascii", DVASCII)
2467*82d56013Sjoerg                        .Case("unicode", DVUnicode);
2468*82d56013Sjoerg   }
2469*82d56013Sjoerg   parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);
2470*82d56013Sjoerg 
2471*82d56013Sjoerg   parseMachOOptions(InputArgs);
2472*82d56013Sjoerg 
2473*82d56013Sjoerg   // Parse -M (--disassembler-options) and deprecated
2474*82d56013Sjoerg   // --x86-asm-syntax={att,intel}.
2475*82d56013Sjoerg   //
2476*82d56013Sjoerg   // Note, for x86, the asm dialect (AssemblerDialect) is initialized when the
2477*82d56013Sjoerg   // MCAsmInfo is constructed. MCInstPrinter::applyTargetSpecificCLOption is
2478*82d56013Sjoerg   // called too late. For now we have to use the internal cl::opt option.
2479*82d56013Sjoerg   const char *AsmSyntax = nullptr;
2480*82d56013Sjoerg   for (const auto *A : InputArgs.filtered(OBJDUMP_disassembler_options_EQ,
2481*82d56013Sjoerg                                           OBJDUMP_x86_asm_syntax_att,
2482*82d56013Sjoerg                                           OBJDUMP_x86_asm_syntax_intel)) {
2483*82d56013Sjoerg     switch (A->getOption().getID()) {
2484*82d56013Sjoerg     case OBJDUMP_x86_asm_syntax_att:
2485*82d56013Sjoerg       AsmSyntax = "--x86-asm-syntax=att";
2486*82d56013Sjoerg       continue;
2487*82d56013Sjoerg     case OBJDUMP_x86_asm_syntax_intel:
2488*82d56013Sjoerg       AsmSyntax = "--x86-asm-syntax=intel";
2489*82d56013Sjoerg       continue;
2490*82d56013Sjoerg     }
2491*82d56013Sjoerg 
2492*82d56013Sjoerg     SmallVector<StringRef, 2> Values;
2493*82d56013Sjoerg     llvm::SplitString(A->getValue(), Values, ",");
2494*82d56013Sjoerg     for (StringRef V : Values) {
2495*82d56013Sjoerg       if (V == "att")
2496*82d56013Sjoerg         AsmSyntax = "--x86-asm-syntax=att";
2497*82d56013Sjoerg       else if (V == "intel")
2498*82d56013Sjoerg         AsmSyntax = "--x86-asm-syntax=intel";
2499*82d56013Sjoerg       else
2500*82d56013Sjoerg         DisassemblerOptions.push_back(V.str());
2501*82d56013Sjoerg     }
2502*82d56013Sjoerg   }
2503*82d56013Sjoerg   if (AsmSyntax) {
2504*82d56013Sjoerg     const char *Argv[] = {"llvm-objdump", AsmSyntax};
2505*82d56013Sjoerg     llvm::cl::ParseCommandLineOptions(2, Argv);
2506*82d56013Sjoerg   }
2507*82d56013Sjoerg 
2508*82d56013Sjoerg   // objdump defaults to a.out if no filenames specified.
2509*82d56013Sjoerg   if (InputFilenames.empty())
2510*82d56013Sjoerg     InputFilenames.push_back("a.out");
2511*82d56013Sjoerg }
25127330f729Sjoerg 
main(int argc,char ** argv)25137330f729Sjoerg int main(int argc, char **argv) {
25147330f729Sjoerg   using namespace llvm;
25157330f729Sjoerg   InitLLVM X(argc, argv);
2516*82d56013Sjoerg 
2517*82d56013Sjoerg   ToolName = argv[0];
2518*82d56013Sjoerg   std::unique_ptr<CommonOptTable> T;
2519*82d56013Sjoerg   OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;
2520*82d56013Sjoerg 
2521*82d56013Sjoerg   StringRef Stem = sys::path::stem(ToolName);
2522*82d56013Sjoerg   auto Is = [=](StringRef Tool) {
2523*82d56013Sjoerg     // We need to recognize the following filenames:
2524*82d56013Sjoerg     //
2525*82d56013Sjoerg     // llvm-objdump -> objdump
2526*82d56013Sjoerg     // llvm-otool-10.exe -> otool
2527*82d56013Sjoerg     // powerpc64-unknown-freebsd13-objdump -> objdump
2528*82d56013Sjoerg     auto I = Stem.rfind_lower(Tool);
2529*82d56013Sjoerg     return I != StringRef::npos &&
2530*82d56013Sjoerg            (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
2531*82d56013Sjoerg   };
2532*82d56013Sjoerg   if (Is("otool")) {
2533*82d56013Sjoerg     T = std::make_unique<OtoolOptTable>();
2534*82d56013Sjoerg     Unknown = OTOOL_UNKNOWN;
2535*82d56013Sjoerg     HelpFlag = OTOOL_help;
2536*82d56013Sjoerg     HelpHiddenFlag = OTOOL_help_hidden;
2537*82d56013Sjoerg     VersionFlag = OTOOL_version;
2538*82d56013Sjoerg   } else {
2539*82d56013Sjoerg     T = std::make_unique<ObjdumpOptTable>();
2540*82d56013Sjoerg     Unknown = OBJDUMP_UNKNOWN;
2541*82d56013Sjoerg     HelpFlag = OBJDUMP_help;
2542*82d56013Sjoerg     HelpHiddenFlag = OBJDUMP_help_hidden;
2543*82d56013Sjoerg     VersionFlag = OBJDUMP_version;
2544*82d56013Sjoerg   }
2545*82d56013Sjoerg 
2546*82d56013Sjoerg   BumpPtrAllocator A;
2547*82d56013Sjoerg   StringSaver Saver(A);
2548*82d56013Sjoerg   opt::InputArgList InputArgs =
2549*82d56013Sjoerg       T->parseArgs(argc, argv, Unknown, Saver,
2550*82d56013Sjoerg                    [&](StringRef Msg) { reportCmdLineError(Msg); });
2551*82d56013Sjoerg 
2552*82d56013Sjoerg   if (InputArgs.size() == 0 || InputArgs.hasArg(HelpFlag)) {
2553*82d56013Sjoerg     T->printHelp(ToolName);
2554*82d56013Sjoerg     return 0;
2555*82d56013Sjoerg   }
2556*82d56013Sjoerg   if (InputArgs.hasArg(HelpHiddenFlag)) {
2557*82d56013Sjoerg     T->printHelp(ToolName, /*show_hidden=*/true);
2558*82d56013Sjoerg     return 0;
2559*82d56013Sjoerg   }
25607330f729Sjoerg 
25617330f729Sjoerg   // Initialize targets and assembly printers/parsers.
25627330f729Sjoerg   InitializeAllTargetInfos();
25637330f729Sjoerg   InitializeAllTargetMCs();
25647330f729Sjoerg   InitializeAllDisassemblers();
25657330f729Sjoerg 
2566*82d56013Sjoerg   if (InputArgs.hasArg(VersionFlag)) {
2567*82d56013Sjoerg     cl::PrintVersionMessage();
2568*82d56013Sjoerg     if (!Is("otool")) {
2569*82d56013Sjoerg       outs() << '\n';
2570*82d56013Sjoerg       TargetRegistry::printRegisteredTargetsForVersion(outs());
2571*82d56013Sjoerg     }
2572*82d56013Sjoerg     return 0;
2573*82d56013Sjoerg   }
25747330f729Sjoerg 
2575*82d56013Sjoerg   if (Is("otool"))
2576*82d56013Sjoerg     parseOtoolOptions(InputArgs);
2577*82d56013Sjoerg   else
2578*82d56013Sjoerg     parseObjdumpOptions(InputArgs);
25797330f729Sjoerg 
25807330f729Sjoerg   if (StartAddress >= StopAddress)
25817330f729Sjoerg     reportCmdLineError("start address should be less than stop address");
25827330f729Sjoerg 
2583*82d56013Sjoerg   // Removes trailing separators from prefix.
2584*82d56013Sjoerg   while (!Prefix.empty() && sys::path::is_separator(Prefix.back()))
2585*82d56013Sjoerg     Prefix.pop_back();
25867330f729Sjoerg 
25877330f729Sjoerg   if (AllHeaders)
25887330f729Sjoerg     ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =
25897330f729Sjoerg         SectionHeaders = SymbolTable = true;
25907330f729Sjoerg 
25917330f729Sjoerg   if (DisassembleAll || PrintSource || PrintLines ||
2592*82d56013Sjoerg       !DisassembleSymbols.empty())
25937330f729Sjoerg     Disassemble = true;
25947330f729Sjoerg 
25957330f729Sjoerg   if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null &&
25967330f729Sjoerg       !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&
25977330f729Sjoerg       !Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&
2598*82d56013Sjoerg       !DynamicSymbolTable && !UnwindInfo && !FaultMapSection &&
25997330f729Sjoerg       !(MachOOpt &&
26007330f729Sjoerg         (Bind || DataInCode || DylibId || DylibsUsed || ExportsTrie ||
2601*82d56013Sjoerg          FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist ||
2602*82d56013Sjoerg          LazyBind || LinkOptHints || ObjcMetaData || Rebase || Rpaths ||
2603*82d56013Sjoerg          UniversalHeaders || WeakBind || !FilterSections.empty()))) {
2604*82d56013Sjoerg     T->printHelp(ToolName);
26057330f729Sjoerg     return 2;
26067330f729Sjoerg   }
26077330f729Sjoerg 
2608*82d56013Sjoerg   DisasmSymbolSet.insert(DisassembleSymbols.begin(), DisassembleSymbols.end());
26097330f729Sjoerg 
26107330f729Sjoerg   llvm::for_each(InputFilenames, dumpInput);
26117330f729Sjoerg 
26127330f729Sjoerg   warnOnNoMatchForSections();
26137330f729Sjoerg 
26147330f729Sjoerg   return EXIT_SUCCESS;
26157330f729Sjoerg }
2616