Author: Yuval Deutscher
Date: 2025-04-22T11:43:23+02:00
New Revision: a86f4ee774e6d2eb9f38502ddda65842179a246a

URL: 
https://github.com/llvm/llvm-project/commit/a86f4ee774e6d2eb9f38502ddda65842179a246a
DIFF: 
https://github.com/llvm/llvm-project/commit/a86f4ee774e6d2eb9f38502ddda65842179a246a.diff

LOG: [lldb] Use correct path for debugserver (#131609)

This solves an issue that arises when running lldb-server through a
symlink which is not named exactly `lldb-server`. For example, in many
distros lldb-server is packaged as e.g.
`/usr/lib/llvm-19/bin/lldb-server` which is then accessed through a
symlink such as `/usr/bin/lldb-server-19`.

It turns out that there is a cascade of bugs here:
* `GetShlibDir` attempts to locate the LLVM library directory by calling
`GetModuleFileSpecForHostAddress` on the address of the function
`ComputeSharedLibraryDirectory`, assuming that it is inside
`liblldb.so`. However, in every packaging I've seen of lldb-server the
function `ComputeSharedLibraryDirectory` is statically linked into the
`lldb-server` binary and is not in `liblldb.so`.
* When run through a symlink, `GetModuleFileSpecForHostAddress` on an
address that is in `lldb-server` returns the path of the symlink, not
the path of the binary itself. So we get e.g. `/usr/bin/` and not
`/usr/lib/llvm-19/bin/`.
* `GetDebugserverPath` attempts to concat `"lldb-server"` to the
directory we obtained, and thus fails when the symlink is not named
exactly `lldb-server`.
* Ironically, the reason that this works in the first place is precisely
because `GetModuleFileSpecForHostAddress` returns an incorrect path -
when the server is run as `lldb-server-19 ...` it returns
`"lldb-server-19"` which then causes `ComputePathRelativeToLibrary` to
fail and then `ComputeSupportExeDirectory` falls back to just using
`GetProgramFileSpec` instead (which is the only option that actually
yields a correct path).

Added: 
    

Modified: 
    
lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
    lldb/tools/lldb-server/SystemInitializerLLGS.h

Removed: 
    


################################################################################
diff  --git 
a/lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
 
b/lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
index c365bc993e338..ea846149e4983 100644
--- 
a/lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
+++ 
b/lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
@@ -58,3 +58,42 @@ def test_platform_process_launch_gdb_server(self):
 
         self.runCmd("target create {}".format(self.getBuildArtifact("a.out")))
         self.expect("run", substrs=["unable to launch a GDB server on"], 
error=True)
+
+    @skipIfRemote
+    @skipUnlessPlatform(["linux"])
+    @add_test_categories(["lldb-server"])
+    def test_lldb_server_weird_symlinks(self):
+        self.build()
+
+        hostname = socket.getaddrinfo("localhost", 0, 
proto=socket.IPPROTO_TCP)[0][4][0]
+        listen_url = "[%s]:0" % hostname
+
+        port_file = self.getBuildArtifact("port")
+        commandline_args = [
+            "platform",
+            "--listen",
+            listen_url,
+            "--socket-file",
+            port_file,
+        ]
+
+        # Run lldb-server from a symlink without any binary called 
"lldb-server" in the directory.
+        new_lldb_server = self.getBuildArtifact(
+            "lldb-server-with-an-unconventional-name"
+        )
+        os.symlink(lldbgdbserverutils.get_lldb_server_exe(), new_lldb_server)
+
+        proc = self.spawnSubprocess(new_lldb_server, commandline_args)
+        socket_id = lldbutil.wait_for_file_on_target(self, port_file)
+
+        new_platform = lldb.SBPlatform("remote-" + self.getPlatform())
+        self.dbg.SetSelectedPlatform(new_platform)
+
+        connect_url = "connect://[%s]:%s" % (hostname, socket_id)
+        self.runCmd("platform connect %s" % connect_url)
+        self.runCmd("target create {}".format(self.getBuildArtifact("a.out")))
+        self.runCmd("run")
+        self.expect(
+            "process status",
+            patterns=["Process .* exited with status = 0"],
+        )

diff  --git a/lldb/tools/lldb-server/SystemInitializerLLGS.h 
b/lldb/tools/lldb-server/SystemInitializerLLGS.h
index 4469a8ba5f60a..c6020b0dd37da 100644
--- a/lldb/tools/lldb-server/SystemInitializerLLGS.h
+++ b/lldb/tools/lldb-server/SystemInitializerLLGS.h
@@ -11,10 +11,17 @@
 
 #include "lldb/Initialization/SystemInitializer.h"
 #include "lldb/Initialization/SystemInitializerCommon.h"
+#include "lldb/Utility/FileSpec.h"
 
 class SystemInitializerLLGS : public lldb_private::SystemInitializerCommon {
 public:
-  SystemInitializerLLGS() : SystemInitializerCommon(nullptr) {}
+  SystemInitializerLLGS()
+      : SystemInitializerCommon(
+            // Finding the shared libraries directory on lldb-server is broken
+            // since lldb-server isn't dynamically linked with liblldb.so.
+            // Clearing the filespec here causes GetShlibDir to fail and
+            // GetSupportExeDir to fall-back to using the binary path instead.
+            [](lldb_private::FileSpec &file) { file.Clear(); }) {}
 
   llvm::Error Initialize() override;
   void Terminate() override;


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to