Skip to content

Commit 3c42572

Browse files
committed
[LLDB][NativePDB] Find global variables in namespaces
1 parent 507ff08 commit 3c42572

File tree

3 files changed

+81
-30
lines changed

3 files changed

+81
-30
lines changed

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

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,22 +1655,62 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) {
16551655
clang->GetNativePDBParser()->Dump(s, filter);
16561656
}
16571657

1658-
void SymbolFileNativePDB::CacheFunctionNames() {
1659-
if (!m_func_full_names.IsEmpty())
1658+
void SymbolFileNativePDB::CacheGlobalBaseNames() {
1659+
if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty())
16601660
return;
16611661

16621662
// (segment, code offset) -> gid
1663-
std::map<std::pair<uint16_t, uint32_t>, uint32_t> addr_ids;
1663+
std::map<std::pair<uint16_t, uint32_t>, uint32_t> func_addr_ids;
16641664

1665-
// First, find all function references in the globals table.
1665+
// First, look through all items in the globals table.
16661666
for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
1667-
CVSymbol ref_sym = m_index->symrecords().readRecord(gid);
1668-
auto kind = ref_sym.kind();
1667+
CVSymbol sym = m_index->symrecords().readRecord(gid);
1668+
auto kind = sym.kind();
1669+
1670+
// If this is a global variable, we only need to look at the name
1671+
llvm::StringRef name;
1672+
switch (kind) {
1673+
case SymbolKind::S_GDATA32:
1674+
case SymbolKind::S_LDATA32: {
1675+
DataSym data =
1676+
llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym));
1677+
name = data.Name;
1678+
break;
1679+
}
1680+
case SymbolKind::S_GTHREAD32:
1681+
case SymbolKind::S_LTHREAD32: {
1682+
ThreadLocalDataSym data = llvm::cantFail(
1683+
SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym));
1684+
name = data.Name;
1685+
break;
1686+
}
1687+
case SymbolKind::S_CONSTANT: {
1688+
ConstantSym data =
1689+
llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym));
1690+
name = data.Name;
1691+
break;
1692+
}
1693+
default:
1694+
break;
1695+
}
1696+
1697+
if (!name.empty()) {
1698+
llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name);
1699+
if (base.empty())
1700+
base = name;
1701+
1702+
m_global_variable_base_names.Append(ConstString(base), gid);
1703+
continue;
1704+
}
1705+
16691706
if (kind != S_PROCREF && kind != S_LPROCREF)
16701707
continue;
16711708

1709+
// For functions, we need to follow the reference to the procedure and look
1710+
// at the type
1711+
16721712
ProcRefSym ref =
1673-
llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(ref_sym));
1713+
llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym));
16741714
if (ref.Name.empty())
16751715
continue;
16761716

@@ -1694,7 +1734,7 @@ void SymbolFileNativePDB::CacheFunctionNames() {
16941734
// The function/procedure symbol only contains the demangled name.
16951735
// The mangled names are in the publics table. Save the address of this
16961736
// function to lookup the mangled name later.
1697-
addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);
1737+
func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);
16981738

16991739
llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name);
17001740
if (basename.empty())
@@ -1729,8 +1769,8 @@ void SymbolFileNativePDB::CacheFunctionNames() {
17291769
continue;
17301770

17311771
// Check if this symbol is for one of our functions.
1732-
auto it = addr_ids.find({pub.Segment, pub.Offset});
1733-
if (it != addr_ids.end())
1772+
auto it = func_addr_ids.find({pub.Segment, pub.Offset});
1773+
if (it != func_addr_ids.end())
17341774
m_func_full_names.Append(ConstString(pub.Name), it->second);
17351775
}
17361776

@@ -1741,31 +1781,35 @@ void SymbolFileNativePDB::CacheFunctionNames() {
17411781
m_func_method_names.SizeToFit();
17421782
m_func_base_names.Sort();
17431783
m_func_base_names.SizeToFit();
1784+
m_global_variable_base_names.Sort(std::less<uint32_t>());
1785+
m_global_variable_base_names.SizeToFit();
17441786
}
17451787

17461788
void SymbolFileNativePDB::FindGlobalVariables(
17471789
ConstString name, const CompilerDeclContext &parent_decl_ctx,
17481790
uint32_t max_matches, VariableList &variables) {
17491791
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1750-
using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
17511792

1752-
std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
1753-
name.GetStringRef(), m_index->symrecords());
1754-
for (const SymbolAndOffset &result : results) {
1755-
switch (result.second.kind()) {
1756-
case SymbolKind::S_GDATA32:
1757-
case SymbolKind::S_LDATA32:
1758-
case SymbolKind::S_GTHREAD32:
1759-
case SymbolKind::S_LTHREAD32:
1760-
case SymbolKind::S_CONSTANT: {
1761-
PdbGlobalSymId global(result.first, false);
1762-
if (VariableSP var = GetOrCreateGlobalVariable(global))
1763-
variables.AddVariable(var);
1764-
break;
1765-
}
1766-
default:
1793+
CacheGlobalBaseNames();
1794+
1795+
std::vector<uint32_t> results;
1796+
m_global_variable_base_names.GetValues(name, results);
1797+
1798+
size_t n_matches = 0;
1799+
for (uint32_t gid : results) {
1800+
PdbGlobalSymId global(gid, false);
1801+
1802+
if (parent_decl_ctx.IsValid() &&
1803+
GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
17671804
continue;
1768-
}
1805+
1806+
VariableSP var = GetOrCreateGlobalVariable(global);
1807+
if (!var)
1808+
continue;
1809+
variables.AddVariable(var);
1810+
1811+
if (++n_matches >= max_matches)
1812+
break;
17691813
}
17701814
}
17711815

@@ -1783,7 +1827,7 @@ void SymbolFileNativePDB::FindFunctions(
17831827
name_type_mask & eFunctionNameTypeBase ||
17841828
name_type_mask & eFunctionNameTypeMethod))
17851829
return;
1786-
CacheFunctionNames();
1830+
CacheGlobalBaseNames();
17871831

17881832
std::set<uint32_t> resolved_ids; // avoid duplicate lookups
17891833
auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,10 @@ class SymbolFileNativePDB : public SymbolFileCommon {
260260

261261
std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti);
262262

263-
void CacheFunctionNames();
263+
/// Caches the basenames of symbols found in the globals stream.
264+
///
265+
/// This includes functions and global variables
266+
void CacheGlobalBaseNames();
264267

265268
void CacheUdtDeclarations();
266269
llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id);
@@ -306,6 +309,9 @@ class SymbolFileNativePDB : public SymbolFileCommon {
306309
lldb_private::UniqueCStringMap<uint32_t> m_func_base_names;
307310
/// method basename -> Global ID(s)
308311
lldb_private::UniqueCStringMap<uint32_t> m_func_method_names;
312+
313+
/// basename -> Global ID(s)
314+
lldb_private::UniqueCStringMap<uint32_t> m_global_variable_base_names;
309315
};
310316

311317
} // namespace npdb

lldb/test/Shell/SymbolFile/PDB/expressions.test

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
REQUIRES: target-windows, msvc
22
RUN: %build --compiler=msvc --nodefaultlib --output=%t.exe %S/Inputs/ExpressionsTest.cpp
3-
RUN: not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s
3+
RUN: env LLDB_USE_NATIVE_PDB_READER=0 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s
4+
RUN: env LLDB_USE_NATIVE_PDB_READER=1 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s
45

56
// Check the variable value through `expression`
67
CHECK: (lldb) expression result

0 commit comments

Comments
 (0)