Skip to content

Commit e9daea1

Browse files
committed
[symbolizer] Add a --pdb option.
Closes #142490
1 parent 68fea00 commit e9daea1

File tree

6 files changed

+69
-40
lines changed

6 files changed

+69
-40
lines changed

llvm/docs/CommandGuide/llvm-symbolizer.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ OPTIONS
442442
}
443443
]
444444
445+
.. option:: --pdb <path>
446+
447+
Use the specified PDB file at ``<path>``, overriding the PDB info
448+
contained in the COFF object.
449+
445450
.. option:: --pretty-print, -p
446451

447452
Print human-readable output. If :option:`--inlining` is specified, the

llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class LLVMSymbolizer {
6464
std::vector<std::string> DsymHints;
6565
std::string FallbackDebugPath;
6666
std::string DWPName;
67+
std::string PDBName;
6768
std::vector<std::string> DebugFileDirectory;
6869
std::vector<std::string> GsymFileDirectory;
6970
size_t MaxCacheSize =

llvm/lib/DebugInfo/Symbolize/Symbolize.cpp

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -662,50 +662,64 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) {
662662
ObjectPair Objects = ObjectsOrErr.get();
663663

664664
std::unique_ptr<DIContext> Context;
665-
// If this is a COFF object containing PDB info and not containing DWARF
666-
// section, use a PDBContext to symbolize. Otherwise, use DWARF.
667-
// Create a DIContext to symbolize as follows:
668-
// - If there is a GSYM file, create a GsymContext.
669-
// - Otherwise, if this is a COFF object containing PDB info, create a
670-
// PDBContext.
671-
// - Otherwise, create a DWARFContext.
672-
const auto GsymFile = lookUpGsymFile(BinaryName.str());
673-
if (!GsymFile.empty()) {
674-
auto ReaderOrErr = gsym::GsymReader::openFile(GsymFile);
675-
676-
if (ReaderOrErr) {
677-
std::unique_ptr<gsym::GsymReader> Reader =
678-
std::make_unique<gsym::GsymReader>(std::move(*ReaderOrErr));
679-
680-
Context = std::make_unique<gsym::GsymContext>(std::move(Reader));
665+
pdb::PDB_ReaderType ReaderType =
666+
Opts.UseDIA ? pdb::PDB_ReaderType::DIA : pdb::PDB_ReaderType::Native;
667+
const auto *CoffObject = dyn_cast<COFFObjectFile>(Objects.first);
668+
669+
// First, if the user specified a pdb file on the command line, use that.
670+
if (CoffObject && !Opts.PDBName.empty()) {
671+
using namespace pdb;
672+
std::unique_ptr<IPDBSession> Session;
673+
if (auto Err = loadDataForPDB(ReaderType, Opts.PDBName, Session)) {
674+
Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
675+
return createFileError(Opts.PDBName, std::move(Err));
681676
}
677+
Context.reset(new PDBContext(*CoffObject, std::move(Session)));
682678
}
679+
683680
if (!Context) {
684-
if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
685-
const codeview::DebugInfo *DebugInfo;
686-
StringRef PDBFileName;
687-
auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
688-
// Use DWARF if there're DWARF sections.
689-
bool HasDwarf = llvm::any_of(
690-
Objects.first->sections(), [](SectionRef Section) -> bool {
691-
if (Expected<StringRef> SectionName = Section.getName())
692-
return SectionName.get() == ".debug_info";
693-
return false;
694-
});
695-
if (!EC && !HasDwarf && DebugInfo != nullptr && !PDBFileName.empty()) {
696-
using namespace pdb;
697-
std::unique_ptr<IPDBSession> Session;
698-
699-
PDB_ReaderType ReaderType =
700-
Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
701-
if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
702-
Session)) {
703-
Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
704-
// Return along the PDB filename to provide more context
705-
return createFileError(PDBFileName, std::move(Err));
706-
}
707-
Context.reset(new PDBContext(*CoffObject, std::move(Session)));
681+
// If this is a COFF object containing PDB info and not containing DWARF
682+
// section, use a PDBContext to symbolize. Otherwise, use DWARF.
683+
// Create a DIContext to symbolize as follows:
684+
// - If there is a GSYM file, create a GsymContext.
685+
// - Otherwise, if this is a COFF object containing PDB info, create a
686+
// PDBContext.
687+
// - Otherwise, create a DWARFContext.
688+
const auto GsymFile = lookUpGsymFile(BinaryName.str());
689+
if (!GsymFile.empty()) {
690+
auto ReaderOrErr = gsym::GsymReader::openFile(GsymFile);
691+
692+
if (ReaderOrErr) {
693+
std::unique_ptr<gsym::GsymReader> Reader =
694+
std::make_unique<gsym::GsymReader>(std::move(*ReaderOrErr));
695+
696+
Context = std::make_unique<gsym::GsymContext>(std::move(Reader));
697+
}
698+
}
699+
}
700+
701+
if (!Context && CoffObject) {
702+
const codeview::DebugInfo *DebugInfo;
703+
StringRef PDBFileName;
704+
auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
705+
// Use DWARF if there're DWARF sections.
706+
bool HasDwarf =
707+
llvm::any_of(Objects.first->sections(), [](SectionRef Section) -> bool {
708+
if (Expected<StringRef> SectionName = Section.getName())
709+
return SectionName.get() == ".debug_info";
710+
return false;
711+
});
712+
if (!EC && !HasDwarf && DebugInfo != nullptr && !PDBFileName.empty()) {
713+
using namespace pdb;
714+
std::unique_ptr<IPDBSession> Session;
715+
716+
if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
717+
Session)) {
718+
Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
719+
// Return along the PDB filename to provide more context
720+
return createFileError(PDBFileName, std::move(Err));
708721
}
722+
Context.reset(new PDBContext(*CoffObject, std::move(Session)));
709723
}
710724
}
711725
if (!Context)

