Skip to content

Commit 5b48860

Browse files
committed
[LLDB][NativePDB] Create functions with mangled name
1 parent a13712e commit 5b48860

File tree

9 files changed

+112
-24
lines changed

9 files changed

+112
-24
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,18 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
3838
TypeIndex func_type_index,
3939
clang::FunctionDecl *&function_decl,
4040
lldb::opaque_compiler_type_t parent_ty,
41-
llvm::StringRef proc_name, CompilerType func_ct)
41+
llvm::StringRef proc_name, ConstString mangled_name,
42+
CompilerType func_ct)
4243
: m_index(m_index), m_clang(m_clang), func_type_index(func_type_index),
4344
function_decl(function_decl), parent_ty(parent_ty),
44-
proc_name(proc_name), func_ct(func_ct) {}
45+
proc_name(proc_name), mangled_name(mangled_name), func_ct(func_ct) {}
4546
PdbIndex &m_index;
4647
TypeSystemClang &m_clang;
4748
TypeIndex func_type_index;
4849
clang::FunctionDecl *&function_decl;
4950
lldb::opaque_compiler_type_t parent_ty;
5051
llvm::StringRef proc_name;
52+
ConstString mangled_name;
5153
CompilerType func_ct;
5254

5355
llvm::Error visitKnownMember(CVMemberRecord &cvr,
@@ -87,8 +89,8 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
8789
bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
8890
MethodOptions::CompilerGenerated;
8991
function_decl = m_clang.AddMethodToCXXRecordType(
90-
parent_ty, proc_name,
91-
/*mangled_name=*/nullptr, func_ct, /*access=*/access_type,
92+
parent_ty, proc_name, mangled_name.GetCString(), func_ct,
93+
/*access=*/access_type,
9294
/*is_virtual=*/is_virtual, /*is_static=*/is_static,
9395
/*is_inline=*/false, /*is_explicit=*/false,
9496
/*is_attr_used=*/false, /*is_artificial=*/is_artificial);
@@ -888,22 +890,27 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
888890
tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();
889891
}
890892
}
893+
894+
ConstString mangled_name;
895+
if (auto mangled_name_opt = pdb->FindMangledFunctionName(func_id))
896+
mangled_name = ConstString(*mangled_name_opt);
897+
891898
if (!tag_record.FieldList.isSimple()) {
892899
CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
893900
FieldListRecord field_list;
894901
if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
895902
field_list_cvt, field_list))
896903
llvm::consumeError(std::move(error));
897904
CreateMethodDecl process(index, m_clang, func_ti, function_decl,
898-
parent_opaque_ty, func_name, func_ct);
905+
parent_opaque_ty, func_name, mangled_name,
906+
func_ct);
899907
if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))
900908
llvm::consumeError(std::move(err));
901909
}
902910

903911
if (!function_decl) {
904912
function_decl = m_clang.AddMethodToCXXRecordType(
905-
parent_opaque_ty, func_name,
906-
/*mangled_name=*/nullptr, func_ct,
913+
parent_opaque_ty, func_name, mangled_name.GetCString(), func_ct,
907914
/*access=*/lldb::AccessType::eAccessPublic,
908915
/*is_virtual=*/false, /*is_static=*/false,
909916
/*is_inline=*/false, /*is_explicit=*/false,

lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ struct SegmentOffset {
8989
SegmentOffset(uint16_t s, uint32_t o) : segment(s), offset(o) {}
9090
uint16_t segment = 0;
9191
uint32_t offset = 0;
92+
93+
bool operator==(SegmentOffset rhs) const {
94+
return segment == rhs.segment && offset == rhs.offset;
95+
}
96+
97+
bool operator<(SegmentOffset rhs) const {
98+
if (segment == rhs.segment)
99+
return offset < rhs.offset;
100+
return segment < rhs.segment;
101+
}
92102
};
93103

94104
struct SegmentOffsetLength {

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
3939
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
4040
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
41+
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
4142
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
4243
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
4344
#include "llvm/DebugInfo/PDB/PDB.h"
@@ -496,7 +497,9 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
496497
return nullptr;
497498

498499
PdbTypeSymId sig_id(proc.FunctionType, false);
499-
Mangled mangled(proc.Name);
500+
auto mangled_opt =
501+
FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset));
502+
Mangled mangled(mangled_opt.value_or(proc.Name));
500503
FunctionSP func_sp = std::make_shared<Function>(
501504
&comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
502505
func_type.get(), func_addr,
@@ -2353,3 +2356,68 @@ SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
23532356
return std::nullopt;
23542357
return parent_iter->second;
23552358
}
2359+
2360+
std::optional<llvm::StringRef>
2361+
SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) {
2362+
const CompilandIndexItem *cci =
2363+
m_index->compilands().GetCompiland(func_id.modi);
2364+
if (!cci)
2365+
return std::nullopt;
2366+
2367+
CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
2368+
if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32)
2369+
return std::nullopt;
2370+
2371+
ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
2372+
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
2373+
return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset));
2374+
}
2375+
2376+
/// Find the mangled name of a function at \a so.
2377+
///
2378+
/// This is similar to the NearestSym function from Microsoft's PDB reference:
2379+
/// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/PDB/dbi/gsi.cpp#L1492-L1581
2380+
/// The main difference is that we search for the exact symbol.
2381+
///
2382+
/// \param so[in] The address of the function given by its segment and code
2383+
/// offset.
2384+
/// \return The mangled function name if found. Otherwise an empty optional.
2385+
std::optional<llvm::StringRef>
2386+
SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so) {
2387+
// The address map is sorted by address, so we do binary search.
2388+
// Each element is an offset into the symbols for a public symbol.
2389+
auto lo = m_index->publics().getAddressMap().begin();
2390+
auto hi = m_index->publics().getAddressMap().end();
2391+
hi -= 1;
2392+
2393+
while (lo < hi) {
2394+
auto tgt = lo + ((hi - lo + 1) / 2);
2395+
auto val = tgt->value();
2396+
auto sym = m_index->symrecords().readRecord(val);
2397+
if (sym.kind() != S_PUB32)
2398+
return std::nullopt; // this is most likely corrupted debug info
2399+
2400+
PublicSym32 psym =
2401+
llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym));
2402+
SegmentOffset cur(psym.Segment, psym.Offset);
2403+
if (so < cur) {
2404+
tgt -= 1;
2405+
hi = tgt;
2406+
} else if (so == cur)
2407+
return psym.Name;
2408+
else
2409+
lo = tgt;
2410+
}
2411+
2412+
// We might've found something, check if it's the symbol we're searching for
2413+
auto val = lo->value();
2414+
auto sym = m_index->symrecords().readRecord(val);
2415+
if (sym.kind() != S_PUB32)
2416+
return std::nullopt;
2417+
PublicSym32 psym =
2418+
llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym));
2419+
if (psym.Segment != so.segment || psym.Offset != so.offset)
2420+
return std::nullopt;
2421+
return psym.Name;
2422+
}
2423+

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ class SymbolFileNativePDB : public SymbolFileCommon {
140140

141141
std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id);
142142

