[llvm-branch-commits] [lldb] [lldb] Resolve dispatch qSymbol requests by exact linkage name (PR #232696)

Karim Alweheshy via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 16 04:59:22 PDT 2026


https://github.com/karim-alweheshy updated https://github.com/llvm/llvm-project/pull/232696

>From 965078e792922f9935e0908f078aed3582b6c5fc Mon Sep 17 00:00:00 2001
From: Karim Alweheshy <karim.alweheshy at reddit.com>
Date: Fri, 16 Oct 2026 12:59:52 +0200
Subject: [PATCH 1/2] [lldb] Resolve dispatch qSymbol requests by exact linkage
 name

Use the opt-in linkage-name lookup for dispatch_queue_offsets while preserving generic matching for other remote requests and existing address and symbol-type handling. Cover C++ basename decoys and an absent dispatch data symbol with the mock server.

Assisted-by: OpenAI Codex
---
 .../GDBRemoteCommunicationClient.cpp          |  8 ++-
 .../gdb_remote_client/TestQSymbol.py          | 61 ++++++++++++++++---
 .../gdb_remote_client/test_qsymbol.yaml       | 25 +++++++-
 3 files changed, 84 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 19b642ed3f65c5..c674641e5bcbac 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -4336,8 +4336,14 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
 
               addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
               lldb_private::SymbolContextList sc_list;
+              // debugserver uses this C ABI data symbol to decode dispatch
+              // queues. C++ basename aliases are not that runtime definition.
+              // Other remote requests retain their usual name matching.
+              const bool match_linkage_names =
+                  symbol_name == "dispatch_queue_offsets";
               process->GetTarget().GetImages().FindSymbolsWithNameAndType(
-                  ConstString(symbol_name), eSymbolTypeAny, sc_list);
+                  ConstString(symbol_name), eSymbolTypeAny, sc_list,
+                  match_linkage_names);
               for (const SymbolContext &sc : sc_list) {
                 if (symbol_load_addr != LLDB_INVALID_ADDRESS)
                   break;
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
index 96d6d83c203304..394c2a80d2b8c7 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
@@ -2,6 +2,7 @@
 Test LLDB's handling of qSymbol sequences.
 """
 
+from pathlib import Path
 from textwrap import dedent
 import lldb
 from lldbsuite.test.lldbtest import *
@@ -12,15 +13,19 @@
 
 
 class MyResponder(MockGDBServerResponder):
-    def __init__(self, test_obj):
+    def __init__(self, test_obj, wanted_symbols=None):
         super().__init__()
-        self.wanted_symbols = [
-            "main",
-            "local_address",
-            "global_value",
-            "local_value",
-            "not_a_symbol",
-        ]
+        self.wanted_symbols = (
+            wanted_symbols
+            if wanted_symbols is not None
+            else [
+                "main",
+                "local_address",
+                "global_value",
+                "local_value",
+                "not_a_symbol",
+            ]
+        )
         self.last_symbol_request = None
         self.symbol_results = {}
         self.test_obj = test_obj
@@ -80,3 +85,43 @@ def test_qsymbol(self):
             ]
         )
         self.assertEqual(expected_results, self.server.responder.symbol_results)
+
+    @skipIfRemote
+    @skipIfLLVMTargetMissing("AArch64")
+    def test_dispatch_symbol_uses_linkage_name(self):
+        self.check_dispatch_symbol(has_dispatch_data=True)
+
+    @skipIfRemote
+    @skipIfLLVMTargetMissing("AArch64")
+    def test_missing_dispatch_symbol_rejects_cpp_basename(self):
+        self.check_dispatch_symbol(has_dispatch_data=False)
+
+    def check_dispatch_symbol(self, has_dispatch_data):
+        self.runCmd("settings set target.preload-symbols false")
+        fixture = Path(self.getSourceDir()) / "test_qsymbol.yaml"
+        if not has_dispatch_data:
+            missing = Path(self.getBuildArtifact("qsymbol-missing.yaml"))
+            missing.write_text(
+                fixture.read_text().replace(
+                    "Name: dispatch_queue_offsets", "Name: unrelated_dispatch_data"
+                )
+            )
+            fixture = missing
+        target = self.createTarget(str(fixture))
+        self.server.responder = MyResponder(
+            self, ["dispatch_queue_offsets", "other_wire_request"]
+        )
+        process = self.connect(target)
+        lldbutil.expect_state_changes(
+            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
+        )
+        self.assertFalse(self.server.responder.wanted_symbols)
+        # The known dispatch ABI must not resolve to the C++ function basename
+        # at 0x1008. Other requests keep their C++ basename lookup behavior.
+        self.assertEqual(
+            self.server.responder.symbol_results,
+            {
+                "dispatch_queue_offsets": 0x2000 if has_dispatch_data else None,
+                "other_wire_request": 0x1009,
+            },
+        )
diff --git a/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml b/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml
index 10a2cb99ea27f8..67b02a3d63e802 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml
+++ b/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml
@@ -9,7 +9,12 @@ Sections:
     Type:  SHT_PROGBITS
     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
     Address: 0x1000
-    Content: C0035FD6 # ret
+    Content: C0035FD6C0035FD6C0035FD6 # ret; ret; ret
+  - Name: .data
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_WRITE ]
+    Address: 0x2000
+    Content: '0000000000000000'
 Symbols:
   - Name: main
     Type: STT_FUNC
@@ -30,4 +35,22 @@ Symbols:
     Index: SHN_ABS
     Value: 0x1234
     Binding: STB_GLOBAL
+  - Name: _Z22dispatch_queue_offsetsv
+    Type: STT_FUNC
+    Section: .text
+    Value: 0x1008
+    Size: 1
+    Binding: STB_GLOBAL
+  - Name: _Z18other_wire_requestv
+    Type: STT_FUNC
+    Section: .text
+    Value: 0x1009
+    Size: 1
+    Binding: STB_GLOBAL
+  - Name: dispatch_queue_offsets
+    Type: STT_OBJECT
+    Section: .data
+    Value: 0x2000
+    Size: 8
+    Binding: STB_GLOBAL
 ...

>From 9c487757b7207271927b43e21a809091f0dd0fd4 Mon Sep 17 00:00:00 2001
From: Karim Alweheshy <karim.alweheshy at reddit.com>
Date: Fri, 16 Oct 2026 13:52:00 +0200
Subject: [PATCH 2/2] [lldb] Keep qSymbol test artifacts in the build directory

Use a relative source fixture path so createTarget does not resolve its output into the source tree.

Assisted-by: OpenAI Codex
---
 .../functionalities/gdb_remote_client/TestQSymbol.py   | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
index 394c2a80d2b8c7..6092dd39081db1 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
@@ -98,16 +98,18 @@ def test_missing_dispatch_symbol_rejects_cpp_basename(self):
 
     def check_dispatch_symbol(self, has_dispatch_data):
         self.runCmd("settings set target.preload-symbols false")
-        fixture = Path(self.getSourceDir()) / "test_qsymbol.yaml"
+        fixture = "test_qsymbol.yaml"
         if not has_dispatch_data:
             missing = Path(self.getBuildArtifact("qsymbol-missing.yaml"))
             missing.write_text(
-                fixture.read_text().replace(
+                (Path(self.getSourceDir()) / fixture)
+                .read_text()
+                .replace(
                     "Name: dispatch_queue_offsets", "Name: unrelated_dispatch_data"
                 )
             )
-            fixture = missing
-        target = self.createTarget(str(fixture))
+            fixture = str(missing)
+        target = self.createTarget(fixture)
         self.server.responder = MyResponder(
             self, ["dispatch_queue_offsets", "other_wire_request"]
         )



More information about the llvm-branch-commits mailing list