llvm/test/tools/llvm-symbolizer/pdb/pdb.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
RUN: rm -rf %t
2+
RUN: mkdir -p %t
3+
14
RUN: echo 0x401380 > %t.input
25
RUN: echo 0x401390 >> %t.input
36
RUN: echo 0x4013A0 >> %t.input
@@ -11,6 +14,10 @@ RUN: | FileCheck %s
1114
RUN: llvm-symbolizer --obj="%p/Inputs/test.exe" --no-demangle < %t.input \
1215
RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
1316

17+
RUN: cp %p/Inputs/test.exe %t/test.exe
18+
RUN: llvm-symbolizer --obj="%t/test.exe" --pdb="%p/Inputs/test.pdb" < %t.input \
19+
RUN: | FileCheck %s
20+
1421
; Check that -dia works
1522
RUN: llvm-symbolizer --dia --obj="%p/Inputs/test.exe" < %t.input \
1623
RUN: | FileCheck %s

llvm/tools/llvm-symbolizer/Opts.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def functions_EQ : Joined<["--"], "functions=">, HelpText<"Print function name f
4141
defm gsym_file_directory : Eq<"gsym-file-directory", "Path to directory where to look for GSYM files">, MetaVarName<"<dir>">, Group<grp_gsym>;
4242
def help : F<"help", "Display this help">;
4343
defm dwp : Eq<"dwp", "Path to DWP file to be use for any split CUs">, MetaVarName<"<file>">;
44+
defm pdb : Eq<"pdb", "Path to PDB file">, MetaVarName<"<file>">;
4445
defm dsym_hint
4546
: Eq<"dsym-hint",
4647
"Path to .dSYM bundles to search for debug info for the object files">,

llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ int llvm_symbolizer_main(int argc, char **argv, const llvm::ToolContext &) {
500500
Opts.DefaultArch = Args.getLastArgValue(OPT_default_arch_EQ).str();
501501
Opts.Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, !IsAddr2Line);
502502
Opts.DWPName = Args.getLastArgValue(OPT_dwp_EQ).str();
503+
Opts.PDBName = Args.getLastArgValue(OPT_pdb_EQ).str();
503504
Opts.FallbackDebugPath =
504505
Args.getLastArgValue(OPT_fallback_debug_path_EQ).str();
505506
Opts.GsymFileDirectory = Args.getAllArgValues(OPT_gsym_file_directory_EQ);

0 commit comments

Comments
 (0)