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