1""" 2Test SBTarget APIs. 3""" 4 5import os 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class TargetAPITestCase(TestBase): 13 def setUp(self): 14 # Call super's setUp(). 15 TestBase.setUp(self) 16 # Find the line number to of function 'c'. 17 self.line1 = line_number( 18 "main.c", "// Find the line number for breakpoint 1 here." 19 ) 20 self.line2 = line_number( 21 "main.c", "// Find the line number for breakpoint 2 here." 22 ) 23 self.line_main = line_number("main.c", "// Set a break at entry to main.") 24 25 # rdar://problem/9700873 26 # Find global variable value fails for dwarf if inferior not started 27 # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) 28 # 29 # It does not segfaults now. But for dwarf, the variable value is None if 30 # the inferior process does not exist yet. The radar has been updated. 31 def test_find_global_variables(self): 32 """Exercise SBTarget.FindGlobalVariables() API.""" 33 d = {"EXE": "b.out"} 34 self.build(dictionary=d) 35 self.setTearDownCleanup(dictionary=d) 36 self.find_global_variables("b.out") 37 38 def test_find_compile_units(self): 39 """Exercise SBTarget.FindCompileUnits() API.""" 40 d = {"EXE": "b.out"} 41 self.build(dictionary=d) 42 self.setTearDownCleanup(dictionary=d) 43 self.find_compile_units(self.getBuildArtifact("b.out")) 44 45 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") 46 def test_find_functions(self): 47 """Exercise SBTarget.FindFunctions() API.""" 48 d = {"EXE": "b.out"} 49 self.build(dictionary=d) 50 self.setTearDownCleanup(dictionary=d) 51 self.find_functions("b.out") 52 53 def test_get_description(self): 54 """Exercise SBTarget.GetDescription() API.""" 55 self.build() 56 self.get_description() 57 58 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") 59 def test_resolve_symbol_context_with_address(self): 60 """Exercise SBTarget.ResolveSymbolContextForAddress() API.""" 61 self.build() 62 self.resolve_symbol_context_with_address() 63 64 def test_get_platform(self): 65 d = {"EXE": "b.out"} 66 self.build(dictionary=d) 67 self.setTearDownCleanup(dictionary=d) 68 target = self.create_simple_target("b.out") 69 platform = target.platform 70 self.assertTrue(platform, VALID_PLATFORM) 71 72 def test_get_data_byte_size(self): 73 d = {"EXE": "b.out"} 74 self.build(dictionary=d) 75 self.setTearDownCleanup(dictionary=d) 76 target = self.create_simple_target("b.out") 77 self.assertEqual(target.data_byte_size, 1) 78 79 def test_get_code_byte_size(self): 80 d = {"EXE": "b.out"} 81 self.build(dictionary=d) 82 self.setTearDownCleanup(dictionary=d) 83 target = self.create_simple_target("b.out") 84 self.assertEqual(target.code_byte_size, 1) 85 86 def test_resolve_file_address(self): 87 d = {"EXE": "b.out"} 88 self.build(dictionary=d) 89 self.setTearDownCleanup(dictionary=d) 90 target = self.create_simple_target("b.out") 91 92 # find the file address in the .data section of the main 93 # module 94 data_section = self.find_data_section(target) 95 data_section_addr = data_section.file_addr 96 97 # resolve the above address, and compare the address produced 98 # by the resolution against the original address/section 99 res_file_addr = target.ResolveFileAddress(data_section_addr) 100 self.assertTrue(res_file_addr.IsValid()) 101 102 self.assertEqual(data_section_addr, res_file_addr.file_addr) 103 104 data_section2 = res_file_addr.section 105 self.assertIsNotNone(data_section2) 106 self.assertEqual(data_section.name, data_section2.name) 107 108 def test_get_ABIName(self): 109 d = {"EXE": "b.out"} 110 self.build(dictionary=d) 111 self.setTearDownCleanup(dictionary=d) 112 target = self.create_simple_target("b.out") 113 114 abi_pre_launch = target.GetABIName() 115 self.assertTrue(len(abi_pre_launch) != 0, "Got an ABI string") 116 117 breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main) 118 self.assertTrue(breakpoint, VALID_BREAKPOINT) 119 120 # Put debugger into synchronous mode so when we target.LaunchSimple returns 121 # it will guaranteed to be at the breakpoint 122 self.dbg.SetAsync(False) 123 124 # Launch the process, and do not stop at the entry point. 125 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 126 abi_after_launch = target.GetABIName() 127 self.assertEqual( 128 abi_pre_launch, abi_after_launch, "ABI's match before and during run" 129 ) 130 131 def test_read_memory(self): 132 d = {"EXE": "b.out"} 133 self.build(dictionary=d) 134 self.setTearDownCleanup(dictionary=d) 135 target = self.create_simple_target("b.out") 136 137 breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main) 138 self.assertTrue(breakpoint, VALID_BREAKPOINT) 139 140 # Put debugger into synchronous mode so when we target.LaunchSimple returns 141 # it will guaranteed to be at the breakpoint 142 self.dbg.SetAsync(False) 143 144 # Launch the process, and do not stop at the entry point. 145 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 146 147 # find the file address in the .data section of the main 148 # module 149 data_section = self.find_data_section(target) 150 sb_addr = lldb.SBAddress(data_section, 0) 151 error = lldb.SBError() 152 content = target.ReadMemory(sb_addr, 1, error) 153 self.assertSuccess(error, "Make sure memory read succeeded") 154 self.assertEqual(len(content), 1) 155 156 @skipIfWindows # stdio manipulation unsupported on Windows 157 @skipIfRemote # stdio manipulation unsupported on remote iOS devices<rdar://problem/54581135> 158 @skipIf(oslist=["linux"], archs=["arm", "aarch64"]) 159 @no_debug_info_test 160 def test_launch_simple(self): 161 d = {"EXE": "b.out"} 162 self.build(dictionary=d) 163 self.setTearDownCleanup(dictionary=d) 164 target = self.create_simple_target("b.out") 165 166 # Set the debugger to synchronous mode so we only continue after the 167 # process has exited. 168 self.dbg.SetAsync(False) 169 170 process = target.LaunchSimple( 171 ["foo", "bar"], ["baz"], self.get_process_working_directory() 172 ) 173 process.Continue() 174 self.assertState(process.GetState(), lldb.eStateExited) 175 output = process.GetSTDOUT(9999) 176 self.assertIn("arg: foo", output) 177 self.assertIn("arg: bar", output) 178 self.assertIn("env: baz", output) 179 180 self.runCmd("setting set target.run-args foo") 181 self.runCmd("setting set target.env-vars bar=baz") 182 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 183 process.Continue() 184 self.assertState(process.GetState(), lldb.eStateExited) 185 output = process.GetSTDOUT(9999) 186 self.assertIn("arg: foo", output) 187 self.assertIn("env: bar=baz", output) 188 189 # Clear all the run args set above. 190 self.runCmd("setting clear target.run-args") 191 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 192 process.Continue() 193 self.assertEqual(process.GetState(), lldb.eStateExited) 194 output = process.GetSTDOUT(9999) 195 self.assertNotIn("arg: foo", output) 196 197 self.runCmd("settings set target.disable-stdio true") 198 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 199 process.Continue() 200 self.assertState(process.GetState(), lldb.eStateExited) 201 output = process.GetSTDOUT(9999) 202 self.assertEqual(output, "") 203 204 def create_simple_target(self, fn): 205 exe = self.getBuildArtifact(fn) 206 target = self.dbg.CreateTarget(exe) 207 self.assertTrue(target, VALID_TARGET) 208 return target 209 210 def find_data_section(self, target): 211 mod = target.GetModuleAtIndex(0) 212 data_section = None 213 for s in mod.sections: 214 sect_type = s.GetSectionType() 215 if sect_type == lldb.eSectionTypeData: 216 data_section = s 217 break 218 elif sect_type == lldb.eSectionTypeContainer: 219 for i in range(s.GetNumSubSections()): 220 ss = s.GetSubSectionAtIndex(i) 221 sect_type = ss.GetSectionType() 222 if sect_type == lldb.eSectionTypeData: 223 data_section = ss 224 break 225 226 self.assertIsNotNone(data_section) 227 return data_section 228 229 def find_global_variables(self, exe_name): 230 """Exercise SBTarget.FindGlobalVariables() API.""" 231 exe = self.getBuildArtifact(exe_name) 232 233 # Create a target by the debugger. 234 target = self.dbg.CreateTarget(exe) 235 self.assertTrue(target, VALID_TARGET) 236 237 # rdar://problem/9700873 238 # Find global variable value fails for dwarf if inferior not started 239 # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) 240 # 241 # Remove the lines to create a breakpoint and to start the inferior 242 # which are workarounds for the dwarf case. 243 244 breakpoint = target.BreakpointCreateByLocation("main.c", self.line1) 245 self.assertTrue(breakpoint, VALID_BREAKPOINT) 246 247 # Now launch the process, and do not stop at entry point. 248 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 249 self.assertTrue(process, PROCESS_IS_VALID) 250 # Make sure we hit our breakpoint: 251 thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) 252 self.assertEqual(len(thread_list), 1) 253 254 value_list = target.FindGlobalVariables("my_global_var_of_char_type", 3) 255 self.assertEqual(value_list.GetSize(), 1) 256 my_global_var = value_list.GetValueAtIndex(0) 257 self.DebugSBValue(my_global_var) 258 self.assertTrue(my_global_var) 259 self.expect( 260 my_global_var.GetName(), exe=False, startstr="my_global_var_of_char_type" 261 ) 262 self.expect(my_global_var.GetTypeName(), exe=False, startstr="char") 263 self.expect(my_global_var.GetValue(), exe=False, startstr="'X'") 264 265 # While we are at it, let's also exercise the similar 266 # SBModule.FindGlobalVariables() API. 267 for m in target.module_iter(): 268 if ( 269 os.path.normpath(m.GetFileSpec().GetDirectory()) == self.getBuildDir() 270 and m.GetFileSpec().GetFilename() == exe_name 271 ): 272 value_list = m.FindGlobalVariables( 273 target, "my_global_var_of_char_type", 3 274 ) 275 self.assertEqual(value_list.GetSize(), 1) 276 self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "'X'") 277 break 278 279 def find_compile_units(self, exe): 280 """Exercise SBTarget.FindCompileUnits() API.""" 281 source_name = "main.c" 282 283 # Create a target by the debugger. 284 target = self.dbg.CreateTarget(exe) 285 self.assertTrue(target, VALID_TARGET) 286 287 list = target.FindCompileUnits(lldb.SBFileSpec(source_name, False)) 288 # Executable has been built just from one source file 'main.c', 289 # so we may check only the first element of list. 290 self.assertEqual( 291 list[0].GetCompileUnit().GetFileSpec().GetFilename(), source_name 292 ) 293 294 def find_functions(self, exe_name): 295 """Exercise SBTarget.FindFunctions() API.""" 296 exe = self.getBuildArtifact(exe_name) 297 298 # Create a target by the debugger. 299 target = self.dbg.CreateTarget(exe) 300 self.assertTrue(target, VALID_TARGET) 301 302 # Try it with a null name: 303 list = target.FindFunctions(None, lldb.eFunctionNameTypeAuto) 304 self.assertEqual(list.GetSize(), 0) 305 306 list = target.FindFunctions("c", lldb.eFunctionNameTypeAuto) 307 self.assertEqual(list.GetSize(), 1) 308 309 for sc in list: 310 self.assertEqual(sc.GetModule().GetFileSpec().GetFilename(), exe_name) 311 self.assertEqual(sc.GetSymbol().GetName(), "c") 312 313 def get_description(self): 314 """Exercise SBTarget.GetDescription() API.""" 315 exe = self.getBuildArtifact("a.out") 316 317 # Create a target by the debugger. 318 target = self.dbg.CreateTarget(exe) 319 self.assertTrue(target, VALID_TARGET) 320 321 from lldbsuite.test.lldbutil import get_description 322 323 # get_description() allows no option to mean 324 # lldb.eDescriptionLevelBrief. 325 desc = get_description(target) 326 # desc = get_description(target, option=lldb.eDescriptionLevelBrief) 327 if not desc: 328 self.fail("SBTarget.GetDescription() failed") 329 self.expect(desc, exe=False, substrs=["a.out"]) 330 self.expect( 331 desc, exe=False, matching=False, substrs=["Target", "Module", "Breakpoint"] 332 ) 333 334 desc = get_description(target, option=lldb.eDescriptionLevelFull) 335 if not desc: 336 self.fail("SBTarget.GetDescription() failed") 337 self.expect( 338 desc, exe=False, substrs=["Target", "Module", "a.out", "Breakpoint"] 339 ) 340 341 @skipIfRemote 342 @no_debug_info_test 343 def test_launch_new_process_and_redirect_stdout(self): 344 """Exercise SBTarget.Launch() API with redirected stdout.""" 345 self.build() 346 exe = self.getBuildArtifact("a.out") 347 348 # Create a target by the debugger. 349 target = self.dbg.CreateTarget(exe) 350 self.assertTrue(target, VALID_TARGET) 351 352 # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done. 353 # We should still see the entire stdout redirected once the process is 354 # finished. 355 line = line_number("main.c", "// a(3) -> c(3)") 356 breakpoint = target.BreakpointCreateByLocation("main.c", line) 357 358 # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file. 359 # The inferior should run to completion after "process.Continue()" 360 # call. 361 local_path = self.getBuildArtifact("stdout.txt") 362 if os.path.exists(local_path): 363 os.remove(local_path) 364 365 if lldb.remote_platform: 366 stdout_path = lldbutil.append_to_process_working_directory( 367 self, "lldb-stdout-redirect.txt" 368 ) 369 else: 370 stdout_path = local_path 371 error = lldb.SBError() 372 process = target.Launch( 373 self.dbg.GetListener(), 374 None, 375 None, 376 None, 377 stdout_path, 378 None, 379 None, 380 0, 381 False, 382 error, 383 ) 384 process.Continue() 385 # self.runCmd("process status") 386 if lldb.remote_platform: 387 # copy output file to host 388 lldb.remote_platform.Get( 389 lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path) 390 ) 391 392 # The 'stdout.txt' file should now exist. 393 self.assertTrue( 394 os.path.isfile(local_path), 395 "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.", 396 ) 397 398 # Read the output file produced by running the program. 399 with open(local_path, "r") as f: 400 output = f.read() 401 402 self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"]) 403 404 def resolve_symbol_context_with_address(self): 405 """Exercise SBTarget.ResolveSymbolContextForAddress() API.""" 406 exe = self.getBuildArtifact("a.out") 407 408 # Create a target by the debugger. 409 target = self.dbg.CreateTarget(exe) 410 self.assertTrue(target, VALID_TARGET) 411 412 # Now create the two breakpoints inside function 'a'. 413 breakpoint1 = target.BreakpointCreateByLocation("main.c", self.line1) 414 breakpoint2 = target.BreakpointCreateByLocation("main.c", self.line2) 415 self.trace("breakpoint1:", breakpoint1) 416 self.trace("breakpoint2:", breakpoint2) 417 self.assertTrue( 418 breakpoint1 and breakpoint1.GetNumLocations() == 1, VALID_BREAKPOINT 419 ) 420 self.assertTrue( 421 breakpoint2 and breakpoint2.GetNumLocations() == 1, VALID_BREAKPOINT 422 ) 423 424 # Now launch the process, and do not stop at entry point. 425 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 426 self.assertTrue(process, PROCESS_IS_VALID) 427 428 # Frame #0 should be on self.line1. 429 self.assertState(process.GetState(), lldb.eStateStopped) 430 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 431 self.assertTrue( 432 thread.IsValid(), 433 "There should be a thread stopped due to breakpoint condition", 434 ) 435 # self.runCmd("process status") 436 frame0 = thread.GetFrameAtIndex(0) 437 lineEntry = frame0.GetLineEntry() 438 self.assertEqual(lineEntry.GetLine(), self.line1) 439 440 address1 = lineEntry.GetStartAddress() 441 442 # Continue the inferior, the breakpoint 2 should be hit. 443 process.Continue() 444 self.assertState(process.GetState(), lldb.eStateStopped) 445 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 446 self.assertTrue( 447 thread.IsValid(), 448 "There should be a thread stopped due to breakpoint condition", 449 ) 450 # self.runCmd("process status") 451 frame0 = thread.GetFrameAtIndex(0) 452 lineEntry = frame0.GetLineEntry() 453 self.assertEqual(lineEntry.GetLine(), self.line2) 454 455 address2 = lineEntry.GetStartAddress() 456 457 self.trace("address1:", address1) 458 self.trace("address2:", address2) 459 460 # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses 461 # from our line entry. 462 context1 = target.ResolveSymbolContextForAddress( 463 address1, lldb.eSymbolContextEverything 464 ) 465 context2 = target.ResolveSymbolContextForAddress( 466 address2, lldb.eSymbolContextEverything 467 ) 468 469 self.assertTrue(context1 and context2) 470 self.trace("context1:", context1) 471 self.trace("context2:", context2) 472 473 # Verify that the context point to the same function 'a'. 474 symbol1 = context1.GetSymbol() 475 symbol2 = context2.GetSymbol() 476 self.assertTrue(symbol1 and symbol2) 477 self.trace("symbol1:", symbol1) 478 self.trace("symbol2:", symbol2) 479 480 from lldbsuite.test.lldbutil import get_description 481 482 desc1 = get_description(symbol1) 483 desc2 = get_description(symbol2) 484 self.assertTrue( 485 desc1 and desc2 and desc1 == desc2, 486 "The two addresses should resolve to the same symbol", 487 ) 488 489 @skipIfRemote 490 def test_default_arch(self): 491 """Test the other two target create methods using LLDB_ARCH_DEFAULT.""" 492 self.build() 493 exe = self.getBuildArtifact("a.out") 494 target = self.dbg.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) 495 self.assertTrue(target.IsValid(), "Default arch made a valid target.") 496 # This should also work with the target's triple: 497 target2 = self.dbg.CreateTargetWithFileAndArch(exe, target.GetTriple()) 498 self.assertTrue(target2.IsValid(), "Round trip with triple works") 499 # And this triple should work for the FileAndTriple API: 500 target3 = self.dbg.CreateTargetWithFileAndTargetTriple(exe, target.GetTriple()) 501 self.assertTrue(target3.IsValid()) 502 503 @skipIfWindows 504 def test_is_loaded(self): 505 """Exercise SBTarget.IsLoaded(SBModule&) API.""" 506 d = {"EXE": "b.out"} 507 self.build(dictionary=d) 508 self.setTearDownCleanup(dictionary=d) 509 target = self.create_simple_target("b.out") 510 511 self.assertFalse(target.IsLoaded(lldb.SBModule())) 512 513 num_modules = target.GetNumModules() 514 for i in range(num_modules): 515 module = target.GetModuleAtIndex(i) 516 self.assertFalse( 517 target.IsLoaded(module), 518 "Target that isn't " "running shouldn't have any module loaded.", 519 ) 520 521 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 522 523 for i in range(num_modules): 524 module = target.GetModuleAtIndex(i) 525 self.assertTrue( 526 target.IsLoaded(module), 527 "Running the target should " "have loaded its modules.", 528 ) 529 530 @no_debug_info_test 531 def test_setting_selected_target_with_invalid_target(self): 532 """Make sure we don't crash when trying to select invalid target.""" 533 target = lldb.SBTarget() 534 self.dbg.SetSelectedTarget(target) 535