[Lldb-commits] [lldb] r265498 - make TestRegisterVariables slightly more resilient

Todd Fiala via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 5 18:14:37 PDT 2016


Author: tfiala
Date: Tue Apr  5 20:14:37 2016
New Revision: 265498

URL: http://llvm.org/viewvc/llvm-project?rev=265498&view=rev
Log:
make TestRegisterVariables slightly more resilient

This test sets the compiler optimization level to -O1 and
makes some assumptions about how local frame vars will be
stored (i.e. in registers).  These assumptions are not always
true.

I did a first-pass set of improvements that:
(1) no longer assumes that every one of the target locations has
    every variable in a register.  Sometimes the compiler
    is even smarter and skips the register entirely.
(2) simply expects one of the 5 or so variables it checks
    to be in a register.

This test probably passes on a whole lot more systems than it
used to now.  This is certainly true on OS X.

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py

Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile?rev=265498&r1=265497&r2=265498&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile Tue Apr  5 20:14:37 2016
@@ -2,6 +2,12 @@ LEVEL = ../../../make
 
 C_SOURCES := test.c
 
-CFLAGS ?= -g -O1
+CFLAGS := -g -O1
+
+$(info OS: $(OS))
+HOST_OS = $(shell uname -s)
+ifeq "$(HOST_OS)" "Darwin"
+	FRAMEWORK_INCLUDES = -isysroot $(shell xcrun -show-sdk-path)
+endif
 
 include $(LEVEL)/Makefile.rules

Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py?rev=265498&r1=265497&r2=265498&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py Tue Apr  5 20:14:37 2016
@@ -2,23 +2,107 @@
 
 from __future__ import print_function
 
-
-
 import os, time
+import re
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 
+# This method attempts to figure out if a given variable
+# is in a register.
+#
+# Return:
+#   True if the value has a readable value and is in a register
+#   False otherwise
+def is_variable_in_register(frame, var_name):
+    # Ensure we can lookup the variable.
+    var = frame.FindVariable(var_name)
+    # print("\nchecking {}...".format(var_name))
+    if var is None or not var.IsValid():
+        # print("{} cannot be found".format(var_name))
+        return False
+
+    # Check that we can get its value.  If not, this
+    # may be a variable that is just out of scope at this point.
+    value = var.GetValue()
+    # print("checking value...")
+    if value is None:
+        # print("value is invalid")
+        return False
+    # else:
+        # print("value is {}".format(value))
+
+    # We have a variable and we can get its value.  The variable is in
+    # a register if we cannot get an address for it, assuming it is
+    # not a struct pointer.  (This is an approximation - compilers can
+    # do other things with spitting up a value into multiple parts of
+    # multiple registers, but what we're verifying here is much more
+    # than it was doing before).
+    var_addr = var.GetAddress()
+    # print("checking address...")
+    if var_addr.IsValid():
+        # We have an address, it must not be in a register.
+        # print("var {} is not in a register: has a valid address {}".format(var_name, var_addr))
+        return False
+    else:
+        # We don't have an address but we can read the value.
+        # It is likely stored in a register.
+        # print("var {} is in a register (we don't have an address for it)".format(var_name))
+        return True
+
+
+def is_struct_pointer_in_register(frame, var_name):
+    # Ensure we can lookup the variable.
+    var = frame.FindVariable(var_name)
+    # print("\nchecking {}...".format(var_name))
+    if var is None or not var.IsValid():
+        # print("{} cannot be found".format(var_name))
+        return False
+
+    # Check that we can get its value.  If not, this
+    # may be a variable that is just out of scope at this point.
+    value = var.GetValue()
+    # print("checking value...")
+    if value is None:
+        # print("value is invalid")
+        return False
+    # else:
+    #     print("value is {}".format(value))
+
+    var_loc = var.GetLocation()
+    # print("checking location: {}".format(var_loc))
+    if var_loc is None or var_loc.startswith("0x"):
+        # The frame var is not in a register but rather a memory location.
+        # print("frame var {} is not in a register".format(var_name))
+        return False
+    else:
+        # print("frame var {} is in a register".format(var_name))
+        return True
+
+
+def re_expr_equals(val_type, val):
+    # Match ({val_type}) ${sum_digits} = {val}
+    return re.compile(r'\(' + val_type + '\) \$\d+ = ' + str(val))
+
+
 class RegisterVariableTestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
-    @expectedFailureAll(oslist=['macosx'], compiler='clang', compiler_version=['<', '7.0.0'], debug_info="dsym")
-    @expectedFailureAll(compiler="clang")
-    @expectedFailureAll(compiler="gcc", compiler_version=['>=', '4.8.2'])
+
+    @expectedFailureAll(compiler="clang", compiler_version=['<', '3.5'])
+    @expectedFailureAll(compiler="gcc", compiler_version=['=', '4.8.2'])
     def test_and_run_command(self):
         """Test expressions on register values."""
+
+        # This test now ensures that each probable
+        # register variable location is actually a register, and
+        # if so, whether we can print out the variable there.
+        # It only requires one of them to be handled in a non-error
+        # way.
+        register_variables_count = 0
+
         self.build()
         exe = os.path.join(os.getcwd(), "a.out")
         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
@@ -41,11 +125,16 @@ class RegisterVariableTestCase(TestBase)
             substrs = [' resolved, hit count = 1'])
 
         # Try some variables that should be visible
-        self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(int) $0 = 2'])
-
-        self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(int) $1 = 3'])
+        frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
+        if is_variable_in_register(frame, 'a'):
+            register_variables_count += 1
+            self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY,
+                patterns = [re_expr_equals('int', 2)])
+
+        if is_struct_pointer_in_register(frame, 'b'):
+            register_variables_count += 1
+            self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY,
+                patterns = [re_expr_equals('int', 3)])
 
         #####################
         # Second breakpoint
@@ -62,11 +151,16 @@ class RegisterVariableTestCase(TestBase)
             substrs = [' resolved, hit count = 1'])
 
         # Try some variables that should be visible
-        self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(int) $2 = 5'])
-
-        self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(int) $3 = 5'])
+        frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
+        if is_struct_pointer_in_register(frame, 'b'):
+            register_variables_count += 1
+            self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY,
+                patterns = [re_expr_equals('int', 5)])
+
+        if is_variable_in_register(frame, 'c'):
+            register_variables_count += 1
+            self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY,
+                patterns = [re_expr_equals('int', 5)])
 
         #####################
         # Third breakpoint
@@ -83,7 +177,14 @@ class RegisterVariableTestCase(TestBase)
             substrs = [' resolved, hit count = 1'])
 
         # Try some variables that should be visible
-        self.expect("expr f", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(float) $4 = 3.1'])
+        frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
+        if is_variable_in_register(frame, 'f'):
+            register_variables_count += 1
+            self.expect("expr f", VARIABLES_DISPLAYED_CORRECTLY,
+                patterns = [re_expr_equals('float', '3.1')])
+
+        # Validate that we verified at least one register variable
+        self.assertTrue(register_variables_count > 0, "expected to verify at least one variable in a register")
+        # print("executed {} expressions with values in registers".format(register_variables_count))
 
         self.runCmd("kill")




More information about the lldb-commits mailing list