diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py --- a/lldb/packages/Python/lldbsuite/test/lldbutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py @@ -953,7 +953,8 @@ bkpt_module = None, in_cwd = True, only_one_thread = True, - extra_images = None): + extra_images = None, + has_locations_before_run = True): """Start up a target, using exe_name as the executable, and run it to a breakpoint set by source regex bkpt_pattern. @@ -964,9 +965,10 @@ # Set the breakpoints breakpoint = target.BreakpointCreateBySourceRegex( bkpt_pattern, source_spec, bkpt_module) - test.assertTrue(breakpoint.GetNumLocations() > 0, - 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' - %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) + if has_locations_before_run: + test.assertTrue(breakpoint.GetNumLocations() > 0, + 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' + %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) return run_to_breakpoint_do_run(test, target, breakpoint, launch_info, only_one_thread, extra_images) diff --git a/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/Makefile b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/Makefile @@ -0,0 +1,9 @@ +CXX_SOURCES := main.cpp +USE_LIBDL := 1 + +lib_b: + $(MAKE) -f $(MAKEFILE_RULES) \ + DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=lib_b +all: lib_b + +include Makefile.rules diff --git a/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/TestBreakInLoadedDylib.py b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/TestBreakInLoadedDylib.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/TestBreakInLoadedDylib.py @@ -0,0 +1,62 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBreakInLoadedDylib(TestBase): + """ Test that we can set a source regex breakpoint that will take in + a dlopened library that hasn't loaded when we set the breakpoint.""" + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIfRemote + def common_setup(self): + self.build() + ctx = self.platformContext + self.main_spec = lldb.SBFileSpec("main.cpp") + self.b_spec = lldb.SBFileSpec("b.cpp") + self.lib_shortname = 'lib_b' + self.lib_fullname = ctx.shlib_prefix + self.lib_shortname + '.' + ctx.shlib_extension + self.lib_spec = lldb.SBFileSpec(self.lib_fullname) + + def test_break_in_dlopen_dylib_using_lldbutils(self): + self.common_setup() + lldbutil.run_to_source_breakpoint(self, "Break here in dylib", self.b_spec, + bkpt_module=self.lib_fullname, + extra_images = [self.lib_shortname], + has_locations_before_run = False) + + @skipIfRemote + def test_break_in_dlopen_dylib_using_target(self): + self.common_setup() + + target, process, _, _ = lldbutil.run_to_source_breakpoint(self, "Break here before we dlopen", self.main_spec, + extra_images = [self.lib_shortname]) + + # Now set some breakpoints that won't take till the library is loaded: + # This one is currently how lldbutils does it but test here in case that changes: + bkpt1 = target.BreakpointCreateBySourceRegex("Break here in dylib", self.b_spec, self.lib_fullname) + self.assertEqual(bkpt1.GetNumLocations(), 0, "Library isn't loaded yet.") + # Try the file list API as well. Put in some bogus entries too, to make sure those + # don't trip us up: + + files_list = lldb.SBFileSpecList() + files_list.Append(self.b_spec) + files_list.Append(self.main_spec) + files_list.Append(lldb.SBFileSpec("I_bet_nobody_has_this_file.cpp")) + + modules_list = lldb.SBFileSpecList() + modules_list.Append(self.lib_spec) + modules_list.Append(lldb.SBFileSpec("libI_bet_not_this_one_either.dylib")) + + bkpt2 = target.BreakpointCreateBySourceRegex("Break here in dylib", modules_list, files_list) + self.assertEqual(bkpt2.GetNumLocations(), 0, "Library isn't loaded yet") + + lldbutil.continue_to_breakpoint(process, bkpt1) + self.assertEqual(bkpt1.GetHitCount(), 1, "Hit breakpoint 1") + self.assertEqual(bkpt2.GetHitCount(), 1, "Hit breakpoint 2") + + + + diff --git a/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/b.cpp b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/b.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/b.cpp @@ -0,0 +1,3 @@ +extern "C" int LLDB_DYLIB_EXPORT b_function() { + return 500; // Break here in dylib +} diff --git a/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/main.cpp b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/break_in_loaded_dylib/main.cpp @@ -0,0 +1,15 @@ +#include "dylib.h" +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + // Break here before we dlopen the 'liblib_b.so' shared library. + void* dylib_handle = dylib_open("lib_b"); + assert(dylib_handle && "dlopen failed"); + void (*func_handle)() = (void (*)()) dylib_get_symbol(dylib_handle, "b_function"); + assert(func_handle && "dlsym failed"); + func_handle(); + return 0; +} diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py --- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py @@ -54,6 +54,17 @@ "Set break point at this line.", self.main_source_spec) self.assertTrue(fancier_bkpt, VALID_BREAKPOINT) + # Also test the list version of this: + file_list = lldb.SBFileSpecList() + file_list.Append(self.main_source_spec) + module_list = lldb.SBFileSpecList() + module_list.Append(self.target.GetExecutable()) + + list_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", module_list, file_list) + self.assertTrue(list_bkpt, VALID_BREAKPOINT) + + not_so_fancy_bkpt = self.target.BreakpointCreateBySourceRegex( "Set break point at this line.", self.main_source_spec) self.assertTrue(not_so_fancy_bkpt, VALID_BREAKPOINT) @@ -114,13 +125,21 @@ error = not_so_fancy_bkpt.SetScriptCallbackFunction("bktptcmd.empty_extra_args", empty_args) self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString())) + # Do list breakpoint like fancy: + stream.Clear() + stream.Print('{"side_effect" : "I come from list input"}') + extra_args.SetFromJSON(stream) + error = list_bkpt.SetScriptCallbackFunction("bktptcmd.a_list_function", extra_args) + self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString())) + # Clear out canary variables side_effect.bktptcmd = None side_effect.callback = None side_effect.fancy = None side_effect.fancier = None side_effect.not_so_fancy = None - + side_effect.a_list_function = None + # Now launch the process, and do not stop at entry point. self.process = self.target.LaunchSimple( None, None, self.get_process_working_directory()) @@ -133,11 +152,13 @@ self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.") self.thread = threads[0] + print("* Num Locations: {0} ; Hit Count {1}".format(list_bkpt.GetNumLocations(), list_bkpt.GetHitCount())) self.assertEquals("callback was here", side_effect.callback) self.assertEquals("function was here", side_effect.bktptcmd) self.assertEquals("I am fancy", side_effect.fancy) self.assertEquals("I am fancier", side_effect.fancier) self.assertEquals("Not so fancy", side_effect.not_so_fancy) + self.assertEquals("I come from list input", side_effect.from_list) def do_bad_args_to_python_command(self): error = lldb.SBError() diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/bktptcmd.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/bktptcmd.py --- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/bktptcmd.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/bktptcmd.py @@ -17,6 +17,12 @@ se_string = se_value.GetStringValue(100) side_effect.fancier = se_string +def a_list_function(frame, bp_loc, extra_args, dict): + se_value = extra_args.GetValueForKey("side_effect") + se_string = se_value.GetStringValue(100) + side_effect.from_list = se_string + + def empty_extra_args(frame, bp_loc, extra_args, dict): if extra_args.IsValid(): side_effect.not_so_fancy = "Extra args should not be valid"