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.assertNotEqual(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 # Make sure reading from 0x0 fails 157 sb_addr = lldb.SBAddress(0, target) 158 self.assertIsNone(target.ReadMemory(sb_addr, 1, error)) 159 self.assertTrue(error.Fail()) 160 161 @skipIfWindows # stdio manipulation unsupported on Windows 162 @skipIfRemote # stdio manipulation unsupported on remote iOS devices<rdar://problem/54581135> 163 @skipIf(oslist=["linux"], archs=["arm", "aarch64"]) 164 @no_debug_info_test 165 def test_launch_simple(self): 166 d = {"EXE": "b.out"} 167 self.build(dictionary=d) 168 self.setTearDownCleanup(dictionary=d) 169 target = self.create_simple_target("b.out") 170 171 # Set the debugger to synchronous mode so we only continue after the 172 # process has exited. 173 self.dbg.SetAsync(False) 174 175 process = target.LaunchSimple( 176 ["foo", "bar"], ["baz"], self.get_process_working_directory() 177 ) 178 process.Continue() 179 self.assertState(process.GetState(), lldb.eStateExited) 180 output = process.GetSTDOUT(9999) 181 self.assertIn("arg: foo", output) 182 self.assertIn("arg: bar", output) 183 self.assertIn("env: baz", output) 184 185 self.runCmd("setting set target.run-args foo") 186 self.runCmd("setting set target.env-vars bar=baz") 187 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 188 process.Continue() 189 self.assertState(process.GetState(), lldb.eStateExited) 190 output = process.GetSTDOUT(9999) 191 self.assertIn("arg: foo", output) 192 self.assertIn("env: bar=baz", output) 193 194 # Clear all the run args set above. 195 self.runCmd("setting clear target.run-args") 196 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 197 process.Continue() 198 self.assertEqual(process.GetState(), lldb.eStateExited) 199 output = process.GetSTDOUT(9999) 200 self.assertNotIn("arg: foo", output) 201 202 self.runCmd("settings set target.disable-stdio true") 203 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 204 process.Continue() 205 self.assertState(process.GetState(), lldb.eStateExited) 206 output = process.GetSTDOUT(9999) 207 self.assertEqual(output, "") 208 209 def create_simple_target(self, fn): 210 exe = self.getBuildArtifact(fn) 211 target = self.dbg.CreateTarget(exe) 212 self.assertTrue(target, VALID_TARGET) 213 return target 214 215 def find_data_section(self, target): 216 mod = target.GetModuleAtIndex(0) 217 data_section = None 218 for s in mod.sections: 219 sect_type = s.GetSectionType() 220 if sect_type == lldb.eSectionTypeData: 221 data_section = s 222 break 223 elif sect_type == lldb.eSectionTypeContainer: 224 for i in range(s.GetNumSubSections()): 225 ss = s.GetSubSectionAtIndex(i) 226 sect_type = ss.GetSectionType() 227 if sect_type == lldb.eSectionTypeData: 228 data_section = ss 229 break 230 231 self.assertIsNotNone(data_section) 232 return data_section 233 234 def find_global_variables(self, exe_name): 235 """Exercise SBTarget.FindGlobalVariables() API.""" 236 exe = self.getBuildArtifact(exe_name) 237 238 # Create a target by the debugger. 239 target = self.dbg.CreateTarget(exe) 240 self.assertTrue(target, VALID_TARGET) 241 242 # rdar://problem/9700873 243 # Find global variable value fails for dwarf if inferior not started 244 # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) 245 # 246 # Remove the lines to create a breakpoint and to start the inferior 247 # which are workarounds for the dwarf case. 248 249 breakpoint = target.BreakpointCreateByLocation("main.c", self.line1) 250 self.assertTrue(breakpoint, VALID_BREAKPOINT) 251 252 # Now launch the process, and do not stop at entry point. 253 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 254 self.assertTrue(process, PROCESS_IS_VALID) 255 # Make sure we hit our breakpoint: 256 thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) 257 self.assertEqual(len(thread_list), 1) 258 259 value_list = target.FindGlobalVariables("my_global_var_of_char_type", 3) 260 self.assertEqual(value_list.GetSize(), 1) 261 my_global_var = value_list.GetValueAtIndex(0) 262 self.DebugSBValue(my_global_var) 263 self.assertTrue(my_global_var) 264 self.expect( 265 my_global_var.GetName(), exe=False, startstr="my_global_var_of_char_type" 266 ) 267 self.expect(my_global_var.GetTypeName(), exe=False, startstr="char") 268 self.expect(my_global_var.GetValue(), exe=False, startstr="'X'") 269 270 # While we are at it, let's also exercise the similar 271 # SBModule.FindGlobalVariables() API. 272 for m in target.module_iter(): 273 if ( 274 os.path.normpath(m.GetFileSpec().GetDirectory()) == self.getBuildDir() 275 and m.GetFileSpec().GetFilename() == exe_name 276 ): 277 value_list = m.FindGlobalVariables( 278 target, "my_global_var_of_char_type", 3 279 ) 280 self.assertEqual(value_list.GetSize(), 1) 281 self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "'X'") 282 break 283 284 def find_compile_units(self, exe): 285 """Exercise SBTarget.FindCompileUnits() API.""" 286 source_name = "main.c" 287 288 # Create a target by the debugger. 289 target = self.dbg.CreateTarget(exe) 290 self.assertTrue(target, VALID_TARGET) 291 292 list = target.FindCompileUnits(lldb.SBFileSpec(source_name, False)) 293 # Executable has been built just from one source file 'main.c', 294 # so we may check only the first element of list. 295 self.assertEqual( 296 list[0].GetCompileUnit().GetFileSpec().GetFilename(), source_name 297 ) 298 299 def find_functions(self, exe_name): 300 """Exercise SBTarget.FindFunctions() API.""" 301 exe = self.getBuildArtifact(exe_name) 302 303 # Create a target by the debugger. 304 target = self.dbg.CreateTarget(exe) 305 self.assertTrue(target, VALID_TARGET) 306 307 # Try it with a null name: 308 list = target.FindFunctions(None, lldb.eFunctionNameTypeAuto) 309 self.assertEqual(list.GetSize(), 0) 310 311 list = target.FindFunctions("c", lldb.eFunctionNameTypeAuto) 312 self.assertEqual(list.GetSize(), 1) 313 314 for sc in list: 315 self.assertEqual(sc.GetModule().GetFileSpec().GetFilename(), exe_name) 316 self.assertEqual(sc.GetSymbol().GetName(), "c") 317 318 def get_description(self): 319 """Exercise SBTarget.GetDescription() API.""" 320 exe = self.getBuildArtifact("a.out") 321 322 # Create a target by the debugger. 323 target = self.dbg.CreateTarget(exe) 324 self.assertTrue(target, VALID_TARGET) 325 326 from lldbsuite.test.lldbutil import get_description 327 328 # get_description() allows no option to mean 329 # lldb.eDescriptionLevelBrief. 330 desc = get_description(target) 331 # desc = get_description(target, option=lldb.eDescriptionLevelBrief) 332 if not desc: 333 self.fail("SBTarget.GetDescription() failed") 334 self.expect(desc, exe=False, substrs=["a.out"]) 335 self.expect( 336 desc, exe=False, matching=False, substrs=["Target", "Module", "Breakpoint"] 337 ) 338 339 desc = get_description(target, option=lldb.eDescriptionLevelFull) 340 if not desc: 341 self.fail("SBTarget.GetDescription() failed") 342 self.expect( 343 desc, exe=False, substrs=["Target", "Module", "a.out", "Breakpoint"] 344 ) 345 346 @skipIfRemote 347 @no_debug_info_test 348 def test_launch_new_process_and_redirect_stdout(self): 349 """Exercise SBTarget.Launch() API with redirected stdout.""" 350 self.build() 351 exe = self.getBuildArtifact("a.out") 352 353 # Create a target by the debugger. 354 target = self.dbg.CreateTarget(exe) 355 self.assertTrue(target, VALID_TARGET) 356 357 # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done. 358 # We should still see the entire stdout redirected once the process is 359 # finished. 360 line = line_number("main.c", "// a(3) -> c(3)") 361 breakpoint = target.BreakpointCreateByLocation("main.c", line) 362 363 # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file. 364 # The inferior should run to completion after "process.Continue()" 365 # call. 366 local_path = self.getBuildArtifact("stdout.txt") 367 if os.path.exists(local_path): 368 os.remove(local_path) 369 370 if lldb.remote_platform: 371 stdout_path = lldbutil.append_to_process_working_directory( 372 self, "lldb-stdout-redirect.txt" 373 ) 374 else: 375 stdout_path = local_path 376 error = lldb.SBError() 377 process = target.Launch( 378 self.dbg.GetListener(), 379 None, 380 None, 381 None, 382 stdout_path, 383 None, 384 None, 385 0, 386 False, 387 error, 388 ) 389 process.Continue() 390 # self.runCmd("process status") 391 if lldb.remote_platform: 392 # copy output file to host 393 lldb.remote_platform.Get( 394 lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path) 395 ) 396 397 # The 'stdout.txt' file should now exist. 398 self.assertTrue( 399 os.path.isfile(local_path), 400 "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.", 401 ) 402 403 # Read the output file produced by running the program. 404 with open(local_path, "r") as f: 405 output = f.read() 406 407 self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"]) 408 409 def resolve_symbol_context_with_address(self): 410 """Exercise SBTarget.ResolveSymbolContextForAddress() API.""" 411 exe = self.getBuildArtifact("a.out") 412 413 # Create a target by the debugger. 414 target = self.dbg.CreateTarget(exe) 415 self.assertTrue(target, VALID_TARGET) 416 417 # Now create the two breakpoints inside function 'a'. 418 breakpoint1 = target.BreakpointCreateByLocation("main.c", self.line1) 419 breakpoint2 = target.BreakpointCreateByLocation("main.c", self.line2) 420 self.trace("breakpoint1:", breakpoint1) 421 self.trace("breakpoint2:", breakpoint2) 422 self.assertTrue( 423 breakpoint1 and breakpoint1.GetNumLocations() == 1, VALID_BREAKPOINT 424 ) 425 self.assertTrue( 426 breakpoint2 and breakpoint2.GetNumLocations() == 1, VALID_BREAKPOINT 427 ) 428 429 # Now launch the process, and do not stop at entry point. 430 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 431 self.assertTrue(process, PROCESS_IS_VALID) 432 433 # Frame #0 should be on self.line1. 434 self.assertState(process.GetState(), lldb.eStateStopped) 435 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 436 self.assertTrue( 437 thread.IsValid(), 438 "There should be a thread stopped due to breakpoint condition", 439 ) 440 # self.runCmd("process status") 441 frame0 = thread.GetFrameAtIndex(0) 442 lineEntry = frame0.GetLineEntry() 443 self.assertEqual(lineEntry.GetLine(), self.line1) 444 445 address1 = lineEntry.GetStartAddress() 446 447 # Continue the inferior, the breakpoint 2 should be hit. 448 process.Continue() 449 self.assertState(process.GetState(), lldb.eStateStopped) 450 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 451 self.assertTrue( 452 thread.IsValid(), 453 "There should be a thread stopped due to breakpoint condition", 454 ) 455 # self.runCmd("process status") 456 frame0 = thread.GetFrameAtIndex(0) 457 lineEntry = frame0.GetLineEntry() 458 self.assertEqual(lineEntry.GetLine(), self.line2) 459 460 address2 = lineEntry.GetStartAddress() 461 462 self.trace("address1:", address1) 463 self.trace("address2:", address2) 464 465 # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses 466 # from our line entry. 467 context1 = target.ResolveSymbolContextForAddress( 468 address1, lldb.eSymbolContextEverything 469 ) 470 context2 = target.ResolveSymbolContextForAddress( 471 address2, lldb.eSymbolContextEverything 472 ) 473 474 self.assertTrue(context1 and context2) 475 self.trace("context1:", context1) 476 self.trace("context2:", context2) 477 478 # Verify that the context point to the same function 'a'. 479 symbol1 = context1.GetSymbol() 480 symbol2 = context2.GetSymbol() 481 self.assertTrue(symbol1 and symbol2) 482 self.trace("symbol1:", symbol1) 483 self.trace("symbol2:", symbol2) 484 485 from lldbsuite.test.lldbutil import get_description 486 487 desc1 = get_description(symbol1) 488 desc2 = get_description(symbol2) 489 self.assertTrue( 490 desc1 and desc2 and desc1 == desc2, 491 "The two addresses should resolve to the same symbol", 492 ) 493 494 @skipIfRemote 495 def test_default_arch(self): 496 """Test the other two target create methods using LLDB_ARCH_DEFAULT.""" 497 self.build() 498 exe = self.getBuildArtifact("a.out") 499 target = self.dbg.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) 500 self.assertTrue(target.IsValid(), "Default arch made a valid target.") 501 # This should also work with the target's triple: 502 target2 = self.dbg.CreateTargetWithFileAndArch(exe, target.GetTriple()) 503 self.assertTrue(target2.IsValid(), "Round trip with triple works") 504 # And this triple should work for the FileAndTriple API: 505 target3 = self.dbg.CreateTargetWithFileAndTargetTriple(exe, target.GetTriple()) 506 self.assertTrue(target3.IsValid()) 507 508 @skipIfWindows 509 def test_is_loaded(self): 510 """Exercise SBTarget.IsLoaded(SBModule&) API.""" 511 d = {"EXE": "b.out"} 512 self.build(dictionary=d) 513 self.setTearDownCleanup(dictionary=d) 514 target = self.create_simple_target("b.out") 515 516 self.assertFalse(target.IsLoaded(lldb.SBModule())) 517 518 num_modules = target.GetNumModules() 519 for i in range(num_modules): 520 module = target.GetModuleAtIndex(i) 521 self.assertFalse( 522 target.IsLoaded(module), 523 "Target that isn't " "running shouldn't have any module loaded.", 524 ) 525 526 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 527 528 for i in range(num_modules): 529 module = target.GetModuleAtIndex(i) 530 self.assertTrue( 531 target.IsLoaded(module), 532 "Running the target should " "have loaded its modules.", 533 ) 534 535 @no_debug_info_test 536 def test_setting_selected_target_with_invalid_target(self): 537 """Make sure we don't crash when trying to select invalid target.""" 538 target = lldb.SBTarget() 539 self.dbg.SetSelectedTarget(target) 540