def test(self): self.build() # Launch and stop before the dlopen call. lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c")) # Delete the breakpoint we no longer need. self.target().DeleteAllBreakpoints() # Check that the executable is the test binary. self.assertEqual(self.target().GetExecutable().GetFilename(), "a.out") # Continue so that dlopen is called. breakpoint = self.target().BreakpointCreateBySourceRegex( "// break after dlopen", lldb.SBFileSpec("main.c")) self.assertNotEqual(breakpoint.GetNumResolvedLocations(), 0) stopped_threads = lldbutil.continue_to_breakpoint( self.process(), breakpoint) self.assertEqual(len(stopped_threads), 1) # Check that the executable is still the test binary and not "other". self.assertEqual(self.target().GetExecutable().GetFilename(), "a.out") # Kill the process and run the program again. err = self.process().Kill() self.assertSuccess(err) # Test that we hit the breakpoint after dlopen. lldbutil.run_to_breakpoint_do_run(self, self.target(), breakpoint)
def test_thread_local(self): # Set a breakpoint on the first instruction of the main function, # before the TLS initialization has run. self.build() exe = self.getBuildArtifact("a.out") (target, process, _, _) = \ lldbutil.run_to_source_breakpoint(self, "Set breakpoint here", lldb.SBFileSpec("main.cpp")) self.expect_expr("tl_local_int + 1", result_type="int", result_value="323") self.expect_expr("*tl_local_ptr + 2", result_type="int", result_value="324") self.expect_expr("tl_global_int", result_type="int", result_value="123") self.expect_expr("*tl_global_ptr", result_type="int", result_value="45") # Create the filespec by which to locate our a.out module. # # - Use the absolute path to get the module for the current variant. # - Use the relative path for reproducers. The modules are never # orphaned because the SB objects are leaked intentionally. This # causes LLDB to reuse the same module for every variant, because the # UUID is the same for all the inferiors. FindModule below only # compares paths and is oblivious to the fact that the UUIDs are the # same. if configuration.is_reproducer(): filespec = lldb.SBFileSpec('a.out', False) else: filespec = lldb.SBFileSpec(exe, False) # Now see if we emit the correct error when the TLS is not yet # initialized. Let's set a breakpoint on the first instruction # of main. main_module = target.FindModule(filespec) self.assertTrue(main_module, VALID_MODULE) main_address = main_module.FindSymbol("main").GetStartAddress() main_bkpt = target.BreakpointCreateBySBAddress(main_address) process.Kill() lldbutil.run_to_breakpoint_do_run(self, target, main_bkpt) self.expect("expr tl_local_int", error=True, substrs=[ "couldn't get the value of variable tl_local_int", "No TLS data currently exists for this thread" ]) self.expect("expr *tl_local_ptr", error=True, substrs=[ "couldn't get the value of variable tl_local_ptr", "No TLS data currently exists for this thread" ])
def test_thread_local(self): # Set a breakpoint on the first instruction of the main function, # before the TLS initialization has run. self.build() exe = self.getBuildArtifact("a.out") (target, process, _, _) = \ lldbutil.run_to_source_breakpoint(self, "Set breakpoint here", lldb.SBFileSpec("main.cpp")) self.expect_expr("tl_local_int + 1", result_type="int", result_value="323") self.expect_expr("*tl_local_ptr + 2", result_type="int", result_value="324") self.expect_expr("tl_global_int", result_type="int", result_value="123") self.expect_expr("*tl_global_ptr", result_type="int", result_value="45") # Create the filespec by which to locate our a.out module. Use the # absolute path to get the module for the current variant. filespec = lldb.SBFileSpec(exe, False) # Now see if we emit the correct error when the TLS is not yet # initialized. Let's set a breakpoint on the first instruction # of main. main_module = target.FindModule(filespec) self.assertTrue(main_module, VALID_MODULE) main_address = main_module.FindSymbol("main").GetStartAddress() main_bkpt = target.BreakpointCreateBySBAddress(main_address) process.Kill() lldbutil.run_to_breakpoint_do_run(self, target, main_bkpt) self.expect("expr tl_local_int", error=True, substrs=[ "couldn't get the value of variable tl_local_int", "No TLS data currently exists for this thread" ]) self.expect("expr *tl_local_ptr", error=True, substrs=[ "couldn't get the value of variable tl_local_ptr", "No TLS data currently exists for this thread" ])
def after_expr_test(self): interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() interp.HandleCommand("target stop-hook add -o 'expr g_var++'", result) self.assertTrue(result.Succeeded, "Set the target stop hook") (target, process, thread, first_bkpt) = lldbutil.run_to_source_breakpoint( self, "Set a breakpoint here", self.main_source_file) var = target.FindFirstGlobalVariable("g_var") self.assertTrue(var.IsValid()) self.assertEqual(var.GetValueAsUnsigned(), 1, "Updated g_var") bkpt = target.BreakpointCreateBySourceRegex("Continue to here", self.main_source_file) self.assertNotEqual(bkpt.GetNumLocations(), 0, "Set the second breakpoint") commands = lldb.SBStringList() commands.AppendString("expr increment_gvar()") bkpt.SetCommandLineCommands(commands) threads = lldbutil.continue_to_breakpoint(process, bkpt) self.assertEqual(len(threads), 1, "Hit my breakpoint") self.assertTrue(var.IsValid()) self.assertEqual(var.GetValueAsUnsigned(), 3, "Updated g_var") # Make sure running an expression does NOT run the stop hook. # Our expression will increment it by one, but the stop shouldn't # have gotten it to 5. threads[0].frames[0].EvaluateExpression("increment_gvar()") self.assertTrue(var.IsValid()) self.assertEqual(var.GetValueAsUnsigned(), 4, "Updated g_var") # Make sure a rerun doesn't upset the state we've set up: process.Kill() lldbutil.run_to_breakpoint_do_run(self, target, first_bkpt) var = target.FindFirstGlobalVariable("g_var") self.assertTrue(var.IsValid()) self.assertEqual(var.GetValueAsUnsigned(), 1, "Updated g_var")
def test_expr(self): with open(self.getBuildArtifact("module.modulemap"), "w") as f: f.write(""" module Foo { header "f.h" } """) with open(self.getBuildArtifact("f.h"), "w") as f: f.write(""" struct Q { int i; }; void f() {} """) mod_cache = self.getBuildArtifact("private-module-cache") if os.path.isdir(mod_cache): shutil.rmtree(mod_cache) d = {'OBJC_SOURCES': 'first.m'} self.build(dictionary=d) self.assertTrue(os.path.isdir(mod_cache), "module cache exists") logfile = self.getBuildArtifact("modules.log") self.runCmd("log enable -f %s lldb module" % logfile) target, process, _, bkpt = lldbutil.run_to_name_breakpoint( self, "main") self.assertIn("int i", str(target.FindTypes('Q').GetTypeAtIndex(0))) self.expect("image list -g", patterns=[r'first\.o', r'Foo.*\.pcm']) # Update the module. with open(self.getBuildArtifact("f.h"), "w") as f: f.write(""" struct S { int i; }; struct S getS() { struct S r = {1}; return r; } void f() {} """) # Rebuild. d = {'OBJC_SOURCES': 'second.m'} self.build(dictionary=d) # Reattach. process.Kill() target, process, _, _ = lldbutil.run_to_breakpoint_do_run( self, target, bkpt) self.assertIn("int i", str(target.FindTypes('S').GetTypeAtIndex(0))) self.expect("image list -g", patterns=[r'second\.o', r'Foo.*\.pcm']) # Check log file. found = False with open(logfile, 'r') as f: for line in f: if "module changed" in line and "Foo" in line: found = True self.assertTrue(found)
def test_rebuild_app_modules_untouched(self): with open(self.getBuildArtifact("module.modulemap"), "w") as f: f.write(""" module Foo { header "f.h" } """) with open(self.getBuildArtifact("f.h"), "w") as f: f.write(""" @import Foundation; @interface Foo : NSObject { int i; } +(instancetype)init; @end """) mod_cache = self.getBuildArtifact("private-module-cache") import os if os.path.isdir(mod_cache): shutil.rmtree(mod_cache) self.build() self.assertTrue(os.path.isdir(mod_cache), "module cache exists") target, process, _, bkpt = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.m")) bar = target.FindTypes('Bar').GetTypeAtIndex(0) foo = bar.GetDirectBaseClassAtIndex(0).GetType() self.assertEqual(foo.GetNumberOfFields(), 1) self.assertEqual(foo.GetFieldAtIndex(0).GetName(), "i") # Rebuild. process.Kill() os.remove(self.getBuildArtifact('main.o')) os.remove(self.getBuildArtifact('a.out')) self.build() # Reattach. target, process, _, _ = lldbutil.run_to_breakpoint_do_run( self, target, bkpt) bar = target.FindTypes('Bar').GetTypeAtIndex(0) foo = bar.GetDirectBaseClassAtIndex(0).GetType() self.assertEqual(foo.GetNumberOfFields(), 1) self.assertEqual(foo.GetFieldAtIndex(0).GetName(), "i")
def do_test(self): """This reads in a python file and sets a breakpoint using it.""" target = self.make_target_and_import() extra_args = self.make_extra_args() file_list = lldb.SBFileSpecList() module_list = lldb.SBFileSpecList() # Make breakpoints with this resolver using different filters, first ones that will take: right = [] # one with no file or module spec - this one should fire: right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # one with the right source file and no module - should also fire: file_list.Append(lldb.SBFileSpec("main.c")) right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # Make sure the help text shows up in the "break list" output: self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") # one with the right source file and right module - should also fire: module_list.Append(lldb.SBFileSpec("a.out")) right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # And one with no source file but the right module: file_list.Clear() right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # Make sure these all got locations: for i in range (0, len(right)): self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) # Now some ones that won't take: module_list.Clear() file_list.Clear() wrong = [] # one with the wrong module - should not fire: module_list.Append(lldb.SBFileSpec("noSuchModule")) wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # one with the wrong file - also should not fire: file_list.Clear() module_list.Clear() file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) # Now make sure the CU level iteration obeys the file filters: file_list.Clear() module_list.Clear() file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) # And the Module filters: file_list.Clear() module_list.Clear() module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) # Now make sure the Function level iteration obeys the file filters: file_list.Clear() module_list.Clear() file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) # And the Module filters: file_list.Clear() module_list.Clear() module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) # Make sure these didn't get locations: for i in range(0, len(wrong)): self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) # Now run to main and ensure we hit the breakpoints we should have: lldbutil.run_to_breakpoint_do_run(self, target, right[0]) # Test the hit counts: for i in range(0, len(right)): self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) for i in range(0, len(wrong)): self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i))
def test_process_handle(self): """Test that calling process handle before we have a target, and before we have a process will affect the process. Also that the signal settings are preserved on rerun.""" self.build() # Make sure we don't accept signal values by signo with no process - we don't know what the # mapping will be so we can't do the right thing with bare numbers: lldbutil.set_actions_for_signal(self, "9", "true", None, None, expect_success=False) # First, I need a reference value so I can see whether changes actually took: (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp")) (default_pass, default_stop, default_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV") # Let's change the value here, then exit and make sure the changed value sticks: new_value = "false" if default_pass == "true": new_value = "false" # First make sure we get an error for bogus values when running: lldbutil.set_actions_for_signal(self, "NOTSIGSEGV", new_value, None, None, expect_success=False) # Then set the one we intend to change. lldbutil.set_actions_for_signal(self, "SIGSEGV", new_value, None, None) process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) # Check that we preserved the setting: (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV", from_target=True) self.assertEqual(curr_pass, new_value, "Pass was set correctly") self.assertEqual(curr_stop, "not set", "Stop was not set by us") self.assertEqual(curr_notify, "not set", "Notify was not set by us") # Run again and make sure that we prime the new process with these settings: process = lldbutil.run_to_breakpoint_do_run(self, target, bkpt) # We check the process settings now, to see what got copied into the process: (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV") self.assertEqual(curr_pass, new_value, "Pass was set correctly") self.assertEqual(curr_stop, default_stop, "Stop was its default value") self.assertEqual(curr_notify, default_notify, "Notify was its default value") # Now kill this target, set the handling and make sure the values get copied from the dummy into the new target. success = self.dbg.DeleteTarget(target) self.assertTrue(success, "Deleted the target") self.assertEqual(self.dbg.GetNumTargets(), 0, "We did delete all the targets.") # The signal settings should be back at their default - we were only setting this on the target: lldbutil.get_actions_for_signal(self, "SIGSEGV", from_target=True, expected_absent=True) # Set a valid one: lldbutil.set_actions_for_signal(self, "SIGSEGV", new_value, None, None) # Set a bogus one - we don't have a way to check pre-run so this is allowed # but we should get an error message when launching: lldbutil.set_actions_for_signal(self, "SIGNOTSIG", new_value, None, None) out_filename = self.getBuildArtifact('output') success = True try: f = open(out_filename, 'w') except: success = False if not success: self.fail("Couldn't open error output file for writing.") self.dbg.SetErrorFileHandle(f, False) # Now make a new process and make sure the right values got copied into the new target (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp")) f.write("TESTPATTERN\n") f.flush() f.close() try: f = open(out_filename, 'r') except: success = False if not success: self.fail("Couldn't open error output file for reading") errors = f.read() f.close() self.assertIn("SIGNOTSIG", errors, "We warned about the unset signal") # Also make sure we didn't accidentally add this bogus setting to the process. lldbutil.set_actions_for_signal(self, "SIGNOTSIG", "true", "true", "true", expect_success=False) # Check that they went into the target: (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV", from_target=True) self.assertEqual(curr_pass, new_value, "Pass was set correctly") self.assertEqual(curr_stop, "not set", "Stop was not set by us") self.assertEqual(curr_notify, "not set", "Notify was not set by us") # And the process: # Check that they went into the target: (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV") self.assertEqual(curr_pass, new_value, "Pass was set correctly") self.assertEqual(curr_stop, default_stop, "Stop was its default value") self.assertEqual(curr_notify, default_notify, "Notify was its default value") # Now clear the handling, and make sure that we get the right signal values again: self.runCmd("process handle -c SIGSEGV") # Check that there is no longer configuration for SIGSEGV in the target: lldbutil.get_actions_for_signal(self, "SIGSEGV", from_target=True, expected_absent=True) # Make a new process, to make sure we did indeed reset the values: (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp")) (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV") self.assertEqual(curr_pass, new_value, "Pass was set correctly") self.assertEqual(curr_stop, default_stop, "Stop was its default value") self.assertEqual(curr_notify, default_notify, "Notify was its default value") # Finally remove this from the dummy target as well, and make sure it was cleared from there: self.runCmd("process handle -c -d SIGSEGV") error = process.Kill() self.assertSuccess(error, "Killed the process") success = self.dbg.DeleteTarget(target) self.assertTrue(success, "Destroyed the target.") (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp")) (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(self, "SIGSEGV") self.assertEqual(curr_pass, default_pass, "Pass was set correctly") self.assertEqual(curr_stop, default_stop, "Stop was its default value") self.assertEqual(curr_notify, default_notify, "Notify was its default value")