Skip to content

Commit

Permalink
[PDB] Fix function names for private symbols in PDBs
Browse files Browse the repository at this point in the history
Summary:
llvm-symbolizer wants to get linkage names of functions for historical
reasons. Linkage names are only recorded in the PDB for public symbols,
and the linkage name is apparently stored separately in some "public
symbol" record. We had a workaround in PDBContext which would look for
such symbols when the user requested linkage names.

However, when given an address that was truly in a private function and
public funciton, we would accidentally find nearby public symbols and
return those function names. The fix is to look for both function
symbols and public symbols and only prefer the public symbol name if the
addresses of the symbols agree.

Fixes PR27492

Reviewers: zturner

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D19571

llvm-svn: 267732
  • Loading branch information
rnk committed Apr 27, 2016
1 parent 5b759f8 commit 0336cc0
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 28 deletions.
26 changes: 12 additions & 14 deletions llvm/lib/DebugInfo/PDB/PDBContext.cpp
Expand Up @@ -96,26 +96,24 @@ std::string PDBContext::getFunctionName(uint64_t Address,
if (NameKind == DINameKind::None)
return std::string();

std::unique_ptr<PDBSymbol> FuncSymbol =
Session->findSymbolByAddress(Address, PDB_SymType::Function);
auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get());

if (NameKind == DINameKind::LinkageName) {
// It is not possible to get the mangled linkage name through a
// PDBSymbolFunc. For that we have to specifically request a
// PDBSymbolPublicSymbol.
auto PublicSym =
Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
if (auto PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get()))
return PS->getName();
if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) {
// If we also have a function symbol, prefer the use of public symbol name
// only if it refers to the same address. The public symbol uses the
// linkage name while the function does not.
if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress())
return PS->getName();
}
}

auto FuncSymbol =
Session->findSymbolByAddress(Address, PDB_SymType::Function);

// This could happen either if there was no public symbol (e.g. not
// external) or the user requested the short name. In the former case,
// although they technically requested the linkage name, if the linkage
// name is not available we fallback to at least returning a non-empty
// string.
if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get()))
return Func->getName();

return std::string();
return Func ? Func->getName() : std::string();
}
4 changes: 4 additions & 0 deletions llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp
Expand Up @@ -10,11 +10,15 @@ struct Foo {
void foo() {
}

static void private_symbol() {
}

int main() {
foo();

NS::Foo f;
f.bar();
private_symbol();
}

extern "C" {
Expand Down
Binary file modified llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe
Binary file not shown.
Binary file modified llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb
Binary file not shown.
32 changes: 18 additions & 14 deletions llvm/test/tools/llvm-symbolizer/pdb/pdb.test
Expand Up @@ -13,33 +13,37 @@ RUN: | %python -c 'import sys;print("\n".join([hex(int(x, 16) - 0x400000) for x
RUN: | llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false --relative-address \
RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE

ADDR: 0x401000
ADDR: 0x401010
ADDR: 0x401070
ADDR: 0x401030
ADDR: 0x401040
ADDR: 0x401050
ADDR: 0x401060
ADDR: 0x500000
ADDR: 0x401380
ADDR: 0x401390
ADDR: 0x4013A0
ADDR: 0x4013C0
ADDR: 0x4013D0
ADDR: 0x4013E0
ADDR: 0x4013F0
ADDR: 0x401420

CHECK: foo(void)
CHECK-NEXT: test.cpp:10
CHECK: main
CHECK: {{^private_symbol$}}
CHECK-NEXT: test.cpp:13:0
CHECK: NS::Foo::bar(void)
CHECK-NEXT: test.cpp:6:0
CHECK: {{^main}}
CHECK-NEXT: test.cpp:16:0
CHECK: {{^foo_cdecl$}}
CHECK: {{^foo_stdcall$}}
CHECK: {{^foo_fastcall$}}
CHECK: {{^foo_vectorcall$}}
CHECK: NS::Foo::bar(void)
CHECK-NEXT: test.cpp:6:0

CHECK-NO-DEMANGLE: ?foo@@YAXXZ
CHECK-NO-DEMANGLE-NEXT: test.cpp:10
CHECK-NO-DEMANGLE: _main
CHECK-NO-DEMANGLE: private_symbol
CHECK-NO-DEMANGLE-NEXT: test.cpp:13
CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ
CHECK-NO-DEMANGLE-NEXT: test.cpp:6
CHECK-NO-DEMANGLE: _main
CHECK-NO-DEMANGLE-NEXT: test.cpp:16
CHECK-NO-DEMANGLE: _foo_cdecl
CHECK-NO-DEMANGLE: _foo_stdcall@0
CHECK-NO-DEMANGLE: @foo_fastcall@0
CHECK-NO-DEMANGLE: foo_vectorcall@@0
CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ
CHECK-NO-DEMANGLE-NEXT: test.cpp:6

0 comments on commit 0336cc0

Please sign in to comment.