1//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This program is a utility that works like binutils "objdump", that is, it
10// dumps out a plethora of information about an object file depending on the
11// flags.
12//
13// The flags and output of this program should be near identical to those of
14// binutils objdump.
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm-objdump.h"
19#include "COFFDump.h"
20#include "ELFDump.h"
21#include "MachODump.h"
22#include "ObjdumpOptID.h"
23#include "OffloadDump.h"
24#include "SourcePrinter.h"
25#include "WasmDump.h"
26#include "XCOFFDump.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/SetOperations.h"
29#include "llvm/ADT/StringExtras.h"
30#include "llvm/ADT/Twine.h"
31#include "llvm/BinaryFormat/Wasm.h"
32#include "llvm/DebugInfo/BTF/BTFParser.h"
33#include "llvm/DebugInfo/DWARF/DWARFContext.h"
34#include "llvm/DebugInfo/Symbolize/Symbolize.h"
35#include "llvm/Debuginfod/BuildIDFetcher.h"
36#include "llvm/Debuginfod/Debuginfod.h"
37#include "llvm/Debuginfod/HTTPClient.h"
38#include "llvm/Demangle/Demangle.h"
39#include "llvm/MC/MCAsmInfo.h"
40#include "llvm/MC/MCContext.h"
41#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
42#include "llvm/MC/MCInst.h"
43#include "llvm/MC/MCInstPrinter.h"
44#include "llvm/MC/MCInstrAnalysis.h"
45#include "llvm/MC/MCInstrInfo.h"
46#include "llvm/MC/MCObjectFileInfo.h"
47#include "llvm/MC/MCRegisterInfo.h"
48#include "llvm/MC/MCTargetOptions.h"
49#include "llvm/MC/TargetRegistry.h"
50#include "llvm/Object/BuildID.h"
51#include "llvm/Object/COFF.h"
52#include "llvm/Object/COFFImportFile.h"
53#include "llvm/Object/ELFObjectFile.h"
54#include "llvm/Object/ELFTypes.h"
55#include "llvm/Object/FaultMapParser.h"
56#include "llvm/Object/MachO.h"
57#include "llvm/Object/MachOUniversal.h"
58#include "llvm/Object/OffloadBinary.h"
59#include "llvm/Object/Wasm.h"
60#include "llvm/Option/Arg.h"
61#include "llvm/Option/ArgList.h"
62#include "llvm/Option/Option.h"
63#include "llvm/Support/Casting.h"
64#include "llvm/Support/Debug.h"
65#include "llvm/Support/Errc.h"
66#include "llvm/Support/FileSystem.h"
67#include "llvm/Support/Format.h"
68#include "llvm/Support/LLVMDriver.h"
69#include "llvm/Support/MemoryBuffer.h"
70#include "llvm/Support/SourceMgr.h"
71#include "llvm/Support/StringSaver.h"
72#include "llvm/Support/TargetSelect.h"
73#include "llvm/Support/WithColor.h"
74#include "llvm/Support/raw_ostream.h"
75#include "llvm/TargetParser/Host.h"
76#include "llvm/TargetParser/Triple.h"
77#include <algorithm>
78#include <cctype>
79#include <cstring>
80#include <optional>
81#include <set>
82#include <system_error>
83#include <unordered_map>
84#include <utility>
85
86using namespace llvm;
87using namespace llvm::object;
88using namespace llvm::objdump;
89using namespace llvm::opt;
90
91namespace {
92
93class CommonOptTable : public opt::GenericOptTable {
94public:
95 CommonOptTable(const StringTable &StrTable,
96 ArrayRef<StringTable::Offset> PrefixesTable,
97 ArrayRef<Info> OptionInfos, const char *Usage,
98 const char *Description)
99 : opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos),
100 Usage(Usage), Description(Description) {
101 setGroupedShortOptions(true);
102 }
103
104 void printHelp(StringRef Argv0, bool ShowHidden = false) const {
105 Argv0 = sys::path::filename(path: Argv0);
106 opt::GenericOptTable::printHelp(OS&: outs(), Usage: (Argv0 + Usage).str().c_str(),
107 Title: Description, ShowHidden, ShowAllAliases: ShowHidden);
108 // TODO Replace this with OptTable API once it adds extrahelp support.
109 outs() << "\nPass @FILE as argument to read options from FILE.\n";
110 }
111
112private:
113 const char *Usage;
114 const char *Description;
115};
116
117// ObjdumpOptID is in ObjdumpOptID.h
118namespace objdump_opt {
119#define OPTTABLE_STR_TABLE_CODE
120#include "ObjdumpOpts.inc"
121#undef OPTTABLE_STR_TABLE_CODE
122
123#define OPTTABLE_PREFIXES_TABLE_CODE
124#include "ObjdumpOpts.inc"
125#undef OPTTABLE_PREFIXES_TABLE_CODE
126
127static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
128#define OPTION(...) \
129 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJDUMP_, __VA_ARGS__),
130#include "ObjdumpOpts.inc"
131#undef OPTION
132};
133} // namespace objdump_opt
134
135class ObjdumpOptTable : public CommonOptTable {
136public:
137 ObjdumpOptTable()
138 : CommonOptTable(
139 objdump_opt::OptionStrTable, objdump_opt::OptionPrefixesTable,
140 objdump_opt::ObjdumpInfoTable, " [options] <input object files>",
141 "llvm object file dumper") {}
142};
143
144enum OtoolOptID {
145 OTOOL_INVALID = 0, // This is not an option ID.
146#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
147#include "OtoolOpts.inc"
148#undef OPTION
149};
150
151namespace otool {
152#define OPTTABLE_STR_TABLE_CODE
153#include "OtoolOpts.inc"
154#undef OPTTABLE_STR_TABLE_CODE
155
156#define OPTTABLE_PREFIXES_TABLE_CODE
157#include "OtoolOpts.inc"
158#undef OPTTABLE_PREFIXES_TABLE_CODE
159
160static constexpr opt::OptTable::Info OtoolInfoTable[] = {
161#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
162#include "OtoolOpts.inc"
163#undef OPTION
164};
165} // namespace otool
166
167class OtoolOptTable : public CommonOptTable {
168public:
169 OtoolOptTable()
170 : CommonOptTable(otool::OptionStrTable, otool::OptionPrefixesTable,
171 otool::OtoolInfoTable, " [option...] [file...]",
172 "Mach-O object file displaying tool") {}
173};
174
175struct BBAddrMapLabel {
176 std::string BlockLabel;
177 std::string PGOAnalysis;
178};
179
180// This class represents the BBAddrMap and PGOMap associated with a single
181// function.
182class BBAddrMapFunctionEntry {
183public:
184 BBAddrMapFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap)
185 : AddrMap(std::move(AddrMap)), PGOMap(std::move(PGOMap)) {}
186
187 const BBAddrMap &getAddrMap() const { return AddrMap; }
188
189 // Returns the PGO string associated with the entry of index `PGOBBEntryIndex`
190 // in `PGOMap`. If PrettyPGOAnalysis is true, prints BFI as relative frequency
191 // and BPI as percentage. Otherwise raw values are displayed.
192 std::string constructPGOLabelString(size_t PGOBBEntryIndex,
193 bool PrettyPGOAnalysis) const {
194 if (!PGOMap.FeatEnable.hasPGOAnalysis())
195 return "";
196 std::string PGOString;
197 raw_string_ostream PGOSS(PGOString);
198
199 PGOSS << " (";
200 if (PGOMap.FeatEnable.FuncEntryCount && PGOBBEntryIndex == 0) {
201 PGOSS << "Entry count: " << Twine(PGOMap.FuncEntryCount);
202 if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {
203 PGOSS << ", ";
204 }
205 }
206
207 if (PGOMap.FeatEnable.hasPGOAnalysisBBData()) {
208
209 assert(PGOBBEntryIndex < PGOMap.BBEntries.size() &&
210 "Expected PGOAnalysisMap and BBAddrMap to have the same entries");
211 const PGOAnalysisMap::PGOBBEntry &PGOBBEntry =
212 PGOMap.BBEntries[PGOBBEntryIndex];
213
214 if (PGOMap.FeatEnable.BBFreq) {
215 PGOSS << "Frequency: ";
216 if (PrettyPGOAnalysis)
217 printRelativeBlockFreq(OS&: PGOSS, EntryFreq: PGOMap.BBEntries.front().BlockFreq,
218 Freq: PGOBBEntry.BlockFreq);
219 else
220 PGOSS << Twine(PGOBBEntry.BlockFreq.getFrequency());
221 if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
222 PGOSS << ", ";
223 }
224 }
225 if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
226 PGOSS << "Successors: ";
227 interleaveComma(
228 c: PGOBBEntry.Successors, os&: PGOSS,
229 each_fn: [&](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) {
230 PGOSS << "BB" << SE.ID << ":";
231 if (PrettyPGOAnalysis)
232 PGOSS << "[" << SE.Prob << "]";
233 else
234 PGOSS.write_hex(N: SE.Prob.getNumerator());
235 });
236 }
237 }
238 PGOSS << ")";
239
240 return PGOString;
241 }
242
243private:
244 const BBAddrMap AddrMap;
245 const PGOAnalysisMap PGOMap;
246};
247
248// This class represents the BBAddrMap and PGOMap of potentially multiple
249// functions in a section.
250class BBAddrMapInfo {
251public:
252 void clear() {
253 FunctionAddrToMap.clear();
254 RangeBaseAddrToFunctionAddr.clear();
255 }
256
257 bool empty() const { return FunctionAddrToMap.empty(); }
258
259 void AddFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap) {
260 uint64_t FunctionAddr = AddrMap.getFunctionAddress();
261 for (size_t I = 1; I < AddrMap.BBRanges.size(); ++I)
262 RangeBaseAddrToFunctionAddr.emplace(args&: AddrMap.BBRanges[I].BaseAddress,
263 args&: FunctionAddr);
264 [[maybe_unused]] auto R = FunctionAddrToMap.try_emplace(
265 k: FunctionAddr, args: std::move(AddrMap), args: std::move(PGOMap));
266 assert(R.second && "duplicate function address");
267 }
268
269 // Returns the BBAddrMap entry for the function associated with `BaseAddress`.
270 // `BaseAddress` could be the function address or the address of a range
271 // associated with that function. Returns `nullptr` if `BaseAddress` is not
272 // mapped to any entry.
273 const BBAddrMapFunctionEntry *getEntryForAddress(uint64_t BaseAddress) const {
274 uint64_t FunctionAddr = BaseAddress;
275 auto S = RangeBaseAddrToFunctionAddr.find(x: BaseAddress);
276 if (S != RangeBaseAddrToFunctionAddr.end())
277 FunctionAddr = S->second;
278 auto R = FunctionAddrToMap.find(x: FunctionAddr);
279 if (R == FunctionAddrToMap.end())
280 return nullptr;
281 return &R->second;
282 }
283
284private:
285 std::unordered_map<uint64_t, BBAddrMapFunctionEntry> FunctionAddrToMap;
286 std::unordered_map<uint64_t, uint64_t> RangeBaseAddrToFunctionAddr;
287};
288
289} // namespace
290
291#define DEBUG_TYPE "objdump"
292
293enum class ColorOutput {
294 Auto,
295 Enable,
296 Disable,
297 Invalid,
298};
299
300static uint64_t AdjustVMA;
301static bool AllHeaders;
302static std::string ArchName;
303bool objdump::ArchiveHeaders;
304bool objdump::Demangle;
305bool objdump::Disassemble;
306bool objdump::DisassembleAll;
307std::vector<std::string> objdump::DisassemblerOptions;
308bool objdump::SymbolDescription;
309bool objdump::TracebackTable;
310static std::vector<std::string> DisassembleSymbols;
311static bool DisassembleZeroes;
312static ColorOutput DisassemblyColor;
313DIDumpType objdump::DwarfDumpType;
314static bool DynamicRelocations;
315static bool FaultMapSection;
316static bool FileHeaders;
317bool objdump::SectionContents;
318static std::vector<std::string> InputFilenames;
319bool objdump::PrintLines;
320static bool MachOOpt;
321std::string objdump::MCPU;
322std::vector<std::string> objdump::MAttrs;
323bool objdump::ShowRawInsn;
324bool objdump::LeadingAddr;
325static bool Offloading;
326static bool RawClangAST;
327bool objdump::Relocations;
328bool objdump::PrintImmHex;
329bool objdump::PrivateHeaders;
330std::vector<std::string> objdump::FilterSections;
331bool objdump::SectionHeaders;
332static bool ShowAllSymbols;
333static bool ShowLMA;
334bool objdump::PrintSource;
335
336static uint64_t StartAddress;
337static bool HasStartAddressFlag;
338static uint64_t StopAddress = UINT64_MAX;
339static bool HasStopAddressFlag;
340
341bool objdump::SymbolTable;
342static bool SymbolizeOperands;
343static bool PrettyPGOAnalysisMap;
344static bool DynamicSymbolTable;
345std::string objdump::TripleName;
346bool objdump::UnwindInfo;
347static bool Wide;
348std::string objdump::Prefix;
349uint32_t objdump::PrefixStrip;
350
351DebugVarsFormat objdump::DbgVariables = DVDisabled;
352
353int objdump::DbgIndent = 52;
354
355static StringSet<> DisasmSymbolSet;
356StringSet<> objdump::FoundSectionSet;
357static StringRef ToolName;
358
359std::unique_ptr<BuildIDFetcher> BIDFetcher;
360
361Dumper::Dumper(const object::ObjectFile &O) : O(O), OS(outs()) {
362 WarningHandler = [this](const Twine &Msg) {
363 if (Warnings.insert(key: Msg.str()).second)
364 reportWarning(Message: Msg, File: this->O.getFileName());
365 return Error::success();
366 };
367}
368
369void Dumper::reportUniqueWarning(Error Err) {
370 reportUniqueWarning(Msg: toString(E: std::move(Err)));
371}
372
373void Dumper::reportUniqueWarning(const Twine &Msg) {
374 cantFail(Err: WarningHandler(Msg));
375}
376
377static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
378 if (const auto *O = dyn_cast<COFFObjectFile>(Val: &Obj))
379 return createCOFFDumper(Obj: *O);
380 if (const auto *O = dyn_cast<ELFObjectFileBase>(Val: &Obj))
381 return createELFDumper(Obj: *O);
382 if (const auto *O = dyn_cast<MachOObjectFile>(Val: &Obj))
383 return createMachODumper(Obj: *O);
384 if (const auto *O = dyn_cast<WasmObjectFile>(Val: &Obj))
385 return createWasmDumper(Obj: *O);
386 if (const auto *O = dyn_cast<XCOFFObjectFile>(Val: &Obj))
387 return createXCOFFDumper(Obj: *O);
388
389 return createStringError(EC: errc::invalid_argument,
390 S: "unsupported object file format");
391}
392
393namespace {
394struct FilterResult {
395 // True if the section should not be skipped.
396 bool Keep;
397
398 // True if the index counter should be incremented, even if the section should
399 // be skipped. For example, sections may be skipped if they are not included
400 // in the --section flag, but we still want those to count toward the section
401 // count.
402 bool IncrementIndex;
403};
404} // namespace
405
406static FilterResult checkSectionFilter(object::SectionRef S) {
407 if (FilterSections.empty())
408 return {/*Keep=*/true, /*IncrementIndex=*/true};
409
410 Expected<StringRef> SecNameOrErr = S.getName();
411 if (!SecNameOrErr) {
412 consumeError(Err: SecNameOrErr.takeError());
413 return {/*Keep=*/false, /*IncrementIndex=*/false};
414 }
415 StringRef SecName = *SecNameOrErr;
416
417 // StringSet does not allow empty key so avoid adding sections with
418 // no name (such as the section with index 0) here.
419 if (!SecName.empty())
420 FoundSectionSet.insert(key: SecName);
421
422 // Only show the section if it's in the FilterSections list, but always
423 // increment so the indexing is stable.
424 return {/*Keep=*/is_contained(Range&: FilterSections, Element: SecName),
425 /*IncrementIndex=*/true};
426}
427
428SectionFilter objdump::ToolSectionFilter(object::ObjectFile const &O,
429 uint64_t *Idx) {
430 // Start at UINT64_MAX so that the first index returned after an increment is
431 // zero (after the unsigned wrap).
432 if (Idx)
433 *Idx = UINT64_MAX;
434 return SectionFilter(
435 [Idx](object::SectionRef S) {
436 FilterResult Result = checkSectionFilter(S);
437 if (Idx != nullptr && Result.IncrementIndex)
438 *Idx += 1;
439 return Result.Keep;
440 },
441 O);
442}
443
444std::string objdump::getFileNameForError(const object::Archive::Child &C,
445 unsigned Index) {
446 Expected<StringRef> NameOrErr = C.getName();
447 if (NameOrErr)
448 return std::string(NameOrErr.get());
449 // If we have an error getting the name then we print the index of the archive
450 // member. Since we are already in an error state, we just ignore this error.
451 consumeError(Err: NameOrErr.takeError());
452 return "<file index: " + std::to_string(val: Index) + ">";
453}
454
455void objdump::reportWarning(const Twine &Message, StringRef File) {
456 // Output order between errs() and outs() matters especially for archive
457 // files where the output is per member object.
458 outs().flush();
459 WithColor::warning(OS&: errs(), Prefix: ToolName)
460 << "'" << File << "': " << Message << "\n";
461}
462
463[[noreturn]] void objdump::reportError(StringRef File, const Twine &Message) {
464 outs().flush();
465 WithColor::error(OS&: errs(), Prefix: ToolName) << "'" << File << "': " << Message << "\n";
466 exit(status: 1);
467}
468
469[[noreturn]] void objdump::reportError(Error E, StringRef FileName,
470 StringRef ArchiveName,
471 StringRef ArchitectureName) {
472 assert(E);
473 outs().flush();
474 WithColor::error(OS&: errs(), Prefix: ToolName);
475 if (ArchiveName != "")
476 errs() << ArchiveName << "(" << FileName << ")";
477 else
478 errs() << "'" << FileName << "'";
479 if (!ArchitectureName.empty())
480 errs() << " (for architecture " << ArchitectureName << ")";
481 errs() << ": ";
482 logAllUnhandledErrors(E: std::move(E), OS&: errs());
483 exit(status: 1);
484}
485
486static void reportCmdLineWarning(const Twine &Message) {
487 WithColor::warning(OS&: errs(), Prefix: ToolName) << Message << "\n";
488}
489
490[[noreturn]] static void reportCmdLineError(const Twine &Message) {
491 WithColor::error(OS&: errs(), Prefix: ToolName) << Message << "\n";
492 exit(status: 1);
493}
494
495static void warnOnNoMatchForSections() {
496 SetVector<StringRef> MissingSections;
497 for (StringRef S : FilterSections) {
498 if (FoundSectionSet.count(Key: S))
499 return;
500 // User may specify a unnamed section. Don't warn for it.
501 if (!S.empty())
502 MissingSections.insert(X: S);
503 }
504
505 // Warn only if no section in FilterSections is matched.
506 for (StringRef S : MissingSections)
507 reportCmdLineWarning(Message: "section '" + S +
508 "' mentioned in a -j/--section option, but not "
509 "found in any input file");
510}
511
512static const Target *getTarget(const ObjectFile *Obj) {
513 // Figure out the target triple.
514 Triple TheTriple("unknown-unknown-unknown");
515 if (TripleName.empty()) {
516 TheTriple = Obj->makeTriple();
517 } else {
518 TheTriple.setTriple(Triple::normalize(Str: TripleName));
519 auto Arch = Obj->getArch();
520 if (Arch == Triple::arm || Arch == Triple::armeb)
521 Obj->setARMSubArch(TheTriple);
522 }
523
524 // Get the target specific parser.
525 std::string Error;
526 const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
527 Error);
528 if (!TheTarget)
529 reportError(File: Obj->getFileName(), Message: "can't find target: " + Error);
530
531 // Update the triple name and return the found target.
532 TripleName = TheTriple.getTriple();
533 return TheTarget;
534}
535
536bool objdump::isRelocAddressLess(RelocationRef A, RelocationRef B) {
537 return A.getOffset() < B.getOffset();
538}
539
540static Error getRelocationValueString(const RelocationRef &Rel,
541 bool SymbolDescription,
542 SmallVectorImpl<char> &Result) {
543 const ObjectFile *Obj = Rel.getObject();
544 if (auto *ELF = dyn_cast<ELFObjectFileBase>(Val: Obj))
545 return getELFRelocationValueString(Obj: ELF, Rel, Result);
546 if (auto *COFF = dyn_cast<COFFObjectFile>(Val: Obj))
547 return getCOFFRelocationValueString(Obj: COFF, Rel, Result);
548 if (auto *Wasm = dyn_cast<WasmObjectFile>(Val: Obj))
549 return getWasmRelocationValueString(Obj: Wasm, RelRef: Rel, Result);
550 if (auto *MachO = dyn_cast<MachOObjectFile>(Val: Obj))
551 return getMachORelocationValueString(Obj: MachO, RelRef: Rel, Result);
552 if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Val: Obj))
553 return getXCOFFRelocationValueString(Obj: *XCOFF, RelRef: Rel, SymbolDescription,
554 Result);
555 llvm_unreachable("unknown object file format");
556}
557
558/// Indicates whether this relocation should hidden when listing
559/// relocations, usually because it is the trailing part of a multipart
560/// relocation that will be printed as part of the leading relocation.
561static bool getHidden(RelocationRef RelRef) {
562 auto *MachO = dyn_cast<MachOObjectFile>(Val: RelRef.getObject());
563 if (!MachO)
564 return false;
565
566 unsigned Arch = MachO->getArch();
567 DataRefImpl Rel = RelRef.getRawDataRefImpl();
568 uint64_t Type = MachO->getRelocationType(Rel);
569
570 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
571 // is always hidden.
572 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc)
573 return Type == MachO::GENERIC_RELOC_PAIR;
574
575 if (Arch == Triple::x86_64) {
576 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
577 // an X86_64_RELOC_SUBTRACTOR.
578 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
579 DataRefImpl RelPrev = Rel;
580 RelPrev.d.a--;
581 uint64_t PrevType = MachO->getRelocationType(Rel: RelPrev);
582 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
583 return true;
584 }
585 }
586
587 return false;
588}
589
590/// Get the column at which we want to start printing the instruction
591/// disassembly, taking into account anything which appears to the left of it.
592unsigned objdump::getInstStartColumn(const MCSubtargetInfo &STI) {
593 return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
594}
595
596static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
597 raw_ostream &OS) {
598 // The output of printInst starts with a tab. Print some spaces so that
599 // the tab has 1 column and advances to the target tab stop.
600 unsigned TabStop = getInstStartColumn(STI);
601 unsigned Column = OS.tell() - Start;
602 OS.indent(NumSpaces: Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
603}
604
605void objdump::printRawData(ArrayRef<uint8_t> Bytes, uint64_t Address,
606 formatted_raw_ostream &OS,
607 MCSubtargetInfo const &STI) {
608 size_t Start = OS.tell();
609 if (LeadingAddr)
610 OS << format(Fmt: "%8" PRIx64 ":", Vals: Address);
611 if (ShowRawInsn) {
612 OS << ' ';
613 dumpBytes(Bytes, OS);
614 }
615 AlignToInstStartColumn(Start, STI, OS);
616}
617
618namespace {
619
620static bool isAArch64Elf(const ObjectFile &Obj) {
621 const auto *Elf = dyn_cast<ELFObjectFileBase>(Val: &Obj);
622 return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
623}
624
625static bool isArmElf(const ObjectFile &Obj) {
626 const auto *Elf = dyn_cast<ELFObjectFileBase>(Val: &Obj);
627 return Elf && Elf->getEMachine() == ELF::EM_ARM;
628}
629
630static bool isCSKYElf(const ObjectFile &Obj) {
631 const auto *Elf = dyn_cast<ELFObjectFileBase>(Val: &Obj);
632 return Elf && Elf->getEMachine() == ELF::EM_CSKY;
633}
634
635static bool hasMappingSymbols(const ObjectFile &Obj) {
636 return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ;
637}
638
639static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
640 const RelocationRef &Rel, uint64_t Address,
641 bool Is64Bits) {
642 StringRef Fmt = Is64Bits ? "%016" PRIx64 ": " : "%08" PRIx64 ": ";
643 SmallString<16> Name;
644 SmallString<32> Val;
645 Rel.getTypeName(Result&: Name);
646 if (Error E = getRelocationValueString(Rel, SymbolDescription, Result&: Val))
647 reportError(E: std::move(E), FileName);
648 OS << (Is64Bits || !LeadingAddr ? "\t\t" : "\t\t\t");
649 if (LeadingAddr)
650 OS << format(Fmt: Fmt.data(), Vals: Address);
651 OS << Name << "\t" << Val;
652}
653
654static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
655 object::SectionedAddress Address,
656 LiveVariablePrinter &LVP) {
657 const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);
658 if (!Reloc)
659 return;
660
661 SmallString<64> Val;
662 BTF.symbolize(Reloc, Result&: Val);
663 FOS << "\t\t";
664 if (LeadingAddr)
665 FOS << format(Fmt: "%016" PRIx64 ": ", Vals: Address.Address + AdjustVMA);
666 FOS << "CO-RE " << Val;
667 LVP.printAfterOtherLine(OS&: FOS, AfterInst: true);
668}
669
670class PrettyPrinter {
671public:
672 virtual ~PrettyPrinter() = default;
673 virtual void
674 printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
675 object::SectionedAddress Address, formatted_raw_ostream &OS,
676 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
677 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
678 LiveVariablePrinter &LVP) {
679 if (SP && (PrintSource || PrintLines))
680 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
681 LVP.printBetweenInsts(OS, MustPrint: false);
682
683 printRawData(Bytes, Address: Address.Address, OS, STI);
684
685 if (MI) {
686 // See MCInstPrinter::printInst. On targets where a PC relative immediate
687 // is relative to the next instruction and the length of a MCInst is
688 // difficult to measure (x86), this is the address of the next
689 // instruction.
690 uint64_t Addr =
691 Address.Address + (STI.getTargetTriple().isX86() ? Bytes.size() : 0);
692 IP.printInst(MI, Address: Addr, Annot: "", STI, OS);
693 } else
694 OS << "\t<unknown>";
695 }
696};
697PrettyPrinter PrettyPrinterInst;
698
699class HexagonPrettyPrinter : public PrettyPrinter {
700public:
701 void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
702 formatted_raw_ostream &OS) {
703 if (LeadingAddr)
704 OS << format(Fmt: "%8" PRIx64 ":", Vals: Address);
705 if (ShowRawInsn) {
706 OS << "\t";
707 if (Bytes.size() >= 4) {
708 dumpBytes(Bytes: Bytes.slice(N: 0, M: 4), OS);
709 uint32_t opcode =
710 (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
711 OS << format(Fmt: "\t%08" PRIx32, Vals: opcode);
712 } else {
713 dumpBytes(Bytes, OS);
714 }
715 }
716 }
717 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
718 object::SectionedAddress Address, formatted_raw_ostream &OS,
719 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
720 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
721 LiveVariablePrinter &LVP) override {
722 if (SP && (PrintSource || PrintLines))
723 SP->printSourceLine(OS, Address, ObjectFilename, LVP, Delimiter: "");
724 if (!MI) {
725 printLead(Bytes, Address: Address.Address, OS);
726 OS << " <unknown>";
727 return;
728 }
729 std::string Buffer;
730 {
731 raw_string_ostream TempStream(Buffer);
732 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS&: TempStream);
733 }
734 StringRef Contents(Buffer);
735 // Split off bundle attributes
736 auto PacketBundle = Contents.rsplit(Separator: '\n');
737 // Split off first instruction from the rest
738 auto HeadTail = PacketBundle.first.split(Separator: '\n');
739 auto Preamble = " { ";
740 auto Separator = "";
741
742 // Hexagon's packets require relocations to be inline rather than
743 // clustered at the end of the packet.
744 std::vector<RelocationRef>::const_iterator RelCur = Rels->begin();
745 std::vector<RelocationRef>::const_iterator RelEnd = Rels->end();
746 auto PrintReloc = [&]() -> void {
747 while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) {
748 if (RelCur->getOffset() == Address.Address) {
749 printRelocation(OS, FileName: ObjectFilename, Rel: *RelCur, Address: Address.Address, Is64Bits: false);
750 return;
751 }
752 ++RelCur;
753 }
754 };
755
756 while (!HeadTail.first.empty()) {
757 OS << Separator;
758 Separator = "\n";
759 if (SP && (PrintSource || PrintLines))
760 SP->printSourceLine(OS, Address, ObjectFilename, LVP, Delimiter: "");
761 printLead(Bytes, Address: Address.Address, OS);
762 OS << Preamble;
763 Preamble = " ";
764 StringRef Inst;
765 auto Duplex = HeadTail.first.split(Separator: '\v');
766 if (!Duplex.second.empty()) {
767 OS << Duplex.first;
768 OS << "; ";
769 Inst = Duplex.second;
770 }
771 else
772 Inst = HeadTail.first;
773 OS << Inst;
774 HeadTail = HeadTail.second.split(Separator: '\n');
775 if (HeadTail.first.empty())
776 OS << " } " << PacketBundle.second;
777 PrintReloc();
778 Bytes = Bytes.slice(N: 4);
779 Address.Address += 4;
780 }
781 }
782};
783HexagonPrettyPrinter HexagonPrettyPrinterInst;
784
785class AMDGCNPrettyPrinter : public PrettyPrinter {
786public:
787 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
788 object::SectionedAddress Address, formatted_raw_ostream &OS,
789 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
790 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
791 LiveVariablePrinter &LVP) override {
792 if (SP && (PrintSource || PrintLines))
793 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
794
795 if (MI) {
796 SmallString<40> InstStr;
797 raw_svector_ostream IS(InstStr);
798
799 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS&: IS);
800
801 OS << left_justify(Str: IS.str(), Width: 60);
802 } else {
803 // an unrecognized encoding - this is probably data so represent it
804 // using the .long directive, or .byte directive if fewer than 4 bytes
805 // remaining
806 if (Bytes.size() >= 4) {
807 OS << format(
808 Fmt: "\t.long 0x%08" PRIx32 " ",
809 Vals: support::endian::read32<llvm::endianness::little>(P: Bytes.data()));
810 OS.indent(NumSpaces: 42);
811 } else {
812 OS << format(Fmt: "\t.byte 0x%02" PRIx8, Vals: Bytes[0]);
813 for (unsigned int i = 1; i < Bytes.size(); i++)
814 OS << format(Fmt: ", 0x%02" PRIx8, Vals: Bytes[i]);
815 OS.indent(NumSpaces: 55 - (6 * Bytes.size()));
816 }
817 }
818
819 OS << format(Fmt: "// %012" PRIX64 ":", Vals: Address.Address);
820 if (Bytes.size() >= 4) {
821 // D should be casted to uint32_t here as it is passed by format to
822 // snprintf as vararg.
823 for (uint32_t D :
824 ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),
825 Bytes.size() / 4))
826 OS << format(Fmt: " %08" PRIX32, Vals: D);
827 } else {
828 for (unsigned char B : Bytes)
829 OS << format(Fmt: " %02" PRIX8, Vals: B);
830 }
831
832 if (!Annot.empty())
833 OS << " // " << Annot;
834 }
835};
836AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
837
838class BPFPrettyPrinter : public PrettyPrinter {
839public:
840 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
841 object::SectionedAddress Address, formatted_raw_ostream &OS,
842 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
843 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
844 LiveVariablePrinter &LVP) override {
845 if (SP && (PrintSource || PrintLines))
846 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
847 if (LeadingAddr)
848 OS << format(Fmt: "%8" PRId64 ":", Vals: Address.Address / 8);
849 if (ShowRawInsn) {
850 OS << "\t";
851 dumpBytes(Bytes, OS);
852 }
853 if (MI)
854 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS);
855 else
856 OS << "\t<unknown>";
857 }
858};
859BPFPrettyPrinter BPFPrettyPrinterInst;
860
861class ARMPrettyPrinter : public PrettyPrinter {
862public:
863 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
864 object::SectionedAddress Address, formatted_raw_ostream &OS,
865 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
866 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
867 LiveVariablePrinter &LVP) override {
868 if (SP && (PrintSource || PrintLines))
869 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
870 LVP.printBetweenInsts(OS, MustPrint: false);
871
872 size_t Start = OS.tell();
873 if (LeadingAddr)
874 OS << format(Fmt: "%8" PRIx64 ":", Vals: Address.Address);
875 if (ShowRawInsn) {
876 size_t Pos = 0, End = Bytes.size();
877 if (STI.checkFeatures(FS: "+thumb-mode")) {
878 for (; Pos + 2 <= End; Pos += 2)
879 OS << ' '
880 << format_hex_no_prefix(
881 N: llvm::support::endian::read<uint16_t>(
882 memory: Bytes.data() + Pos, endian: InstructionEndianness),
883 Width: 4);
884 } else {
885 for (; Pos + 4 <= End; Pos += 4)
886 OS << ' '
887 << format_hex_no_prefix(
888 N: llvm::support::endian::read<uint32_t>(
889 memory: Bytes.data() + Pos, endian: InstructionEndianness),
890 Width: 8);
891 }
892 if (Pos < End) {
893 OS << ' ';
894 dumpBytes(Bytes: Bytes.slice(N: Pos), OS);
895 }
896 }
897
898 AlignToInstStartColumn(Start, STI, OS);
899
900 if (MI) {
901 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS);
902 } else
903 OS << "\t<unknown>";
904 }
905
906 void setInstructionEndianness(llvm::endianness Endianness) {
907 InstructionEndianness = Endianness;
908 }
909
910private:
911 llvm::endianness InstructionEndianness = llvm::endianness::little;
912};
913ARMPrettyPrinter ARMPrettyPrinterInst;
914
915class AArch64PrettyPrinter : public PrettyPrinter {
916public:
917 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
918 object::SectionedAddress Address, formatted_raw_ostream &OS,
919 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
920 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
921 LiveVariablePrinter &LVP) override {
922 if (SP && (PrintSource || PrintLines))
923 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
924 LVP.printBetweenInsts(OS, MustPrint: false);
925
926 size_t Start = OS.tell();
927 if (LeadingAddr)
928 OS << format(Fmt: "%8" PRIx64 ":", Vals: Address.Address);
929 if (ShowRawInsn) {
930 size_t Pos = 0, End = Bytes.size();
931 for (; Pos + 4 <= End; Pos += 4)
932 OS << ' '
933 << format_hex_no_prefix(
934 N: llvm::support::endian::read<uint32_t>(
935 memory: Bytes.data() + Pos, endian: llvm::endianness::little),
936 Width: 8);
937 if (Pos < End) {
938 OS << ' ';
939 dumpBytes(Bytes: Bytes.slice(N: Pos), OS);
940 }
941 }
942
943 AlignToInstStartColumn(Start, STI, OS);
944
945 if (MI) {
946 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS);
947 } else
948 OS << "\t<unknown>";
949 }
950};
951AArch64PrettyPrinter AArch64PrettyPrinterInst;
952
953class RISCVPrettyPrinter : public PrettyPrinter {
954public:
955 void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
956 object::SectionedAddress Address, formatted_raw_ostream &OS,
957 StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
958 StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
959 LiveVariablePrinter &LVP) override {
960 if (SP && (PrintSource || PrintLines))
961 SP->printSourceLine(OS, Address, ObjectFilename, LVP);
962 LVP.printBetweenInsts(OS, MustPrint: false);
963
964 size_t Start = OS.tell();
965 if (LeadingAddr)
966 OS << format(Fmt: "%8" PRIx64 ":", Vals: Address.Address);
967 if (ShowRawInsn) {
968 size_t Pos = 0, End = Bytes.size();
969 if (End % 4 == 0) {
970 // 32-bit and 64-bit instructions.
971 for (; Pos + 4 <= End; Pos += 4)
972 OS << ' '
973 << format_hex_no_prefix(
974 N: llvm::support::endian::read<uint32_t>(
975 memory: Bytes.data() + Pos, endian: llvm::endianness::little),
976 Width: 8);
977 } else if (End % 2 == 0) {
978 // 16-bit and 48-bits instructions.
979 for (; Pos + 2 <= End; Pos += 2)
980 OS << ' '
981 << format_hex_no_prefix(
982 N: llvm::support::endian::read<uint16_t>(
983 memory: Bytes.data() + Pos, endian: llvm::endianness::little),
984 Width: 4);
985 }
986 if (Pos < End) {
987 OS << ' ';
988 dumpBytes(Bytes: Bytes.slice(N: Pos), OS);
989 }
990 }
991
992 AlignToInstStartColumn(Start, STI, OS);
993
994 if (MI) {
995 IP.printInst(MI, Address: Address.Address, Annot: "", STI, OS);
996 } else
997 OS << "\t<unknown>";
998 }
999};
1000RISCVPrettyPrinter RISCVPrettyPrinterInst;
1001
1002PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
1003 switch(Triple.getArch()) {
1004 default:
1005 return PrettyPrinterInst;
1006 case Triple::hexagon:
1007 return HexagonPrettyPrinterInst;
1008 case Triple::amdgcn:
1009 return AMDGCNPrettyPrinterInst;
1010 case Triple::bpfel:
1011 case Triple::bpfeb:
1012 return BPFPrettyPrinterInst;
1013 case Triple::arm:
1014 case Triple::armeb:
1015 case Triple::thumb:
1016 case Triple::thumbeb:
1017 return ARMPrettyPrinterInst;
1018 case Triple::aarch64:
1019 case Triple::aarch64_be:
1020 case Triple::aarch64_32:
1021 return AArch64PrettyPrinterInst;
1022 case Triple::riscv32:
1023 case Triple::riscv64:
1024 return RISCVPrettyPrinterInst;
1025 }
1026}
1027
1028class DisassemblerTarget {
1029public:
1030 const Target *TheTarget;
1031 std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;
1032 std::shared_ptr<MCContext> Context;
1033 std::unique_ptr<MCDisassembler> DisAsm;
1034 std::shared_ptr<MCInstrAnalysis> InstrAnalysis;
1035 std::shared_ptr<MCInstPrinter> InstPrinter;
1036 PrettyPrinter *Printer;
1037
1038 DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
1039 StringRef TripleName, StringRef MCPU,
1040 SubtargetFeatures &Features);
1041 DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);
1042
1043private:
1044 MCTargetOptions Options;
1045 std::shared_ptr<const MCRegisterInfo> RegisterInfo;
1046 std::shared_ptr<const MCAsmInfo> AsmInfo;
1047 std::shared_ptr<const MCInstrInfo> InstrInfo;
1048 std::shared_ptr<MCObjectFileInfo> ObjectFileInfo;
1049};
1050
1051DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
1052 StringRef TripleName, StringRef MCPU,
1053 SubtargetFeatures &Features)
1054 : TheTarget(TheTarget),
1055 Printer(&selectPrettyPrinter(Triple: Triple(TripleName))),
1056 RegisterInfo(TheTarget->createMCRegInfo(TT: TripleName)) {
1057 if (!RegisterInfo)
1058 reportError(File: Obj.getFileName(), Message: "no register info for target " + TripleName);
1059
1060 // Set up disassembler.
1061 AsmInfo.reset(p: TheTarget->createMCAsmInfo(MRI: *RegisterInfo, TheTriple: TripleName, Options));
1062 if (!AsmInfo)
1063 reportError(File: Obj.getFileName(), Message: "no assembly info for target " + TripleName);
1064
1065 SubtargetInfo.reset(
1066 p: TheTarget->createMCSubtargetInfo(TheTriple: TripleName, CPU: MCPU, Features: Features.getString()));
1067 if (!SubtargetInfo)
1068 reportError(File: Obj.getFileName(),
1069 Message: "no subtarget info for target " + TripleName);
1070 InstrInfo.reset(p: TheTarget->createMCInstrInfo());
1071 if (!InstrInfo)
1072 reportError(File: Obj.getFileName(),
1073 Message: "no instruction info for target " + TripleName);
1074 Context =
1075 std::make_shared<MCContext>(args: Triple(TripleName), args: AsmInfo.get(),
1076 args: RegisterInfo.get(), args: SubtargetInfo.get());
1077
1078 // FIXME: for now initialize MCObjectFileInfo with default values
1079 ObjectFileInfo.reset(
1080 p: TheTarget->createMCObjectFileInfo(Ctx&: *Context, /*PIC=*/false));
1081 Context->setObjectFileInfo(ObjectFileInfo.get());
1082
1083 DisAsm.reset(p: TheTarget->createMCDisassembler(STI: *SubtargetInfo, Ctx&: *Context));
1084 if (!DisAsm)
1085 reportError(File: Obj.getFileName(), Message: "no disassembler for target " + TripleName);
1086
1087 if (auto *ELFObj = dyn_cast<ELFObjectFileBase>(Val: &Obj))
1088 DisAsm->setABIVersion(ELFObj->getEIdentABIVersion());
1089
1090 InstrAnalysis.reset(p: TheTarget->createMCInstrAnalysis(Info: InstrInfo.get()));
1091
1092 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
1093 InstPrinter.reset(p: TheTarget->createMCInstPrinter(T: Triple(TripleName),
1094 SyntaxVariant: AsmPrinterVariant, MAI: *AsmInfo,
1095 MII: *InstrInfo, MRI: *RegisterInfo));
1096 if (!InstPrinter)
1097 reportError(File: Obj.getFileName(),
1098 Message: "no instruction printer for target " + TripleName);
1099 InstPrinter->setPrintImmHex(PrintImmHex);
1100 InstPrinter->setPrintBranchImmAsAddress(true);
1101 InstPrinter->setSymbolizeOperands(SymbolizeOperands);
1102 InstPrinter->setMCInstrAnalysis(InstrAnalysis.get());
1103
1104 switch (DisassemblyColor) {
1105 case ColorOutput::Enable:
1106 InstPrinter->setUseColor(true);
1107 break;
1108 case ColorOutput::Auto:
1109 InstPrinter->setUseColor(outs().has_colors());
1110 break;
1111 case ColorOutput::Disable:
1112 case ColorOutput::Invalid:
1113 InstPrinter->setUseColor(false);
1114 break;
1115 };
1116}
1117
1118DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,
1119 SubtargetFeatures &Features)
1120 : TheTarget(Other.TheTarget),
1121 SubtargetInfo(TheTarget->createMCSubtargetInfo(TheTriple: TripleName, CPU: MCPU,
1122 Features: Features.getString())),
1123 Context(Other.Context),
1124 DisAsm(TheTarget->createMCDisassembler(STI: *SubtargetInfo, Ctx&: *Context)),
1125 InstrAnalysis(Other.InstrAnalysis), InstPrinter(Other.InstPrinter),
1126 Printer(Other.Printer), RegisterInfo(Other.RegisterInfo),
1127 AsmInfo(Other.AsmInfo), InstrInfo(Other.InstrInfo),
1128 ObjectFileInfo(Other.ObjectFileInfo) {}
1129} // namespace
1130
1131static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
1132 assert(Obj.isELF());
1133 if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Val: &Obj))
1134 return unwrapOrError(EO: Elf32LEObj->getSymbol(Sym: Sym.getRawDataRefImpl()),
1135 Args: Obj.getFileName())
1136 ->getType();
1137 if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Val: &Obj))
1138 return unwrapOrError(EO: Elf64LEObj->getSymbol(Sym: Sym.getRawDataRefImpl()),
1139 Args: Obj.getFileName())
1140 ->getType();
1141 if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Val: &Obj))
1142 return unwrapOrError(EO: Elf32BEObj->getSymbol(Sym: Sym.getRawDataRefImpl()),
1143 Args: Obj.getFileName())
1144 ->getType();
1145 if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Val: &Obj))
1146 return unwrapOrError(EO: Elf64BEObj->getSymbol(Sym: Sym.getRawDataRefImpl()),
1147 Args: Obj.getFileName())
1148 ->getType();
1149 llvm_unreachable("Unsupported binary format");
1150}
1151
1152template <class ELFT>
1153static void
1154addDynamicElfSymbols(const ELFObjectFile<ELFT> &Obj,
1155 std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
1156 for (auto Symbol : Obj.getDynamicSymbolIterators()) {
1157 uint8_t SymbolType = Symbol.getELFType();
1158 if (SymbolType == ELF::STT_SECTION)
1159 continue;
1160
1161 uint64_t Address = unwrapOrError(Symbol.getAddress(), Obj.getFileName());
1162 // ELFSymbolRef::getAddress() returns size instead of value for common
1163 // symbols which is not desirable for disassembly output. Overriding.
1164 if (SymbolType == ELF::STT_COMMON)
1165 Address = unwrapOrError(Obj.getSymbol(Symbol.getRawDataRefImpl()),
1166 Obj.getFileName())
1167 ->st_value;
1168
1169 StringRef Name = unwrapOrError(Symbol.getName(), Obj.getFileName());
1170 if (Name.empty())
1171 continue;
1172
1173 section_iterator SecI =
1174 unwrapOrError(Symbol.getSection(), Obj.getFileName());
1175 if (SecI == Obj.section_end())
1176 continue;
1177
1178 AllSymbols[*SecI].emplace_back(args&: Address, args&: Name, args&: SymbolType);
1179 }
1180}
1181
1182static void
1183addDynamicElfSymbols(const ELFObjectFileBase &Obj,
1184 std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
1185 if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Val: &Obj))
1186 addDynamicElfSymbols(Obj: *Elf32LEObj, AllSymbols);
1187 else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Val: &Obj))
1188 addDynamicElfSymbols(Obj: *Elf64LEObj, AllSymbols);
1189 else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Val: &Obj))
1190 addDynamicElfSymbols(Obj: *Elf32BEObj, AllSymbols);
1191 else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Val: &Obj))
1192 addDynamicElfSymbols(Obj: *Elf64BEObj, AllSymbols);
1193 else
1194 llvm_unreachable("Unsupported binary format");
1195}
1196
1197static std::optional<SectionRef> getWasmCodeSection(const WasmObjectFile &Obj) {
1198 for (auto SecI : Obj.sections()) {
1199 const WasmSection &Section = Obj.getWasmSection(Section: SecI);
1200 if (Section.Type == wasm::WASM_SEC_CODE)
1201 return SecI;
1202 }
1203 return std::nullopt;
1204}
1205
1206static void
1207addMissingWasmCodeSymbols(const WasmObjectFile &Obj,
1208 std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
1209 std::optional<SectionRef> Section = getWasmCodeSection(Obj);
1210 if (!Section)
1211 return;
1212 SectionSymbolsTy &Symbols = AllSymbols[*Section];
1213
1214 std::set<uint64_t> SymbolAddresses;
1215 for (const auto &Sym : Symbols)
1216 SymbolAddresses.insert(x: Sym.Addr);
1217
1218 for (const wasm::WasmFunction &Function : Obj.functions()) {
1219 // This adjustment mirrors the one in WasmObjectFile::getSymbolAddress.
1220 uint32_t Adjustment = Obj.isRelocatableObject() || Obj.isSharedObject()
1221 ? 0
1222 : Section->getAddress();
1223 uint64_t Address = Function.CodeSectionOffset + Adjustment;
1224 // Only add fallback symbols for functions not already present in the symbol
1225 // table.
1226 if (SymbolAddresses.count(x: Address))
1227 continue;
1228 // This function has no symbol, so it should have no SymbolName.
1229 assert(Function.SymbolName.empty());
1230 // We use DebugName for the name, though it may be empty if there is no
1231 // "name" custom section, or that section is missing a name for this
1232 // function.
1233 StringRef Name = Function.DebugName;
1234 Symbols.emplace_back(args&: Address, args&: Name, args: ELF::STT_NOTYPE);
1235 }
1236}
1237
1238static DenseMap<StringRef, SectionRef> getSectionNames(const ObjectFile &Obj) {
1239 DenseMap<StringRef, SectionRef> Sections;
1240 for (SectionRef Section : Obj.sections()) {
1241 Expected<StringRef> SecNameOrErr = Section.getName();
1242 if (!SecNameOrErr) {
1243 consumeError(Err: SecNameOrErr.takeError());
1244 continue;
1245 }
1246 Sections[*SecNameOrErr] = Section;
1247 }
1248 return Sections;
1249}
1250
1251static void addPltEntries(const MCSubtargetInfo &STI, const ObjectFile &Obj,
1252 DenseMap<StringRef, SectionRef> &SectionNames,
1253 std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
1254 StringSaver &Saver) {
1255 auto *ElfObj = dyn_cast<ELFObjectFileBase>(Val: &Obj);
1256 if (!ElfObj)
1257 return;
1258 for (auto Plt : ElfObj->getPltEntries(STI)) {
1259 if (Plt.Symbol) {
1260 SymbolRef Symbol(*Plt.Symbol, ElfObj);
1261 uint8_t SymbolType = getElfSymbolType(Obj, Sym: Symbol);
1262 if (Expected<StringRef> NameOrErr = Symbol.getName()) {
1263 if (!NameOrErr->empty())
1264 AllSymbols[SectionNames[Plt.Section]].emplace_back(
1265 args&: Plt.Address, args: Saver.save(S: (*NameOrErr + "@plt").str()), args&: SymbolType);
1266 continue;
1267 } else {
1268 // The warning has been reported in disassembleObject().
1269 consumeError(Err: NameOrErr.takeError());
1270 }
1271 }
1272 reportWarning(Message: "PLT entry at 0x" + Twine::utohexstr(Val: Plt.Address) +
1273 " references an invalid symbol",
1274 File: Obj.getFileName());
1275 }
1276}
1277
1278// Normally the disassembly output will skip blocks of zeroes. This function
1279// returns the number of zero bytes that can be skipped when dumping the
1280// disassembly of the instructions in Buf.
1281static size_t countSkippableZeroBytes(ArrayRef<uint8_t> Buf) {
1282 // Find the number of leading zeroes.
1283 size_t N = 0;
1284 while (N < Buf.size() && !Buf[N])
1285 ++N;
1286
1287 // We may want to skip blocks of zero bytes, but unless we see
1288 // at least 8 of them in a row.
1289 if (N < 8)
1290 return 0;
1291
1292 // We skip zeroes in multiples of 4 because do not want to truncate an
1293 // instruction if it starts with a zero byte.
1294 return N & ~0x3;
1295}
1296
1297// Returns a map from sections to their relocations.
1298static std::map<SectionRef, std::vector<RelocationRef>>
1299getRelocsMap(object::ObjectFile const &Obj) {
1300 std::map<SectionRef, std::vector<RelocationRef>> Ret;
1301 uint64_t I = (uint64_t)-1;
1302 for (SectionRef Sec : Obj.sections()) {
1303 ++I;
1304 Expected<section_iterator> RelocatedOrErr = Sec.getRelocatedSection();
1305 if (!RelocatedOrErr)
1306 reportError(File: Obj.getFileName(),
1307 Message: "section (" + Twine(I) +
1308 "): failed to get a relocated section: " +
1309 toString(E: RelocatedOrErr.takeError()));
1310
1311 section_iterator Relocated = *RelocatedOrErr;
1312 if (Relocated == Obj.section_end() || !checkSectionFilter(S: *Relocated).Keep)
1313 continue;
1314 std::vector<RelocationRef> &V = Ret[*Relocated];
1315 append_range(C&: V, R: Sec.relocations());
1316 // Sort relocations by address.
1317 llvm::stable_sort(Range&: V, C: isRelocAddressLess);
1318 }
1319 return Ret;
1320}
1321
1322// Used for --adjust-vma to check if address should be adjusted by the
1323// specified value for a given section.
1324// For ELF we do not adjust non-allocatable sections like debug ones,
1325// because they are not loadable.
1326// TODO: implement for other file formats.
1327static bool shouldAdjustVA(const SectionRef &Section) {
1328 const ObjectFile *Obj = Section.getObject();
1329 if (Obj->isELF())
1330 return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;
1331 return false;
1332}
1333
1334
1335typedef std::pair<uint64_t, char> MappingSymbolPair;
1336static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
1337 uint64_t Address) {
1338 auto It =
1339 partition_point(Range&: MappingSymbols, P: [Address](const MappingSymbolPair &Val) {
1340 return Val.first <= Address;
1341 });
1342 // Return zero for any address before the first mapping symbol; this means
1343 // we should use the default disassembly mode, depending on the target.
1344 if (It == MappingSymbols.begin())
1345 return '\x00';
1346 return (It - 1)->second;
1347}
1348
1349static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,
1350 uint64_t End, const ObjectFile &Obj,
1351 ArrayRef<uint8_t> Bytes,
1352 ArrayRef<MappingSymbolPair> MappingSymbols,
1353 const MCSubtargetInfo &STI, raw_ostream &OS) {
1354 llvm::endianness Endian =
1355 Obj.isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;
1356 size_t Start = OS.tell();
1357 OS << format(Fmt: "%8" PRIx64 ": ", Vals: SectionAddr + Index);
1358 if (Index + 4 <= End) {
1359 dumpBytes(Bytes: Bytes.slice(N: Index, M: 4), OS);
1360 AlignToInstStartColumn(Start, STI, OS);
1361 OS << "\t.word\t"
1362 << format_hex(N: support::endian::read32(P: Bytes.data() + Index, E: Endian),
1363 Width: 10);
1364 return 4;
1365 }
1366 if (Index + 2 <= End) {
1367 dumpBytes(Bytes: Bytes.slice(N: Index, M: 2), OS);
1368 AlignToInstStartColumn(Start, STI, OS);
1369 OS << "\t.short\t"
1370 << format_hex(N: support::endian::read16(P: Bytes.data() + Index, E: Endian), Width: 6);
1371 return 2;
1372 }
1373 dumpBytes(Bytes: Bytes.slice(N: Index, M: 1), OS);
1374 AlignToInstStartColumn(Start, STI, OS);
1375 OS << "\t.byte\t" << format_hex(N: Bytes[Index], Width: 4);
1376 return 1;
1377}
1378
1379static void dumpELFData(uint64_t SectionAddr, uint64_t Index, uint64_t End,
1380 ArrayRef<uint8_t> Bytes, raw_ostream &OS) {
1381 // print out data up to 8 bytes at a time in hex and ascii
1382 uint8_t AsciiData[9] = {'\0'};
1383 uint8_t Byte;
1384 int NumBytes = 0;
1385
1386 for (; Index < End; ++Index) {
1387 if (NumBytes == 0)
1388 OS << format(Fmt: "%8" PRIx64 ":", Vals: SectionAddr + Index);
1389 Byte = Bytes.slice(N: Index)[0];
1390 OS << format(Fmt: " %02x", Vals: Byte);
1391 AsciiData[NumBytes] = isPrint(C: Byte) ? Byte : '.';
1392
1393 uint8_t IndentOffset = 0;
1394 NumBytes++;
1395 if (Index == End - 1 || NumBytes > 8) {
1396 // Indent the space for less than 8 bytes data.
1397 // 2 spaces for byte and one for space between bytes
1398 IndentOffset = 3 * (8 - NumBytes);
1399 for (int Excess = NumBytes; Excess < 8; Excess++)
1400 AsciiData[Excess] = '\0';
1401 NumBytes = 8;
1402 }
1403 if (NumBytes == 8) {
1404 AsciiData[8] = '\0';
1405 OS << std::string(IndentOffset, ' ') << " ";
1406 OS << reinterpret_cast<char *>(AsciiData);
1407 OS << '\n';
1408 NumBytes = 0;
1409 }
1410 }
1411}
1412
1413SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
1414 const SymbolRef &Symbol,
1415 bool IsMappingSymbol) {
1416 const StringRef FileName = Obj.getFileName();
1417 const uint64_t Addr = unwrapOrError(EO: Symbol.getAddress(), Args: FileName);
1418 const StringRef Name = unwrapOrError(EO: Symbol.getName(), Args: FileName);
1419
1420 if (Obj.isXCOFF() && (SymbolDescription || TracebackTable)) {
1421 const auto &XCOFFObj = cast<XCOFFObjectFile>(Val: Obj);
1422 DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();
1423
1424 const uint32_t SymbolIndex = XCOFFObj.getSymbolIndex(SymEntPtr: SymbolDRI.p);
1425 std::optional<XCOFF::StorageMappingClass> Smc =
1426 getXCOFFSymbolCsectSMC(Obj: XCOFFObj, Sym: Symbol);
1427 return SymbolInfoTy(Smc, Addr, Name, SymbolIndex,
1428 isLabel(Obj: XCOFFObj, Sym: Symbol));
1429 } else if (Obj.isXCOFF()) {
1430 const SymbolRef::Type SymType = unwrapOrError(EO: Symbol.getType(), Args: FileName);
1431 return SymbolInfoTy(Addr, Name, SymType, /*IsMappingSymbol=*/false,
1432 /*IsXCOFF=*/true);
1433 } else if (Obj.isWasm()) {
1434 uint8_t SymType =
1435 cast<WasmObjectFile>(Val: &Obj)->getWasmSymbol(Symbol).Info.Kind;
1436 return SymbolInfoTy(Addr, Name, SymType, false);
1437 } else {
1438 uint8_t Type =
1439 Obj.isELF() ? getElfSymbolType(Obj, Sym: Symbol) : (uint8_t)ELF::STT_NOTYPE;
1440 return SymbolInfoTy(Addr, Name, Type, IsMappingSymbol);
1441 }
1442}
1443
1444static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
1445 const uint64_t Addr, StringRef &Name,
1446 uint8_t Type) {
1447 if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))
1448 return SymbolInfoTy(std::nullopt, Addr, Name, std::nullopt, false);
1449 if (Obj.isWasm())
1450 return SymbolInfoTy(Addr, Name, wasm::WASM_SYMBOL_TYPE_SECTION);
1451 return SymbolInfoTy(Addr, Name, Type);
1452}
1453
1454static void collectBBAddrMapLabels(
1455 const BBAddrMapInfo &FullAddrMap, uint64_t SectionAddr, uint64_t Start,
1456 uint64_t End,
1457 std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> &Labels) {
1458 if (FullAddrMap.empty())
1459 return;
1460 Labels.clear();
1461 uint64_t StartAddress = SectionAddr + Start;
1462 uint64_t EndAddress = SectionAddr + End;
1463 const BBAddrMapFunctionEntry *FunctionMap =
1464 FullAddrMap.getEntryForAddress(BaseAddress: StartAddress);
1465 if (!FunctionMap)
1466 return;
1467 std::optional<size_t> BBRangeIndex =
1468 FunctionMap->getAddrMap().getBBRangeIndexForBaseAddress(BaseAddress: StartAddress);
1469 if (!BBRangeIndex)
1470 return;
1471 size_t NumBBEntriesBeforeRange = 0;
1472 for (size_t I = 0; I < *BBRangeIndex; ++I)
1473 NumBBEntriesBeforeRange +=
1474 FunctionMap->getAddrMap().BBRanges[I].BBEntries.size();
1475 const auto &BBRange = FunctionMap->getAddrMap().BBRanges[*BBRangeIndex];
1476 for (size_t I = 0; I < BBRange.BBEntries.size(); ++I) {
1477 const BBAddrMap::BBEntry &BBEntry = BBRange.BBEntries[I];
1478 uint64_t BBAddress = BBEntry.Offset + BBRange.BaseAddress;
1479 if (BBAddress >= EndAddress)
1480 continue;
1481
1482 std::string LabelString = ("BB" + Twine(BBEntry.ID)).str();
1483 Labels[BBAddress].push_back(
1484 x: {.BlockLabel: LabelString, .PGOAnalysis: FunctionMap->constructPGOLabelString(
1485 PGOBBEntryIndex: NumBBEntriesBeforeRange + I, PrettyPGOAnalysis: PrettyPGOAnalysisMap)});
1486 }
1487}
1488
1489static void
1490collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA,
1491 MCDisassembler *DisAsm, MCInstPrinter *IP,
1492 const MCSubtargetInfo *STI, uint64_t SectionAddr,
1493 uint64_t Start, uint64_t End,
1494 std::unordered_map<uint64_t, std::string> &Labels) {
1495 // Supported by certain targets.
1496 const bool isPPC = STI->getTargetTriple().isPPC();
1497 const bool isX86 = STI->getTargetTriple().isX86();
1498 const bool isAArch64 = STI->getTargetTriple().isAArch64();
1499 const bool isBPF = STI->getTargetTriple().isBPF();
1500 if (!isPPC && !isX86 && !isAArch64 && !isBPF)
1501 return;
1502
1503 if (MIA)
1504 MIA->resetState();
1505
1506 std::set<uint64_t> Targets;
1507 Start += SectionAddr;
1508 End += SectionAddr;
1509 const bool isXCOFF = STI->getTargetTriple().isOSBinFormatXCOFF();
1510 for (uint64_t Index = Start; Index < End;) {
1511 // Disassemble a real instruction and record function-local branch labels.
1512 MCInst Inst;
1513 uint64_t Size;
1514 ArrayRef<uint8_t> ThisBytes = Bytes.slice(N: Index - SectionAddr);
1515 bool Disassembled =
1516 DisAsm->getInstruction(Instr&: Inst, Size, Bytes: ThisBytes, Address: Index, CStream&: nulls());
1517 if (Size == 0)
1518 Size = std::min<uint64_t>(a: ThisBytes.size(),
1519 b: DisAsm->suggestBytesToSkip(Bytes: ThisBytes, Address: Index));
1520
1521 if (MIA) {
1522 if (Disassembled) {
1523 uint64_t Target;
1524 bool TargetKnown = MIA->evaluateBranch(Inst, Addr: Index, Size, Target);
1525 if (TargetKnown && (Target >= Start && Target < End) &&
1526 !Targets.count(x: Target)) {
1527 // On PowerPC and AIX, a function call is encoded as a branch to 0.
1528 // On other PowerPC platforms (ELF), a function call is encoded as
1529 // a branch to self. Do not add a label for these cases.
1530 if (!(isPPC &&
1531 ((Target == 0 && isXCOFF) || (Target == Index && !isXCOFF))))
1532 Targets.insert(x: Target);
1533 }
1534 MIA->updateState(Inst, Addr: Index);
1535 } else
1536 MIA->resetState();
1537 }
1538 Index += Size;
1539 }
1540
1541 Labels.clear();
1542 for (auto [Idx, Target] : enumerate(First&: Targets))
1543 Labels[Target] = ("L" + Twine(Idx)).str();
1544}
1545
1546// Create an MCSymbolizer for the target and add it to the MCDisassembler.
1547// This is currently only used on AMDGPU, and assumes the format of the
1548// void * argument passed to AMDGPU's createMCSymbolizer.
1549static void addSymbolizer(
1550 MCContext &Ctx, const Target *Target, StringRef TripleName,
1551 MCDisassembler *DisAsm, uint64_t SectionAddr, ArrayRef<uint8_t> Bytes,
1552 SectionSymbolsTy &Symbols,
1553 std::vector<std::unique_ptr<std::string>> &SynthesizedLabelNames) {
1554
1555 std::unique_ptr<MCRelocationInfo> RelInfo(
1556 Target->createMCRelocationInfo(TT: TripleName, Ctx));
1557 if (!RelInfo)
1558 return;
1559 std::unique_ptr<MCSymbolizer> Symbolizer(Target->createMCSymbolizer(
1560 TT: TripleName, GetOpInfo: nullptr, SymbolLookUp: nullptr, DisInfo: &Symbols, Ctx: &Ctx, RelInfo: std::move(RelInfo)));
1561 MCSymbolizer *SymbolizerPtr = &*Symbolizer;
1562 DisAsm->setSymbolizer(std::move(Symbolizer));
1563
1564 if (!SymbolizeOperands)
1565 return;
1566
1567 // Synthesize labels referenced by branch instructions by
1568 // disassembling, discarding the output, and collecting the referenced
1569 // addresses from the symbolizer.
1570 for (size_t Index = 0; Index != Bytes.size();) {
1571 MCInst Inst;
1572 uint64_t Size;
1573 ArrayRef<uint8_t> ThisBytes = Bytes.slice(N: Index);
1574 const uint64_t ThisAddr = SectionAddr + Index;
1575 DisAsm->getInstruction(Instr&: Inst, Size, Bytes: ThisBytes, Address: ThisAddr, CStream&: nulls());
1576 if (Size == 0)
1577 Size = std::min<uint64_t>(a: ThisBytes.size(),
1578 b: DisAsm->suggestBytesToSkip(Bytes: ThisBytes, Address: Index));
1579 Index += Size;
1580 }
1581 ArrayRef<uint64_t> LabelAddrsRef = SymbolizerPtr->getReferencedAddresses();
1582 // Copy and sort to remove duplicates.
1583 std::vector<uint64_t> LabelAddrs;
1584 llvm::append_range(C&: LabelAddrs, R&: LabelAddrsRef);
1585 llvm::sort(C&: LabelAddrs);
1586 LabelAddrs.resize(new_size: llvm::unique(R&: LabelAddrs) - LabelAddrs.begin());
1587 // Add the labels.
1588 for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) {
1589 auto Name = std::make_unique<std::string>();
1590 *Name = (Twine("L") + Twine(LabelNum)).str();
1591 SynthesizedLabelNames.push_back(x: std::move(Name));
1592 Symbols.push_back(x: SymbolInfoTy(
1593 LabelAddrs[LabelNum], *SynthesizedLabelNames.back(), ELF::STT_NOTYPE));
1594 }
1595 llvm::stable_sort(Range&: Symbols);
1596 // Recreate the symbolizer with the new symbols list.
1597 RelInfo.reset(p: Target->createMCRelocationInfo(TT: TripleName, Ctx));
1598 Symbolizer.reset(p: Target->createMCSymbolizer(
1599 TT: TripleName, GetOpInfo: nullptr, SymbolLookUp: nullptr, DisInfo: &Symbols, Ctx: &Ctx, RelInfo: std::move(RelInfo)));
1600 DisAsm->setSymbolizer(std::move(Symbolizer));
1601}
1602
1603static StringRef getSegmentName(const MachOObjectFile *MachO,
1604 const SectionRef &Section) {
1605 if (MachO) {
1606 DataRefImpl DR = Section.getRawDataRefImpl();
1607 StringRef SegmentName = MachO->getSectionFinalSegmentName(Sec: DR);
1608 return SegmentName;
1609 }
1610 return "";
1611}
1612
1613static void emitPostInstructionInfo(formatted_raw_ostream &FOS,
1614 const MCAsmInfo &MAI,
1615 const MCSubtargetInfo &STI,
1616 StringRef Comments,
1617 LiveVariablePrinter &LVP) {
1618 do {
1619 if (!Comments.empty()) {
1620 // Emit a line of comments.
1621 StringRef Comment;
1622 std::tie(args&: Comment, args&: Comments) = Comments.split(Separator: '\n');
1623 // MAI.getCommentColumn() assumes that instructions are printed at the
1624 // position of 8, while getInstStartColumn() returns the actual position.
1625 unsigned CommentColumn =
1626 MAI.getCommentColumn() - 8 + getInstStartColumn(STI);
1627 FOS.PadToColumn(NewCol: CommentColumn);
1628 FOS << MAI.getCommentString() << ' ' << Comment;
1629 }
1630 LVP.printAfterInst(OS&: FOS);
1631 FOS << '\n';
1632 } while (!Comments.empty());
1633 FOS.flush();
1634}
1635
1636static void createFakeELFSections(ObjectFile &Obj) {
1637 assert(Obj.isELF());
1638 if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Val: &Obj))
1639 Elf32LEObj->createFakeSections();
1640 else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Val: &Obj))
1641 Elf64LEObj->createFakeSections();
1642 else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Val: &Obj))
1643 Elf32BEObj->createFakeSections();
1644 else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Val: &Obj))
1645 Elf64BEObj->createFakeSections();
1646 else
1647 llvm_unreachable("Unsupported binary format");
1648}
1649
1650// Tries to fetch a more complete version of the given object file using its
1651// Build ID. Returns std::nullopt if nothing was found.
1652static std::optional<OwningBinary<Binary>>
1653fetchBinaryByBuildID(const ObjectFile &Obj) {
1654 object::BuildIDRef BuildID = getBuildID(Obj: &Obj);
1655 if (BuildID.empty())
1656 return std::nullopt;
1657 std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
1658 if (!Path)
1659 return std::nullopt;
1660 Expected<OwningBinary<Binary>> DebugBinary = createBinary(Path: *Path);
1661 if (!DebugBinary) {
1662 reportWarning(Message: toString(E: DebugBinary.takeError()), File: *Path);
1663 return std::nullopt;
1664 }
1665 return std::move(*DebugBinary);
1666}
1667
1668static void
1669disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
1670 DisassemblerTarget &PrimaryTarget,
1671 std::optional<DisassemblerTarget> &SecondaryTarget,
1672 SourcePrinter &SP, bool InlineRelocs, raw_ostream &OS) {
1673 DisassemblerTarget *DT = &PrimaryTarget;
1674 bool PrimaryIsThumb = false;
1675 SmallVector<std::pair<uint64_t, uint64_t>, 0> CHPECodeMap;
1676
1677 if (SecondaryTarget) {
1678 if (isArmElf(Obj)) {
1679 PrimaryIsThumb =
1680 PrimaryTarget.SubtargetInfo->checkFeatures(FS: "+thumb-mode");
1681 } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Val: &Obj)) {
1682 const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
1683 if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
1684 uintptr_t CodeMapInt;
1685 cantFail(Err: COFFObj->getRvaPtr(Rva: CHPEMetadata->CodeMap, Res&: CodeMapInt));
1686 auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);
1687
1688 for (uint32_t i = 0; i < CHPEMetadata->CodeMapCount; ++i) {
1689 if (CodeMap[i].getType() == chpe_range_type::Amd64 &&
1690 CodeMap[i].Length) {
1691 // Store x86_64 CHPE code ranges.
1692 uint64_t Start = CodeMap[i].getStart() + COFFObj->getImageBase();
1693 CHPECodeMap.emplace_back(Args&: Start, Args: Start + CodeMap[i].Length);
1694 }
1695 }
1696 llvm::sort(C&: CHPECodeMap);
1697 }
1698 }
1699 }
1700
1701 std::map<SectionRef, std::vector<RelocationRef>> RelocMap;
1702 if (InlineRelocs || Obj.isXCOFF())
1703 RelocMap = getRelocsMap(Obj);
1704 bool Is64Bits = Obj.getBytesInAddress() > 4;
1705
1706 // Create a mapping from virtual address to symbol name. This is used to
1707 // pretty print the symbols while disassembling.
1708 std::map<SectionRef, SectionSymbolsTy> AllSymbols;
1709 std::map<SectionRef, SmallVector<MappingSymbolPair, 0>> AllMappingSymbols;
1710 SectionSymbolsTy AbsoluteSymbols;
1711 const StringRef FileName = Obj.getFileName();
1712 const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Val: &Obj);
1713 for (const SymbolRef &Symbol : Obj.symbols()) {
1714 Expected<StringRef> NameOrErr = Symbol.getName();
1715 if (!NameOrErr) {
1716 reportWarning(Message: toString(E: NameOrErr.takeError()), File: FileName);
1717 continue;
1718 }
1719 if (NameOrErr->empty() && !(Obj.isXCOFF() && SymbolDescription))
1720 continue;
1721
1722 if (Obj.isELF() &&
1723 (cantFail(ValOrErr: Symbol.getFlags()) & SymbolRef::SF_FormatSpecific)) {
1724 // Symbol is intended not to be displayed by default (STT_FILE,
1725 // STT_SECTION, or a mapping symbol). Ignore STT_SECTION symbols. We will
1726 // synthesize a section symbol if no symbol is defined at offset 0.
1727 //
1728 // For a mapping symbol, store it within both AllSymbols and
1729 // AllMappingSymbols. If --show-all-symbols is unspecified, its label will
1730 // not be printed in disassembly listing.
1731 if (getElfSymbolType(Obj, Sym: Symbol) != ELF::STT_SECTION &&
1732 hasMappingSymbols(Obj)) {
1733 section_iterator SecI = unwrapOrError(EO: Symbol.getSection(), Args: FileName);
1734 if (SecI != Obj.section_end()) {
1735 uint64_t SectionAddr = SecI->getAddress();
1736 uint64_t Address = cantFail(ValOrErr: Symbol.getAddress());
1737 StringRef Name = *NameOrErr;
1738 if (Name.consume_front(Prefix: "$") && Name.size() &&
1739 strchr(s: "adtx", c: Name[0])) {
1740 AllMappingSymbols[*SecI].emplace_back(Args: Address - SectionAddr,
1741 Args: Name[0]);
1742 AllSymbols[*SecI].push_back(
1743 x: createSymbolInfo(Obj, Symbol, /*MappingSymbol=*/IsMappingSymbol: true));
1744 }
1745 }
1746 }
1747 continue;
1748 }
1749
1750 if (MachO) {
1751 // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special
1752 // symbols that support MachO header introspection. They do not bind to
1753 // code locations and are irrelevant for disassembly.
1754 if (NameOrErr->starts_with(Prefix: "__mh_") && NameOrErr->ends_with(Suffix: "_header"))
1755 continue;
1756 // Don't ask a Mach-O STAB symbol for its section unless you know that
1757 // STAB symbol's section field refers to a valid section index. Otherwise
1758 // the symbol may error trying to load a section that does not exist.
1759 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1760 uint8_t NType = (MachO->is64Bit() ?
1761 MachO->getSymbol64TableEntry(DRI: SymDRI).n_type:
1762 MachO->getSymbolTableEntry(DRI: SymDRI).n_type);
1763 if (NType & MachO::N_STAB)
1764 continue;
1765 }
1766
1767 section_iterator SecI = unwrapOrError(EO: Symbol.getSection(), Args: FileName);
1768 if (SecI != Obj.section_end())
1769 AllSymbols[*SecI].push_back(x: createSymbolInfo(Obj, Symbol));
1770 else
1771 AbsoluteSymbols.push_back(x: createSymbolInfo(Obj, Symbol));
1772 }
1773
1774 if (AllSymbols.empty() && Obj.isELF())
1775 addDynamicElfSymbols(Obj: cast<ELFObjectFileBase>(Val&: Obj), AllSymbols);
1776
1777 if (Obj.isWasm())
1778 addMissingWasmCodeSymbols(Obj: cast<WasmObjectFile>(Val&: Obj), AllSymbols);
1779
1780 if (Obj.isELF() && Obj.sections().empty())
1781 createFakeELFSections(Obj);
1782
1783 DisassemblerTarget *PltTarget = DT;
1784 auto SectionNames = getSectionNames(Obj);
1785 if (SecondaryTarget && isArmElf(Obj)) {
1786 auto PltSectionRef = SectionNames.find(Val: ".plt");
1787 if (PltSectionRef != SectionNames.end()) {
1788 bool PltIsThumb = false;
1789 for (auto [Addr, SymbolName] : AllMappingSymbols[PltSectionRef->second]) {
1790 if (Addr != 0)
1791 continue;
1792
1793 if (SymbolName == 't') {
1794 PltIsThumb = true;
1795 break;
1796 }
1797 if (SymbolName == 'a')
1798 break;
1799 }
1800
1801 if (PrimaryTarget.SubtargetInfo->checkFeatures(FS: "+thumb-mode"))
1802 PltTarget = PltIsThumb ? &PrimaryTarget : &*SecondaryTarget;
1803 else
1804 PltTarget = PltIsThumb ? &*SecondaryTarget : &PrimaryTarget;
1805 }
1806 }
1807 BumpPtrAllocator A;
1808 StringSaver Saver(A);
1809 addPltEntries(STI: *PltTarget->SubtargetInfo, Obj, SectionNames, AllSymbols,
1810 Saver);
1811
1812 // Create a mapping from virtual address to section. An empty section can
1813 // cause more than one section at the same address. Sort such sections to be
1814 // before same-addressed non-empty sections so that symbol lookups prefer the
1815 // non-empty section.
1816 std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;
1817 for (SectionRef Sec : Obj.sections())
1818 SectionAddresses.emplace_back(args: Sec.getAddress(), args&: Sec);
1819 llvm::stable_sort(Range&: SectionAddresses, C: [](const auto &LHS, const auto &RHS) {
1820 if (LHS.first != RHS.first)
1821 return LHS.first < RHS.first;
1822 return LHS.second.getSize() < RHS.second.getSize();
1823 });
1824
1825 // Linked executables (.exe and .dll files) typically don't include a real
1826 // symbol table but they might contain an export table.
1827 if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Val: &Obj)) {
1828 for (const auto &ExportEntry : COFFObj->export_directories()) {
1829 StringRef Name;
1830 if (Error E = ExportEntry.getSymbolName(Result&: Name))
1831 reportError(E: std::move(E), FileName: Obj.getFileName());
1832 if (Name.empty())
1833 continue;
1834
1835 uint32_t RVA;
1836 if (Error E = ExportEntry.getExportRVA(Result&: RVA))
1837 reportError(E: std::move(E), FileName: Obj.getFileName());
1838
1839 uint64_t VA = COFFObj->getImageBase() + RVA;
1840 auto Sec = partition_point(
1841 Range&: SectionAddresses, P: [VA](const std::pair<uint64_t, SectionRef> &O) {
1842 return O.first <= VA;
1843 });
1844 if (Sec != SectionAddresses.begin()) {
1845 --Sec;
1846 AllSymbols[Sec->second].emplace_back(args&: VA, args&: Name, args: ELF::STT_NOTYPE);
1847 } else
1848 AbsoluteSymbols.emplace_back(args&: VA, args&: Name, args: ELF::STT_NOTYPE);
1849 }
1850 }
1851
1852 // Sort all the symbols, this allows us to use a simple binary search to find
1853 // Multiple symbols can have the same address. Use a stable sort to stabilize
1854 // the output.
1855 StringSet<> FoundDisasmSymbolSet;
1856 for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
1857 llvm::stable_sort(Range&: SecSyms.second);
1858 llvm::stable_sort(Range&: AbsoluteSymbols);
1859
1860 std::unique_ptr<DWARFContext> DICtx;
1861 LiveVariablePrinter LVP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
1862
1863 if (DbgVariables != DVDisabled) {
1864 DICtx = DWARFContext::create(Obj: DbgObj);
1865 for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
1866 LVP.addCompileUnit(D: CU->getUnitDIE(ExtractUnitDIEOnly: false));
1867 }
1868
1869 LLVM_DEBUG(LVP.dump());
1870
1871 BBAddrMapInfo FullAddrMap;
1872 auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
1873 std::nullopt) {
1874 FullAddrMap.clear();
1875 if (const auto *Elf = dyn_cast<ELFObjectFileBase>(Val: &Obj)) {
1876 std::vector<PGOAnalysisMap> PGOAnalyses;
1877 auto BBAddrMapsOrErr = Elf->readBBAddrMap(TextSectionIndex: SectionIndex, PGOAnalyses: &PGOAnalyses);
1878 if (!BBAddrMapsOrErr) {
1879 reportWarning(Message: toString(E: BBAddrMapsOrErr.takeError()), File: Obj.getFileName());
1880 return;
1881 }
1882 for (auto &&[FunctionBBAddrMap, FunctionPGOAnalysis] :
1883 zip_equal(t&: *std::move(BBAddrMapsOrErr), u: std::move(PGOAnalyses))) {
1884 FullAddrMap.AddFunctionEntry(AddrMap: std::move(FunctionBBAddrMap),
1885 PGOMap: std::move(FunctionPGOAnalysis));
1886 }
1887 }
1888 };
1889
1890 // For non-relocatable objects, Read all LLVM_BB_ADDR_MAP sections into a
1891 // single mapping, since they don't have any conflicts.
1892 if (SymbolizeOperands && !Obj.isRelocatableObject())
1893 ReadBBAddrMap();
1894
1895 std::optional<llvm::BTFParser> BTF;
1896 if (InlineRelocs && BTFParser::hasBTFSections(Obj)) {
1897 BTF.emplace();
1898 BTFParser::ParseOptions Opts = {};
1899 Opts.LoadTypes = true;
1900 Opts.LoadRelocs = true;
1901 if (Error E = BTF->parse(Obj, Opts))
1902 WithColor::defaultErrorHandler(Err: std::move(E));
1903 }
1904
1905 for (const SectionRef &Section : ToolSectionFilter(O: Obj)) {
1906 if (FilterSections.empty() && !DisassembleAll &&
1907 (!Section.isText() || Section.isVirtual()))
1908 continue;
1909
1910 uint64_t SectionAddr = Section.getAddress();
1911 uint64_t SectSize = Section.getSize();
1912 if (!SectSize)
1913 continue;
1914
1915 // For relocatable object files, read the LLVM_BB_ADDR_MAP section
1916 // corresponding to this section, if present.
1917 if (SymbolizeOperands && Obj.isRelocatableObject())
1918 ReadBBAddrMap(Section.getIndex());
1919
1920 // Get the list of all the symbols in this section.
1921 SectionSymbolsTy &Symbols = AllSymbols[Section];
1922 auto &MappingSymbols = AllMappingSymbols[Section];
1923 llvm::sort(C&: MappingSymbols);
1924
1925 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
1926 Input: unwrapOrError(EO: Section.getContents(), Args: Obj.getFileName()));
1927
1928 std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;
1929 if (Obj.isELF() && Obj.getArch() == Triple::amdgcn) {
1930 // AMDGPU disassembler uses symbolizer for printing labels
1931 addSymbolizer(Ctx&: *DT->Context, Target: DT->TheTarget, TripleName, DisAsm: DT->DisAsm.get(),
1932 SectionAddr, Bytes, Symbols, SynthesizedLabelNames);
1933 }
1934
1935 StringRef SegmentName = getSegmentName(MachO, Section);
1936 StringRef SectionName = unwrapOrError(EO: Section.getName(), Args: Obj.getFileName());
1937 // If the section has no symbol at the start, just insert a dummy one.
1938 // Without --show-all-symbols, also insert one if all symbols at the start
1939 // are mapping symbols.
1940 bool CreateDummy = Symbols.empty();
1941 if (!CreateDummy) {
1942 CreateDummy = true;
1943 for (auto &Sym : Symbols) {
1944 if (Sym.Addr != SectionAddr)
1945 break;
1946 if (!Sym.IsMappingSymbol || ShowAllSymbols)
1947 CreateDummy = false;
1948 }
1949 }
1950 if (CreateDummy) {
1951 SymbolInfoTy Sym = createDummySymbolInfo(
1952 Obj, Addr: SectionAddr, Name&: SectionName,
1953 Type: Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT);
1954 if (Obj.isXCOFF())
1955 Symbols.insert(position: Symbols.begin(), x: Sym);
1956 else
1957 Symbols.insert(position: llvm::lower_bound(Range&: Symbols, Value&: Sym), x: Sym);
1958 }
1959
1960 SmallString<40> Comments;
1961 raw_svector_ostream CommentStream(Comments);
1962
1963 uint64_t VMAAdjustment = 0;
1964 if (shouldAdjustVA(Section))
1965 VMAAdjustment = AdjustVMA;
1966
1967 // In executable and shared objects, r_offset holds a virtual address.
1968 // Subtract SectionAddr from the r_offset field of a relocation to get
1969 // the section offset.
1970 uint64_t RelAdjustment = Obj.isRelocatableObject() ? 0 : SectionAddr;
1971 uint64_t Size;
1972 uint64_t Index;
1973 bool PrintedSection = false;
1974 std::vector<RelocationRef> Rels = RelocMap[Section];
1975 std::vector<RelocationRef>::const_iterator RelCur = Rels.begin();
1976 std::vector<RelocationRef>::const_iterator RelEnd = Rels.end();
1977
1978 // Loop over each chunk of code between two points where at least
1979 // one symbol is defined.
1980 for (size_t SI = 0, SE = Symbols.size(); SI != SE;) {
1981 // Advance SI past all the symbols starting at the same address,
1982 // and make an ArrayRef of them.
1983 unsigned FirstSI = SI;
1984 uint64_t Start = Symbols[SI].Addr;
1985 ArrayRef<SymbolInfoTy> SymbolsHere;
1986 while (SI != SE && Symbols[SI].Addr == Start)
1987 ++SI;
1988 SymbolsHere = ArrayRef<SymbolInfoTy>(&Symbols[FirstSI], SI - FirstSI);
1989
1990 // Get the demangled names of all those symbols. We end up with a vector
1991 // of StringRef that holds the names we're going to use, and a vector of
1992 // std::string that stores the new strings returned by demangle(), if
1993 // any. If we don't call demangle() then that vector can stay empty.
1994 std::vector<StringRef> SymNamesHere;
1995 std::vector<std::string> DemangledSymNamesHere;
1996 if (Demangle) {
1997 // Fetch the demangled names and store them locally.
1998 for (const SymbolInfoTy &Symbol : SymbolsHere)
1999 DemangledSymNamesHere.push_back(x: demangle(MangledName: Symbol.Name));
2000 // Now we've finished modifying that vector, it's safe to make
2001 // a vector of StringRefs pointing into it.
2002 SymNamesHere.insert(position: SymNamesHere.begin(), first: DemangledSymNamesHere.begin(),
2003 last: DemangledSymNamesHere.end());
2004 } else {
2005 for (const SymbolInfoTy &Symbol : SymbolsHere)
2006 SymNamesHere.push_back(x: Symbol.Name);
2007 }
2008
2009 // Distinguish ELF data from code symbols, which will be used later on to
2010 // decide whether to 'disassemble' this chunk as a data declaration via
2011 // dumpELFData(), or whether to treat it as code.
2012 //
2013 // If data _and_ code symbols are defined at the same address, the code
2014 // takes priority, on the grounds that disassembling code is our main
2015 // purpose here, and it would be a worse failure to _not_ interpret
2016 // something that _was_ meaningful as code than vice versa.
2017 //
2018 // Any ELF symbol type that is not clearly data will be regarded as code.
2019 // In particular, one of the uses of STT_NOTYPE is for branch targets
2020 // inside functions, for which STT_FUNC would be inaccurate.
2021 //
2022 // So here, we spot whether there's any non-data symbol present at all,
2023 // and only set the DisassembleAsELFData flag if there isn't. Also, we use
2024 // this distinction to inform the decision of which symbol to print at
2025 // the head of the section, so that if we're printing code, we print a
2026 // code-related symbol name to go with it.
2027 bool DisassembleAsELFData = false;
2028 size_t DisplaySymIndex = SymbolsHere.size() - 1;
2029 if (Obj.isELF() && !DisassembleAll && Section.isText()) {
2030 DisassembleAsELFData = true; // unless we find a code symbol below
2031
2032 for (size_t i = 0; i < SymbolsHere.size(); ++i) {
2033 uint8_t SymTy = SymbolsHere[i].Type;
2034 if (SymTy != ELF::STT_OBJECT && SymTy != ELF::STT_COMMON) {
2035 DisassembleAsELFData = false;
2036 DisplaySymIndex = i;
2037 }
2038 }
2039 }
2040
2041 // Decide which symbol(s) from this collection we're going to print.
2042 std::vector<bool> SymsToPrint(SymbolsHere.size(), false);
2043 // If the user has given the --disassemble-symbols option, then we must
2044 // display every symbol in that set, and no others.
2045 if (!DisasmSymbolSet.empty()) {
2046 bool FoundAny = false;
2047 for (size_t i = 0; i < SymbolsHere.size(); ++i) {
2048 if (DisasmSymbolSet.count(Key: SymNamesHere[i])) {
2049 SymsToPrint[i] = true;
2050 FoundAny = true;
2051 }
2052 }
2053
2054 // And if none of the symbols here is one that the user asked for, skip
2055 // disassembling this entire chunk of code.
2056 if (!FoundAny)
2057 continue;
2058 } else if (!SymbolsHere[DisplaySymIndex].IsMappingSymbol) {
2059 // Otherwise, print whichever symbol at this location is last in the
2060 // Symbols array, because that array is pre-sorted in a way intended to
2061 // correlate with priority of which symbol to display.
2062 SymsToPrint[DisplaySymIndex] = true;
2063 }
2064
2065 // Now that we know we're disassembling this section, override the choice
2066 // of which symbols to display by printing _all_ of them at this address
2067 // if the user asked for all symbols.
2068 //
2069 // That way, '--show-all-symbols --disassemble-symbol=foo' will print
2070 // only the chunk of code headed by 'foo', but also show any other
2071 // symbols defined at that address, such as aliases for 'foo', or the ARM
2072 // mapping symbol preceding its code.
2073 if (ShowAllSymbols) {
2074 for (size_t i = 0; i < SymbolsHere.size(); ++i)
2075 SymsToPrint[i] = true;
2076 }
2077
2078 if (Start < SectionAddr || StopAddress <= Start)
2079 continue;
2080
2081 FoundDisasmSymbolSet.insert_range(R&: SymNamesHere);
2082
2083 // The end is the section end, the beginning of the next symbol, or
2084 // --stop-address.
2085 uint64_t End = std::min<uint64_t>(a: SectionAddr + SectSize, b: StopAddress);
2086 if (SI < SE)
2087 End = std::min(a: End, b: Symbols[SI].Addr);
2088 if (Start >= End || End <= StartAddress)
2089 continue;
2090 Start -= SectionAddr;
2091 End -= SectionAddr;
2092
2093 if (!PrintedSection) {
2094 PrintedSection = true;
2095 OS << "\nDisassembly of section ";
2096 if (!SegmentName.empty())
2097 OS << SegmentName << ",";
2098 OS << SectionName << ":\n";
2099 }
2100
2101 bool PrintedLabel = false;
2102 for (size_t i = 0; i < SymbolsHere.size(); ++i) {
2103 if (!SymsToPrint[i])
2104 continue;
2105
2106 const SymbolInfoTy &Symbol = SymbolsHere[i];
2107 const StringRef SymbolName = SymNamesHere[i];
2108
2109 if (!PrintedLabel) {
2110 OS << '\n';
2111 PrintedLabel = true;
2112 }
2113 if (LeadingAddr)
2114 OS << format(Fmt: Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
2115 Vals: SectionAddr + Start + VMAAdjustment);
2116 if (Obj.isXCOFF() && SymbolDescription) {
2117 OS << getXCOFFSymbolDescription(SymbolInfo: Symbol, SymbolName) << ":\n";
2118 } else
2119 OS << '<' << SymbolName << ">:\n";
2120 }
2121
2122 // Don't print raw contents of a virtual section. A virtual section
2123 // doesn't have any contents in the file.
2124 if (Section.isVirtual()) {
2125 OS << "...\n";
2126 continue;
2127 }
2128
2129 // See if any of the symbols defined at this location triggers target-
2130 // specific disassembly behavior, e.g. of special descriptors or function
2131 // prelude information.
2132 //
2133 // We stop this loop at the first symbol that triggers some kind of
2134 // interesting behavior (if any), on the assumption that if two symbols
2135 // defined at the same address trigger two conflicting symbol handlers,
2136 // the object file is probably confused anyway, and it would make even
2137 // less sense to present the output of _both_ handlers, because that
2138 // would describe the same data twice.
2139 for (size_t SHI = 0; SHI < SymbolsHere.size(); ++SHI) {
2140 SymbolInfoTy Symbol = SymbolsHere[SHI];
2141
2142 Expected<bool> RespondedOrErr = DT->DisAsm->onSymbolStart(
2143 Symbol, Size, Bytes: Bytes.slice(N: Start, M: End - Start), Address: SectionAddr + Start);
2144
2145 if (RespondedOrErr && !*RespondedOrErr) {
2146 // This symbol didn't trigger any interesting handling. Try the other
2147 // symbols defined at this address.
2148 continue;
2149 }
2150
2151 // If onSymbolStart returned an Error, that means it identified some
2152 // kind of special data at this address, but wasn't able to disassemble
2153 // it meaningfully. So we fall back to printing the error out and
2154 // disassembling the failed region as bytes, assuming that the target
2155 // detected the failure before printing anything.
2156 if (!RespondedOrErr) {
2157 std::string ErrMsgStr = toString(E: RespondedOrErr.takeError());
2158 StringRef ErrMsg = ErrMsgStr;
2159 do {
2160 StringRef Line;
2161 std::tie(args&: Line, args&: ErrMsg) = ErrMsg.split(Separator: '\n');
2162 OS << DT->Context->getAsmInfo()->getCommentString()
2163 << " error decoding " << SymNamesHere[SHI] << ": " << Line
2164 << '\n';
2165 } while (!ErrMsg.empty());
2166
2167 if (Size) {
2168 OS << DT->Context->getAsmInfo()->getCommentString()
2169 << " decoding failed region as bytes\n";
2170 for (uint64_t I = 0; I < Size; ++I)
2171 OS << "\t.byte\t " << format_hex(N: Bytes[I], Width: 1, /*Upper=*/true)
2172 << '\n';
2173 }
2174 }
2175
2176 // Regardless of whether onSymbolStart returned an Error or true, 'Size'
2177 // will have been set to the amount of data covered by whatever prologue
2178 // the target identified. So we advance our own position to beyond that.
2179 // Sometimes that will be the entire distance to the next symbol, and
2180 // sometimes it will be just a prologue and we should start
2181 // disassembling instructions from where it left off.
2182 Start += Size;
2183 break;
2184 }
2185 formatted_raw_ostream FOS(OS);
2186 Index = Start;
2187 if (SectionAddr < StartAddress)
2188 Index = std::max<uint64_t>(a: Index, b: StartAddress - SectionAddr);
2189
2190 if (DisassembleAsELFData) {
2191 dumpELFData(SectionAddr, Index, End, Bytes, OS&: FOS);
2192 Index = End;
2193 continue;
2194 }
2195
2196 // Skip relocations from symbols that are not dumped.
2197 for (; RelCur != RelEnd; ++RelCur) {
2198 uint64_t Offset = RelCur->getOffset() - RelAdjustment;
2199 if (Index <= Offset)
2200 break;
2201 }
2202
2203 bool DumpARMELFData = false;
2204 bool DumpTracebackTableForXCOFFFunction =
2205 Obj.isXCOFF() && Section.isText() && TracebackTable &&
2206 Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&
2207 (*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);
2208
2209 std::unordered_map<uint64_t, std::string> AllLabels;
2210 std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;
2211 if (SymbolizeOperands) {
2212 collectLocalBranchTargets(Bytes, MIA: DT->InstrAnalysis.get(),
2213 DisAsm: DT->DisAsm.get(), IP: DT->InstPrinter.get(),
2214 STI: PrimaryTarget.SubtargetInfo.get(),
2215 SectionAddr, Start: Index, End, Labels&: AllLabels);
2216 collectBBAddrMapLabels(FullAddrMap, SectionAddr, Start: Index, End,
2217 Labels&: BBAddrMapLabels);
2218 }
2219
2220 if (DT->InstrAnalysis)
2221 DT->InstrAnalysis->resetState();
2222
2223 while (Index < End) {
2224 uint64_t RelOffset;
2225
2226 // ARM and AArch64 ELF binaries can interleave data and text in the
2227 // same section. We rely on the markers introduced to understand what
2228 // we need to dump. If the data marker is within a function, it is
2229 // denoted as a word/short etc.
2230 if (!MappingSymbols.empty()) {
2231 char Kind = getMappingSymbolKind(MappingSymbols, Address: Index);
2232 DumpARMELFData = Kind == 'd';
2233 if (SecondaryTarget) {
2234 if (Kind == 'a') {
2235 DT = PrimaryIsThumb ? &*SecondaryTarget : &PrimaryTarget;
2236 } else if (Kind == 't') {
2237 DT = PrimaryIsThumb ? &PrimaryTarget : &*SecondaryTarget;
2238 }
2239 }
2240 } else if (!CHPECodeMap.empty()) {
2241 uint64_t Address = SectionAddr + Index;
2242 auto It = partition_point(
2243 Range&: CHPECodeMap,
2244 P: [Address](const std::pair<uint64_t, uint64_t> &Entry) {
2245 return Entry.first <= Address;
2246 });
2247 if (It != CHPECodeMap.begin() && Address < (It - 1)->second) {
2248 DT = &*SecondaryTarget;
2249 } else {
2250 DT = &PrimaryTarget;
2251 // X64 disassembler range may have left Index unaligned, so
2252 // make sure that it's aligned when we switch back to ARM64
2253 // code.
2254 Index = llvm::alignTo(Value: Index, Align: 4);
2255 if (Index >= End)
2256 break;
2257 }
2258 }
2259
2260 auto findRel = [&]() {
2261 while (RelCur != RelEnd) {
2262 RelOffset = RelCur->getOffset() - RelAdjustment;
2263 // If this relocation is hidden, skip it.
2264 if (getHidden(RelRef: *RelCur) || SectionAddr + RelOffset < StartAddress) {
2265 ++RelCur;
2266 continue;
2267 }
2268
2269 // Stop when RelCur's offset is past the disassembled
2270 // instruction/data.
2271 if (RelOffset >= Index + Size)
2272 return false;
2273 if (RelOffset >= Index)
2274 return true;
2275 ++RelCur;
2276 }
2277 return false;
2278 };
2279
2280 // When -z or --disassemble-zeroes are given we always dissasemble
2281 // them. Otherwise we might want to skip zero bytes we see.
2282 if (!DisassembleZeroes) {
2283 uint64_t MaxOffset = End - Index;
2284 // For --reloc: print zero blocks patched by relocations, so that
2285 // relocations can be shown in the dump.
2286 if (InlineRelocs && RelCur != RelEnd)
2287 MaxOffset = std::min(a: RelCur->getOffset() - RelAdjustment - Index,
2288 b: MaxOffset);
2289
2290 if (size_t N =
2291 countSkippableZeroBytes(Buf: Bytes.slice(N: Index, M: MaxOffset))) {
2292 FOS << "\t\t..." << '\n';
2293 Index += N;
2294 continue;
2295 }
2296 }
2297
2298 if (DumpARMELFData) {
2299 Size = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,
2300 MappingSymbols, STI: *DT->SubtargetInfo, OS&: FOS);
2301 } else {
2302
2303 if (DumpTracebackTableForXCOFFFunction &&
2304 doesXCOFFTracebackTableBegin(Bytes: Bytes.slice(N: Index, M: 4))) {
2305 dumpTracebackTable(Bytes: Bytes.slice(N: Index),
2306 Address: SectionAddr + Index + VMAAdjustment, OS&: FOS,
2307 End: SectionAddr + End + VMAAdjustment,
2308 STI: *DT->SubtargetInfo, Obj: cast<XCOFFObjectFile>(Val: &Obj));
2309 Index = End;
2310 continue;
2311 }
2312
2313 // Print local label if there's any.
2314 auto Iter1 = BBAddrMapLabels.find(x: SectionAddr + Index);
2315 if (Iter1 != BBAddrMapLabels.end()) {
2316 for (const auto &BBLabel : Iter1->second)
2317 FOS << "<" << BBLabel.BlockLabel << ">" << BBLabel.PGOAnalysis
2318 << ":\n";
2319 } else {
2320 auto Iter2 = AllLabels.find(x: SectionAddr + Index);
2321 if (Iter2 != AllLabels.end())
2322 FOS << "<" << Iter2->second << ">:\n";
2323 }
2324
2325 // Disassemble a real instruction or a data when disassemble all is
2326 // provided
2327 MCInst Inst;
2328 ArrayRef<uint8_t> ThisBytes = Bytes.slice(N: Index);
2329 uint64_t ThisAddr = SectionAddr + Index + VMAAdjustment;
2330 bool Disassembled = DT->DisAsm->getInstruction(
2331 Instr&: Inst, Size, Bytes: ThisBytes, Address: ThisAddr, CStream&: CommentStream);
2332 if (Size == 0)
2333 Size = std::min<uint64_t>(
2334 a: ThisBytes.size(),
2335 b: DT->DisAsm->suggestBytesToSkip(Bytes: ThisBytes, Address: ThisAddr));
2336
2337 LVP.update(ThisAddr: {.Address: Index, .SectionIndex: Section.getIndex()},
2338 NextAddr: {.Address: Index + Size, .SectionIndex: Section.getIndex()}, IncludeDefinedVars: Index + Size != End);
2339
2340 DT->InstPrinter->setCommentStream(CommentStream);
2341
2342 DT->Printer->printInst(
2343 IP&: *DT->InstPrinter, MI: Disassembled ? &Inst : nullptr,
2344 Bytes: Bytes.slice(N: Index, M: Size),
2345 Address: {.Address: SectionAddr + Index + VMAAdjustment, .SectionIndex: Section.getIndex()}, OS&: FOS,
2346 Annot: "", STI: *DT->SubtargetInfo, SP: &SP, ObjectFilename: Obj.getFileName(), Rels: &Rels, LVP);
2347
2348 DT->InstPrinter->setCommentStream(llvm::nulls());
2349
2350 // If disassembly succeeds, we try to resolve the target address
2351 // (jump target or memory operand address) and print it to the
2352 // right of the instruction.
2353 //
2354 // Otherwise, we don't print anything else so that we avoid
2355 // analyzing invalid or incomplete instruction information.
2356 if (Disassembled && DT->InstrAnalysis) {
2357 llvm::raw_ostream *TargetOS = &FOS;
2358 uint64_t Target;
2359 bool PrintTarget = DT->InstrAnalysis->evaluateBranch(
2360 Inst, Addr: SectionAddr + Index, Size, Target);
2361
2362 if (!PrintTarget) {
2363 if (std::optional<uint64_t> MaybeTarget =
2364 DT->InstrAnalysis->evaluateMemoryOperandAddress(
2365 Inst, STI: DT->SubtargetInfo.get(), Addr: SectionAddr + Index,
2366 Size)) {
2367 Target = *MaybeTarget;
2368 PrintTarget = true;
2369 // Do not print real address when symbolizing.
2370 if (!SymbolizeOperands) {
2371 // Memory operand addresses are printed as comments.
2372 TargetOS = &CommentStream;
2373 *TargetOS << "0x" << Twine::utohexstr(Val: Target);
2374 }
2375 }
2376 }
2377
2378 if (PrintTarget) {
2379 // In a relocatable object, the target's section must reside in
2380 // the same section as the call instruction or it is accessed
2381 // through a relocation.
2382 //
2383 // In a non-relocatable object, the target may be in any section.
2384 // In that case, locate the section(s) containing the target
2385 // address and find the symbol in one of those, if possible.
2386 //
2387 // N.B. Except for XCOFF, we don't walk the relocations in the
2388 // relocatable case yet.
2389 std::vector<const SectionSymbolsTy *> TargetSectionSymbols;
2390 if (!Obj.isRelocatableObject()) {
2391 auto It = llvm::partition_point(
2392 Range&: SectionAddresses,
2393 P: [=](const std::pair<uint64_t, SectionRef> &O) {
2394 return O.first <= Target;
2395 });
2396 uint64_t TargetSecAddr = 0;
2397 while (It != SectionAddresses.begin()) {
2398 --It;
2399 if (TargetSecAddr == 0)
2400 TargetSecAddr = It->first;
2401 if (It->first != TargetSecAddr)
2402 break;
2403 TargetSectionSymbols.push_back(x: &AllSymbols[It->second]);
2404 }
2405 } else {
2406 TargetSectionSymbols.push_back(x: &Symbols);
2407 }
2408 TargetSectionSymbols.push_back(x: &AbsoluteSymbols);
2409
2410 // Find the last symbol in the first candidate section whose
2411 // offset is less than or equal to the target. If there are no
2412 // such symbols, try in the next section and so on, before finally
2413 // using the nearest preceding absolute symbol (if any), if there
2414 // are no other valid symbols.
2415 const SymbolInfoTy *TargetSym = nullptr;
2416 for (const SectionSymbolsTy *TargetSymbols :
2417 TargetSectionSymbols) {
2418 auto It = llvm::partition_point(
2419 Range: *TargetSymbols,
2420 P: [=](const SymbolInfoTy &O) { return O.Addr <= Target; });
2421 while (It != TargetSymbols->begin()) {
2422 --It;
2423 // Skip mapping symbols to avoid possible ambiguity as they
2424 // do not allow uniquely identifying the target address.
2425 if (!It->IsMappingSymbol) {
2426 TargetSym = &*It;
2427 break;
2428 }
2429 }
2430 if (TargetSym)
2431 break;
2432 }
2433
2434 // Branch targets are printed just after the instructions.
2435 // Print the labels corresponding to the target if there's any.
2436 bool BBAddrMapLabelAvailable = BBAddrMapLabels.count(x: Target);
2437 bool LabelAvailable = AllLabels.count(x: Target);
2438
2439 if (TargetSym != nullptr) {
2440 uint64_t TargetAddress = TargetSym->Addr;
2441 uint64_t Disp = Target - TargetAddress;
2442 std::string TargetName = Demangle ? demangle(MangledName: TargetSym->Name)
2443 : TargetSym->Name.str();
2444 bool RelFixedUp = false;
2445 SmallString<32> Val;
2446
2447 *TargetOS << " <";
2448 // On XCOFF, we use relocations, even without -r, so we
2449 // can print the correct name for an extern function call.
2450 if (Obj.isXCOFF() && findRel()) {
2451 // Check for possible branch relocations and
2452 // branches to fixup code.
2453 bool BranchRelocationType = true;
2454 XCOFF::RelocationType RelocType;
2455 if (Obj.is64Bit()) {
2456 const XCOFFRelocation64 *Reloc =
2457 reinterpret_cast<XCOFFRelocation64 *>(
2458 RelCur->getRawDataRefImpl().p);
2459 RelFixedUp = Reloc->isFixupIndicated();
2460 RelocType = Reloc->Type;
2461 } else {
2462 const XCOFFRelocation32 *Reloc =
2463 reinterpret_cast<XCOFFRelocation32 *>(
2464 RelCur->getRawDataRefImpl().p);
2465 RelFixedUp = Reloc->isFixupIndicated();
2466 RelocType = Reloc->Type;
2467 }
2468 BranchRelocationType =
2469 RelocType == XCOFF::R_BA || RelocType == XCOFF::R_BR ||
2470 RelocType == XCOFF::R_RBA || RelocType == XCOFF::R_RBR;
2471
2472 // If we have a valid relocation, try to print its
2473 // corresponding symbol name. Multiple relocations on the
2474 // same instruction are not handled.
2475 // Branches to fixup code will have the RelFixedUp flag set in
2476 // the RLD. For these instructions, we print the correct
2477 // branch target, but print the referenced symbol as a
2478 // comment.
2479 if (Error E = getRelocationValueString(Rel: *RelCur, SymbolDescription: false, Result&: Val)) {
2480 // If -r was used, this error will be printed later.
2481 // Otherwise, we ignore the error and print what
2482 // would have been printed without using relocations.
2483 consumeError(Err: std::move(E));
2484 *TargetOS << TargetName;
2485 RelFixedUp = false; // Suppress comment for RLD sym name
2486 } else if (BranchRelocationType && !RelFixedUp)
2487 *TargetOS << Val;
2488 else
2489 *TargetOS << TargetName;
2490 if (Disp)
2491 *TargetOS << "+0x" << Twine::utohexstr(Val: Disp);
2492 } else if (!Disp) {
2493 *TargetOS << TargetName;
2494 } else if (BBAddrMapLabelAvailable) {
2495 *TargetOS << BBAddrMapLabels[Target].front().BlockLabel;
2496 } else if (LabelAvailable) {
2497 *TargetOS << AllLabels[Target];
2498 } else {
2499 // Always Print the binary symbol plus an offset if there's no
2500 // local label corresponding to the target address.
2501 *TargetOS << TargetName << "+0x" << Twine::utohexstr(Val: Disp);
2502 }
2503 *TargetOS << ">";
2504 if (RelFixedUp && !InlineRelocs) {
2505 // We have fixup code for a relocation. We print the
2506 // referenced symbol as a comment.
2507 *TargetOS << "\t# " << Val;
2508 }
2509
2510 } else if (BBAddrMapLabelAvailable) {
2511 *TargetOS << " <" << BBAddrMapLabels[Target].front().BlockLabel
2512 << ">";
2513 } else if (LabelAvailable) {
2514 *TargetOS << " <" << AllLabels[Target] << ">";
2515 }
2516 // By convention, each record in the comment stream should be
2517 // terminated.
2518 if (TargetOS == &CommentStream)
2519 *TargetOS << "\n";
2520 }
2521
2522 DT->InstrAnalysis->updateState(Inst, Addr: SectionAddr + Index);
2523 } else if (!Disassembled && DT->InstrAnalysis) {
2524 DT->InstrAnalysis->resetState();
2525 }
2526 }
2527
2528 assert(DT->Context->getAsmInfo());
2529 emitPostInstructionInfo(FOS, MAI: *DT->Context->getAsmInfo(),
2530 STI: *DT->SubtargetInfo, Comments: CommentStream.str(), LVP);
2531 Comments.clear();
2532
2533 if (BTF)
2534 printBTFRelocation(FOS, BTF&: *BTF, Address: {.Address: Index, .SectionIndex: Section.getIndex()}, LVP);
2535
2536 // Hexagon handles relocs in pretty printer
2537 if (InlineRelocs && Obj.getArch() != Triple::hexagon) {
2538 while (findRel()) {
2539 // When --adjust-vma is used, update the address printed.
2540 printRelocation(OS&: FOS, FileName: Obj.getFileName(), Rel: *RelCur,
2541 Address: SectionAddr + RelOffset + VMAAdjustment, Is64Bits);
2542 LVP.printAfterOtherLine(OS&: FOS, AfterInst: true);
2543 ++RelCur;
2544 }
2545 }
2546
2547 Index += Size;
2548 }
2549 }
2550 }
2551 StringSet<> MissingDisasmSymbolSet =
2552 set_difference(S1: DisasmSymbolSet, S2: FoundDisasmSymbolSet);
2553 for (StringRef Sym : MissingDisasmSymbolSet.keys())
2554 reportWarning(Message: "failed to disassemble missing symbol " + Sym, File: FileName);
2555}
2556
2557static void disassembleObject(ObjectFile *Obj, bool InlineRelocs,
2558 raw_ostream &OS) {
2559 // If information useful for showing the disassembly is missing, try to find a
2560 // more complete binary and disassemble that instead.
2561 OwningBinary<Binary> FetchedBinary;
2562 if (Obj->symbols().empty()) {
2563 if (std::optional<OwningBinary<Binary>> FetchedBinaryOpt =
2564 fetchBinaryByBuildID(Obj: *Obj)) {
2565 if (auto *O = dyn_cast<ObjectFile>(Val: FetchedBinaryOpt->getBinary())) {
2566 if (!O->symbols().empty() ||
2567 (!O->sections().empty() && Obj->sections().empty())) {
2568 FetchedBinary = std::move(*FetchedBinaryOpt);
2569 Obj = O;
2570 }
2571 }
2572 }
2573 }
2574
2575 const Target *TheTarget = getTarget(Obj);
2576
2577 // Package up features to be passed to target/subtarget
2578 Expected<SubtargetFeatures> FeaturesValue = Obj->getFeatures();
2579 if (!FeaturesValue)
2580 reportError(E: FeaturesValue.takeError(), FileName: Obj->getFileName());
2581 SubtargetFeatures Features = *FeaturesValue;
2582 if (!MAttrs.empty()) {
2583 for (unsigned I = 0; I != MAttrs.size(); ++I)
2584 Features.AddFeature(String: MAttrs[I]);
2585 } else if (MCPU.empty() && Obj->makeTriple().isAArch64()) {
2586 Features.AddFeature(String: "+all");
2587 }
2588
2589 if (MCPU.empty())
2590 MCPU = Obj->tryGetCPUName().value_or(u: "").str();
2591
2592 if (isArmElf(Obj: *Obj)) {
2593 // When disassembling big-endian Arm ELF, the instruction endianness is
2594 // determined in a complex way. In relocatable objects, AAELF32 mandates
2595 // that instruction endianness matches the ELF file endianness; in
2596 // executable images, that's true unless the file header has the EF_ARM_BE8
2597 // flag, in which case instructions are little-endian regardless of data
2598 // endianness.
2599 //
2600 // We must set the big-endian-instructions SubtargetFeature to make the
2601 // disassembler read the instructions the right way round, and also tell
2602 // our own prettyprinter to retrieve the encodings the same way to print in
2603 // hex.
2604 const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(Val: Obj);
2605
2606 if (Elf32BE && (Elf32BE->isRelocatableObject() ||
2607 !(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8))) {
2608 Features.AddFeature(String: "+big-endian-instructions");
2609 ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::big);
2610 } else {
2611 ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::little);
2612 }
2613 }
2614
2615 DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);
2616
2617 // If we have an ARM object file, we need a second disassembler, because
2618 // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
2619 // We use mapping symbols to switch between the two assemblers, where
2620 // appropriate.
2621 std::optional<DisassemblerTarget> SecondaryTarget;
2622
2623 if (isArmElf(Obj: *Obj)) {
2624 if (!PrimaryTarget.SubtargetInfo->checkFeatures(FS: "+mclass")) {
2625 if (PrimaryTarget.SubtargetInfo->checkFeatures(FS: "+thumb-mode"))
2626 Features.AddFeature(String: "-thumb-mode");
2627 else
2628 Features.AddFeature(String: "+thumb-mode");
2629 SecondaryTarget.emplace(args&: PrimaryTarget, args&: Features);
2630 }
2631 } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Val: Obj)) {
2632 const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
2633 if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
2634 // Set up x86_64 disassembler for ARM64EC binaries.
2635 Triple X64Triple(TripleName);
2636 X64Triple.setArch(Kind: Triple::ArchType::x86_64);
2637
2638 std::string Error;
2639 const Target *X64Target =
2640 TargetRegistry::lookupTarget(ArchName: "", TheTriple&: X64Triple, Error);
2641 if (X64Target) {
2642 SubtargetFeatures X64Features;
2643 SecondaryTarget.emplace(args&: X64Target, args&: *Obj, args: X64Triple.getTriple(), args: "",
2644 args&: X64Features);
2645 } else {
2646 reportWarning(Message: Error, File: Obj->getFileName());
2647 }
2648 }
2649 }
2650
2651 const ObjectFile *DbgObj = Obj;
2652 if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
2653 if (std::optional<OwningBinary<Binary>> DebugBinaryOpt =
2654 fetchBinaryByBuildID(Obj: *Obj)) {
2655 if (auto *FetchedObj =
2656 dyn_cast<const ObjectFile>(Val: DebugBinaryOpt->getBinary())) {
2657 if (FetchedObj->hasDebugInfo()) {
2658 FetchedBinary = std::move(*DebugBinaryOpt);
2659 DbgObj = FetchedObj;
2660 }
2661 }
2662 }
2663 }
2664
2665 std::unique_ptr<object::Binary> DSYMBinary;
2666 std::unique_ptr<MemoryBuffer> DSYMBuf;
2667 if (!DbgObj->hasDebugInfo()) {
2668 if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Val: &*Obj)) {
2669 DbgObj = objdump::getMachODSymObject(O: MachOOF, Filename: Obj->getFileName(),
2670 DSYMBinary, DSYMBuf);
2671 if (!DbgObj)
2672 return;
2673 }
2674 }
2675
2676 SourcePrinter SP(DbgObj, TheTarget->getName());
2677
2678 for (StringRef Opt : DisassemblerOptions)
2679 if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))
2680 reportError(File: Obj->getFileName(),
2681 Message: "Unrecognized disassembler option: " + Opt);
2682
2683 disassembleObject(Obj&: *Obj, DbgObj: *DbgObj, PrimaryTarget, SecondaryTarget, SP,
2684 InlineRelocs, OS);
2685}
2686
2687void Dumper::printRelocations() {
2688 StringRef Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
2689
2690 // Build a mapping from relocation target to a vector of relocation
2691 // sections. Usually, there is an only one relocation section for
2692 // each relocated section.
2693 MapVector<SectionRef, std::vector<SectionRef>> SecToRelSec;
2694 uint64_t Ndx;
2695 for (const SectionRef &Section : ToolSectionFilter(O, Idx: &Ndx)) {
2696 if (O.isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))
2697 continue;
2698 if (Section.relocation_begin() == Section.relocation_end())
2699 continue;
2700 Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
2701 if (!SecOrErr)
2702 reportError(File: O.getFileName(),
2703 Message: "section (" + Twine(Ndx) +
2704 "): unable to get a relocation target: " +
2705 toString(E: SecOrErr.takeError()));
2706 SecToRelSec[**SecOrErr].push_back(x: Section);
2707 }
2708
2709 for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {
2710 StringRef SecName = unwrapOrError(EO: P.first.getName(), Args: O.getFileName());
2711 outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";
2712 uint32_t OffsetPadding = (O.getBytesInAddress() > 4 ? 16 : 8);
2713 uint32_t TypePadding = 24;
2714 outs() << left_justify(Str: "OFFSET", Width: OffsetPadding) << " "
2715 << left_justify(Str: "TYPE", Width: TypePadding) << " "
2716 << "VALUE\n";
2717
2718 for (SectionRef Section : P.second) {
2719 // CREL sections require decoding, each section may have its own specific
2720 // decode problems.
2721 if (O.isELF() && ELFSectionRef(Section).getType() == ELF::SHT_CREL) {
2722 StringRef Err =
2723 cast<const ELFObjectFileBase>(Val: O).getCrelDecodeProblem(Sec: Section);
2724 if (!Err.empty()) {
2725 reportUniqueWarning(Msg: Err);
2726 continue;
2727 }
2728 }
2729 for (const RelocationRef &Reloc : Section.relocations()) {
2730 uint64_t Address = Reloc.getOffset();
2731 SmallString<32> RelocName;
2732 SmallString<32> ValueStr;
2733 if (Address < StartAddress || Address > StopAddress || getHidden(RelRef: Reloc))
2734 continue;
2735 Reloc.getTypeName(Result&: RelocName);
2736 if (Error E =
2737 getRelocationValueString(Rel: Reloc, SymbolDescription, Result&: ValueStr))
2738 reportUniqueWarning(Err: std::move(E));
2739
2740 outs() << format(Fmt: Fmt.data(), Vals: Address) << " "
2741 << left_justify(Str: RelocName, Width: TypePadding) << " " << ValueStr
2742 << "\n";
2743 }
2744 }
2745 }
2746}
2747
2748// Returns true if we need to show LMA column when dumping section headers. We
2749// show it only when the platform is ELF and either we have at least one section
2750// whose VMA and LMA are different and/or when --show-lma flag is used.
2751static bool shouldDisplayLMA(const ObjectFile &Obj) {
2752 if (!Obj.isELF())
2753 return false;
2754 for (const SectionRef &S : ToolSectionFilter(O: Obj))
2755 if (S.getAddress() != getELFSectionLMA(Sec: S))
2756 return true;
2757 return ShowLMA;
2758}
2759
2760static size_t getMaxSectionNameWidth(const ObjectFile &Obj) {
2761 // Default column width for names is 13 even if no names are that long.
2762 size_t MaxWidth = 13;
2763 for (const SectionRef &Section : ToolSectionFilter(O: Obj)) {
2764 StringRef Name = unwrapOrError(EO: Section.getName(), Args: Obj.getFileName());
2765 MaxWidth = std::max(a: MaxWidth, b: Name.size());
2766 }
2767 return MaxWidth;
2768}
2769
2770void objdump::printSectionHeaders(ObjectFile &Obj) {
2771 if (Obj.isELF() && Obj.sections().empty())
2772 createFakeELFSections(Obj);
2773
2774 size_t NameWidth = getMaxSectionNameWidth(Obj);
2775 size_t AddressWidth = 2 * Obj.getBytesInAddress();
2776 bool HasLMAColumn = shouldDisplayLMA(Obj);
2777 outs() << "\nSections:\n";
2778 if (HasLMAColumn)
2779 outs() << "Idx " << left_justify(Str: "Name", Width: NameWidth) << " Size "
2780 << left_justify(Str: "VMA", Width: AddressWidth) << " "
2781 << left_justify(Str: "LMA", Width: AddressWidth) << " Type\n";
2782 else
2783 outs() << "Idx " << left_justify(Str: "Name", Width: NameWidth) << " Size "
2784 << left_justify(Str: "VMA", Width: AddressWidth) << " Type\n";
2785
2786 uint64_t Idx;
2787 for (const SectionRef &Section : ToolSectionFilter(O: Obj, Idx: &Idx)) {
2788 StringRef Name = unwrapOrError(EO: Section.getName(), Args: Obj.getFileName());
2789 uint64_t VMA = Section.getAddress();
2790 if (shouldAdjustVA(Section))
2791 VMA += AdjustVMA;
2792
2793 uint64_t Size = Section.getSize();
2794
2795 std::string Type = Section.isText() ? "TEXT" : "";
2796 if (Section.isData())
2797 Type += Type.empty() ? "DATA" : ", DATA";
2798 if (Section.isBSS())
2799 Type += Type.empty() ? "BSS" : ", BSS";
2800 if (Section.isDebugSection())
2801 Type += Type.empty() ? "DEBUG" : ", DEBUG";
2802
2803 if (HasLMAColumn)
2804 outs() << format(Fmt: "%3" PRIu64 " %-*s %08" PRIx64 " ", Vals: Idx, Vals: NameWidth,
2805 Vals: Name.str().c_str(), Vals: Size)
2806 << format_hex_no_prefix(N: VMA, Width: AddressWidth) << " "
2807 << format_hex_no_prefix(N: getELFSectionLMA(Sec: Section), Width: AddressWidth)
2808 << " " << Type << "\n";
2809 else
2810 outs() << format(Fmt: "%3" PRIu64 " %-*s %08" PRIx64 " ", Vals: Idx, Vals: NameWidth,
2811 Vals: Name.str().c_str(), Vals: Size)
2812 << format_hex_no_prefix(N: VMA, Width: AddressWidth) << " " << Type << "\n";
2813 }
2814}
2815
2816void objdump::printSectionContents(const ObjectFile *Obj) {
2817 const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Val: Obj);
2818
2819 for (const SectionRef &Section : ToolSectionFilter(O: *Obj)) {
2820 StringRef Name = unwrapOrError(EO: Section.getName(), Args: Obj->getFileName());
2821 uint64_t BaseAddr = Section.getAddress();
2822 uint64_t Size = Section.getSize();
2823 if (!Size)
2824 continue;
2825
2826 outs() << "Contents of section ";
2827 StringRef SegmentName = getSegmentName(MachO, Section);
2828 if (!SegmentName.empty())
2829 outs() << SegmentName << ",";
2830 outs() << Name << ":\n";
2831 if (Section.isBSS()) {
2832 outs() << format(Fmt: "<skipping contents of bss section at [%04" PRIx64
2833 ", %04" PRIx64 ")>\n",
2834 Vals: BaseAddr, Vals: BaseAddr + Size);
2835 continue;
2836 }
2837
2838 StringRef Contents = unwrapOrError(EO: Section.getContents(), Args: Obj->getFileName());
2839
2840 // Dump out the content as hex and printable ascii characters.
2841 for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {
2842 outs() << format(Fmt: " %04" PRIx64 " ", Vals: BaseAddr + Addr);
2843 // Dump line of hex.
2844 for (std::size_t I = 0; I < 16; ++I) {
2845 if (I != 0 && I % 4 == 0)
2846 outs() << ' ';
2847 if (Addr + I < End)
2848 outs() << hexdigit(X: (Contents[Addr + I] >> 4) & 0xF, LowerCase: true)
2849 << hexdigit(X: Contents[Addr + I] & 0xF, LowerCase: true);
2850 else
2851 outs() << " ";
2852 }
2853 // Print ascii.
2854 outs() << " ";
2855 for (std::size_t I = 0; I < 16 && Addr + I < End; ++I) {
2856 if (isPrint(C: static_cast<unsigned char>(Contents[Addr + I]) & 0xFF))
2857 outs() << Contents[Addr + I];
2858 else
2859 outs() << ".";
2860 }
2861 outs() << "\n";
2862 }
2863 }
2864}
2865
2866void Dumper::printSymbolTable(StringRef ArchiveName, StringRef ArchitectureName,
2867 bool DumpDynamic) {
2868 if (O.isCOFF() && !DumpDynamic) {
2869 outs() << "\nSYMBOL TABLE:\n";
2870 printCOFFSymbolTable(O: cast<const COFFObjectFile>(Val: O));
2871 return;
2872 }
2873
2874 const StringRef FileName = O.getFileName();
2875
2876 if (!DumpDynamic) {
2877 outs() << "\nSYMBOL TABLE:\n";
2878 for (auto I = O.symbol_begin(); I != O.symbol_end(); ++I)
2879 printSymbol(Symbol: *I, SymbolVersions: {}, FileName, ArchiveName, ArchitectureName, DumpDynamic);
2880 return;
2881 }
2882
2883 outs() << "\nDYNAMIC SYMBOL TABLE:\n";
2884 if (!O.isELF()) {
2885 reportWarning(
2886 Message: "this operation is not currently supported for this file format",
2887 File: FileName);
2888 return;
2889 }
2890
2891 const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(Val: &O);
2892 auto Symbols = ELF->getDynamicSymbolIterators();
2893 Expected<std::vector<VersionEntry>> SymbolVersionsOrErr =
2894 ELF->readDynsymVersions();
2895 if (!SymbolVersionsOrErr) {
2896 reportWarning(Message: toString(E: SymbolVersionsOrErr.takeError()), File: FileName);
2897 SymbolVersionsOrErr = std::vector<VersionEntry>();
2898 (void)!SymbolVersionsOrErr;
2899 }
2900 for (auto &Sym : Symbols)
2901 printSymbol(Symbol: Sym, SymbolVersions: *SymbolVersionsOrErr, FileName, ArchiveName,
2902 ArchitectureName, DumpDynamic);
2903}
2904
2905void Dumper::printSymbol(const SymbolRef &Symbol,
2906 ArrayRef<VersionEntry> SymbolVersions,
2907 StringRef FileName, StringRef ArchiveName,
2908 StringRef ArchitectureName, bool DumpDynamic) {
2909 const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Val: &O);
2910 Expected<uint64_t> AddrOrErr = Symbol.getAddress();
2911 if (!AddrOrErr) {
2912 reportUniqueWarning(Err: AddrOrErr.takeError());
2913 return;
2914 }
2915
2916 // Don't ask a Mach-O STAB symbol for its section unless you know that
2917 // STAB symbol's section field refers to a valid section index. Otherwise
2918 // the symbol may error trying to load a section that does not exist.
2919 bool IsSTAB = false;
2920 if (MachO) {
2921 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
2922 uint8_t NType =
2923 (MachO->is64Bit() ? MachO->getSymbol64TableEntry(DRI: SymDRI).n_type
2924 : MachO->getSymbolTableEntry(DRI: SymDRI).n_type);
2925 if (NType & MachO::N_STAB)
2926 IsSTAB = true;
2927 }
2928 section_iterator Section = IsSTAB
2929 ? O.section_end()
2930 : unwrapOrError(EO: Symbol.getSection(), Args&: FileName,
2931 Args&: ArchiveName, Args&: ArchitectureName);
2932
2933 uint64_t Address = *AddrOrErr;
2934 if (Section != O.section_end() && shouldAdjustVA(Section: *Section))
2935 Address += AdjustVMA;
2936 if ((Address < StartAddress) || (Address > StopAddress))
2937 return;
2938 SymbolRef::Type Type =
2939 unwrapOrError(EO: Symbol.getType(), Args&: FileName, Args&: ArchiveName, Args&: ArchitectureName);
2940 uint32_t Flags =
2941 unwrapOrError(EO: Symbol.getFlags(), Args&: FileName, Args&: ArchiveName, Args&: ArchitectureName);
2942
2943 StringRef Name;
2944 if (Type == SymbolRef::ST_Debug && Section != O.section_end()) {
2945 if (Expected<StringRef> NameOrErr = Section->getName())
2946 Name = *NameOrErr;
2947 else
2948 consumeError(Err: NameOrErr.takeError());
2949
2950 } else {
2951 Name = unwrapOrError(EO: Symbol.getName(), Args&: FileName, Args&: ArchiveName,
2952 Args&: ArchitectureName);
2953 }
2954
2955 bool Global = Flags & SymbolRef::SF_Global;
2956 bool Weak = Flags & SymbolRef::SF_Weak;
2957 bool Absolute = Flags & SymbolRef::SF_Absolute;
2958 bool Common = Flags & SymbolRef::SF_Common;
2959 bool Hidden = Flags & SymbolRef::SF_Hidden;
2960
2961 char GlobLoc = ' ';
2962 if ((Section != O.section_end() || Absolute) && !Weak)
2963 GlobLoc = Global ? 'g' : 'l';
2964 char IFunc = ' ';
2965 if (O.isELF()) {
2966 if (ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC)
2967 IFunc = 'i';
2968 if (ELFSymbolRef(Symbol).getBinding() == ELF::STB_GNU_UNIQUE)
2969 GlobLoc = 'u';
2970 }
2971
2972 char Debug = ' ';
2973 if (DumpDynamic)
2974 Debug = 'D';
2975 else if (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
2976 Debug = 'd';
2977
2978 char FileFunc = ' ';
2979 if (Type == SymbolRef::ST_File)
2980 FileFunc = 'f';
2981 else if (Type == SymbolRef::ST_Function)
2982 FileFunc = 'F';
2983 else if (Type == SymbolRef::ST_Data)
2984 FileFunc = 'O';
2985
2986 const char *Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
2987
2988 outs() << format(Fmt, Vals: Address) << " "
2989 << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
2990 << (Weak ? 'w' : ' ') // Weak?
2991 << ' ' // Constructor. Not supported yet.
2992 << ' ' // Warning. Not supported yet.
2993 << IFunc // Indirect reference to another symbol.
2994 << Debug // Debugging (d) or dynamic (D) symbol.
2995 << FileFunc // Name of function (F), file (f) or object (O).
2996 << ' ';
2997 if (Absolute) {
2998 outs() << "*ABS*";
2999 } else if (Common) {
3000 outs() << "*COM*";
3001 } else if (Section == O.section_end()) {
3002 if (O.isXCOFF()) {
3003 XCOFFSymbolRef XCOFFSym = cast<const XCOFFObjectFile>(Val: O).toSymbolRef(
3004 Ref: Symbol.getRawDataRefImpl());
3005 if (XCOFF::N_DEBUG == XCOFFSym.getSectionNumber())
3006 outs() << "*DEBUG*";
3007 else
3008 outs() << "*UND*";
3009 } else
3010 outs() << "*UND*";
3011 } else {
3012 StringRef SegmentName = getSegmentName(MachO, Section: *Section);
3013 if (!SegmentName.empty())
3014 outs() << SegmentName << ",";
3015 StringRef SectionName = unwrapOrError(EO: Section->getName(), Args&: FileName);
3016 outs() << SectionName;
3017 if (O.isXCOFF()) {
3018 std::optional<SymbolRef> SymRef =
3019 getXCOFFSymbolContainingSymbolRef(Obj: cast<XCOFFObjectFile>(Val: O), Sym: Symbol);
3020 if (SymRef) {
3021
3022 Expected<StringRef> NameOrErr = SymRef->getName();
3023
3024 if (NameOrErr) {
3025 outs() << " (csect:";
3026 std::string SymName =
3027 Demangle ? demangle(MangledName: *NameOrErr) : NameOrErr->str();
3028
3029 if (SymbolDescription)
3030 SymName = getXCOFFSymbolDescription(SymbolInfo: createSymbolInfo(Obj: O, Symbol: *SymRef),
3031 SymbolName: SymName);
3032
3033 outs() << ' ' << SymName;
3034 outs() << ") ";
3035 } else
3036 reportWarning(Message: toString(E: NameOrErr.takeError()), File: FileName);
3037 }
3038 }
3039 }
3040
3041 if (Common)
3042 outs() << '\t' << format(Fmt, Vals: static_cast<uint64_t>(Symbol.getAlignment()));
3043 else if (O.isXCOFF())
3044 outs() << '\t'
3045 << format(Fmt, Vals: cast<XCOFFObjectFile>(Val: O).getSymbolSize(
3046 Symb: Symbol.getRawDataRefImpl()));
3047 else if (O.isELF())
3048 outs() << '\t' << format(Fmt, Vals: ELFSymbolRef(Symbol).getSize());
3049 else if (O.isWasm())
3050 outs() << '\t'
3051 << format(Fmt, Vals: static_cast<uint64_t>(
3052 cast<WasmObjectFile>(Val: O).getSymbolSize(Sym: Symbol)));
3053
3054 if (O.isELF()) {
3055 if (!SymbolVersions.empty()) {
3056 const VersionEntry &Ver =
3057 SymbolVersions[Symbol.getRawDataRefImpl().d.b - 1];
3058 std::string Str;
3059 if (!Ver.Name.empty())
3060 Str = Ver.IsVerDef ? ' ' + Ver.Name : '(' + Ver.Name + ')';
3061 outs() << ' ' << left_justify(Str, Width: 12);
3062 }
3063
3064 uint8_t Other = ELFSymbolRef(Symbol).getOther();
3065 switch (Other) {
3066 case ELF::STV_DEFAULT:
3067 break;
3068 case ELF::STV_INTERNAL:
3069 outs() << " .internal";
3070 break;
3071 case ELF::STV_HIDDEN:
3072 outs() << " .hidden";
3073 break;
3074 case ELF::STV_PROTECTED:
3075 outs() << " .protected";
3076 break;
3077 default:
3078 outs() << format(Fmt: " 0x%02x", Vals: Other);
3079 break;
3080 }
3081 } else if (Hidden) {
3082 outs() << " .hidden";
3083 }
3084
3085 std::string SymName = Demangle ? demangle(MangledName: Name) : Name.str();
3086 if (O.isXCOFF() && SymbolDescription)
3087 SymName = getXCOFFSymbolDescription(SymbolInfo: createSymbolInfo(Obj: O, Symbol), SymbolName: SymName);
3088
3089 outs() << ' ' << SymName << '\n';
3090}
3091
3092static void printUnwindInfo(const ObjectFile *O) {
3093 outs() << "Unwind info:\n\n";
3094
3095 if (const COFFObjectFile *Coff = dyn_cast<COFFObjectFile>(Val: O))
3096 printCOFFUnwindInfo(O: Coff);
3097 else if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: O))
3098 printMachOUnwindInfo(O: MachO);
3099 else
3100 // TODO: Extract DWARF dump tool to objdump.
3101 WithColor::error(OS&: errs(), Prefix: ToolName)
3102 << "This operation is only currently supported "
3103 "for COFF and MachO object files.\n";
3104}
3105
3106/// Dump the raw contents of the __clangast section so the output can be piped
3107/// into llvm-bcanalyzer.
3108static void printRawClangAST(const ObjectFile *Obj) {
3109 if (outs().is_displayed()) {
3110 WithColor::error(OS&: errs(), Prefix: ToolName)
3111 << "The -raw-clang-ast option will dump the raw binary contents of "
3112 "the clang ast section.\n"
3113 "Please redirect the output to a file or another program such as "
3114 "llvm-bcanalyzer.\n";
3115 return;
3116 }
3117
3118 StringRef ClangASTSectionName("__clangast");
3119 if (Obj->isCOFF()) {
3120 ClangASTSectionName = "clangast";
3121 }
3122
3123 std::optional<object::SectionRef> ClangASTSection;
3124 for (auto Sec : ToolSectionFilter(O: *Obj)) {
3125 StringRef Name;
3126 if (Expected<StringRef> NameOrErr = Sec.getName())
3127 Name = *NameOrErr;
3128 else
3129 consumeError(Err: NameOrErr.takeError());
3130
3131 if (Name == ClangASTSectionName) {
3132 ClangASTSection = Sec;
3133 break;
3134 }
3135 }
3136 if (!ClangASTSection)
3137 return;
3138
3139 StringRef ClangASTContents =
3140 unwrapOrError(EO: ClangASTSection->getContents(), Args: Obj->getFileName());
3141 outs().write(Ptr: ClangASTContents.data(), Size: ClangASTContents.size());
3142}
3143
3144static void printFaultMaps(const ObjectFile *Obj) {
3145 StringRef FaultMapSectionName;
3146
3147 if (Obj->isELF()) {
3148 FaultMapSectionName = ".llvm_faultmaps";
3149 } else if (Obj->isMachO()) {
3150 FaultMapSectionName = "__llvm_faultmaps";
3151 } else {
3152 WithColor::error(OS&: errs(), Prefix: ToolName)
3153 << "This operation is only currently supported "
3154 "for ELF and Mach-O executable files.\n";
3155 return;
3156 }
3157
3158 std::optional<object::SectionRef> FaultMapSection;
3159
3160 for (auto Sec : ToolSectionFilter(O: *Obj)) {
3161 StringRef Name;
3162 if (Expected<StringRef> NameOrErr = Sec.getName())
3163 Name = *NameOrErr;
3164 else
3165 consumeError(Err: NameOrErr.takeError());
3166
3167 if (Name == FaultMapSectionName) {
3168 FaultMapSection = Sec;
3169 break;
3170 }
3171 }
3172
3173 outs() << "FaultMap table:\n";
3174
3175 if (!FaultMapSection) {
3176 outs() << "<not found>\n";
3177 return;
3178 }
3179
3180 StringRef FaultMapContents =
3181 unwrapOrError(EO: FaultMapSection->getContents(), Args: Obj->getFileName());
3182 FaultMapParser FMP(FaultMapContents.bytes_begin(),
3183 FaultMapContents.bytes_end());
3184
3185 outs() << FMP;
3186}
3187
3188void Dumper::printPrivateHeaders() {
3189 reportError(File: O.getFileName(), Message: "Invalid/Unsupported object file format");
3190}
3191
3192static void printFileHeaders(const ObjectFile *O) {
3193 if (!O->isELF() && !O->isCOFF() && !O->isXCOFF())
3194 reportError(File: O->getFileName(), Message: "Invalid/Unsupported object file format");
3195
3196 Triple::ArchType AT = O->getArch();
3197 outs() << "architecture: " << Triple::getArchTypeName(Kind: AT) << "\n";
3198 uint64_t Address = unwrapOrError(EO: O->getStartAddress(), Args: O->getFileName());
3199
3200 StringRef Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
3201 outs() << "start address: "
3202 << "0x" << format(Fmt: Fmt.data(), Vals: Address) << "\n";
3203}
3204
3205static void printArchiveChild(StringRef Filename, const Archive::Child &C) {
3206 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
3207 if (!ModeOrErr) {
3208 WithColor::error(OS&: errs(), Prefix: ToolName) << "ill-formed archive entry.\n";
3209 consumeError(Err: ModeOrErr.takeError());
3210 return;
3211 }
3212 sys::fs::perms Mode = ModeOrErr.get();
3213 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
3214 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
3215 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
3216 outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
3217 outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
3218 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
3219 outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
3220 outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
3221 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
3222
3223 outs() << " ";
3224
3225 outs() << format(Fmt: "%d/%d %6" PRId64 " ", Vals: unwrapOrError(EO: C.getUID(), Args&: Filename),
3226 Vals: unwrapOrError(EO: C.getGID(), Args&: Filename),
3227 Vals: unwrapOrError(EO: C.getRawSize(), Args&: Filename));
3228
3229 StringRef RawLastModified = C.getRawLastModified();
3230 unsigned Seconds;
3231 if (RawLastModified.getAsInteger(Radix: 10, Result&: Seconds))
3232 outs() << "(date: \"" << RawLastModified
3233 << "\" contains non-decimal chars) ";
3234 else {
3235 // Since ctime(3) returns a 26 character string of the form:
3236 // "Sun Sep 16 01:03:52 1973\n\0"
3237 // just print 24 characters.
3238 time_t t = Seconds;
3239 outs() << format(Fmt: "%.24s ", Vals: ctime(timer: &t));
3240 }
3241
3242 StringRef Name = "";
3243 Expected<StringRef> NameOrErr = C.getName();
3244 if (!NameOrErr) {
3245 consumeError(Err: NameOrErr.takeError());
3246 Name = unwrapOrError(EO: C.getRawName(), Args&: Filename);
3247 } else {
3248 Name = NameOrErr.get();
3249 }
3250 outs() << Name << "\n";
3251}
3252
3253// For ELF only now.
3254static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {
3255 if (const auto *Elf = dyn_cast<ELFObjectFileBase>(Val: Obj)) {
3256 if (Elf->getEType() != ELF::ET_REL)
3257 return true;
3258 }
3259 return false;
3260}
3261
3262static void checkForInvalidStartStopAddress(ObjectFile *Obj,
3263 uint64_t Start, uint64_t Stop) {
3264 if (!shouldWarnForInvalidStartStopAddress(Obj))
3265 return;
3266
3267 for (const SectionRef &Section : Obj->sections())
3268 if (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC) {
3269 uint64_t BaseAddr = Section.getAddress();
3270 uint64_t Size = Section.getSize();
3271 if ((Start < BaseAddr + Size) && Stop > BaseAddr)
3272 return;
3273 }
3274
3275 if (!HasStartAddressFlag)
3276 reportWarning(Message: "no section has address less than 0x" +
3277 Twine::utohexstr(Val: Stop) + " specified by --stop-address",
3278 File: Obj->getFileName());
3279 else if (!HasStopAddressFlag)
3280 reportWarning(Message: "no section has address greater than or equal to 0x" +
3281 Twine::utohexstr(Val: Start) + " specified by --start-address",
3282 File: Obj->getFileName());
3283 else
3284 reportWarning(Message: "no section overlaps the range [0x" +
3285 Twine::utohexstr(Val: Start) + ",0x" + Twine::utohexstr(Val: Stop) +
3286 ") specified by --start-address/--stop-address",
3287 File: Obj->getFileName());
3288}
3289
3290static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
3291 const Archive::Child *C = nullptr) {
3292 Expected<std::unique_ptr<Dumper>> DumperOrErr = createDumper(Obj: *O);
3293 if (!DumperOrErr) {
3294 reportError(E: DumperOrErr.takeError(), FileName: O->getFileName(),
3295 ArchiveName: A ? A->getFileName() : "");
3296 return;
3297 }
3298 Dumper &D = **DumperOrErr;
3299
3300 // Avoid other output when using a raw option.
3301 if (!RawClangAST) {
3302 outs() << '\n';
3303 if (A)
3304 outs() << A->getFileName() << "(" << O->getFileName() << ")";
3305 else
3306 outs() << O->getFileName();
3307 outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n";
3308 }
3309
3310 if (HasStartAddressFlag || HasStopAddressFlag)
3311 checkForInvalidStartStopAddress(Obj: O, Start: StartAddress, Stop: StopAddress);
3312
3313 // TODO: Change print* free functions to Dumper member functions to utilitize
3314 // stateful functions like reportUniqueWarning.
3315
3316 // Note: the order here matches GNU objdump for compatability.
3317 StringRef ArchiveName = A ? A->getFileName() : "";
3318 if (ArchiveHeaders && !MachOOpt && C)
3319 printArchiveChild(Filename: ArchiveName, C: *C);
3320 if (FileHeaders)
3321 printFileHeaders(O);
3322 if (PrivateHeaders || FirstPrivateHeader)
3323 D.printPrivateHeaders();
3324 if (SectionHeaders)
3325 printSectionHeaders(Obj&: *O);
3326 if (SymbolTable)
3327 D.printSymbolTable(ArchiveName);
3328 if (DynamicSymbolTable)
3329 D.printSymbolTable(ArchiveName, /*ArchitectureName=*/"",
3330 /*DumpDynamic=*/true);
3331 if (DwarfDumpType != DIDT_Null) {
3332 std::unique_ptr<DIContext> DICtx = DWARFContext::create(Obj: *O);
3333 // Dump the complete DWARF structure.
3334 DIDumpOptions DumpOpts;
3335 DumpOpts.DumpType = DwarfDumpType;
3336 DICtx->dump(OS&: outs(), DumpOpts);
3337 }
3338 if (Relocations && !Disassemble)
3339 D.printRelocations();
3340 if (DynamicRelocations)
3341 D.printDynamicRelocations();
3342 if (SectionContents)
3343 printSectionContents(Obj: O);
3344 if (Disassemble)
3345 disassembleObject(Obj: O, InlineRelocs: Relocations, OS&: outs());
3346 if (UnwindInfo)
3347 printUnwindInfo(O);
3348
3349 // Mach-O specific options:
3350 if (ExportsTrie)
3351 printExportsTrie(O);
3352 if (Rebase)
3353 printRebaseTable(O);
3354 if (Bind)
3355 printBindTable(O);
3356 if (LazyBind)
3357 printLazyBindTable(O);
3358 if (WeakBind)
3359 printWeakBindTable(O);
3360
3361 // Other special sections:
3362 if (RawClangAST)
3363 printRawClangAST(Obj: O);
3364 if (FaultMapSection)
3365 printFaultMaps(Obj: O);
3366 if (Offloading)
3367 dumpOffloadBinary(O: *O, ArchName: StringRef(ArchName));
3368}
3369
3370static void dumpObject(const COFFImportFile *I, const Archive *A,
3371 const Archive::Child *C = nullptr) {
3372 StringRef ArchiveName = A ? A->getFileName() : "";
3373
3374 // Avoid other output when using a raw option.
3375 if (!RawClangAST)
3376 outs() << '\n'
3377 << ArchiveName << "(" << I->getFileName() << ")"
3378 << ":\tfile format COFF-import-file"
3379 << "\n\n";
3380
3381 if (ArchiveHeaders && !MachOOpt && C)
3382 printArchiveChild(Filename: ArchiveName, C: *C);
3383 if (SymbolTable)
3384 printCOFFSymbolTable(I: *I);
3385}
3386
3387/// Dump each object file in \a a;
3388static void dumpArchive(const Archive *A) {
3389 Error Err = Error::success();
3390 unsigned I = -1;
3391 for (auto &C : A->children(Err)) {
3392 ++I;
3393 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
3394 if (!ChildOrErr) {
3395 if (auto E = isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
3396 reportError(E: std::move(E), FileName: getFileNameForError(C, Index: I), ArchiveName: A->getFileName());
3397 continue;
3398 }
3399 if (ObjectFile *O = dyn_cast<ObjectFile>(Val: &*ChildOrErr.get()))
3400 dumpObject(O, A, C: &C);
3401 else if (COFFImportFile *I = dyn_cast<COFFImportFile>(Val: &*ChildOrErr.get()))
3402 dumpObject(I, A, C: &C);
3403 else
3404 reportError(E: errorCodeToError(EC: object_error::invalid_file_type),
3405 FileName: A->getFileName());
3406 }
3407 if (Err)
3408 reportError(E: std::move(Err), FileName: A->getFileName());
3409}
3410
3411/// Open file and figure out how to dump it.
3412static void dumpInput(StringRef file) {
3413 // If we are using the Mach-O specific object file parser, then let it parse
3414 // the file and process the command line options. So the -arch flags can
3415 // be used to select specific slices, etc.
3416 if (MachOOpt) {
3417 parseInputMachO(Filename: file);
3418 return;
3419 }
3420
3421 // Attempt to open the binary.
3422 OwningBinary<Binary> OBinary = unwrapOrError(EO: createBinary(Path: file), Args&: file);
3423 Binary &Binary = *OBinary.getBinary();
3424
3425 if (Archive *A = dyn_cast<Archive>(Val: &Binary))
3426 dumpArchive(A);
3427 else if (ObjectFile *O = dyn_cast<ObjectFile>(Val: &Binary))
3428 dumpObject(O);
3429 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Val: &Binary))
3430 parseInputMachO(UB);
3431 else if (OffloadBinary *OB = dyn_cast<OffloadBinary>(Val: &Binary))
3432 dumpOffloadSections(OB: *OB);
3433 else
3434 reportError(E: errorCodeToError(EC: object_error::invalid_file_type), FileName: file);
3435}
3436
3437template <typename T>
3438static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
3439 T &Value) {
3440 if (const opt::Arg *A = InputArgs.getLastArg(Ids: ID)) {
3441 StringRef V(A->getValue());
3442 if (!llvm::to_integer(V, Value, 0)) {
3443 reportCmdLineError(Message: A->getSpelling() +
3444 ": expected a non-negative integer, but got '" + V +
3445 "'");
3446 }
3447 }
3448}
3449
3450static object::BuildID parseBuildIDArg(const opt::Arg *A) {
3451 StringRef V(A->getValue());
3452 object::BuildID BID = parseBuildID(Str: V);
3453 if (BID.empty())
3454 reportCmdLineError(Message: A->getSpelling() + ": expected a build ID, but got '" +
3455 V + "'");
3456 return BID;
3457}
3458
3459void objdump::invalidArgValue(const opt::Arg *A) {
3460 reportCmdLineError(Message: "'" + StringRef(A->getValue()) +
3461 "' is not a valid value for '" + A->getSpelling() + "'");
3462}
3463
3464static std::vector<std::string>
3465commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
3466 std::vector<std::string> Values;
3467 for (StringRef Value : InputArgs.getAllArgValues(Id: ID)) {
3468 llvm::SmallVector<StringRef, 2> SplitValues;
3469 llvm::SplitString(Source: Value, OutFragments&: SplitValues, Delimiters: ",");
3470 for (StringRef SplitValue : SplitValues)
3471 Values.push_back(x: SplitValue.str());
3472 }
3473 return Values;
3474}
3475
3476static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
3477 MachOOpt = true;
3478 FullLeadingAddr = true;
3479 PrintImmHex = true;
3480
3481 ArchName = InputArgs.getLastArgValue(Id: OTOOL_arch).str();
3482 LinkOptHints = InputArgs.hasArg(Ids: OTOOL_C);
3483 if (InputArgs.hasArg(Ids: OTOOL_d))
3484 FilterSections.push_back(x: "__DATA,__data");
3485 DylibId = InputArgs.hasArg(Ids: OTOOL_D);
3486 UniversalHeaders = InputArgs.hasArg(Ids: OTOOL_f);
3487 DataInCode = InputArgs.hasArg(Ids: OTOOL_G);
3488 FirstPrivateHeader = InputArgs.hasArg(Ids: OTOOL_h);
3489 IndirectSymbols = InputArgs.hasArg(Ids: OTOOL_I);
3490 ShowRawInsn = InputArgs.hasArg(Ids: OTOOL_j);
3491 PrivateHeaders = InputArgs.hasArg(Ids: OTOOL_l);
3492 DylibsUsed = InputArgs.hasArg(Ids: OTOOL_L);
3493 MCPU = InputArgs.getLastArgValue(Id: OTOOL_mcpu_EQ).str();
3494 ObjcMetaData = InputArgs.hasArg(Ids: OTOOL_o);
3495 DisSymName = InputArgs.getLastArgValue(Id: OTOOL_p).str();
3496 InfoPlist = InputArgs.hasArg(Ids: OTOOL_P);
3497 Relocations = InputArgs.hasArg(Ids: OTOOL_r);
3498 if (const Arg *A = InputArgs.getLastArg(Ids: OTOOL_s)) {
3499 auto Filter = (A->getValue(N: 0) + StringRef(",") + A->getValue(N: 1)).str();
3500 FilterSections.push_back(x: Filter);
3501 }
3502 if (InputArgs.hasArg(Ids: OTOOL_t))
3503 FilterSections.push_back(x: "__TEXT,__text");
3504 Verbose = InputArgs.hasArg(Ids: OTOOL_v) || InputArgs.hasArg(Ids: OTOOL_V) ||
3505 InputArgs.hasArg(Ids: OTOOL_o);
3506 SymbolicOperands = InputArgs.hasArg(Ids: OTOOL_V);
3507 if (InputArgs.hasArg(Ids: OTOOL_x))
3508 FilterSections.push_back(x: ",__text");
3509 LeadingAddr = LeadingHeaders = !InputArgs.hasArg(Ids: OTOOL_X);
3510
3511 ChainedFixups = InputArgs.hasArg(Ids: OTOOL_chained_fixups);
3512 DyldInfo = InputArgs.hasArg(Ids: OTOOL_dyld_info);
3513
3514 InputFilenames = InputArgs.getAllArgValues(Id: OTOOL_INPUT);
3515 if (InputFilenames.empty())
3516 reportCmdLineError(Message: "no input file");
3517
3518 for (const Arg *A : InputArgs) {
3519 const Option &O = A->getOption();
3520 if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {
3521 reportCmdLineWarning(Message: O.getPrefixedName() +
3522 " is obsolete and not implemented");
3523 }
3524 }
3525}
3526
3527static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
3528 parseIntArg(InputArgs, ID: OBJDUMP_adjust_vma_EQ, Value&: AdjustVMA);
3529 AllHeaders = InputArgs.hasArg(Ids: OBJDUMP_all_headers);
3530 ArchName = InputArgs.getLastArgValue(Id: OBJDUMP_arch_name_EQ).str();
3531 ArchiveHeaders = InputArgs.hasArg(Ids: OBJDUMP_archive_headers);
3532 Demangle = InputArgs.hasArg(Ids: OBJDUMP_demangle);
3533 Disassemble = InputArgs.hasArg(Ids: OBJDUMP_disassemble);
3534 DisassembleAll = InputArgs.hasArg(Ids: OBJDUMP_disassemble_all);
3535 SymbolDescription = InputArgs.hasArg(Ids: OBJDUMP_symbol_description);
3536 TracebackTable = InputArgs.hasArg(Ids: OBJDUMP_traceback_table);
3537 DisassembleSymbols =
3538 commaSeparatedValues(InputArgs, ID: OBJDUMP_disassemble_symbols_EQ);
3539 DisassembleZeroes = InputArgs.hasArg(Ids: OBJDUMP_disassemble_zeroes);
3540 if (const opt::Arg *A = InputArgs.getLastArg(Ids: OBJDUMP_dwarf_EQ)) {
3541 DwarfDumpType = StringSwitch<DIDumpType>(A->getValue())
3542 .Case(S: "frames", Value: DIDT_DebugFrame)
3543 .Default(Value: DIDT_Null);
3544 if (DwarfDumpType == DIDT_Null)
3545 invalidArgValue(A);
3546 }
3547 DynamicRelocations = InputArgs.hasArg(Ids: OBJDUMP_dynamic_reloc);
3548 FaultMapSection = InputArgs.hasArg(Ids: OBJDUMP_fault_map_section);
3549 Offloading = InputArgs.hasArg(Ids: OBJDUMP_offloading);
3550 FileHeaders = InputArgs.hasArg(Ids: OBJDUMP_file_headers);
3551 SectionContents = InputArgs.hasArg(Ids: OBJDUMP_full_contents);
3552 PrintLines = InputArgs.hasArg(Ids: OBJDUMP_line_numbers);
3553 InputFilenames = InputArgs.getAllArgValues(Id: OBJDUMP_INPUT);
3554 MachOOpt = InputArgs.hasArg(Ids: OBJDUMP_macho);
3555 MCPU = InputArgs.getLastArgValue(Id: OBJDUMP_mcpu_EQ).str();
3556 MAttrs = commaSeparatedValues(InputArgs, ID: OBJDUMP_mattr_EQ);
3557 ShowRawInsn = !InputArgs.hasArg(Ids: OBJDUMP_no_show_raw_insn);
3558 LeadingAddr = !InputArgs.hasArg(Ids: OBJDUMP_no_leading_addr);
3559 RawClangAST = InputArgs.hasArg(Ids: OBJDUMP_raw_clang_ast);
3560 Relocations = InputArgs.hasArg(Ids: OBJDUMP_reloc);
3561 PrintImmHex =
3562 InputArgs.hasFlag(Pos: OBJDUMP_print_imm_hex, Neg: OBJDUMP_no_print_imm_hex, Default: true);
3563 PrivateHeaders = InputArgs.hasArg(Ids: OBJDUMP_private_headers);
3564 FilterSections = InputArgs.getAllArgValues(Id: OBJDUMP_section_EQ);
3565 SectionHeaders = InputArgs.hasArg(Ids: OBJDUMP_section_headers);
3566 ShowAllSymbols = InputArgs.hasArg(Ids: OBJDUMP_show_all_symbols);
3567 ShowLMA = InputArgs.hasArg(Ids: OBJDUMP_show_lma);
3568 PrintSource = InputArgs.hasArg(Ids: OBJDUMP_source);
3569 parseIntArg(InputArgs, ID: OBJDUMP_start_address_EQ, Value&: StartAddress);
3570 HasStartAddressFlag = InputArgs.hasArg(Ids: OBJDUMP_start_address_EQ);
3571 parseIntArg(InputArgs, ID: OBJDUMP_stop_address_EQ, Value&: StopAddress);
3572 HasStopAddressFlag = InputArgs.hasArg(Ids: OBJDUMP_stop_address_EQ);
3573 SymbolTable = InputArgs.hasArg(Ids: OBJDUMP_syms);
3574 SymbolizeOperands = InputArgs.hasArg(Ids: OBJDUMP_symbolize_operands);
3575 PrettyPGOAnalysisMap = InputArgs.hasArg(Ids: OBJDUMP_pretty_pgo_analysis_map);
3576 if (PrettyPGOAnalysisMap && !SymbolizeOperands)
3577 reportCmdLineWarning(Message: "--symbolize-operands must be enabled for "
3578 "--pretty-pgo-analysis-map to have an effect");
3579 DynamicSymbolTable = InputArgs.hasArg(Ids: OBJDUMP_dynamic_syms);
3580 TripleName = InputArgs.getLastArgValue(Id: OBJDUMP_triple_EQ).str();
3581 UnwindInfo = InputArgs.hasArg(Ids: OBJDUMP_unwind_info);
3582 Wide = InputArgs.hasArg(Ids: OBJDUMP_wide);
3583 Prefix = InputArgs.getLastArgValue(Id: OBJDUMP_prefix).str();
3584 parseIntArg(InputArgs, ID: OBJDUMP_prefix_strip, Value&: PrefixStrip);
3585 if (const opt::Arg *A = InputArgs.getLastArg(Ids: OBJDUMP_debug_vars_EQ)) {
3586 DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
3587 .Case(S: "ascii", Value: DVASCII)
3588 .Case(S: "unicode", Value: DVUnicode)
3589 .Default(Value: DVInvalid);
3590 if (DbgVariables == DVInvalid)
3591 invalidArgValue(A);
3592 }
3593 if (const opt::Arg *A = InputArgs.getLastArg(Ids: OBJDUMP_disassembler_color_EQ)) {
3594 DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())
3595 .Case(S: "on", Value: ColorOutput::Enable)
3596 .Case(S: "off", Value: ColorOutput::Disable)
3597 .Case(S: "terminal", Value: ColorOutput::Auto)
3598 .Default(Value: ColorOutput::Invalid);
3599 if (DisassemblyColor == ColorOutput::Invalid)
3600 invalidArgValue(A);
3601 }
3602
3603 parseIntArg(InputArgs, ID: OBJDUMP_debug_vars_indent_EQ, Value&: DbgIndent);
3604
3605 parseMachOOptions(InputArgs);
3606
3607 // Parse -M (--disassembler-options) and deprecated
3608 // --x86-asm-syntax={att,intel}.
3609 //
3610 // Note, for x86, the asm dialect (AssemblerDialect) is initialized when the
3611 // MCAsmInfo is constructed. MCInstPrinter::applyTargetSpecificCLOption is
3612 // called too late. For now we have to use the internal cl::opt option.
3613 const char *AsmSyntax = nullptr;
3614 for (const auto *A : InputArgs.filtered(Ids: OBJDUMP_disassembler_options_EQ,
3615 Ids: OBJDUMP_x86_asm_syntax_att,
3616 Ids: OBJDUMP_x86_asm_syntax_intel)) {
3617 switch (A->getOption().getID()) {
3618 case OBJDUMP_x86_asm_syntax_att:
3619 AsmSyntax = "--x86-asm-syntax=att";
3620 continue;
3621 case OBJDUMP_x86_asm_syntax_intel:
3622 AsmSyntax = "--x86-asm-syntax=intel";
3623 continue;
3624 }
3625
3626 SmallVector<StringRef, 2> Values;
3627 llvm::SplitString(Source: A->getValue(), OutFragments&: Values, Delimiters: ",");
3628 for (StringRef V : Values) {
3629 if (V == "att")
3630 AsmSyntax = "--x86-asm-syntax=att";
3631 else if (V == "intel")
3632 AsmSyntax = "--x86-asm-syntax=intel";
3633 else
3634 DisassemblerOptions.push_back(x: V.str());
3635 }
3636 }
3637 SmallVector<const char *> Args = {"llvm-objdump"};
3638 for (const opt::Arg *A : InputArgs.filtered(Ids: OBJDUMP_mllvm))
3639 Args.push_back(Elt: A->getValue());
3640 if (AsmSyntax)
3641 Args.push_back(Elt: AsmSyntax);
3642 if (Args.size() > 1)
3643 llvm::cl::ParseCommandLineOptions(argc: Args.size(), argv: Args.data());
3644
3645 // Look up any provided build IDs, then append them to the input filenames.
3646 for (const opt::Arg *A : InputArgs.filtered(Ids: OBJDUMP_build_id)) {
3647 object::BuildID BuildID = parseBuildIDArg(A);
3648 std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
3649 if (!Path) {
3650 reportCmdLineError(Message: A->getSpelling() + ": could not find build ID '" +
3651 A->getValue() + "'");
3652 }
3653 InputFilenames.push_back(x: std::move(*Path));
3654 }
3655
3656 // objdump defaults to a.out if no filenames specified.
3657 if (InputFilenames.empty())
3658 InputFilenames.push_back(x: "a.out");
3659}
3660
3661int llvm_objdump_main(int argc, char **argv, const llvm::ToolContext &) {
3662 using namespace llvm;
3663
3664 ToolName = argv[0];
3665 std::unique_ptr<CommonOptTable> T;
3666 OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;
3667
3668 StringRef Stem = sys::path::stem(path: ToolName);
3669 auto Is = [=](StringRef Tool) {
3670 // We need to recognize the following filenames:
3671 //
3672 // llvm-objdump -> objdump
3673 // llvm-otool-10.exe -> otool
3674 // powerpc64-unknown-freebsd13-objdump -> objdump
3675 auto I = Stem.rfind_insensitive(Str: Tool);
3676 return I != StringRef::npos &&
3677 (I + Tool.size() == Stem.size() || !isAlnum(C: Stem[I + Tool.size()]));
3678 };
3679 if (Is("otool")) {
3680 T = std::make_unique<OtoolOptTable>();
3681 Unknown = OTOOL_UNKNOWN;
3682 HelpFlag = OTOOL_help;
3683 HelpHiddenFlag = OTOOL_help_hidden;
3684 VersionFlag = OTOOL_version;
3685 } else {
3686 T = std::make_unique<ObjdumpOptTable>();
3687 Unknown = OBJDUMP_UNKNOWN;
3688 HelpFlag = OBJDUMP_help;
3689 HelpHiddenFlag = OBJDUMP_help_hidden;
3690 VersionFlag = OBJDUMP_version;
3691 }
3692
3693 BumpPtrAllocator A;
3694 StringSaver Saver(A);
3695 opt::InputArgList InputArgs =
3696 T->parseArgs(Argc: argc, Argv: argv, Unknown, Saver,
3697 ErrorFn: [&](StringRef Msg) { reportCmdLineError(Message: Msg); });
3698
3699 if (InputArgs.size() == 0 || InputArgs.hasArg(Ids: HelpFlag)) {
3700 T->printHelp(Argv0: ToolName);
3701 return 0;
3702 }
3703 if (InputArgs.hasArg(Ids: HelpHiddenFlag)) {
3704 T->printHelp(Argv0: ToolName, /*ShowHidden=*/true);
3705 return 0;
3706 }
3707
3708 // Initialize targets and assembly printers/parsers.
3709 InitializeAllTargetInfos();
3710 InitializeAllTargetMCs();
3711 InitializeAllDisassemblers();
3712
3713 if (InputArgs.hasArg(Ids: VersionFlag)) {
3714 cl::PrintVersionMessage();
3715 if (!Is("otool")) {
3716 outs() << '\n';
3717 TargetRegistry::printRegisteredTargetsForVersion(OS&: outs());
3718 }
3719 return 0;
3720 }
3721
3722 // Initialize debuginfod.
3723 const bool ShouldUseDebuginfodByDefault =
3724 InputArgs.hasArg(Ids: OBJDUMP_build_id) || canUseDebuginfod();
3725 std::vector<std::string> DebugFileDirectories =
3726 InputArgs.getAllArgValues(Id: OBJDUMP_debug_file_directory);
3727 if (InputArgs.hasFlag(Pos: OBJDUMP_debuginfod, Neg: OBJDUMP_no_debuginfod,
3728 Default: ShouldUseDebuginfodByDefault)) {
3729 HTTPClient::initialize();
3730 BIDFetcher =
3731 std::make_unique<DebuginfodFetcher>(args: std::move(DebugFileDirectories));
3732 } else {
3733 BIDFetcher =
3734 std::make_unique<BuildIDFetcher>(args: std::move(DebugFileDirectories));
3735 }
3736
3737 if (Is("otool"))
3738 parseOtoolOptions(InputArgs);
3739 else
3740 parseObjdumpOptions(InputArgs);
3741
3742 if (StartAddress >= StopAddress)
3743 reportCmdLineError(Message: "start address should be less than stop address");
3744
3745 // Removes trailing separators from prefix.
3746 while (!Prefix.empty() && sys::path::is_separator(value: Prefix.back()))
3747 Prefix.pop_back();
3748
3749 if (AllHeaders)
3750 ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =
3751 SectionHeaders = SymbolTable = true;
3752
3753 if (DisassembleAll || PrintSource || PrintLines || TracebackTable ||
3754 !DisassembleSymbols.empty())
3755 Disassemble = true;
3756
3757 if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null &&
3758 !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&
3759 !Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&
3760 !DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading &&
3761 !(MachOOpt &&
3762 (Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||
3763 DylibsUsed || ExportsTrie || FirstPrivateHeader ||
3764 FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||
3765 InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
3766 Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()))) {
3767 T->printHelp(Argv0: ToolName);
3768 return 2;
3769 }
3770
3771 DisasmSymbolSet.insert_range(R&: DisassembleSymbols);
3772
3773 llvm::for_each(Range&: InputFilenames, F: dumpInput);
3774
3775 warnOnNoMatchForSections();
3776
3777 return EXIT_SUCCESS;
3778}
3779