[lldb] Fix lookup for global constants in namespaces
LLDB uses mangled name to construct a fully qualified name for global variables. Sometimes DW_TAG_linkage_name attribute is missing from debug info, so LLDB has to rely on parent entries to construct the fully qualified name. Currently, the fallback is handled when the parent DW_TAG is either DW_TAG_compiled_unit or DW_TAG_partial_unit, which may not work well for global constants in namespaces. For example: namespace ns { const int x = 10; } may produce the following debug info: <1><2a>: Abbrev Number: 2 (DW_TAG_namespace) <2b> DW_AT_name : (indirect string, offset: 0x5e): ns <2><2f>: Abbrev Number: 3 (DW_TAG_variable) <30> DW_AT_name : (indirect string, offset: 0x61): x <34> DW_AT_type : <0x3c> <38> DW_AT_decl_file : 1 <39> DW_AT_decl_line : 2 <3a> DW_AT_const_value : 10 Since the fallback didn't handle the case when parent tag is DW_TAG_namespace, LLDB wasn't able to match the variable by its fully qualified name "ns::x". This change fixes this by additional check if the parent is a DW_TAG_namespace. Reviewed By: werat, clayborg Differential Revision: https://reviews.llvm.org/D112147
This commit is contained in:
parent
5ee625bf6b
commit
f66b69a392
|
@ -3271,15 +3271,14 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
|||
}
|
||||
|
||||
const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
|
||||
const dw_tag_t parent_tag = die.GetParent().Tag();
|
||||
const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
|
||||
const dw_tag_t parent_tag = sc_parent_die.Tag();
|
||||
bool is_static_member = (parent_tag == DW_TAG_compile_unit ||
|
||||
parent_tag == DW_TAG_partial_unit) &&
|
||||
(parent_context_die.Tag() == DW_TAG_class_type ||
|
||||
parent_context_die.Tag() == DW_TAG_structure_type);
|
||||
|
||||
ValueType scope = eValueTypeInvalid;
|
||||
|
||||
const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
|
||||
SymbolContextScope *symbol_context_scope = nullptr;
|
||||
|
||||
bool has_explicit_mangled = mangled != nullptr;
|
||||
|
|
|
@ -15,12 +15,11 @@ class GlobalVariablesCppTestCase(TestBase):
|
|||
TestBase.setUp(self)
|
||||
self.source = lldb.SBFileSpec('main.cpp')
|
||||
|
||||
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
|
||||
def test(self):
|
||||
self.build()
|
||||
|
||||
(target, _, _, _) = lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", self.source)
|
||||
|
||||
|
||||
# Check that we can access g_file_global_int by its name
|
||||
self.expect("target variable g_file_global_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
substrs=['42'])
|
||||
|
@ -29,6 +28,30 @@ class GlobalVariablesCppTestCase(TestBase):
|
|||
self.expect("target variable xyz::g_file_global_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
error=True, substrs=['can\'t find global variable'])
|
||||
|
||||
# Check that we can access g_file_global_const_int by its name
|
||||
self.expect("target variable g_file_global_const_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
substrs=['1337'])
|
||||
self.expect("target variable abc::g_file_global_const_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
substrs=['1337'])
|
||||
self.expect("target variable xyz::g_file_global_const_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
error=True, substrs=['can\'t find global variable'])
|
||||
|
||||
# Try accessing a global variable in anonymous namespace.
|
||||
self.expect("target variable g_anon_namespace_const_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
substrs=['100'])
|
||||
self.expect("target variable abc::g_anon_namespace_const_int", VARIABLES_DISPLAYED_CORRECTLY,
|
||||
error=True, substrs=['can\'t find global variable'])
|
||||
var = target.FindFirstGlobalVariable("abc::(anonymous namespace)::g_anon_namespace_const_int")
|
||||
self.assertTrue(var.IsValid())
|
||||
self.assertEqual(var.GetName(), "abc::(anonymous namespace)::g_anon_namespace_const_int")
|
||||
self.assertEqual(var.GetValue(), "100")
|
||||
|
||||
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
|
||||
def test_access_by_mangled_name(self):
|
||||
self.build()
|
||||
|
||||
(target, _, _, _) = lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", self.source)
|
||||
|
||||
# Check that we can access g_file_global_int by its mangled name
|
||||
addr = target.EvaluateExpression("&abc::g_file_global_int").GetValueAsUnsigned()
|
||||
self.assertNotEqual(addr, 0)
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
#include <stdio.h>
|
||||
|
||||
namespace abc {
|
||||
int g_file_global_int = 42;
|
||||
int g_file_global_int = 42;
|
||||
const int g_file_global_const_int = 1337;
|
||||
|
||||
namespace {
|
||||
const int g_anon_namespace_const_int = 100;
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
return abc::g_file_global_int; // Set break point at this line.
|
||||
int unused = abc::g_file_global_const_int;
|
||||
int unused2 = abc::g_anon_namespace_const_int;
|
||||
return abc::g_file_global_int; // Set break point at this line.
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue