#include "llvm-dwarfdump.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <cstdlib>
usingnamespacellvm;
usingnamespacellvm::dwarfdump;
usingnamespacellvm::object;
namespace {
struct OffsetOption { … };
struct BoolOption : public OffsetOption { … };
}
namespace llvm {
namespace cl {
template <>
class parser<OffsetOption> final : public basic_parser<OffsetOption> { … };
template <> class parser<BoolOption> final : public basic_parser<BoolOption> { … };
}
}
namespace {
usingnamespacecl;
enum ErrorDetailLevel { … };
OptionCategory DwarfDumpCategory("Specific Options");
static list<std::string>
InputFilenames(Positional, desc("<input object files or .dSYM bundles>"),
cat(DwarfDumpCategory));
cl::OptionCategory SectionCategory("Section-specific Dump Options",
"These control which sections are dumped. "
"Where applicable these parameters take an "
"optional =<offset> argument to dump only "
"the entry at the specified offset.");
static opt<bool> DumpAll("all", desc("Dump all debug info sections"),
cat(SectionCategory));
static alias DumpAllAlias("a", desc("Alias for --all"), aliasopt(DumpAll),
cl::NotHidden);
static unsigned DumpType = …;
static std::array<std::optional<uint64_t>, (unsigned)DIDT_ID_Count> DumpOffsets;
#define HANDLE_DWARF_SECTION …
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
static alias DumpDebugFrameAlias("eh-frame", desc("Alias for --debug-frame"),
NotHidden, cat(SectionCategory),
aliasopt(DumpDebugFrame));
static list<std::string>
ArchFilters("arch",
desc("Dump debug information for the specified CPU "
"architecture only. Architectures may be specified by "
"name or by number. This option can be specified "
"multiple times, once for each desired architecture."),
cat(DwarfDumpCategory));
static opt<bool>
Diff("diff",
desc("Emit diff-friendly output by omitting offsets and addresses."),
cat(DwarfDumpCategory));
static list<std::string>
Find("find",
desc("Search for the exact match for <name> in the accelerator tables "
"and print the matching debug information entries. When no "
"accelerator tables are available, the slower but more complete "
"-name option can be used instead."),
value_desc("name"), cat(DwarfDumpCategory));
static alias FindAlias("f", desc("Alias for --find."), aliasopt(Find),
cl::NotHidden);
static opt<bool> FindAllApple(
"find-all-apple",
desc("Print every debug information entry in the accelerator tables."),
cat(DwarfDumpCategory));
static opt<bool> IgnoreCase("ignore-case",
desc("Ignore case distinctions when using --name."),
value_desc("i"), cat(DwarfDumpCategory));
static opt<bool> DumpNonSkeleton(
"dwo",
desc("Dump the non skeleton DIE in the .dwo or .dwp file after dumping the "
"skeleton DIE from the main executable. This allows dumping the .dwo "
"files with resolved addresses."),
value_desc("d"), cat(DwarfDumpCategory));
static alias IgnoreCaseAlias("i", desc("Alias for --ignore-case."),
aliasopt(IgnoreCase), cl::NotHidden);
static list<std::string> Name(
"name",
desc("Find and print all debug info entries whose name (DW_AT_name "
"attribute) matches the exact text in <pattern>. When used with the "
"the -regex option <pattern> is interpreted as a regular expression."),
value_desc("pattern"), cat(DwarfDumpCategory));
static alias NameAlias("n", desc("Alias for --name"), aliasopt(Name),
cl::NotHidden);
static opt<uint64_t>
Lookup("lookup",
desc("Lookup <address> in the debug information and print out any "
"available file, function, block and line table details."),
value_desc("address"), cat(DwarfDumpCategory));
static opt<std::string>
OutputFilename("o", cl::init("-"),
cl::desc("Redirect output to the specified file."),
cl::value_desc("filename"), cat(DwarfDumpCategory));
static alias OutputFilenameAlias("out-file", desc("Alias for -o."),
aliasopt(OutputFilename));
static opt<bool> UseRegex(
"regex",
desc("Treat any <pattern> strings as regular "
"expressions when searching with --name. If --ignore-case is also "
"specified, the regular expression becomes case-insensitive."),
cat(DwarfDumpCategory));
static alias RegexAlias("x", desc("Alias for --regex"), aliasopt(UseRegex),
cl::NotHidden);
static opt<bool>
ShowChildren("show-children",
desc("Show a debug info entry's children when selectively "
"printing entries."),
cat(DwarfDumpCategory));
static alias ShowChildrenAlias("c", desc("Alias for --show-children."),
aliasopt(ShowChildren), cl::NotHidden);
static opt<bool>
ShowParents("show-parents",
desc("Show a debug info entry's parents when selectively "
"printing entries."),
cat(DwarfDumpCategory));
static alias ShowParentsAlias("p", desc("Alias for --show-parents."),
aliasopt(ShowParents), cl::NotHidden);
static opt<bool>
ShowForm("show-form",
desc("Show DWARF form types after the DWARF attribute types."),
cat(DwarfDumpCategory));
static alias ShowFormAlias("F", desc("Alias for --show-form."),
aliasopt(ShowForm), cat(DwarfDumpCategory),
cl::NotHidden);
static opt<unsigned>
ChildRecurseDepth("recurse-depth",
desc("Only recurse to a depth of N when displaying "
"children of debug info entries."),
cat(DwarfDumpCategory), init(-1U), value_desc("N"));
static alias ChildRecurseDepthAlias("r", desc("Alias for --recurse-depth."),
aliasopt(ChildRecurseDepth), cl::NotHidden);
static opt<unsigned>
ParentRecurseDepth("parent-recurse-depth",
desc("Only recurse to a depth of N when displaying "
"parents of debug info entries."),
cat(DwarfDumpCategory), init(-1U), value_desc("N"));
static opt<bool>
SummarizeTypes("summarize-types",
desc("Abbreviate the description of type unit entries."),
cat(DwarfDumpCategory));
static cl::opt<bool>
Statistics("statistics",
cl::desc("Emit JSON-formatted debug info quality metrics."),
cat(DwarfDumpCategory));
static cl::opt<bool>
ShowSectionSizes("show-section-sizes",
cl::desc("Show the sizes of all debug sections, "
"expressed in bytes."),
cat(DwarfDumpCategory));
static cl::opt<bool> ManuallyGenerateUnitIndex(
"manually-generate-unit-index",
cl::desc("if the input is dwp file, parse .debug_info "
"section and use it to populate "
"DW_SECT_INFO contributions in cu-index. "
"For DWARF5 it also populated TU Index."),
cl::init(false), cl::Hidden, cl::cat(DwarfDumpCategory));
static cl::opt<bool>
ShowSources("show-sources",
cl::desc("Show the sources across all compilation units."),
cat(DwarfDumpCategory));
static opt<bool> Verify("verify", desc("Verify the DWARF debug info."),
cat(DwarfDumpCategory));
static opt<ErrorDetailLevel> ErrorDetails(
"error-display", init(Unspecified),
desc("Set the level of detail and summary to display when verifying "
"(implies --verify)"),
values(clEnumValN(NoDetailsOrSummary, "quiet",
"Only display whether errors occurred."),
clEnumValN(NoDetailsOnlySummary, "summary",
"Display only a summary of the errors found."),
clEnumValN(OnlyDetailsNoSummary, "details",
"Display each error in detail but no summary."),
clEnumValN(BothDetailsAndSummary, "full",
"Display each error as well as a summary. [default]")),
cat(DwarfDumpCategory));
static opt<std::string> JsonErrSummaryFile(
"verify-json", init(""),
desc("Output JSON-formatted error summary to the specified file. "
"(Implies --verify)"),
value_desc("filename.json"), cat(DwarfDumpCategory));
static opt<bool> Quiet("quiet", desc("Use with -verify to not emit to STDOUT."),
cat(DwarfDumpCategory));
static opt<bool> DumpUUID("uuid", desc("Show the UUID for each architecture."),
cat(DwarfDumpCategory));
static alias DumpUUIDAlias("u", desc("Alias for --uuid."), aliasopt(DumpUUID),
cl::NotHidden);
static opt<bool> Verbose("verbose",
desc("Print more low-level encoding details."),
cat(DwarfDumpCategory));
static alias VerboseAlias("v", desc("Alias for --verbose."), aliasopt(Verbose),
cat(DwarfDumpCategory), cl::NotHidden);
static cl::extrahelp
HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
}
static void error(Error Err) { … }
static void error(StringRef Prefix, Error Err) { … }
static void error(StringRef Prefix, std::error_code EC) { … }
static DIDumpOptions getDumpOpts(DWARFContext &C) { … }
static uint32_t getCPUType(MachOObjectFile &MachO) { … }
static bool filterArch(ObjectFile &Obj) { … }
HandlerFn;
static bool filterByName(
const StringSet<> &Names, DWARFDie Die, StringRef NameRef, raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { … }
static void filterByName(
const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { … }
static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel,
StringRef Name, SmallVectorImpl<DWARFDie> &Dies) { … }
static DWARFDie toDie(const DWARFDebugNames::Entry &Entry,
DWARFContext &DICtx) { … }
static void getDies(DWARFContext &DICtx, const DWARFDebugNames &Accel,
StringRef Name, SmallVectorImpl<DWARFDie> &Dies) { … }
static void filterByAccelName(
ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { … }
static void findAllApple(
DWARFContext &DICtx, raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { … }
static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address,
raw_ostream &OS) { … }
static bool collectLineTableSources(const DWARFDebugLine::LineTable <,
StringRef CompDir,
std::vector<std::string> &Sources) { … }
static bool collectObjectSources(ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) { … }
static std::unique_ptr<MCRegisterInfo>
createRegInfo(const object::ObjectFile &Obj) { … }
static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) { … }
static bool verifyObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) { … }
static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
HandlerFn HandleObj, raw_ostream &OS);
static bool handleArchive(StringRef Filename, Archive &Arch,
HandlerFn HandleObj, raw_ostream &OS) { … }
static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
HandlerFn HandleObj, raw_ostream &OS) { … }
static bool handleFile(StringRef Filename, HandlerFn HandleObj,
raw_ostream &OS) { … }
int main(int argc, char **argv) { … }