[Lldb-commits] [lldb] [lldb] Lookup static const members in FindGlobalVariables (PR #111859)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 10 09:00:22 PDT 2024
https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/111859
>From 4c394ec162b58b3cde3af924a5e9be1de8250a07 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 30 Jul 2024 17:02:10 +0500
Subject: [PATCH] [lldb] Lookup static const members in FindGlobalVariables
Static const members initialized inside a class definition might not have a corresponding DW_TAG_variable (DWARF 4 and earlier), so they're not indexed by ManualDWARFIndex.
Add an additional lookup in FindGlobalVariables. Try looking up the enclosing type (e.g. foo::bar for foo::bar::A) and then searching for a static const member (A) within this type.
---
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 130 ++++++++++++++++++
.../SymbolFile/DWARF/SymbolFileDWARF.h | 3 +
.../API/python_api/frame/globals/Makefile | 4 +
.../frame/globals/TestTargetGlobals.py | 43 ++++++
.../API/python_api/frame/globals/main.cpp | 12 ++
5 files changed, 192 insertions(+)
create mode 100644 lldb/test/API/python_api/frame/globals/Makefile
create mode 100644 lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
create mode 100644 lldb/test/API/python_api/frame/globals/main.cpp
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9287d4baf19e9c..d53da79c1efcee 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2439,6 +2439,48 @@ void SymbolFileDWARF::FindGlobalVariables(
return variables.GetSize() - original_size < max_matches;
});
+ // If we don't have enough matches and the variable context is not empty, try
+ // to resolve the context as a type and look for static const members.
+ if (variables.GetSize() - original_size < max_matches && !context.empty()) {
+ llvm::StringRef type_name;
+ if (std::optional<Type::ParsedName> parsed_name =
+ Type::GetTypeScopeAndBasename(context))
+ type_name = parsed_name->basename;
+ else
+ type_name = context;
+
+ m_index->GetTypes(ConstString(type_name), [&](DWARFDIE parent) {
+ llvm::StringRef parent_type_name = parent.GetDWARFDeclContext()
+ .GetQualifiedNameAsConstString()
+ .GetStringRef();
+
+ // This type is from another scope, skip it.
+ if (!parent_type_name.ends_with(context))
+ return true;
+
+ auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(parent.GetCU());
+ if (!dwarf_cu)
+ return true;
+
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
+
+ for (DWARFDIE die = parent.GetFirstChild(); die.IsValid();
+ die = die.GetSibling()) {
+ // Try parsing the entry as a static const member.
+ if (auto var_sp = ParseStaticConstMemberDIE(sc, die)) {
+ if (var_sp->GetUnqualifiedName().GetStringRef() != basename)
+ continue;
+
+ // There can be only one member with a given name.
+ variables.AddVariableIfUnique(var_sp);
+ break;
+ }
+ }
+
+ return variables.GetSize() - original_size < max_matches;
+ });
+ }
+
// Return the number of variable that were appended to the list
const uint32_t num_matches = variables.GetSize() - original_size;
if (log && num_matches > 0) {
@@ -3371,6 +3413,94 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
return 0;
}
+VariableSP SymbolFileDWARF::ParseStaticConstMemberDIE(
+ const lldb_private::SymbolContext &sc, const DWARFDIE &die) {
+ if (die.GetDWARF() != this)
+ return die.GetDWARF()->ParseStaticConstMemberDIE(sc, die);
+
+ // Look only for members, ignore all other types of entries.
+ if (die.Tag() != DW_TAG_member)
+ return nullptr;
+
+ if (VariableSP var_sp = GetDIEToVariable()[die.GetDIE()])
+ return var_sp; // Already been parsed!
+
+ const char *name = nullptr;
+ const char *mangled = nullptr;
+ Declaration decl;
+ DWARFExpression location;
+ DWARFFormValue type_die_form;
+ DWARFFormValue const_value_form;
+
+ DWARFAttributes attributes = die.GetAttributes();
+ const size_t num_attributes = attributes.Size();
+
+ for (size_t i = 0; i < num_attributes; ++i) {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+
+ if (!attributes.ExtractFormValueAtIndex(i, form_value))
+ continue;
+
+ switch (attr) {
+ case DW_AT_decl_file:
+ decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
+ form_value.Unsigned()));
+ break;
+ case DW_AT_decl_line:
+ decl.SetLine(form_value.Unsigned());
+ break;
+ case DW_AT_decl_column:
+ decl.SetColumn(form_value.Unsigned());
+ break;
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ type_die_form = form_value;
+ break;
+ case DW_AT_const_value:
+ const_value_form = form_value;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Look only for static const members with const values.
+ if (!DWARFFormValue::IsDataForm(const_value_form.Form()))
+ return nullptr;
+
+ SymbolFileTypeSP type_sp = std::make_shared<SymbolFileType>(
+ *this, type_die_form.Reference().GetID());
+
+ if (type_sp->GetType()) {
+ location.UpdateValue(const_value_form.Unsigned(),
+ type_sp->GetType()->GetByteSize(nullptr).value_or(0),
+ die.GetCU()->GetAddressByteSize());
+ }
+
+ if (Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
+ mangled =
+ die.GetDWARFDeclContext().GetQualifiedNameAsConstString().GetCString();
+
+ ValueType scope = eValueTypeVariableGlobal;
+ Variable::RangeList scope_ranges;
+
+ DWARFExpressionList location_list(GetObjectFile()->GetModule(), location,
+ die.GetCU());
+ VariableSP var_sp = std::make_shared<Variable>(
+ die.GetID(), name, mangled, type_sp, scope, sc.comp_unit, scope_ranges,
+ &decl, location_list, /*is_external*/ true, /*is_artificial*/ false,
+ /*is_static_member*/ true);
+ var_sp->SetLocationIsConstantValueData(true);
+
+ // Cache this variable, so we don't parse it over and over again.
+ GetDIEToVariable()[die.GetDIE()] = var_sp;
+
+ return var_sp;
+}
+
VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
const DWARFDIE &die) {
if (!die)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 4967b37d753a09..380b5d4a289300 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -408,6 +408,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module,
SupportFileList &support_files);
+ lldb::VariableSP ParseStaticConstMemberDIE(const SymbolContext &sc,
+ const DWARFDIE &die);
+
lldb::VariableSP ParseVariableDIE(const SymbolContext &sc,
const DWARFDIE &die,
const lldb::addr_t func_low_pc);
diff --git a/lldb/test/API/python_api/frame/globals/Makefile b/lldb/test/API/python_api/frame/globals/Makefile
new file mode 100644
index 00000000000000..c24259ec8c9d93
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/Makefile
@@ -0,0 +1,4 @@
+CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -gdwarf-4
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py b/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
new file mode 100644
index 00000000000000..54d2cd89560a1a
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
@@ -0,0 +1,43 @@
+"""
+Test SBTarget::FindGlobalVariables API.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TargetAPITestCase(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ @add_test_categories(["pyapi"])
+ def test_find_global_variables(self):
+ """Exercise SBTarget.FindGlobalVariables() API."""
+ self.build()
+
+ # Don't need to launch a process, since we're only interested in
+ # looking up global variables.
+ target = self.dbg.CreateTarget(self.getBuildArtifact())
+
+ def test_global_var(query, name, type_name, value):
+ value_list = target.FindGlobalVariables(query, 1)
+ self.assertEqual(value_list.GetSize(), 1)
+ var = value_list.GetValueAtIndex(0)
+ self.DebugSBValue(var)
+ self.assertTrue(var)
+ self.assertEqual(var.GetName(), name)
+ self.assertEqual(var.GetTypeName(), type_name)
+ self.assertEqual(var.GetValue(), value)
+
+ test_global_var("Vars::inline_static", "Vars::inline_static", "double", "1.5")
+ test_global_var(
+ "Vars::static_constexpr", "Vars::static_constexpr", "const int", "2"
+ )
+ test_global_var(
+ "Vars::static_const_out_out_class",
+ "Vars::static_const_out_out_class",
+ "const int",
+ "3",
+ )
+ test_global_var(
+ "global_var_of_char_type", "::global_var_of_char_type", "char", "'X'"
+ )
\ No newline at end of file
diff --git a/lldb/test/API/python_api/frame/globals/main.cpp b/lldb/test/API/python_api/frame/globals/main.cpp
new file mode 100644
index 00000000000000..e2095e80082677
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/main.cpp
@@ -0,0 +1,12 @@
+class Vars {
+public:
+ inline static double inline_static = 1.5;
+ static constexpr int static_constexpr = 2;
+ static const int static_const_out_out_class;
+};
+
+const int Vars::static_const_out_out_class = 3;
+
+char global_var_of_char_type = 'X';
+
+int main() {}
More information about the lldb-commits
mailing list