283 lines · python
1"""2Test some SBValue APIs.3"""4 5import lldb6from lldbsuite.test import lldbutil7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9 10 11class ValueAPITestCase(TestBase):12 def setUp(self):13 # Call super's setUp().14 TestBase.setUp(self)15 # We'll use the test method name as the exe_name.16 self.exe_name = self.testMethodName17 # Find the line number to of function 'c'.18 self.line = line_number("main.c", "// Break at this line")19 20 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772")21 def test(self):22 """Exercise some SBValue APIs."""23 d = {"EXE": self.exe_name}24 self.build(dictionary=d)25 self.setTearDownCleanup(dictionary=d)26 exe = self.getBuildArtifact(self.exe_name)27 28 # Create a target by the debugger.29 target = self.dbg.CreateTarget(exe)30 self.assertTrue(target, VALID_TARGET)31 32 # Create the breakpoint inside function 'main'.33 breakpoint = target.BreakpointCreateByLocation("main.c", self.line)34 self.assertTrue(breakpoint, VALID_BREAKPOINT)35 36 # Now launch the process, and do not stop at entry point.37 process = target.LaunchSimple(None, None, self.get_process_working_directory())38 self.assertTrue(process, PROCESS_IS_VALID)39 40 # Get Frame #0.41 self.assertState(process.GetState(), lldb.eStateStopped)42 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)43 self.assertTrue(44 thread.IsValid(),45 "There should be a thread stopped due to breakpoint condition",46 )47 frame0 = thread.GetFrameAtIndex(0)48 49 # Get global variable 'days_of_week'.50 list = target.FindGlobalVariables("days_of_week", 1)51 days_of_week = list.GetValueAtIndex(0)52 self.assertTrue(days_of_week, VALID_VARIABLE)53 self.assertEqual(days_of_week.GetNumChildren(), 7, VALID_VARIABLE)54 self.DebugSBValue(days_of_week)55 56 # Use this to test the "child" and "children" accessors:57 children = days_of_week.children58 self.assertEqual(len(children), 7, VALID_VARIABLE)59 for i in range(0, len(children)):60 day = days_of_week.child[i]61 list_day = children[i]62 self.assertNotEqual(day, None)63 self.assertNotEqual(list_day, None)64 self.assertEqual(day.GetSummary(), list_day.GetSummary(), VALID_VARIABLE)65 66 # Spot check the actual value:67 first_day = days_of_week.child[1]68 self.assertEqual(first_day.GetSummary(), '"Monday"', VALID_VARIABLE)69 70 # Get global variable 'weekdays'.71 list = target.FindGlobalVariables("weekdays", 1)72 weekdays = list.GetValueAtIndex(0)73 self.assertTrue(weekdays, VALID_VARIABLE)74 self.assertEqual(weekdays.GetNumChildren(), 5, VALID_VARIABLE)75 self.DebugSBValue(weekdays)76 77 # Get global variable 'g_table'.78 list = target.FindGlobalVariables("g_table", 1)79 g_table = list.GetValueAtIndex(0)80 self.assertTrue(g_table, VALID_VARIABLE)81 self.assertEqual(g_table.GetNumChildren(), 2, VALID_VARIABLE)82 self.DebugSBValue(g_table)83 84 fmt = lldbutil.BasicFormatter()85 cvf = lldbutil.ChildVisitingFormatter(indent_child=2)86 rdf = lldbutil.RecursiveDescentFormatter(indent_child=2)87 if self.TraceOn():88 print(fmt.format(days_of_week))89 print(cvf.format(days_of_week))90 print(cvf.format(weekdays))91 print(rdf.format(g_table))92 93 # Get variable 'my_int_ptr'.94 value = frame0.FindVariable("my_int_ptr")95 self.assertTrue(value, VALID_VARIABLE)96 self.DebugSBValue(value)97 98 # Get what 'my_int_ptr' points to.99 pointed = value.GetChildAtIndex(0)100 self.assertTrue(pointed, VALID_VARIABLE)101 self.DebugSBValue(pointed)102 103 # While we are at it, verify that 'my_int_ptr' points to 'g_my_int'.104 symbol = target.ResolveLoadAddress(int(pointed.GetLocation(), 0)).GetSymbol()105 self.assertTrue(symbol)106 self.expect(symbol.GetName(), exe=False, startstr="g_my_int")107 108 # Get variable 'str_ptr'.109 value = frame0.FindVariable("str_ptr")110 self.assertTrue(value, VALID_VARIABLE)111 self.DebugSBValue(value)112 113 # SBValue::TypeIsPointerType() should return true.114 self.assertTrue(value.TypeIsPointerType())115 116 # Verify the SBValue::GetByteSize() API is working correctly.117 arch = self.getArchitecture()118 if arch == "i386":119 self.assertEqual(value.GetByteSize(), 4)120 elif arch == "x86_64":121 self.assertEqual(value.GetByteSize(), 8)122 123 # Get child at index 5 => 'Friday'.124 child = value.GetChildAtIndex(5, lldb.eNoDynamicValues, True)125 self.assertTrue(child, VALID_VARIABLE)126 self.DebugSBValue(child)127 128 self.expect(child.GetSummary(), exe=False, substrs=["Friday"])129 130 # Now try to get at the same variable using GetValueForExpressionPath().131 # These two SBValue objects should have the same value.132 val2 = value.GetValueForExpressionPath("[5]")133 self.assertTrue(val2, VALID_VARIABLE)134 self.DebugSBValue(val2)135 self.assertTrue(136 child.GetValue() == val2.GetValue()137 and child.GetSummary() == val2.GetSummary()138 )139 140 val_i = target.EvaluateExpression("i")141 val_s = target.EvaluateExpression("s")142 val_a = target.EvaluateExpression("a")143 self.assertTrue(val_s.member["a"].GetAddress().IsValid(), VALID_VARIABLE)144 self.assertTrue(val_s.member["a"].AddressOf(), VALID_VARIABLE)145 self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE)146 147 # Test some other cases of the Cast API. We allow casts from one struct type148 # to another, which is a little weird, but we don't support casting from a149 # smaller type to a larger when the underlying data is not in the inferior,150 # since then we have no way to fetch the out-of-bounds values.151 # For an expression that references a variable, or a FindVariable result,152 # or an SBValue made from an address and a type, we can get back to the target,153 # so those will work. Make sure they do and get the right extra values as well.154 155 # We're casting everything to the type of "f", so get that first:156 f_var = frame0.FindVariable("f")157 self.assertSuccess(f_var.error, "Got f")158 bigger_type = f_var.GetType()159 160 # First try a value that we got from FindVariable161 container = frame0.FindVariable("my_container")162 self.assertSuccess(container.error, "Found my_container")163 fv_small = container.GetValueForExpressionPath(".data.small")164 self.assertSuccess(fv_small.error, "Found small in my_container")165 fv_cast = fv_small.Cast(bigger_type)166 self.assertSuccess(fv_cast.error, "Can cast up from FindVariable")167 child_checks = [168 ValueCheck(name="a", value="33", type="int"),169 ValueCheck(name="b", value="44", type="int"),170 ValueCheck(name="c", value="55", type="int"),171 ]172 cast_check = ValueCheck(type=bigger_type.name, children=child_checks)173 174 # Now try one we made with expr. This one should fail, because expr175 # stores the "canonical value" in host memory, and doesn't know how176 # to augment that from the live address.177 expr_cont = frame0.EvaluateExpression("my_container")178 self.assertSuccess(expr_cont.error, "Got my_container by expr")179 expr_small = expr_cont.GetValueForExpressionPath(".data.small")180 self.assertSuccess(expr_small.error, "Got small by expr")181 expr_cast = expr_small.Cast(bigger_type)182 self.assertFailure(expr_cast.error, msg="Cannot cast expr result")183 184 # Now try one we made with CreateValueFromAddress. That will succeed185 # because this directly tracks the inferior memory.186 small_addr = fv_small.addr187 self.assertTrue(small_addr.IsValid())188 small_type = fv_small.GetType()189 vfa_small = target.CreateValueFromAddress(190 "small_from_addr", small_addr, small_type191 )192 self.assertSuccess(vfa_small.error, "Made small from address")193 vfa_cast = vfa_small.Cast(bigger_type)194 self.assertSuccess(vfa_cast.error, "Made a cast from vfa_small")195 cast_check.check_value(self, vfa_cast, "Cast of ValueFromAddress succeeds")196 197 # Next try ValueObject created from data. They should fail as there's no198 # way to grow the data:199 data_small = target.CreateValueFromData(200 "small_from_data", fv_small.data, fv_small.type201 )202 self.assertSuccess(data_small.error, "Made a valid object from data")203 data_cast = data_small.Cast(bigger_type)204 self.assertFailure(data_cast.error, msg="Cannot cast data backed SBValue")205 206 # Now check casting from a larger type to a smaller, we can always do this,207 # so just test one case:208 weird_cast = f_var.Cast(val_s.GetType())209 self.assertSuccess(weird_cast.GetError(), "Can cast from a larger to a smaller")210 self.assertEqual(211 weird_cast.member["a"].GetValueAsSigned(0),212 33,213 "Got the right value",214 )215 216 # Check that lldb.value implements truth testing.217 self.assertFalse(lldb.value(frame0.FindVariable("bogus")))218 self.assertTrue(lldb.value(frame0.FindVariable("uinthex")))219 220 self.assertEqual(221 int(lldb.value(frame0.FindVariable("uinthex"))),222 3768803088,223 "uinthex == 3768803088",224 )225 self.assertEqual(226 int(lldb.value(frame0.FindVariable("sinthex"))),227 -526164208,228 "sinthex == -526164208",229 )230 231 # Check value_iter works correctly.232 for v in [233 lldb.value(frame0.FindVariable("uinthex")),234 lldb.value(frame0.FindVariable("sinthex")),235 ]:236 self.assertTrue(v)237 238 self.assertEqual(239 frame0.FindVariable("uinthex").GetValueAsUnsigned(),240 3768803088,241 "unsigned uinthex == 3768803088",242 )243 self.assertEqual(244 frame0.FindVariable("sinthex").GetValueAsUnsigned(),245 3768803088,246 "unsigned sinthex == 3768803088",247 )248 249 self.assertEqual(250 frame0.FindVariable("uinthex").GetValueAsSigned(),251 -526164208,252 "signed uinthex == -526164208",253 )254 self.assertEqual(255 frame0.FindVariable("sinthex").GetValueAsSigned(),256 -526164208,257 "signed sinthex == -526164208",258 )259 260 # Check that hex value printing works as expected.261 self.assertEqual(262 frame0.FindVariable("fixed_int_ptr").GetValue(),263 "0x000000aa" if target.addr_size == 4 else "0x00000000000000aa",264 )265 self.runCmd(266 "settings set target.show-hex-variable-values-with-leading-zeroes false"267 )268 self.assertEqual(269 frame0.FindVariable("another_fixed_int_ptr").GetValue(),270 "0xaa",271 )272 a_null_int_ptr = frame0.FindVariable("a_null_int_ptr")273 self.assertEqual(a_null_int_ptr.GetValue(), "0x0")274 275 # Check that dereferencing a null pointer produces reasonable results276 # (does not crash).277 self.assertEqual(278 a_null_int_ptr.Dereference().GetError().GetCString(), "parent is NULL"279 )280 self.assertEqual(281 a_null_int_ptr.Dereference().GetLoadAddress(), lldb.LLDB_INVALID_ADDRESS282 )283