199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtSet breakpoints on objective-c class and instance methods in foundation. 399451b44SJordan RupprechtAlso lookup objective-c data types and evaluate expressions. 499451b44SJordan Rupprecht""" 599451b44SJordan Rupprecht 699451b44SJordan Rupprechtimport os 799451b44SJordan Rupprechtimport os.path 899451b44SJordan Rupprechtimport lldb 999451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 1099451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1199451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprechtfile_index = 0 1499451b44SJordan Rupprecht 1599451b44SJordan Rupprecht 1699451b44SJordan Rupprechtclass FoundationTestCase(TestBase): 1799451b44SJordan Rupprecht def setUp(self): 1899451b44SJordan Rupprecht # Call super's setUp(). 1999451b44SJordan Rupprecht TestBase.setUp(self) 2099451b44SJordan Rupprecht # Find the line number to break inside main(). 2199451b44SJordan Rupprecht self.main_source = "main.m" 22*2238dcc3SJonas Devlieghere self.line = line_number(self.main_source, "// Set break point at this line.") 2399451b44SJordan Rupprecht 2499451b44SJordan Rupprecht def test_break(self): 2599451b44SJordan Rupprecht """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" 2699451b44SJordan Rupprecht self.build() 2799451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 2899451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 2999451b44SJordan Rupprecht 3099451b44SJordan Rupprecht # Stop at +[NSString stringWithFormat:]. 3199451b44SJordan Rupprecht break_results = lldbutil.run_break_set_command( 32*2238dcc3SJonas Devlieghere self, "_regexp-break +[NSString stringWithFormat:]" 33*2238dcc3SJonas Devlieghere ) 3499451b44SJordan Rupprecht lldbutil.check_breakpoint_result( 3599451b44SJordan Rupprecht self, 3699451b44SJordan Rupprecht break_results, 37*2238dcc3SJonas Devlieghere symbol_name="+[NSString stringWithFormat:]", 38*2238dcc3SJonas Devlieghere num_locations=1, 39*2238dcc3SJonas Devlieghere ) 4099451b44SJordan Rupprecht 4199451b44SJordan Rupprecht # Stop at -[MyString initWithNSString:]. 4299451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 4399451b44SJordan Rupprecht self, 44*2238dcc3SJonas Devlieghere "-[MyString initWithNSString:]", 4599451b44SJordan Rupprecht num_expected_locations=1, 46*2238dcc3SJonas Devlieghere sym_exact=True, 47*2238dcc3SJonas Devlieghere ) 4899451b44SJordan Rupprecht 4999451b44SJordan Rupprecht # Stop at the "description" selector. 5099451b44SJordan Rupprecht lldbutil.run_break_set_by_selector( 51*2238dcc3SJonas Devlieghere self, "description", num_expected_locations=1, module_name="a.out" 52*2238dcc3SJonas Devlieghere ) 5399451b44SJordan Rupprecht 5499451b44SJordan Rupprecht # Stop at -[NSAutoreleasePool release]. 5599451b44SJordan Rupprecht break_results = lldbutil.run_break_set_command( 56*2238dcc3SJonas Devlieghere self, "_regexp-break -[NSAutoreleasePool release]" 57*2238dcc3SJonas Devlieghere ) 5899451b44SJordan Rupprecht lldbutil.check_breakpoint_result( 5999451b44SJordan Rupprecht self, 6099451b44SJordan Rupprecht break_results, 61*2238dcc3SJonas Devlieghere symbol_name="-[NSAutoreleasePool release]", 62*2238dcc3SJonas Devlieghere num_locations=1, 63*2238dcc3SJonas Devlieghere ) 6499451b44SJordan Rupprecht 6599451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 6699451b44SJordan Rupprecht 6799451b44SJordan Rupprecht # First stop is +[NSString stringWithFormat:]. 6899451b44SJordan Rupprecht self.expect( 6999451b44SJordan Rupprecht "thread backtrace", 7099451b44SJordan Rupprecht "Stop at +[NSString stringWithFormat:]", 71*2238dcc3SJonas Devlieghere substrs=["Foundation`+[NSString stringWithFormat:]"], 72*2238dcc3SJonas Devlieghere ) 7399451b44SJordan Rupprecht 7499451b44SJordan Rupprecht self.runCmd("process continue") 7599451b44SJordan Rupprecht 7699451b44SJordan Rupprecht # Second stop is still +[NSString stringWithFormat:]. 7799451b44SJordan Rupprecht self.expect( 7899451b44SJordan Rupprecht "thread backtrace", 7999451b44SJordan Rupprecht "Stop at +[NSString stringWithFormat:]", 80*2238dcc3SJonas Devlieghere substrs=["Foundation`+[NSString stringWithFormat:]"], 81*2238dcc3SJonas Devlieghere ) 8299451b44SJordan Rupprecht 8399451b44SJordan Rupprecht self.runCmd("process continue") 8499451b44SJordan Rupprecht 8599451b44SJordan Rupprecht # Followed by a.out`-[MyString initWithNSString:]. 8699451b44SJordan Rupprecht self.expect( 8799451b44SJordan Rupprecht "thread backtrace", 8899451b44SJordan Rupprecht "Stop at a.out`-[MyString initWithNSString:]", 89*2238dcc3SJonas Devlieghere substrs=["a.out`-[MyString initWithNSString:]"], 90*2238dcc3SJonas Devlieghere ) 9199451b44SJordan Rupprecht 9299451b44SJordan Rupprecht self.runCmd("process continue") 9399451b44SJordan Rupprecht 9499451b44SJordan Rupprecht # Followed by -[MyString description]. 95*2238dcc3SJonas Devlieghere self.expect( 96*2238dcc3SJonas Devlieghere "thread backtrace", 97*2238dcc3SJonas Devlieghere "Stop at -[MyString description]", 98*2238dcc3SJonas Devlieghere substrs=["a.out`-[MyString description]"], 99*2238dcc3SJonas Devlieghere ) 10099451b44SJordan Rupprecht 10199451b44SJordan Rupprecht self.runCmd("process continue") 10299451b44SJordan Rupprecht 10399451b44SJordan Rupprecht # Followed by the same -[MyString description]. 104*2238dcc3SJonas Devlieghere self.expect( 105*2238dcc3SJonas Devlieghere "thread backtrace", 106*2238dcc3SJonas Devlieghere "Stop at -[MyString description]", 107*2238dcc3SJonas Devlieghere substrs=["a.out`-[MyString description]"], 108*2238dcc3SJonas Devlieghere ) 10999451b44SJordan Rupprecht 11099451b44SJordan Rupprecht self.runCmd("process continue") 11199451b44SJordan Rupprecht 11299451b44SJordan Rupprecht # Followed by -[NSAutoreleasePool release]. 113*2238dcc3SJonas Devlieghere self.expect( 114*2238dcc3SJonas Devlieghere "thread backtrace", 115*2238dcc3SJonas Devlieghere "Stop at -[NSAutoreleasePool release]", 116*2238dcc3SJonas Devlieghere substrs=["Foundation`-[NSAutoreleasePool release]"], 117*2238dcc3SJonas Devlieghere ) 11899451b44SJordan Rupprecht 11999451b44SJordan Rupprecht # rdar://problem/8542091 12099451b44SJordan Rupprecht # rdar://problem/8492646 12199451b44SJordan Rupprecht def test_data_type_and_expr(self): 12299451b44SJordan Rupprecht """Lookup objective-c data types and evaluate expressions.""" 12399451b44SJordan Rupprecht self.build() 12499451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 12599451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 12699451b44SJordan Rupprecht 12799451b44SJordan Rupprecht # Stop at -[MyString description]. 12899451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 129*2238dcc3SJonas Devlieghere self, "-[MyString description]", num_expected_locations=1, sym_exact=True 130*2238dcc3SJonas Devlieghere ) 13199451b44SJordan Rupprecht # self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED, 13299451b44SJordan Rupprecht # startstr = "Breakpoint created: 1: name = '-[MyString description]', 13399451b44SJordan Rupprecht # locations = 1") 13499451b44SJordan Rupprecht 13599451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 13699451b44SJordan Rupprecht 137c21dfa9eSDave Lee self.runCmd("settings set target.prefer-dynamic-value no-dynamic-values") 138c21dfa9eSDave Lee 13999451b44SJordan Rupprecht # The backtrace should show we stop at -[MyString description]. 140*2238dcc3SJonas Devlieghere self.expect( 141*2238dcc3SJonas Devlieghere "thread backtrace", 142*2238dcc3SJonas Devlieghere "Stop at -[MyString description]", 143*2238dcc3SJonas Devlieghere substrs=["a.out`-[MyString description]"], 144*2238dcc3SJonas Devlieghere ) 14599451b44SJordan Rupprecht 14699451b44SJordan Rupprecht # Lookup objc data type MyString and evaluate some expressions. 14799451b44SJordan Rupprecht 148*2238dcc3SJonas Devlieghere self.expect( 149*2238dcc3SJonas Devlieghere "image lookup -t NSString", 150*2238dcc3SJonas Devlieghere DATA_TYPES_DISPLAYED_CORRECTLY, 151*2238dcc3SJonas Devlieghere substrs=['name = "NSString"', 'compiler_type = "@interface NSString'], 152*2238dcc3SJonas Devlieghere ) 15399451b44SJordan Rupprecht 154*2238dcc3SJonas Devlieghere self.expect( 155*2238dcc3SJonas Devlieghere "image lookup -t MyString", 156*2238dcc3SJonas Devlieghere DATA_TYPES_DISPLAYED_CORRECTLY, 157*2238dcc3SJonas Devlieghere substrs=[ 158*2238dcc3SJonas Devlieghere 'name = "MyString"', 15999451b44SJordan Rupprecht 'compiler_type = "@interface MyString', 160*2238dcc3SJonas Devlieghere "NSString * str;", 161*2238dcc3SJonas Devlieghere "NSDate * date;", 162*2238dcc3SJonas Devlieghere ], 163*2238dcc3SJonas Devlieghere ) 16499451b44SJordan Rupprecht 16599451b44SJordan Rupprecht self.expect( 16699451b44SJordan Rupprecht "frame variable --show-types --scope", 16799451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 16899451b44SJordan Rupprecht substrs=["ARG: (MyString *) self"], 169*2238dcc3SJonas Devlieghere patterns=["ARG: \(.*\) _cmd", "(objc_selector *)|(SEL)"], 170*2238dcc3SJonas Devlieghere ) 17199451b44SJordan Rupprecht 17299451b44SJordan Rupprecht # rdar://problem/8651752 17399451b44SJordan Rupprecht # don't crash trying to ask clang how many children an empty record has 17499451b44SJordan Rupprecht self.runCmd("frame variable *_cmd") 17599451b44SJordan Rupprecht 17699451b44SJordan Rupprecht # rdar://problem/8492646 17799451b44SJordan Rupprecht # test/foundation fails after updating to tot r115023 17899451b44SJordan Rupprecht # self->str displays nothing as output 17999451b44SJordan Rupprecht self.expect( 18099451b44SJordan Rupprecht "frame variable --show-types self->str", 18199451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 182*2238dcc3SJonas Devlieghere startstr="(NSString *) self->str", 183*2238dcc3SJonas Devlieghere ) 18499451b44SJordan Rupprecht 18599451b44SJordan Rupprecht # rdar://problem/8447030 18699451b44SJordan Rupprecht # 'frame variable self->date' displays the wrong data member 18799451b44SJordan Rupprecht self.expect( 18899451b44SJordan Rupprecht "frame variable --show-types self->date", 18999451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 190*2238dcc3SJonas Devlieghere startstr="(NSDate *) self->date", 191*2238dcc3SJonas Devlieghere ) 19299451b44SJordan Rupprecht 19399451b44SJordan Rupprecht # This should display the str and date member fields as well. 19499451b44SJordan Rupprecht self.expect( 19599451b44SJordan Rupprecht "frame variable --show-types *self", 19699451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 197*2238dcc3SJonas Devlieghere substrs=["(MyString) *self", "(NSString *) str", "(NSDate *) date"], 198*2238dcc3SJonas Devlieghere ) 19999451b44SJordan Rupprecht 20099451b44SJordan Rupprecht # isa should be accessible. 201*2238dcc3SJonas Devlieghere self.expect( 202*2238dcc3SJonas Devlieghere "expression self->isa", VARIABLES_DISPLAYED_CORRECTLY, substrs=["Class)"] 203*2238dcc3SJonas Devlieghere ) 20499451b44SJordan Rupprecht 20599451b44SJordan Rupprecht # This should fail expectedly. 20699451b44SJordan Rupprecht self.expect( 20799451b44SJordan Rupprecht "expression self->non_existent_member", 20899451b44SJordan Rupprecht COMMAND_FAILED_AS_EXPECTED, 20999451b44SJordan Rupprecht error=True, 210*2238dcc3SJonas Devlieghere substrs=[ 211*2238dcc3SJonas Devlieghere "error:", 212*2238dcc3SJonas Devlieghere "'MyString' does not have a member named 'non_existent_member'", 213*2238dcc3SJonas Devlieghere ], 214*2238dcc3SJonas Devlieghere ) 21599451b44SJordan Rupprecht 21699451b44SJordan Rupprecht # Use expression parser. 21799451b44SJordan Rupprecht self.runCmd("expression self->str") 21899451b44SJordan Rupprecht self.runCmd("expression self->date") 21999451b44SJordan Rupprecht 22099451b44SJordan Rupprecht # (lldb) expression self->str 22199451b44SJordan Rupprecht # error: instance variable 'str' is protected 22299451b44SJordan Rupprecht # error: 1 errors parsing expression 22399451b44SJordan Rupprecht # 22499451b44SJordan Rupprecht # (lldb) expression self->date 22599451b44SJordan Rupprecht # error: instance variable 'date' is protected 22699451b44SJordan Rupprecht # error: 1 errors parsing expression 22799451b44SJordan Rupprecht # 22899451b44SJordan Rupprecht 22999451b44SJordan Rupprecht self.runCmd("breakpoint delete 1") 23099451b44SJordan Rupprecht lldbutil.run_break_set_by_file_and_line( 231*2238dcc3SJonas Devlieghere self, "main.m", self.line, num_expected_locations=1, loc_exact=True 232*2238dcc3SJonas Devlieghere ) 23399451b44SJordan Rupprecht 23499451b44SJordan Rupprecht self.runCmd("process continue") 23599451b44SJordan Rupprecht 23699451b44SJordan Rupprecht # rdar://problem/8542091 23799451b44SJordan Rupprecht # test/foundation: expr -o -- my not working? 23899451b44SJordan Rupprecht # 23999451b44SJordan Rupprecht # Test new feature with r115115: 24099451b44SJordan Rupprecht # Add "-o" option to "expression" which prints the object description 24199451b44SJordan Rupprecht # if available. 24299451b44SJordan Rupprecht self.expect( 24399451b44SJordan Rupprecht "expression --object-description -- my", 24499451b44SJordan Rupprecht "Object description displayed correctly", 245*2238dcc3SJonas Devlieghere patterns=["Hello from.*a.out.*with timestamp: "], 246*2238dcc3SJonas Devlieghere ) 24799451b44SJordan Rupprecht 248*2238dcc3SJonas Devlieghere @add_test_categories(["pyapi"]) 24999451b44SJordan Rupprecht def test_print_ivars_correctly(self): 25099451b44SJordan Rupprecht self.build() 25199451b44SJordan Rupprecht # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets 25299451b44SJordan Rupprecht # Only fails for the ObjC 2.0 runtime. 25399451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 25499451b44SJordan Rupprecht 25599451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 25699451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 25799451b44SJordan Rupprecht 25899451b44SJordan Rupprecht break1 = target.BreakpointCreateByLocation(self.main_source, self.line) 25999451b44SJordan Rupprecht self.assertTrue(break1, VALID_BREAKPOINT) 26099451b44SJordan Rupprecht 26199451b44SJordan Rupprecht # Now launch the process, and do not stop at entry point. 262*2238dcc3SJonas Devlieghere process = target.LaunchSimple(None, None, self.get_process_working_directory()) 26399451b44SJordan Rupprecht 26499451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 26599451b44SJordan Rupprecht 26699451b44SJordan Rupprecht # The stop reason of the thread should be breakpoint. 26799451b44SJordan Rupprecht thread = process.GetThreadAtIndex(0) 26899451b44SJordan Rupprecht if thread.GetStopReason() != lldb.eStopReasonBreakpoint: 26999451b44SJordan Rupprecht from lldbsuite.test.lldbutil import stop_reason_to_str 270*2238dcc3SJonas Devlieghere 271*2238dcc3SJonas Devlieghere self.fail( 272*2238dcc3SJonas Devlieghere STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS 273*2238dcc3SJonas Devlieghere % stop_reason_to_str(thread.GetStopReason()) 274*2238dcc3SJonas Devlieghere ) 27599451b44SJordan Rupprecht 27699451b44SJordan Rupprecht # Make sure we stopped at the first breakpoint. 27799451b44SJordan Rupprecht 27899451b44SJordan Rupprecht cur_frame = thread.GetFrameAtIndex(0) 27999451b44SJordan Rupprecht 28099451b44SJordan Rupprecht line_number = cur_frame.GetLineEntry().GetLine() 281619e2e09SDave Lee self.assertEqual(line_number, self.line, "Hit the first breakpoint.") 28299451b44SJordan Rupprecht 28399451b44SJordan Rupprecht my_var = cur_frame.FindVariable("my") 28499451b44SJordan Rupprecht self.assertTrue(my_var, "Made a variable object for my") 28599451b44SJordan Rupprecht 28699451b44SJordan Rupprecht str_var = cur_frame.FindVariable("str") 28799451b44SJordan Rupprecht self.assertTrue(str_var, "Made a variable object for str") 28899451b44SJordan Rupprecht 28999451b44SJordan Rupprecht # Now make sure that the my->str == str: 29099451b44SJordan Rupprecht 29199451b44SJordan Rupprecht my_str_var = my_var.GetChildMemberWithName("str") 29299451b44SJordan Rupprecht self.assertTrue(my_str_var, "Found a str ivar in my") 29399451b44SJordan Rupprecht 29499451b44SJordan Rupprecht str_value = int(str_var.GetValue(), 0) 29599451b44SJordan Rupprecht 29699451b44SJordan Rupprecht my_str_value = int(my_str_var.GetValue(), 0) 29799451b44SJordan Rupprecht 298*2238dcc3SJonas Devlieghere self.assertEqual(str_value, my_str_value, "Got the correct value for my->str") 29999451b44SJordan Rupprecht 30099451b44SJordan Rupprecht def test_expression_lookups_objc(self): 30199451b44SJordan Rupprecht """Test running an expression detect spurious debug info lookups (DWARF).""" 30299451b44SJordan Rupprecht self.build() 30399451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 30499451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 30599451b44SJordan Rupprecht 30699451b44SJordan Rupprecht # Stop at -[MyString initWithNSString:]. 30799451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 30899451b44SJordan Rupprecht self, 309*2238dcc3SJonas Devlieghere "-[MyString initWithNSString:]", 31099451b44SJordan Rupprecht num_expected_locations=1, 311*2238dcc3SJonas Devlieghere sym_exact=True, 312*2238dcc3SJonas Devlieghere ) 31399451b44SJordan Rupprecht 31499451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 31599451b44SJordan Rupprecht 31699451b44SJordan Rupprecht global file_index 31799451b44SJordan Rupprecht # Log any DWARF lookups 31899451b44SJordan Rupprecht ++file_index 31999451b44SJordan Rupprecht logfile = os.path.join( 32099451b44SJordan Rupprecht self.getBuildDir(), 321*2238dcc3SJonas Devlieghere "dwarf-lookups-" + self.getArchitecture() + "-" + str(file_index) + ".txt", 322*2238dcc3SJonas Devlieghere ) 32399451b44SJordan Rupprecht self.runCmd("log enable -f %s dwarf lookups" % (logfile)) 32499451b44SJordan Rupprecht self.runCmd("expr self") 32599451b44SJordan Rupprecht self.runCmd("log disable dwarf lookups") 32699451b44SJordan Rupprecht 32799451b44SJordan Rupprecht def cleanup(): 32899451b44SJordan Rupprecht if os.path.exists(logfile): 32999451b44SJordan Rupprecht os.unlink(logfile) 33099451b44SJordan Rupprecht 33199451b44SJordan Rupprecht self.addTearDownHook(cleanup) 33299451b44SJordan Rupprecht 33399451b44SJordan Rupprecht if os.path.exists(logfile): 33499451b44SJordan Rupprecht f = open(logfile) 33599451b44SJordan Rupprecht lines = f.readlines() 33699451b44SJordan Rupprecht num_errors = 0 33799451b44SJordan Rupprecht for line in lines: 33899451b44SJordan Rupprecht if "$__lldb" in line: 33999451b44SJordan Rupprecht if num_errors == 0: 34099451b44SJordan Rupprecht print( 341*2238dcc3SJonas Devlieghere "error: found spurious name lookups when evaluating an expression:" 342*2238dcc3SJonas Devlieghere ) 34399451b44SJordan Rupprecht num_errors += 1 344*2238dcc3SJonas Devlieghere print(line, end="") 345619e2e09SDave Lee self.assertEqual(num_errors, 0, "Spurious lookups detected") 34699451b44SJordan Rupprecht f.close() 347