Skip to content

Commit 7ac1c78

Browse files
committedFeb 9, 2018
[SymbolFilePDB] Add support for function symbols
Summary: This is combination of following changes, - Resolve function symbols in PDB symbol file. `lldb-test symbols` will display information about function symbols. - Implement SymbolFilePDB::FindFunctions methods. On lldb console, searching function symbol by name and by regular expression are both available. - Create lldb type for PDBSymbolFunc. - Add tests to check whether functions with the same name but from different sources can be resolved correctly. Reviewers: zturner, lldb-commits Reviewed By: zturner Subscribers: amccarth, labath, llvm-commits Differential Revision: https://reviews.llvm.org/D42443 llvm-svn: 324707
1 parent 33b9fa7 commit 7ac1c78

File tree

7 files changed

+872
-21
lines changed

7 files changed

+872
-21
lines changed
 
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Static function
2+
namespace {
3+
static long StaticFunction(int a)
4+
{
5+
return 2;
6+
}
7+
}
8+
9+
// Inlined function
10+
static inline int InlinedFunction(long a) { return 10; }
11+
12+
void FunctionCall()
13+
{
14+
StaticFunction(1);
15+
InlinedFunction(1);
16+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
// Global functions
3+
int Func_arg_array(int array[]) { return 1; }
4+
void Func_arg_void(void) { return; }
5+
void Func_arg_none(void) { return; }
6+
void Func_varargs(...) { return; }
7+
8+
// Class
9+
namespace MemberTest {
10+
class A {
11+
public:
12+
int Func(int a, ...) { return 1; }
13+
};
14+
}
15+
16+
// Template
17+
template <int N=1, class ...T>
18+
void TemplateFunc(T ...Arg) {
19+
return;
20+
}
21+
22+
// namespace
23+
namespace {
24+
void Func(int a, const long b, volatile bool c, ...) { return; }
25+
}
26+
27+
namespace NS {
28+
void Func(char a, int b) {
29+
return;
30+
}
31+
}
32+
33+
// Static function
34+
static long StaticFunction(int a)
35+
{
36+
return 2;
37+
}
38+
39+
// Inlined function
40+
inline void InlinedFunction(long a) { return; }
41+
42+
extern void FunctionCall();
43+
44+
int main() {
45+
MemberTest::A v1;
46+
v1.Func('a',10);
47+
48+
Func(1, 5, true, 10, 8);
49+
NS::Func('c', 2);
50+
51+
TemplateFunc(10);
52+
TemplateFunc(10,11,88);
53+
54+
StaticFunction(2);
55+
InlinedFunction(1);
56+
57+
FunctionCall();
58+
return 0;
59+
}

‎lldb/lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ EnumClass EnumClassVar;
3434

3535
enum struct EnumStruct { red, blue, black };
3636
EnumStruct EnumStructVar;
37-
37+
3838
int main() {
3939
return 0;
4040
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
REQUIRES: windows
2+
RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/FuncSymbolsTestMain.cpp /o %T/FuncSymbolsTestMain.cpp.obj
3+
RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/FuncSymbols.cpp /o %T/FuncSymbols.cpp.obj
4+
RUN: link %T/FuncSymbolsTestMain.cpp.obj %T/FuncSymbols.cpp.obj /DEBUG /nodefaultlib /Entry:main /OUT:%T/FuncSymbolsTest.exe
5+
RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck %s
6+
7+
; Link multiple objects
8+
; In this test, We don't check demangled name of a mangled function.
9+
10+
CHECK: Module [[MD:.*]]
11+
CHECK-DAG: {{.*}}: SymbolVendor ([[MD]])
12+
CHECK-DAG: [[TY0:.*]]: Type{[[UID0:.*]]} , name = "Func_arg_array", decl = FuncSymbolsTestMain.cpp:3, compiler_type = {{.*}} int (int *)
13+
CHECK-DAG: [[TY1:.*]]: Type{[[UID1:.*]]} , name = "Func_arg_void", decl = FuncSymbolsTestMain.cpp:4, compiler_type = {{.*}} void (void)
14+
CHECK-DAG: [[TY2:.*]]: Type{[[UID2:.*]]} , name = "Func_arg_none", decl = FuncSymbolsTestMain.cpp:5, compiler_type = {{.*}} void (void)
15+
CHECK-DAG: [[TY3:.*]]: Type{[[UID3:.*]]} , name = "Func_varargs", decl = FuncSymbolsTestMain.cpp:6, compiler_type = {{.*}} void (...)
16+
CHECK-DAG: [[TY4:.*]]: Type{[[UID4:.*]]} , name = "NS::Func", decl = FuncSymbolsTestMain.cpp:28, compiler_type = {{.*}} void (signed char, int)
17+
CHECK-DAG: [[TY5:.*]]: Type{[[UID5:.*]]} , name = "main", decl = FuncSymbolsTestMain.cpp:44, compiler_type = {{.*}} int (void)
18+
CHECK-DAG: [[TY6:.*]]: Type{[[UID6:.*]]} , name = "`anonymous namespace'::Func", decl = FuncSymbolsTestMain.cpp:24, compiler_type = {{.*}} void (int, const long, volatile _Bool, ...)
19+
CHECK-DAG: [[TY7:.*]]: Type{[[UID7:.*]]} , name = "StaticFunction", decl = FuncSymbolsTestMain.cpp:35, compiler_type = {{.*}} long (int)
20+
CHECK-DAG: [[TY8:.*]]: Type{[[UID8:.*]]} , name = "MemberTest::A::Func", decl = FuncSymbolsTestMain.cpp:12, compiler_type = {{.*}} int (int, ...)
21+
CHECK-DAG: [[TY9:.*]]: Type{[[UID9:.*]]} , name = "TemplateFunc<1,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int)
22+
CHECK-DAG: [[TY10:.*]]: Type{[[UID10:.*]]} , name = "TemplateFunc<1,int,int,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int, int, int)
23+
CHECK-DAG: [[TY11:.*]]: Type{[[UID11:.*]]} , name = "InlinedFunction", decl = FuncSymbolsTestMain.cpp:40, compiler_type = {{.*}} void (long)
24+
25+
; We expect new types observed in another compile unit
26+
CHECK-DAG: [[TY30:.*]]: Type{[[UID30:.*]]} , name = "FunctionCall", decl = FuncSymbols.cpp:13, compiler_type = {{.*}} void (void)
27+
CHECK-DAG: [[TY31:.*]]: Type{[[UID31:.*]]} , name = "`anonymous namespace'::StaticFunction", decl = FuncSymbols.cpp:4, compiler_type = {{.*}} long (int)
28+
CHECK-DAG: [[TY32:.*]]: Type{[[UID32:.*]]} , name = "InlinedFunction", decl = FuncSymbols.cpp:10, compiler_type = {{.*}} int (long)
29+
30+
CHECK: {{.*}}: CompileUnit{{.*}}, language = "c++", file = '{{.*}}\FuncSymbolsTestMain.cpp'
31+
CHECK-DAG: Function{[[UID0]]}, mangled = ?Func_arg_array@@YAHQAH@Z, demangled = {{.*}}, type = [[TY0]]
32+
CHECK-DAG: Function{[[UID1]]}, mangled = ?Func_arg_void@@YAXXZ, demangled = {{.*}}, type = [[TY1]]
33+
CHECK-DAG: Function{[[UID2]]}, mangled = ?Func_arg_none@@YAXXZ, demangled = {{.*}}, type = [[TY2]]
34+
CHECK-DAG: Function{[[UID3]]}, mangled = ?Func_varargs@@YAXZZ, demangled = {{.*}}, type = [[TY3]]
35+
CHECK-DAG: Function{[[UID4]]}, mangled = ?Func@NS@@YAXDH@Z, demangled = {{.*}}, type = [[TY4]]
36+
CHECK-DAG: Function{[[UID5]]}, mangled = _main, demangled = {{.*}}, type = [[TY5]]
37+
CHECK-DAG: Function{[[UID6]]}, demangled = `anonymous namespace'::Func, type = [[TY6]]
38+
CHECK-DAG: Function{[[UID7]]}, demangled = StaticFunction, type = [[TY7]]
39+
CHECK-DAG: Function{[[UID8]]}, mangled = ?Func@A@MemberTest@@QAAHHZZ, demangled = {{.*}}, type = [[TY8]]
40+
CHECK-DAG: Function{[[UID9]]}, mangled = ??$TemplateFunc@$00H@@YAXH@Z, demangled = {{.*}}, type = [[TY9]]
41+
CHECK-DAG: Function{[[UID10]]}, mangled = ??$TemplateFunc@$00HHH@@YAXHHH@Z, demangled = {{.*}}, type = [[TY10]]
42+
CHECK-DAG: Function{[[UID11]]}, mangled = ?InlinedFunction@@YAXJ@Z, demangled = {{.*}}, type = [[TY11]]
43+
44+
CHECK: {{.*}}: CompileUnit{{.*}}, language = "c++", file = '{{.*}}\FuncSymbols.cpp'
45+
CHECK-DAG: Function{[[UID30]]}, mangled = ?FunctionCall@@YAXXZ, demangled = {{.*}}, type = [[TY30]]
46+
CHECK-DAG: Function{[[UID31]]}, demangled = `anonymous namespace'::StaticFunction, type = [[TY31]]
47+
CHECK-DAG: Function{[[UID32]]}, demangled = InlinedFunction, type = [[TY32]]

‎lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
#include "lldb/Symbol/SymbolFile.h"
2020
#include "lldb/Symbol/TypeSystem.h"
2121

22+
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
23+
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
2224
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
2325
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
26+
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
2427
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
2528
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
2629
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
@@ -166,6 +169,28 @@ ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin *pdb_type,
166169
}
167170
return compiler_type.GetTypeName();
168171
}
172+
173+
bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) {
174+
auto &raw_sym = symbol.getRawSymbol();
175+
auto lines_up = symbol.getSession().findLineNumbersByAddress(
176+
raw_sym.getVirtualAddress(), raw_sym.getLength());
177+
if (!lines_up)
178+
return false;
179+
auto first_line_up = lines_up->getNext();
180+
if (!first_line_up)
181+
return false;
182+
183+
uint32_t src_file_id = first_line_up->getSourceFileId();
184+
auto src_file_up = symbol.getSession().getSourceFileById(src_file_id);
185+
if (!src_file_up)
186+
return false;
187+
188+
FileSpec spec(src_file_up->getFileName(), /*resolve_path*/false);
189+
decl.SetFile(spec);
190+
decl.SetColumn(first_line_up->getColumnNumber());
191+
decl.SetLine(first_line_up->getLineNumber());
192+
return true;
193+
}
169194
}
170195

