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.
# 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)
--- /dev/null
+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
--- /dev/null
+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")
+
+
+
+
--- /dev/null
+extern "C" int LLDB_DYLIB_EXPORT b_function() {
+ return 500; // Break here in dylib
+}
--- /dev/null
+#include "dylib.h"
+#include <cassert>
+#include <cstdio>
+#include <thread>
+#include <chrono>
+
+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;
+}
"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)
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())
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()
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"