[Lldb-commits] [lldb] 1cbdc07 - [lldb] Add support for debugging via the dynamic linker.
Rumeet Dhindsa via lldb-commits
lldb-commits at lists.llvm.org
Tue Aug 24 13:41:41 PDT 2021
Author: Rumeet Dhindsa
Date: 2021-08-24T13:41:22-07:00
New Revision: 1cbdc07ec015d83038c08dc562d55eccfd808591
URL: https://github.com/llvm/llvm-project/commit/1cbdc07ec015d83038c08dc562d55eccfd808591
DIFF: https://github.com/llvm/llvm-project/commit/1cbdc07ec015d83038c08dc562d55eccfd808591.diff
LOG: [lldb] Add support for debugging via the dynamic linker.
This patch adds support for shared library load when the executable is
called through ld.so.
Differential Revision:https://reviews.llvm.org/D108061
Added:
lldb/test/API/functionalities/dyld-launch-linux/Makefile
lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py
lldb/test/API/functionalities/dyld-launch-linux/main.cpp
lldb/test/API/functionalities/dyld-launch-linux/signal_file.cpp
lldb/test/API/functionalities/dyld-launch-linux/signal_file.h
Modified:
lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 866acbddbdc8..e385b583cef9 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -56,6 +56,19 @@ static addr_t ResolveRendezvousAddress(Process *process) {
"%s resolved via direct object file approach to 0x%" PRIx64,
__FUNCTION__, info_location);
} else {
+ const Symbol *_r_debug =
+ target->GetExecutableModule()->FindFirstSymbolWithNameAndType(
+ ConstString("_r_debug"));
+ if (_r_debug) {
+ info_addr = _r_debug->GetAddress().GetLoadAddress(target);
+ if (info_addr != LLDB_INVALID_ADDRESS) {
+ LLDB_LOGF(log,
+ "%s resolved by finding symbol '_r_debug' whose value is "
+ "0x%" PRIx64,
+ __FUNCTION__, info_addr);
+ return info_addr;
+ }
+ }
LLDB_LOGF(log,
"%s FAILED - direct object file approach did not yield a "
"valid address",
@@ -276,6 +289,14 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo(
entry.base_addr = base_addr;
entry.dyn_addr = dyn_addr;
+ // ld.so saves empty file name for the executable file in the link map.
+ // When executable is run using ld.so, we need to be update executable path.
+ if (name.empty()) {
+ MemoryRegionInfo region;
+ Status region_status =
+ m_process->GetMemoryRegionInfo(entry.dyn_addr, region);
+ name = region.GetName().AsCString();
+ }
entry.file_spec.SetFile(name, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, name);
@@ -547,6 +568,15 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
return false;
std::string file_path = ReadStringFromMemory(entry.path_addr);
+
+ // ld.so saves empty file name for the executable file in the link map.
+ // When executable is run using ld.so, we need to be update executable path.
+ if (file_path.empty()) {
+ MemoryRegionInfo region;
+ Status region_status =
+ m_process->GetMemoryRegionInfo(entry.dyn_addr, region);
+ file_path = region.GetName().AsCString();
+ }
entry.file_spec.SetFile(file_path, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, file_path);
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 160faa74af23..09d0523f676c 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -333,28 +333,48 @@ bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
LLDB_LOG(log, "Rendezvous structure is not set up yet. "
"Trying to locate rendezvous breakpoint in the interpreter "
"by symbol name.");
- ModuleSP interpreter = LoadInterpreterModule();
- if (!interpreter) {
- LLDB_LOG(log, "Can't find interpreter, rendezvous breakpoint isn't set.");
- return false;
- }
-
- // Function names from
diff erent dynamic loaders that are known to be used
- // as rendezvous between the loader and debuggers.
+ // Function names from
diff erent dynamic loaders that are known to be
+ // used as rendezvous between the loader and debuggers.
static std::vector<std::string> DebugStateCandidates{
"_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
"r_debug_state", "_r_debug_state", "_rtld_debug_state",
};
- FileSpecList containingModules;
- containingModules.Append(interpreter->GetFileSpec());
- dyld_break = target.CreateBreakpoint(
- &containingModules, nullptr /* containingSourceFiles */,
- DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
- 0, /* offset */
- eLazyBoolNo, /* skip_prologue */
- true, /* internal */
- false /* request_hardware */);
+ ModuleSP interpreter = LoadInterpreterModule();
+ if (!interpreter) {
+ if (NameMatches(m_process->GetTarget()
+ .GetExecutableModulePointer()
+ ->GetFileSpec()
+ .GetFilename()
+ .GetCString(),
+ NameMatch::StartsWith, "ld-")) {
+ FileSpecList containingModules;
+ containingModules.Append(
+ m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec());
+
+ dyld_break = target.CreateBreakpoint(
+ &containingModules, /*containingSourceFiles=*/nullptr,
+ DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+ /*offset=*/0,
+ /*skip_prologue=*/eLazyBoolNo,
+ /*internal=*/true,
+ /*request_hardware=*/false);
+ } else {
+ LLDB_LOG(log,
+ "Can't find interpreter, rendezvous breakpoint isn't set.");
+ return false;
+ }
+ } else {
+ FileSpecList containingModules;
+ containingModules.Append(interpreter->GetFileSpec());
+ dyld_break = target.CreateBreakpoint(
+ &containingModules, /*containingSourceFiles=*/nullptr,
+ DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+ /*offset=*/0,
+ /*skip_prologue=*/eLazyBoolNo,
+ /*internal=*/true,
+ /*request_hardware=*/false);
+ }
}
if (dyld_break->GetNumResolvedLocations() != 1) {
diff --git a/lldb/test/API/functionalities/dyld-launch-linux/Makefile b/lldb/test/API/functionalities/dyld-launch-linux/Makefile
new file mode 100644
index 000000000000..36bfbb52590d
--- /dev/null
+++ b/lldb/test/API/functionalities/dyld-launch-linux/Makefile
@@ -0,0 +1,15 @@
+CXX_SOURCES := main.cpp
+LD_EXTRAS := -Wl,-rpath "-Wl,$(shell pwd)"
+USE_LIBDL := 1
+
+include Makefile.rules
+
+# The following shared library will be used to test breakpoints under dynamic loading
+libsignal_file.so: signal_file.cpp
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_ONLY=YES DYLIB_CXX_SOURCES=signal_file.cpp DYLIB_NAME=signal_file
+
+a.out: libsignal_file.so main.cpp
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ CXX_SOURCES=main.cpp LD_EXTRAS=libsignal_file.so
+
diff --git a/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py b/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py
new file mode 100644
index 000000000000..bf7ce12effc4
--- /dev/null
+++ b/lldb/test/API/functionalities/dyld-launch-linux/TestDyldLaunchLinux.py
@@ -0,0 +1,46 @@
+"""
+Test that LLDB can launch a linux executable through the dynamic loader and still hit a breakpoint.
+"""
+
+import lldb
+import os
+
+from lldbsuite.test.lldbtest import *
+
+class TestLinux64LaunchingViaDynamicLoader(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test(self):
+ self.build()
+ exe = "/lib64/ld-linux-x86-64.so.2"
+ if(os.path.exists(exe)):
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Set breakpoints both on shared library function as well as on
+ # main. Both of them will be pending breakpoints.
+ breakpoint_main = target.BreakpointCreateBySourceRegex("// Break here", lldb.SBFileSpec("main.cpp"))
+ breakpoint_shared_library = target.BreakpointCreateBySourceRegex("get_signal_crash", lldb.SBFileSpec("signal_file.cpp"))
+ launch_info = lldb.SBLaunchInfo([ "--library-path",self.get_process_working_directory(),self.getBuildArtifact("a.out")])
+ launch_info.SetWorkingDirectory(self.get_process_working_directory())
+ error = lldb.SBError()
+ process = target.Launch(launch_info,error)
+ self.assertTrue(error.Success())
+
+ # Stopped on main here.
+ self.assertEqual(process.GetState(), lldb.eStateStopped)
+ thread = process.GetSelectedThread()
+ self.assertIn("main",thread.GetFrameAtIndex(0).GetDisplayFunctionName())
+ process.Continue()
+
+ # Stopped on get_signal_crash function here.
+ self.assertEqual(process.GetState(), lldb.eStateStopped)
+ self.assertIn("get_signal_crash",thread.GetFrameAtIndex(0).GetDisplayFunctionName())
+ process.Continue()
+
+ # Stopped because of generated signal.
+ self.assertEqual(process.GetState(), lldb.eStateStopped)
+ self.assertIn("raise",thread.GetFrameAtIndex(0).GetDisplayFunctionName())
+ self.assertIn("get_signal_crash",thread.GetFrameAtIndex(1).GetDisplayFunctionName())
+
+
diff --git a/lldb/test/API/functionalities/dyld-launch-linux/main.cpp b/lldb/test/API/functionalities/dyld-launch-linux/main.cpp
new file mode 100644
index 000000000000..0ff05466c58c
--- /dev/null
+++ b/lldb/test/API/functionalities/dyld-launch-linux/main.cpp
@@ -0,0 +1,6 @@
+#include "signal_file.h"
+
+int main() {
+ // Break here
+ return get_signal_crash();
+}
diff --git a/lldb/test/API/functionalities/dyld-launch-linux/signal_file.cpp b/lldb/test/API/functionalities/dyld-launch-linux/signal_file.cpp
new file mode 100644
index 000000000000..3c904a34f421
--- /dev/null
+++ b/lldb/test/API/functionalities/dyld-launch-linux/signal_file.cpp
@@ -0,0 +1,7 @@
+#include "signal_file.h"
+#include <signal.h>
+
+int get_signal_crash(void) {
+ raise(SIGSEGV);
+ return 0;
+}
diff --git a/lldb/test/API/functionalities/dyld-launch-linux/signal_file.h b/lldb/test/API/functionalities/dyld-launch-linux/signal_file.h
new file mode 100644
index 000000000000..7c8676f71109
--- /dev/null
+++ b/lldb/test/API/functionalities/dyld-launch-linux/signal_file.h
@@ -0,0 +1 @@
+int get_signal_crash(void);
More information about the lldb-commits
mailing list