From cd3c6fc646260703218fa8c511ab0cfc2f41f240 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Wed, 15 Oct 2025 21:25:43 +0200 Subject: [PATCH] [LLDB][NativePDB] Create simple types from function arguments and return types --- .../NativePDB/SymbolFileNativePDB.cpp | 25 +++++++++++++++++++ .../NativePDB/SymbolFileNativePDB.h | 2 ++ .../SymbolFile/NativePDB/simple-types.cpp | 12 ++++----- lldb/test/Shell/SymbolFile/PDB/typedefs.test | 23 +++++++++-------- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index ecd3188b3d564..e76b7a3cf274a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -754,6 +754,10 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, const MemberFunctionRecord &mfr, CompilerType ct) { + if (mfr.ReturnType.isSimple()) + GetOrCreateType(mfr.ReturnType); + CreateSimpleArgumentListTypes(mfr.ArgumentList); + Declaration decl; return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, @@ -763,12 +767,33 @@ TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, const ProcedureRecord &pr, CompilerType ct) { + if (pr.ReturnType.isSimple()) + GetOrCreateType(pr.ReturnType); + CreateSimpleArgumentListTypes(pr.ArgumentList); + Declaration decl; return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, lldb_private::Type::ResolveState::Full); } +void SymbolFileNativePDB::CreateSimpleArgumentListTypes( + llvm::codeview::TypeIndex arglist_ti) { + if (arglist_ti.isNoneType()) + return; + + CVType arglist_cvt = m_index->tpi().getType(arglist_ti); + if (arglist_cvt.kind() != LF_ARGLIST) + return; // invalid debug info + + ArgListRecord alr; + llvm::cantFail( + TypeDeserializer::deserializeAs(arglist_cvt, alr)); + for (TypeIndex id : alr.getIndices()) + if (!id.isNoneType() && id.isSimple()) + GetOrCreateType(id); +} + TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { if (type_id.index.isSimple()) return CreateSimpleType(type_id.index, ct); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index a5fef354af65c..11b982e6fc67e 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -255,6 +255,8 @@ class SymbolFileNativePDB : public SymbolFileCommon { VariableList &variables); size_t ParseVariablesForBlock(PdbCompilandSymId block_id); + void CreateSimpleArgumentListTypes(llvm::codeview::TypeIndex arglist_ti); + llvm::Expected GetFileIndex(const CompilandIndexItem &cii, uint32_t file_id); diff --git a/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp index 3781194e2e992..3664b04fd22bd 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp @@ -3,7 +3,6 @@ // Test that simple types can be found // RUN: %build --std=c++20 --nodefaultlib --compiler=clang-cl --arch=64 -o %t.exe -- %s // RUN: lldb-test symbols %t.exe | FileCheck %s -// RUN: lldb-test symbols %t.exe | FileCheck --check-prefix=FUNC-PARAMS %s bool *PB; bool &RB = *PB; @@ -101,12 +100,14 @@ int main() { // CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = 0x{{[0-9a-f]+}} float // CHECK-DAG: Type{{.*}} , name = "const float", size = 4, compiler_type = 0x{{[0-9a-f]+}} const float +// CHECK-DAG: Type{{.*}} , name = "double", size = 8, compiler_type = 0x{{[0-9a-f]+}} double + // CHECK-DAG: Type{{.*}} , name = "_Complex float", size = 4, compiler_type = 0x{{[0-9a-f]+}} _Complex float // CHECK-DAG: Type{{.*}} , name = "_Complex double", size = 8, compiler_type = 0x{{[0-9a-f]+}} _Complex double -// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct1", size = 1, decl = simple-types.cpp:21, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 { -// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct2", size = 1, decl = simple-types.cpp:22, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 { -// CHECK-DAG: Type{{.*}} , name = "MyStruct", size = 1, decl = simple-types.cpp:24, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct { +// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct1", size = 1, decl = simple-types.cpp:20, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 { +// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct2", size = 1, decl = simple-types.cpp:21, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 { +// CHECK-DAG: Type{{.*}} , name = "MyStruct", size = 1, decl = simple-types.cpp:23, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct { // CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct *const // CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const struct MyStruct *const @@ -137,6 +138,3 @@ int main() { // CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 (char *) // CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} long[2] - -// double is used as a parameter to `PF`, but not created as an LLDB type -// FUNC-PARAMS-NOT: Type{{.*}} , name = "double" diff --git a/lldb/test/Shell/SymbolFile/PDB/typedefs.test b/lldb/test/Shell/SymbolFile/PDB/typedefs.test index 86846fb51126a..31bf7140b9219 100644 --- a/lldb/test/Shell/SymbolFile/PDB/typedefs.test +++ b/lldb/test/Shell/SymbolFile/PDB/typedefs.test @@ -1,7 +1,8 @@ REQUIRES: system-windows, msvc RUN: mkdir -p %t.dir RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%t.dir/SimpleTypesTest.cpp.typedefs.exe %S/Inputs/SimpleTypesTest.cpp -RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=0 lldb-test symbols %t.dir/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s ; Generate 32-bit target @@ -13,7 +14,7 @@ RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s ; both of them is the same. CHECK: Module [[MOD:.*]] -CHECK: SymbolFile pdb ([[MOD]]) +CHECK: SymbolFile {{(native-)?}}pdb ([[MOD]]) CHECK-DAG: name = "char32_t", size = 4, compiler_type = {{.*}} char32_t CHECK-DAG: name = "char16_t", size = 2, compiler_type = {{.*}} char16_t CHECK-DAG: Type{{.*}} , name = "unsigned long", size = 4, compiler_type = {{.*}} unsigned long @@ -23,7 +24,7 @@ CHECK-DAG: Type{{.*}} , size = 40, compiler_type = {{.*}} unsigned long[10] CHECK-DAG: Type{{.*}} , name = "double", size = 8, compiler_type = {{.*}} double CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} double * CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} double *& -CHECK-DAG: Type{{.*}} , name = "RefTypedef", compiler_type = {{.*}} typedef RefTypedef +CHECK-DAG: Type{{.*}} , name = "RefTypedef"{{(, size = 4)?}}, compiler_type = {{.*}} typedef RefTypedef CHECK-DAG: Type{{.*}} , name = "wchar_t", size = 2, compiler_type = {{.*}} wchar_t @@ -37,23 +38,23 @@ CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} short * CHECK-DAG: Type{{.*}} , name = "const double", size = 8, compiler_type = {{.*}} const double CHECK-DAG: Type{{.*}} , name = "volatile bool", size = 1, compiler_type = {{.*}} volatile _Bool CHECK-DAG: Type{{.*}} , name = "long long", size = 8, compiler_type = {{.*}} long long -CHECK-DAG: Type{{.*}} , compiler_type = {{.*}} long long (int &, unsigned char **, short *, const double, volatile _Bool) -CHECK-DAG: Type{{.*}} , name = "FuncPtrTypedef", compiler_type = {{.*}} typedef FuncPtrTypedef +CHECK-DAG: Type{{.*}} {{(, size = 0)?}}, compiler_type = {{.*}} long long (int &, unsigned char **, short *, const double, volatile _Bool) +CHECK-DAG: Type{{.*}} , name = "FuncPtrTypedef"{{(, size = 4)?}}, compiler_type = {{.*}} typedef FuncPtrTypedef -CHECK-DAG: Type{{.*}} , name = "void", compiler_type = {{.*}} void +CHECK-DAG: Type{{.*}} , name = "void"{{(, size = 0)?}}, compiler_type = {{.*}} void CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} void * CHECK-DAG: Type{{.*}} , name = "long", size = 4, compiler_type = {{.*}} long CHECK-DAG: Type{{.*}} , name = "unsigned short", size = 2, compiler_type = {{.*}} unsigned short -CHECK-DAG: Type{{.*}} , name = "unsigned int", size = 4, compiler_type = {{.*}} unsigned int +CHECK-DAG: Type{{.*}} , name = "unsigned{{( int)?}}", size = 4, compiler_type = {{.*}} unsigned int CHECK-DAG: Type{{.*}} , name = "char", size = 1, compiler_type = {{.*}} char CHECK-DAG: Type{{.*}} , name = "signed char", size = 1, compiler_type = {{.*}} signed char -CHECK-DAG: Type{{.*}} , compiler_type = {{.*}} char (void *, long, unsigned short, unsigned int, ...) +CHECK-DAG: Type{{.*}} {{(, size = 0)?}}, compiler_type = {{.*}} char (void *, long, unsigned short, unsigned int, ...) CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} char (*)(void *, long, unsigned short, unsigned int, ...) -CHECK-DAG: Type{{.*}} , name = "VarArgsFuncTypedef", compiler_type = {{.*}} typedef VarArgsFuncTypedef +CHECK-DAG: Type{{.*}} , name = "VarArgsFuncTypedef"{{(, size = 4)?}}, compiler_type = {{.*}} typedef VarArgsFuncTypedef CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = {{.*}} float -CHECK-DAG: Type{{.*}} , compiler_type = {{.*}} float (...) +CHECK-DAG: Type{{.*}} {{(, size = 0)?}}, compiler_type = {{.*}} float (...) CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} float (*)(...) -CHECK-DAG: Type{{.*}} , name = "VarArgsFuncTypedefA", compiler_type = {{.*}} typedef VarArgsFuncTypedefA +CHECK-DAG: Type{{.*}} , name = "VarArgsFuncTypedefA"{{(, size = 4)?}}, compiler_type = {{.*}} typedef VarArgsFuncTypedefA CHECK-DAG: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\SimpleTypesTest.cpp'