Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp =================================================================== --- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -556,7 +556,8 @@ } } - if (exe_idx != UINT32_MAX) { + // Set the target executable if we haven't found one so far. + if (exe_idx != UINT32_MAX && !target.GetExecutableModule()) { const bool can_create = true; ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, nullptr)); Index: lldb/test/API/functionalities/dlopen_other_executable/Makefile =================================================================== --- /dev/null +++ lldb/test/API/functionalities/dlopen_other_executable/Makefile @@ -0,0 +1,8 @@ +C_SOURCES := main.c +USE_LIBDL := 1 + +other: + $(MAKE) -f $(MAKEFILE_RULES) C_SOURCES=other.c EXE=other +all: other + +include Makefile.rules Index: lldb/test/API/functionalities/dlopen_other_executable/TestDlopenOtherExecutable.py =================================================================== --- /dev/null +++ lldb/test/API/functionalities/dlopen_other_executable/TestDlopenOtherExecutable.py @@ -0,0 +1,42 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfRemote + @skipIfWindows + # glibc's dlopen doesn't support opening executables. + # https://sourceware.org/bugzilla/show_bug.cgi?id=11754 + @skipIfLinux + @no_debug_info_test + 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.assertTrue(err.Success(), str(err)) + + # Test that we hit the breakpoint after dlopen. + lldbutil.run_to_breakpoint_do_run(self, self.target(), breakpoint) Index: lldb/test/API/functionalities/dlopen_other_executable/main.c =================================================================== --- /dev/null +++ lldb/test/API/functionalities/dlopen_other_executable/main.c @@ -0,0 +1,10 @@ +#include +#include + +int main() { + int i = 0; // break here + // dlopen the 'other' test executable. + int h = dlopen("other", RTLD_LAZY); + assert(h && "dlopen failed?"); + return i; // break after dlopen +} Index: lldb/test/API/functionalities/dlopen_other_executable/other.c =================================================================== --- /dev/null +++ lldb/test/API/functionalities/dlopen_other_executable/other.c @@ -0,0 +1 @@ +int main() {}