171196
PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {}
@@ -182,7 +207,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
182207
clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
183208
Declaration decl;
184209

185-
if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type)) {
210+
switch (type.getSymTag()) {
211+
case PDB_SymType::UDT: {
212+
auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type);
213+
assert(udt);
186214
AccessType access = lldb::eAccessPublic;
187215
PDB_UdtType udt_kind = udt->getUdtKind();
188216
auto tag_type_kind = TranslateUdtKind(udt_kind);
@@ -203,7 +231,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
203231
ConstString(udt->getName()), udt->getLength(), nullptr,
204232
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
205233
lldb_private::Type::eResolveStateForward);
206-
} else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type)) {
234+
} break;
235+
case PDB_SymType::Enum: {
236+
auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
237+
assert(enum_type);
207238
auto underlying_type_up = enum_type->getUnderlyingType();
208239
if (!underlying_type_up)
209240
return nullptr;
@@ -244,7 +275,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
244275
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
245276
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
246277
ast_enum, lldb_private::Type::eResolveStateFull);
247-
} else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type)) {
278+
} break;
279+
case PDB_SymType::Typedef: {
280+
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
281+
assert(type_def);
248282
lldb_private::Type *target_type =
249283
m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
250284
if (!target_type)
@@ -261,7 +295,24 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
261295
bytes, nullptr, target_type->GetID(),
262296
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
263297
lldb_private::Type::eResolveStateFull);
264-
} else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
298+
} break;
299+
case PDB_SymType::Function:
300+
case PDB_SymType::FunctionSig: {
301+
std::string name;
302+
PDBSymbolTypeFunctionSig *func_sig = nullptr;
303+
if (auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(&type)) {
304+
auto sig = pdb_func->getSignature();
305+
if (!sig)
306+
return nullptr;
307+
func_sig = sig.release();
308+
// Function type is named.
309+
name = pdb_func->getName();
310+
} else if (auto pdb_func_sig =
311+
llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
312+
func_sig = const_cast<PDBSymbolTypeFunctionSig*>(pdb_func_sig);
313+
} else
314+
llvm_unreachable("Unexpected PDB symbol!");
315+
265316
auto arg_enum = func_sig->getArguments();
266317
uint32_t num_args = arg_enum->getChildCount();
267318
std::vector<CompilerType> arg_list;
@@ -302,11 +353,15 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
302353
return_ast_type, arg_list.data(), arg_list.size(), is_variadic,
303354
type_quals);
304355

