llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: nerix (Nerixyz) <details> <summary>Changes</summary> Tag types like stucts or enums didn't have a declaration attached to them. The source locations are present in the IPI stream in `LF_UDT_MOD_SRC_LINE` records: ``` 0x101F | LF_UDT_MOD_SRC_LINE [size = 18, hash = 0x1C63] udt = 0x1058, mod = 3, file = 1, line = 0 0x2789 | LF_UDT_MOD_SRC_LINE [size = 18, hash = 0x1E5A] udt = 0x1253, mod = 35, file = 93, line = 17069 ``` The file is an ID in the string table `/names`: ``` ID | String 1 | '\<unknown>' 12 | 'D:\a\_work\1\s\src\ExternalAPIs\WindowsSDKInc\c\Include\10.0.22621.0\um\wingdi.h' 93 | 'D:\a\_work\1\s\src\ExternalAPIs\WindowsSDKInc\c\Include\10.0.22621.0\um\winnt.h' ``` Here, we're not interested in `mod`. This would indicate which module contributed the UDT. I was looking at Rustc's PDB and found that it uses `<unknown>` for some types, so I added a check for that. This makes two DIA PDB shell tests to work with the native PDB plugin. --- Full diff: https://github.com/llvm/llvm-project/pull/152579.diff 4 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (+54-3) - (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (+10) - (modified) lldb/test/Shell/SymbolFile/PDB/class-layout.test (+11-1) - (modified) lldb/test/Shell/SymbolFile/PDB/enums-layout.test (+6) ``````````diff diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index dcea33dd9f854..684d46d1da4e6 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -643,8 +643,7 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id, std::string uname = GetUnqualifiedTypeName(record); - // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE. - Declaration decl; + Declaration decl = ResolveUdtDeclaration(type_id); return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, Type::ResolveState::Forward); @@ -667,7 +666,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, CompilerType ct) { std::string uname = GetUnqualifiedTypeName(er); - Declaration decl; + Declaration decl = ResolveUdtDeclaration(type_id); TypeSP underlying_type = GetOrCreateType(er.UnderlyingType); return MakeType( @@ -2441,3 +2440,55 @@ SymbolFileNativePDB::GetContextForType(TypeIndex ti) { } return ctx; } + +void SymbolFileNativePDB::CacheUdtDeclarations() { + if (m_has_cached_udt_declatations) + return; + m_has_cached_udt_declatations = true; + + for (CVType cvt : m_index->ipi().typeArray()) { + if (cvt.kind() != LF_UDT_MOD_SRC_LINE) + continue; + + UdtModSourceLineRecord udt_mod_src; + llvm::cantFail(TypeDeserializer::deserializeAs(cvt, udt_mod_src)); + // Some types might be contributed by multiple modules. We assume that they + // all point to the same file and line because we can only provide one + // location. + m_udt_declarations.try_emplace(udt_mod_src.UDT, + udt_mod_src.SourceFile.getIndex(), + udt_mod_src.LineNumber); + } +} + +Declaration SymbolFileNativePDB::ResolveUdtDeclaration(PdbTypeSymId type_id) { + CacheUdtDeclarations(); + auto it = m_udt_declarations.find(type_id.index); + if (it == m_udt_declarations.end()) + return Declaration(); + + auto [file_index, line] = it->second; + auto string_table = m_index->pdb().getStringTable(); + if (!string_table) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), string_table.takeError(), + "Failed to get string table: {0}"); + return Declaration(); + } + + llvm::Expected<llvm::StringRef> file_name = + string_table->getStringTable().getString(file_index); + if (!file_name) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), file_name.takeError(), + "Failed to get string with id {1}: {0}", file_index); + return Declaration(); + } + + // rustc sets the filename to "<unknown>" for some files + if (*file_name == "\\<unknown>") + return Declaration(); + + FileSpec::Style style = file_name->starts_with("/") + ? FileSpec::Style::posix + : FileSpec::Style::windows; + return Declaration(FileSpec(*file_name, style), line); +} diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index eda375d4cebe7..2e8270794af1a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -260,6 +260,9 @@ class SymbolFileNativePDB : public SymbolFileCommon { std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti); + void CacheUdtDeclarations(); + Declaration ResolveUdtDeclaration(PdbTypeSymId type_id); + llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; @@ -281,6 +284,13 @@ class SymbolFileNativePDB : public SymbolFileCommon { llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex> m_parent_types; + /// type index -> (filename index, line) + /// + /// The filename index is an index into the `/names` section (string table) + llvm::DenseMap<llvm::codeview::TypeIndex, std::pair<uint32_t, uint32_t>> + m_udt_declarations; + bool m_has_cached_udt_declatations = false; + lldb_private::UniqueCStringMap<uint32_t> m_type_base_names; }; diff --git a/lldb/test/Shell/SymbolFile/PDB/class-layout.test b/lldb/test/Shell/SymbolFile/PDB/class-layout.test index e9a7d1c0daa9e..eca910e997e40 100644 --- a/lldb/test/Shell/SymbolFile/PDB/class-layout.test +++ b/lldb/test/Shell/SymbolFile/PDB/class-layout.test @@ -12,9 +12,19 @@ RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=BASE %s RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=FRIEND %s RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=CLASS %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNION %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=STRUCT %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=COMPLEX %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=LIST %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNNAMED-STRUCT %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=BASE %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=FRIEND %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=CLASS %s CHECK: Module [[MOD:.*]] -CHECK: SymbolFile pdb ([[MOD]]) +CHECK: SymbolFile {{(native-)?}}pdb ([[MOD]]) CHECK: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\ClassLayoutTest.cpp' ENUM: name = "Enum", size = 4, decl = ClassLayoutTest.cpp:5 diff --git a/lldb/test/Shell/SymbolFile/PDB/enums-layout.test b/lldb/test/Shell/SymbolFile/PDB/enums-layout.test index 6f861c6d65adf..9766d6f8b0324 100644 --- a/lldb/test/Shell/SymbolFile/PDB/enums-layout.test +++ b/lldb/test/Shell/SymbolFile/PDB/enums-layout.test @@ -7,6 +7,12 @@ RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check- RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=UCHAR-ENUM %s RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CLASS-ENUM %s RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=STRUCT-ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CONST-ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=EMPTY-ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=UCHAR-ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CLASS-ENUM %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=STRUCT-ENUM %s ; FIXME: PDB does not have information about scoped enumeration (Enum class) so the ; compiler type used is the same as the one for unscoped enumeration. `````````` </details> https://github.com/llvm/llvm-project/pull/152579 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits