1 """ 2 Set breakpoints on objective-c class and instance methods in foundation. 3 Also lookup objective-c data types and evaluate expressions. 4 """ 5 6 import os, time 7 import unittest2 8 import lldb 9 from lldbtest import * 10 import lldbutil 11 12 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 13 class FoundationTestCase(TestBase): 14 15 mydir = os.path.join("lang", "objc", "foundation") 16 17 @dsym_test 18 def test_break_with_dsym(self): 19 """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" 20 self.buildDsym() 21 self.break_on_objc_methods() 22 23 @dwarf_test 24 def test_break_with_dwarf(self): 25 """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" 26 self.buildDwarf() 27 self.break_on_objc_methods() 28 29 #@unittest2.expectedFailure 30 # rdar://problem/8542091 31 # rdar://problem/8492646 32 @dsym_test 33 def test_data_type_and_expr_with_dsym(self): 34 """Lookup objective-c data types and evaluate expressions.""" 35 self.buildDsym() 36 self.data_type_and_expr_objc() 37 38 #@unittest2.expectedFailure 39 # rdar://problem/8542091 40 # rdar://problem/8492646 41 @dwarf_test 42 def test_data_type_and_expr_with_dwarf(self): 43 """Lookup objective-c data types and evaluate expressions.""" 44 self.buildDwarf() 45 self.data_type_and_expr_objc() 46 47 @python_api_test 48 @dsym_test 49 def test_print_ivars_correctly_with_dsym (self): 50 self.buildDsym() 51 self.print_ivars_correctly() 52 53 @python_api_test 54 @dwarf_test 55 def test_print_ivars_correctly_with_dwarf (self): 56 self.buildDwarf() 57 self.print_ivars_correctly() 58 59 def break_on_objc_methods(self): 60 """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" 61 exe = os.path.join(os.getcwd(), "a.out") 62 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 63 64 # Stop at +[NSString stringWithFormat:]. 65 break_results = lldbutil.run_break_set_command(self, "_regexp-break +[NSString stringWithFormat:]") 66 lldbutil.check_breakpoint_result (self, break_results, symbol_name='+[NSString stringWithFormat:]', num_locations=1) 67 68 # Stop at -[MyString initWithNSString:]. 69 lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True) 70 71 # Stop at the "description" selector. 72 lldbutil.run_break_set_by_selector (self, 'description', num_expected_locations=1, module_name='a.out') 73 74 # Stop at -[NSAutoreleasePool release]. 75 break_results = lldbutil.run_break_set_command(self, "_regexp-break -[NSAutoreleasePool release]") 76 lldbutil.check_breakpoint_result (self, break_results, symbol_name='-[NSAutoreleasePool release]', num_locations=1) 77 78 self.runCmd("run", RUN_SUCCEEDED) 79 80 # First stop is +[NSString stringWithFormat:]. 81 self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", 82 substrs = ["Foundation`+[NSString stringWithFormat:]"]) 83 84 self.runCmd("process continue") 85 86 # Second stop is still +[NSString stringWithFormat:]. 87 self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", 88 substrs = ["Foundation`+[NSString stringWithFormat:]"]) 89 90 self.runCmd("process continue") 91 92 # Followed by a.out`-[MyString initWithNSString:]. 93 self.expect("thread backtrace", "Stop at a.out`-[MyString initWithNSString:]", 94 substrs = ["a.out`-[MyString initWithNSString:]"]) 95 96 self.runCmd("process continue") 97 98 # Followed by -[MyString description]. 99 self.expect("thread backtrace", "Stop at -[MyString description]", 100 substrs = ["a.out`-[MyString description]"]) 101 102 self.runCmd("process continue") 103 104 # Followed by the same -[MyString description]. 105 self.expect("thread backtrace", "Stop at -[MyString description]", 106 substrs = ["a.out`-[MyString description]"]) 107 108 self.runCmd("process continue") 109 110 # Followed by -[NSAutoreleasePool release]. 111 self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]", 112 substrs = ["Foundation`-[NSAutoreleasePool release]"]) 113 114 def setUp(self): 115 # Call super's setUp(). 116 TestBase.setUp(self) 117 # Find the line number to break inside main(). 118 self.main_source = "main.m" 119 self.line = line_number(self.main_source, '// Set break point at this line.') 120 121 def data_type_and_expr_objc(self): 122 """Lookup objective-c data types and evaluate expressions.""" 123 exe = os.path.join(os.getcwd(), "a.out") 124 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 125 126 # Stop at -[MyString description]. 127 lldbutil.run_break_set_by_symbol (self, '-[MyString description]', num_expected_locations=1, sym_exact=True) 128 # self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED, 129 # startstr = "Breakpoint created: 1: name = '-[MyString description]', locations = 1") 130 131 self.runCmd("run", RUN_SUCCEEDED) 132 133 # The backtrace should show we stop at -[MyString description]. 134 self.expect("thread backtrace", "Stop at -[MyString description]", 135 substrs = ["a.out`-[MyString description]"]) 136 137 # Lookup objc data type MyString and evaluate some expressions. 138 139 self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY, 140 substrs = ['name = "NSString"', 141 'clang_type = "@interface NSString']) 142 143 self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY, 144 substrs = ['name = "MyString"', 145 'clang_type = "@interface MyString', 146 'NSString * str;', 147 'NSDate * date;']) 148 149 self.expect("frame variable --show-types --scope", VARIABLES_DISPLAYED_CORRECTLY, 150 substrs = ["ARG: (MyString *) self"], 151 patterns = ["ARG: \(.*\) _cmd", 152 "(objc_selector *)|(SEL)"]) 153 154 # rdar://problem/8651752 155 # don't crash trying to ask clang how many children an empty record has 156 self.runCmd("frame variable *_cmd") 157 158 # rdar://problem/8492646 159 # test/foundation fails after updating to tot r115023 160 # self->str displays nothing as output 161 self.expect("frame variable --show-types self->str", VARIABLES_DISPLAYED_CORRECTLY, 162 startstr = "(NSString *) self->str") 163 164 # rdar://problem/8447030 165 # 'frame variable self->date' displays the wrong data member 166 self.expect("frame variable --show-types self->date", VARIABLES_DISPLAYED_CORRECTLY, 167 startstr = "(NSDate *) self->date") 168 169 # This should display the str and date member fields as well. 170 self.expect("frame variable --show-types *self", VARIABLES_DISPLAYED_CORRECTLY, 171 substrs = ["(MyString) *self", 172 "(NSString *) str", 173 "(NSDate *) date"]) 174 175 # isa should be accessible. 176 self.expect("expression self->isa", VARIABLES_DISPLAYED_CORRECTLY, 177 substrs = ["(Class)"]) 178 179 # This should fail expectedly. 180 self.expect("expression self->non_existent_member", 181 COMMAND_FAILED_AS_EXPECTED, error=True, 182 startstr = "error: 'MyString' does not have a member named 'non_existent_member'") 183 184 # Use expression parser. 185 self.runCmd("expression self->str") 186 self.runCmd("expression self->date") 187 188 # (lldb) expression self->str 189 # error: instance variable 'str' is protected 190 # error: 1 errors parsing expression 191 # 192 # (lldb) expression self->date 193 # error: instance variable 'date' is protected 194 # error: 1 errors parsing expression 195 # 196 197 self.runCmd("breakpoint delete 1") 198 lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) 199 200 self.runCmd("process continue") 201 202 # rdar://problem/8542091 203 # test/foundation: expr -o -- my not working? 204 # 205 # Test new feature with r115115: 206 # Add "-o" option to "expression" which prints the object description if available. 207 self.expect("expression --object-description -- my", "Object description displayed correctly", 208 patterns = ["Hello from.*a.out.*with timestamp: "]) 209 210 # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets 211 # Only fails for the ObjC 2.0 runtime. 212 def print_ivars_correctly(self) : 213 exe = os.path.join(os.getcwd(), "a.out") 214 215 target = self.dbg.CreateTarget(exe) 216 self.assertTrue(target, VALID_TARGET) 217 218 break1 = target.BreakpointCreateByLocation(self.main_source, self.line) 219 self.assertTrue(break1, VALID_BREAKPOINT) 220 221 # Now launch the process, and do not stop at entry point. 222 process = target.LaunchSimple(None, None, os.getcwd()) 223 224 self.assertTrue(process, PROCESS_IS_VALID) 225 226 # The stop reason of the thread should be breakpoint. 227 thread = process.GetThreadAtIndex(0) 228 if thread.GetStopReason() != lldb.eStopReasonBreakpoint: 229 from lldbutil import stop_reason_to_str 230 self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % 231 stop_reason_to_str(thread.GetStopReason())) 232 233 # Make sure we stopped at the first breakpoint. 234 235 cur_frame = thread.GetFrameAtIndex(0) 236 237 line_number = cur_frame.GetLineEntry().GetLine() 238 self.assertTrue (line_number == self.line, "Hit the first breakpoint.") 239 240 my_var = cur_frame.FindVariable("my") 241 self.assertTrue(my_var, "Made a variable object for my") 242 243 str_var = cur_frame.FindVariable("str") 244 self.assertTrue(str_var, "Made a variable object for str") 245 246 # Now make sure that the my->str == str: 247 248 my_str_var = my_var.GetChildMemberWithName("str") 249 self.assertTrue(my_str_var, "Found a str ivar in my") 250 251 str_value = int(str_var.GetValue(), 0) 252 253 my_str_value = int(my_str_var.GetValue(), 0) 254 255 self.assertTrue(str_value == my_str_value, "Got the correct value for my->str") 256 257 if __name__ == '__main__': 258 import atexit 259 lldb.SBDebugger.Initialize() 260 atexit.register(lambda: lldb.SBDebugger.Terminate()) 261 unittest2.main() 262