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 Rupprechtfrom __future__ import print_function 799451b44SJordan Rupprecht 899451b44SJordan Rupprecht 999451b44SJordan Rupprechtimport os 1099451b44SJordan Rupprechtimport os.path 1199451b44SJordan Rupprechtimport lldb 1299451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 1399451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1499451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1599451b44SJordan Rupprecht 1699451b44SJordan Rupprechtfile_index = 0 1799451b44SJordan Rupprecht 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprechtclass FoundationTestCase(TestBase): 2099451b44SJordan Rupprecht 2199451b44SJordan Rupprecht def setUp(self): 2299451b44SJordan Rupprecht # Call super's setUp(). 2399451b44SJordan Rupprecht TestBase.setUp(self) 2499451b44SJordan Rupprecht # Find the line number to break inside main(). 2599451b44SJordan Rupprecht self.main_source = "main.m" 2699451b44SJordan Rupprecht self.line = line_number( 2799451b44SJordan Rupprecht self.main_source, 2899451b44SJordan Rupprecht '// Set break point at this line.') 2999451b44SJordan Rupprecht 3099451b44SJordan Rupprecht def test_break(self): 3199451b44SJordan Rupprecht """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" 3299451b44SJordan Rupprecht self.build() 3399451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 3499451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 3599451b44SJordan Rupprecht 3699451b44SJordan Rupprecht # Stop at +[NSString stringWithFormat:]. 3799451b44SJordan Rupprecht break_results = lldbutil.run_break_set_command( 3899451b44SJordan Rupprecht self, "_regexp-break +[NSString stringWithFormat:]") 3999451b44SJordan Rupprecht lldbutil.check_breakpoint_result( 4099451b44SJordan Rupprecht self, 4199451b44SJordan Rupprecht break_results, 4299451b44SJordan Rupprecht symbol_name='+[NSString stringWithFormat:]', 4399451b44SJordan Rupprecht num_locations=1) 4499451b44SJordan Rupprecht 4599451b44SJordan Rupprecht # Stop at -[MyString initWithNSString:]. 4699451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 4799451b44SJordan Rupprecht self, 4899451b44SJordan Rupprecht '-[MyString initWithNSString:]', 4999451b44SJordan Rupprecht num_expected_locations=1, 5099451b44SJordan Rupprecht sym_exact=True) 5199451b44SJordan Rupprecht 5299451b44SJordan Rupprecht # Stop at the "description" selector. 5399451b44SJordan Rupprecht lldbutil.run_break_set_by_selector( 5499451b44SJordan Rupprecht self, 5599451b44SJordan Rupprecht 'description', 5699451b44SJordan Rupprecht num_expected_locations=1, 5799451b44SJordan Rupprecht module_name='a.out') 5899451b44SJordan Rupprecht 5999451b44SJordan Rupprecht # Stop at -[NSAutoreleasePool release]. 6099451b44SJordan Rupprecht break_results = lldbutil.run_break_set_command( 6199451b44SJordan Rupprecht self, "_regexp-break -[NSAutoreleasePool release]") 6299451b44SJordan Rupprecht lldbutil.check_breakpoint_result( 6399451b44SJordan Rupprecht self, 6499451b44SJordan Rupprecht break_results, 6599451b44SJordan Rupprecht symbol_name='-[NSAutoreleasePool release]', 6699451b44SJordan Rupprecht num_locations=1) 6799451b44SJordan Rupprecht 6899451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 6999451b44SJordan Rupprecht 7099451b44SJordan Rupprecht # First stop is +[NSString stringWithFormat:]. 7199451b44SJordan Rupprecht self.expect( 7299451b44SJordan Rupprecht "thread backtrace", 7399451b44SJordan Rupprecht "Stop at +[NSString stringWithFormat:]", 7499451b44SJordan Rupprecht substrs=["Foundation`+[NSString stringWithFormat:]"]) 7599451b44SJordan Rupprecht 7699451b44SJordan Rupprecht self.runCmd("process continue") 7799451b44SJordan Rupprecht 7899451b44SJordan Rupprecht # Second stop is still +[NSString stringWithFormat:]. 7999451b44SJordan Rupprecht self.expect( 8099451b44SJordan Rupprecht "thread backtrace", 8199451b44SJordan Rupprecht "Stop at +[NSString stringWithFormat:]", 8299451b44SJordan Rupprecht substrs=["Foundation`+[NSString stringWithFormat:]"]) 8399451b44SJordan Rupprecht 8499451b44SJordan Rupprecht self.runCmd("process continue") 8599451b44SJordan Rupprecht 8699451b44SJordan Rupprecht # Followed by a.out`-[MyString initWithNSString:]. 8799451b44SJordan Rupprecht self.expect( 8899451b44SJordan Rupprecht "thread backtrace", 8999451b44SJordan Rupprecht "Stop at a.out`-[MyString initWithNSString:]", 9099451b44SJordan Rupprecht substrs=["a.out`-[MyString initWithNSString:]"]) 9199451b44SJordan Rupprecht 9299451b44SJordan Rupprecht self.runCmd("process continue") 9399451b44SJordan Rupprecht 9499451b44SJordan Rupprecht # Followed by -[MyString description]. 9599451b44SJordan Rupprecht self.expect("thread backtrace", "Stop at -[MyString description]", 9699451b44SJordan Rupprecht substrs=["a.out`-[MyString description]"]) 9799451b44SJordan Rupprecht 9899451b44SJordan Rupprecht self.runCmd("process continue") 9999451b44SJordan Rupprecht 10099451b44SJordan Rupprecht # Followed by the same -[MyString description]. 10199451b44SJordan Rupprecht self.expect("thread backtrace", "Stop at -[MyString description]", 10299451b44SJordan Rupprecht substrs=["a.out`-[MyString description]"]) 10399451b44SJordan Rupprecht 10499451b44SJordan Rupprecht self.runCmd("process continue") 10599451b44SJordan Rupprecht 10699451b44SJordan Rupprecht # Followed by -[NSAutoreleasePool release]. 10799451b44SJordan Rupprecht self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]", 10899451b44SJordan Rupprecht substrs=["Foundation`-[NSAutoreleasePool release]"]) 10999451b44SJordan Rupprecht 11099451b44SJordan Rupprecht # rdar://problem/8542091 11199451b44SJordan Rupprecht # rdar://problem/8492646 11299451b44SJordan Rupprecht def test_data_type_and_expr(self): 11399451b44SJordan Rupprecht """Lookup objective-c data types and evaluate expressions.""" 11499451b44SJordan Rupprecht self.build() 11599451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 11699451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 11799451b44SJordan Rupprecht 11899451b44SJordan Rupprecht # Stop at -[MyString description]. 11999451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 12099451b44SJordan Rupprecht self, 12199451b44SJordan Rupprecht '-[MyString description]', 12299451b44SJordan Rupprecht num_expected_locations=1, 12399451b44SJordan Rupprecht sym_exact=True) 12499451b44SJordan Rupprecht# self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED, 12599451b44SJordan Rupprecht# startstr = "Breakpoint created: 1: name = '-[MyString description]', 12699451b44SJordan Rupprecht# locations = 1") 12799451b44SJordan Rupprecht 12899451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 12999451b44SJordan Rupprecht 13099451b44SJordan Rupprecht # The backtrace should show we stop at -[MyString description]. 13199451b44SJordan Rupprecht self.expect("thread backtrace", "Stop at -[MyString description]", 13299451b44SJordan Rupprecht substrs=["a.out`-[MyString description]"]) 13399451b44SJordan Rupprecht 13499451b44SJordan Rupprecht # Lookup objc data type MyString and evaluate some expressions. 13599451b44SJordan Rupprecht 13699451b44SJordan Rupprecht self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY, 13799451b44SJordan Rupprecht substrs=['name = "NSString"', 13899451b44SJordan Rupprecht 'compiler_type = "@interface NSString']) 13999451b44SJordan Rupprecht 14099451b44SJordan Rupprecht self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY, 14199451b44SJordan Rupprecht substrs=['name = "MyString"', 14299451b44SJordan Rupprecht 'compiler_type = "@interface MyString', 14399451b44SJordan Rupprecht 'NSString * str;', 14499451b44SJordan Rupprecht 'NSDate * date;']) 14599451b44SJordan Rupprecht 14699451b44SJordan Rupprecht self.expect( 14799451b44SJordan Rupprecht "frame variable --show-types --scope", 14899451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 14999451b44SJordan Rupprecht substrs=["ARG: (MyString *) self"], 15099451b44SJordan Rupprecht patterns=[ 15199451b44SJordan Rupprecht "ARG: \(.*\) _cmd", 15299451b44SJordan Rupprecht "(objc_selector *)|(SEL)"]) 15399451b44SJordan Rupprecht 15499451b44SJordan Rupprecht # rdar://problem/8651752 15599451b44SJordan Rupprecht # don't crash trying to ask clang how many children an empty record has 15699451b44SJordan Rupprecht self.runCmd("frame variable *_cmd") 15799451b44SJordan Rupprecht 15899451b44SJordan Rupprecht # rdar://problem/8492646 15999451b44SJordan Rupprecht # test/foundation fails after updating to tot r115023 16099451b44SJordan Rupprecht # self->str displays nothing as output 16199451b44SJordan Rupprecht self.expect( 16299451b44SJordan Rupprecht "frame variable --show-types self->str", 16399451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 16499451b44SJordan Rupprecht startstr="(NSString *) self->str") 16599451b44SJordan Rupprecht 16699451b44SJordan Rupprecht # rdar://problem/8447030 16799451b44SJordan Rupprecht # 'frame variable self->date' displays the wrong data member 16899451b44SJordan Rupprecht self.expect( 16999451b44SJordan Rupprecht "frame variable --show-types self->date", 17099451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 17199451b44SJordan Rupprecht startstr="(NSDate *) self->date") 17299451b44SJordan Rupprecht 17399451b44SJordan Rupprecht # This should display the str and date member fields as well. 17499451b44SJordan Rupprecht self.expect( 17599451b44SJordan Rupprecht "frame variable --show-types *self", 17699451b44SJordan Rupprecht VARIABLES_DISPLAYED_CORRECTLY, 17799451b44SJordan Rupprecht substrs=[ 17899451b44SJordan Rupprecht "(MyString) *self", 17999451b44SJordan Rupprecht "(NSString *) str", 18099451b44SJordan Rupprecht "(NSDate *) date"]) 18199451b44SJordan Rupprecht 18299451b44SJordan Rupprecht # isa should be accessible. 18399451b44SJordan Rupprecht self.expect("expression self->isa", VARIABLES_DISPLAYED_CORRECTLY, 184d8fb631dSAdrian Prantl substrs=["Class)"]) 18599451b44SJordan Rupprecht 18699451b44SJordan Rupprecht # This should fail expectedly. 18799451b44SJordan Rupprecht self.expect( 18899451b44SJordan Rupprecht "expression self->non_existent_member", 18999451b44SJordan Rupprecht COMMAND_FAILED_AS_EXPECTED, 19099451b44SJordan Rupprecht error=True, 19199451b44SJordan Rupprecht substrs=["error:", "'MyString' does not have a member named 'non_existent_member'"]) 19299451b44SJordan Rupprecht 19399451b44SJordan Rupprecht # Use expression parser. 19499451b44SJordan Rupprecht self.runCmd("expression self->str") 19599451b44SJordan Rupprecht self.runCmd("expression self->date") 19699451b44SJordan Rupprecht 19799451b44SJordan Rupprecht # (lldb) expression self->str 19899451b44SJordan Rupprecht # error: instance variable 'str' is protected 19999451b44SJordan Rupprecht # error: 1 errors parsing expression 20099451b44SJordan Rupprecht # 20199451b44SJordan Rupprecht # (lldb) expression self->date 20299451b44SJordan Rupprecht # error: instance variable 'date' is protected 20399451b44SJordan Rupprecht # error: 1 errors parsing expression 20499451b44SJordan Rupprecht # 20599451b44SJordan Rupprecht 20699451b44SJordan Rupprecht self.runCmd("breakpoint delete 1") 20799451b44SJordan Rupprecht lldbutil.run_break_set_by_file_and_line( 20899451b44SJordan Rupprecht self, "main.m", self.line, num_expected_locations=1, loc_exact=True) 20999451b44SJordan Rupprecht 21099451b44SJordan Rupprecht self.runCmd("process continue") 21199451b44SJordan Rupprecht 21299451b44SJordan Rupprecht # rdar://problem/8542091 21399451b44SJordan Rupprecht # test/foundation: expr -o -- my not working? 21499451b44SJordan Rupprecht # 21599451b44SJordan Rupprecht # Test new feature with r115115: 21699451b44SJordan Rupprecht # Add "-o" option to "expression" which prints the object description 21799451b44SJordan Rupprecht # if available. 21899451b44SJordan Rupprecht self.expect( 21999451b44SJordan Rupprecht "expression --object-description -- my", 22099451b44SJordan Rupprecht "Object description displayed correctly", 22199451b44SJordan Rupprecht patterns=["Hello from.*a.out.*with timestamp: "]) 22299451b44SJordan Rupprecht 22399451b44SJordan Rupprecht @add_test_categories(['pyapi']) 22499451b44SJordan Rupprecht def test_print_ivars_correctly(self): 22599451b44SJordan Rupprecht self.build() 22699451b44SJordan Rupprecht # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets 22799451b44SJordan Rupprecht # Only fails for the ObjC 2.0 runtime. 22899451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 22999451b44SJordan Rupprecht 23099451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 23199451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 23299451b44SJordan Rupprecht 23399451b44SJordan Rupprecht break1 = target.BreakpointCreateByLocation(self.main_source, self.line) 23499451b44SJordan Rupprecht self.assertTrue(break1, VALID_BREAKPOINT) 23599451b44SJordan Rupprecht 23699451b44SJordan Rupprecht # Now launch the process, and do not stop at entry point. 23799451b44SJordan Rupprecht process = target.LaunchSimple( 23899451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 23999451b44SJordan Rupprecht 24099451b44SJordan Rupprecht self.assertTrue(process, PROCESS_IS_VALID) 24199451b44SJordan Rupprecht 24299451b44SJordan Rupprecht # The stop reason of the thread should be breakpoint. 24399451b44SJordan Rupprecht thread = process.GetThreadAtIndex(0) 24499451b44SJordan Rupprecht if thread.GetStopReason() != lldb.eStopReasonBreakpoint: 24599451b44SJordan Rupprecht from lldbsuite.test.lldbutil import stop_reason_to_str 24699451b44SJordan Rupprecht self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % 24799451b44SJordan Rupprecht stop_reason_to_str(thread.GetStopReason())) 24899451b44SJordan Rupprecht 24999451b44SJordan Rupprecht # Make sure we stopped at the first breakpoint. 25099451b44SJordan Rupprecht 25199451b44SJordan Rupprecht cur_frame = thread.GetFrameAtIndex(0) 25299451b44SJordan Rupprecht 25399451b44SJordan Rupprecht line_number = cur_frame.GetLineEntry().GetLine() 254619e2e09SDave Lee self.assertEqual(line_number, self.line, "Hit the first breakpoint.") 25599451b44SJordan Rupprecht 25699451b44SJordan Rupprecht my_var = cur_frame.FindVariable("my") 25799451b44SJordan Rupprecht self.assertTrue(my_var, "Made a variable object for my") 25899451b44SJordan Rupprecht 25999451b44SJordan Rupprecht str_var = cur_frame.FindVariable("str") 26099451b44SJordan Rupprecht self.assertTrue(str_var, "Made a variable object for str") 26199451b44SJordan Rupprecht 26299451b44SJordan Rupprecht # Now make sure that the my->str == str: 26399451b44SJordan Rupprecht 26499451b44SJordan Rupprecht my_str_var = my_var.GetChildMemberWithName("str") 26599451b44SJordan Rupprecht self.assertTrue(my_str_var, "Found a str ivar in my") 26699451b44SJordan Rupprecht 26799451b44SJordan Rupprecht str_value = int(str_var.GetValue(), 0) 26899451b44SJordan Rupprecht 26999451b44SJordan Rupprecht my_str_value = int(my_str_var.GetValue(), 0) 27099451b44SJordan Rupprecht 271*0ed758b2SDave Lee self.assertEqual( 272*0ed758b2SDave Lee str_value, my_str_value, 27399451b44SJordan Rupprecht "Got the correct value for my->str") 27499451b44SJordan Rupprecht 27599451b44SJordan Rupprecht def test_expression_lookups_objc(self): 27699451b44SJordan Rupprecht """Test running an expression detect spurious debug info lookups (DWARF).""" 27799451b44SJordan Rupprecht self.build() 27899451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 27999451b44SJordan Rupprecht self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 28099451b44SJordan Rupprecht 28199451b44SJordan Rupprecht # Stop at -[MyString initWithNSString:]. 28299451b44SJordan Rupprecht lldbutil.run_break_set_by_symbol( 28399451b44SJordan Rupprecht self, 28499451b44SJordan Rupprecht '-[MyString initWithNSString:]', 28599451b44SJordan Rupprecht num_expected_locations=1, 28699451b44SJordan Rupprecht sym_exact=True) 28799451b44SJordan Rupprecht 28899451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 28999451b44SJordan Rupprecht 29099451b44SJordan Rupprecht global file_index 29199451b44SJordan Rupprecht # Log any DWARF lookups 29299451b44SJordan Rupprecht ++file_index 29399451b44SJordan Rupprecht logfile = os.path.join( 29499451b44SJordan Rupprecht self.getBuildDir(), 29599451b44SJordan Rupprecht "dwarf-lookups-" + 29699451b44SJordan Rupprecht self.getArchitecture() + 29799451b44SJordan Rupprecht "-" + 29899451b44SJordan Rupprecht str(file_index) + 29999451b44SJordan Rupprecht ".txt") 30099451b44SJordan Rupprecht self.runCmd("log enable -f %s dwarf lookups" % (logfile)) 30199451b44SJordan Rupprecht self.runCmd("expr self") 30299451b44SJordan Rupprecht self.runCmd("log disable dwarf lookups") 30399451b44SJordan Rupprecht 30499451b44SJordan Rupprecht def cleanup(): 30599451b44SJordan Rupprecht if os.path.exists(logfile): 30699451b44SJordan Rupprecht os.unlink(logfile) 30799451b44SJordan Rupprecht 30899451b44SJordan Rupprecht self.addTearDownHook(cleanup) 30999451b44SJordan Rupprecht 31099451b44SJordan Rupprecht if os.path.exists(logfile): 31199451b44SJordan Rupprecht f = open(logfile) 31299451b44SJordan Rupprecht lines = f.readlines() 31399451b44SJordan Rupprecht num_errors = 0 31499451b44SJordan Rupprecht for line in lines: 31599451b44SJordan Rupprecht if "$__lldb" in line: 31699451b44SJordan Rupprecht if num_errors == 0: 31799451b44SJordan Rupprecht print( 31899451b44SJordan Rupprecht "error: found spurious name lookups when evaluating an expression:") 31999451b44SJordan Rupprecht num_errors += 1 32099451b44SJordan Rupprecht print(line, end='') 321619e2e09SDave Lee self.assertEqual(num_errors, 0, "Spurious lookups detected") 32299451b44SJordan Rupprecht f.close() 323