356+
GetDeclarationForSymbol(type, decl);
305357
return std::make_shared<lldb_private::Type>(
306-
func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0,
358+
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), 0,
307359
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
308360
func_sig_ast_type, lldb_private::Type::eResolveStateFull);
309-
} else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type)) {
361+
} break;
362+
case PDB_SymType::ArrayType: {
363+
auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
364+
assert(array_type);
310365
uint32_t num_elements = array_type->getCount();
311366
uint32_t element_uid = array_type->getElementType()->getSymIndexId();
312367
uint32_t bytes = array_type->getLength();
@@ -322,7 +377,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
322377
array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
323378
bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
324379
decl, array_ast_type, lldb_private::Type::eResolveStateFull);
325-
} else if (auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type)) {
380+
} break;
381+
case PDB_SymType::BuiltinType: {
382+
auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type);
383+
assert(builtin_type);
326384
PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType();
327385
if (builtin_kind == PDB_BuiltinType::None)
328386
return nullptr;
@@ -347,7 +405,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
347405
builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name,
348406
bytes, nullptr, LLDB_INVALID_UID, encoding_data_type,
349407
decl, builtin_ast_type, lldb_private::Type::eResolveStateFull);
350-
} else if (auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type)) {
408+
} break;
409+
case PDB_SymType::PointerType: {
410+
auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
411+
assert(pointer_type);
351412
Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID(
352413
pointer_type->getPointeeType()->getSymIndexId());
353414
if (!pointee_type)
@@ -367,6 +428,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
367428
pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
368429
encoding_data_type, decl, pointer_ast_type,
369430
lldb_private::Type::eResolveStateFull);
431+
} break;
432+
default: break;
370433
}
371434
return nullptr;
372435
}

0 commit comments

Comments
 (0)