Files
clang-p2996/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
Tonko Sabolčec f66b69a392 [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
2021-11-23 12:53:03 +01:00

64 lines
2.9 KiB
Python

"""Test that C++ global variables can be inspected by name and also their mangled name."""
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class GlobalVariablesCppTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
def setUp(self):
TestBase.setUp(self)
self.source = lldb.SBFileSpec('main.cpp')
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'])
self.expect("target variable abc::g_file_global_int", VARIABLES_DISPLAYED_CORRECTLY,
substrs=['42'])
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)
mangled = lldb.SBAddress(addr, target).GetSymbol().GetMangledName()
self.assertNotEqual(mangled, None)
gv = target.FindFirstGlobalVariable(mangled)
self.assertTrue(gv.IsValid())
self.assertEqual(gv.GetName(), "abc::g_file_global_int")
self.assertEqual(gv.GetValueAsUnsigned(), 42)