143+
std::optional<llvm::StringRef> FindMangledFunctionName(PdbCompilandSymId id);
144+
std::optional<llvm::StringRef> FindMangledSymbol(SegmentOffset so);
145+
143146
void FindTypes(const lldb_private::TypeQuery &match,
144147
lldb_private::TypeResults &results) override;
145148

lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ int main(int argc, char **argv) {
5050
// CHECK: 1: name = 'main', locations = 1
5151
// CHECK: 1.1: where = break-by-function.cpp.tmp.exe`main + {{[0-9]+}}
5252
// CHECK: 2: name = 'OvlGlobalFn', locations = 3
53-
// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
54-
// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`OvlGlobalFn
55-
// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
53+
// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int) + {{[0-9]+}}
54+
// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int)
55+
// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int, int) + {{[0-9]+}}
5656
// CHECK: 3: name = 'StaticFn', locations = 1
5757
// CHECK: 3.1: where = break-by-function.cpp.tmp.exe`StaticFn + {{[0-9]+}}
5858
// CHECK: 4: name = 'DoesntExist', locations = 0 (pending)

lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ int main(int argc, char **argv) {
2424
// CHECK: (lldb) target create "{{.*}}break-by-line.cpp.tmp.exe"
2525
// CHECK: Current executable set to '{{.*}}break-by-line.cpp.tmp.exe'
2626
// CHECK: (lldb) break set -f break-by-line.cpp -l 15
27-
// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`NS::NamespaceFn + {{[0-9]+}} at break-by-line.cpp:15
27+
// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`int NS::NamespaceFn(int) + {{[0-9]+}} at break-by-line.cpp:15

lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int main(int argc, char **argv) {
2727
// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+12>: mov qword ptr [rsp + 0x28], rdx
2828
// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+17>: mov dword ptr [rsp + 0x24], ecx
2929
// CHECK: ** 15 foo();
30-
// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; foo at disassembly.cpp:12
30+
// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; int foo(void) at disassembly.cpp:12
3131
// CHECK: ** 16 return 0;
3232
// CHECK-NEXT: 17 }
3333
// CHECK-NEXT: 18

lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ int main(int argc, char **argv) {
5555
// CHECK-NEXT: (lldb) step
5656
// CHECK-NEXT: Process {{.*}} stopped
5757
// CHECK-NEXT: * thread #1, stop reason = step in
58-
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
58+
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
5959
// CHECK-NEXT: 6
6060
// CHECK-NEXT: 7
6161
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
@@ -71,7 +71,7 @@ int main(int argc, char **argv) {
7171
// CHECK-NEXT: (lldb) step
7272
// CHECK-NEXT: Process {{.*}} stopped
7373
// CHECK-NEXT: * thread #1, stop reason = step in
74-
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
74+
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
7575
// CHECK-NEXT: 7
7676
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
7777
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
8989
// CHECK-NEXT: (lldb) step
9090
// CHECK-NEXT: Process {{.*}} stopped
9191
// CHECK-NEXT: * thread #1, stop reason = step in
92-
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
92+
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
9393
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
9494
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
9595
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
@@ -109,7 +109,7 @@ int main(int argc, char **argv) {
109109
// CHECK-NEXT: (lldb) step
110110
// CHECK-NEXT: Process {{.*}} stopped
111111
// CHECK-NEXT: * thread #1, stop reason = step in
112-
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
112+
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
113113
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
114114
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
115115
// CHECK-NEXT: 11 ++Local1;
@@ -129,7 +129,7 @@ int main(int argc, char **argv) {
129129
// CHECK-NEXT: (lldb) step
130130
// CHECK-NEXT: Process {{.*}} stopped
131131
// CHECK-NEXT: * thread #1, stop reason = step in
132-
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
132+
// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
133133
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
134134
// CHECK-NEXT: 11 ++Local1;
135135
// CHECK-NEXT: 12 ++Local2;

lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ int main(int argc, char **argv) {
2424

2525
// CHECK: (lldb) thread backtrace
2626
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
27-
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
27+
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
2828
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
2929

3030

3131
// CHECK: (lldb) thread backtrace
3232
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
33-
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
34-
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
33+
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
34+
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
3535
// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
3636

3737
// CHECK: (lldb) thread backtrace
3838
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
39-
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12
40-
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
41-
// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
39+
// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12
40+
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
41+
// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
4242
// CHECK-NEXT: frame #3: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20

0 commit comments

Comments
 (0)