Author: David Spickett
Date: 2026-07-21T09:02:51+01:00
New Revision: ba9d799b1bf2433bf960a08ff995497f5b6d2feb

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

LOG: [lldb][test] Add test for qSymbol handling when using an ELF (#200411)

qSymbol is sent to the debug server every time libraries are loaded. It
can respond to this with symbols it wants to know the value for. It's
rarely used so I expect that's why we had zero test coverage for it.

In this commit I'm adding a test case, derived from the bug being
reported in #200134. The mock debug server has a list of symbols to ask
for and records the results. After LLDB has connected we check with the
mock that it got all the answers it wanted. Right now, 2 of the symbols
don't have values, but should according to the author of the bug report.
One symbol is intentionally missing to check that LLDB handles that
situation properly, even when the others have been fixed.

While I was doing this I realised the documentaiton for an unknown
symbol response was wrong. You can cross check this with GDB's:
https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html#General-Query-Packets

In theory we should test the MachO behaviour too. However I was not able
to create a MachO example that did not end up using a host AArch64 Linux
binary that it found via. PID, while also getting far enough to send
qSymbol. Every workaround broke one of those 2 things. ELF testing is
better than the nothing we currently have.

Assisted by: ChatGPT 5.5

Added: 
    lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
    lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml

Modified: 
    lldb/docs/resources/lldbgdbremote.md

Removed: 
    


################################################################################
diff  --git a/lldb/docs/resources/lldbgdbremote.md 
b/lldb/docs/resources/lldbgdbremote.md
index e487261ea4a54..93090c19c5ec0 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -2132,10 +2132,10 @@ symbol:
 read packet: qSymbol:6578616D706C65
 ```
 
-This should be looked up by LLDB then sent back to the server. Include the name
-again, with the vaue as a hex number:
+This should be looked up by LLDB then sent back to the server. Include the 
value
+as a hex number, then the name of the symbol:
 ```
-read packet: qSymbol:6578616D706C65:CAFEF00D
+read packet: qSymbol:CAFEF00D:6578616D706C65
 ```
 
 If LLDB cannot find the value, it should respond with only the name. Note that

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py 
b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
new file mode 100644
index 0000000000000..eac176b3809d7
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestQSymbol.py
@@ -0,0 +1,84 @@
+"""
+Test LLDB's handling of qSymbol sequences.
+"""
+
+from textwrap import dedent
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+from lldbsuite.support.seven import hexlify, unhexlify
+
+
+class MyResponder(MockGDBServerResponder):
+    def __init__(self, test_obj):
+        super().__init__()
+        self.wanted_symbols = [
+            "main",
+            "local_address",
+            "global_value",
+            "local_value",
+            "not_a_symbol",
+        ]
+        self.last_symbol_request = None
+        self.symbol_results = {}
+        self.test_obj = test_obj
+
+    def qSymbol(self, args):
+        # args will be <name hex encoded>:<hex value>.
+        # In the initial packet both fields are empty.
+        if args == ":":
+            self.test_obj.assertIsNone(self.last_symbol_request)
+        else:
+            # Anything else should be a response to our previous request.
+            value, name = args.split(":")
+            name = unhexlify(name)
+            self.test_obj.assertEqual(name, self.last_symbol_request)
+
+            if value:
+                self.symbol_results[name] = int(value, 16)
+
+        if self.wanted_symbols:
+            want = self.wanted_symbols.pop(0)
+            self.last_symbol_request = want
+            self.symbol_results[want] = None
+
+            return "qSymbol:" + hexlify(want)
+
+        # "OK" ends the qSymbol sequence.
+        return "OK"
+
+
+class TestQSymbol(GDBRemoteTestBase):
+    @skipIfRemote
+    @skipIfLLVMTargetMissing("AArch64")
+    def test_qsymbol(self):
+        target = self.createTarget("test_qsymbol.yaml")
+        self.server.responder = MyResponder(self)
+
+        if self.TraceOn():
+            self.runCmd("log enable gdb-remote packets")
+            self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote 
packets"))
+
+        # LLDB will send a qSymbol shortly after connecting, which starts the 
sequence.
+        process = self.connect(target)
+        lldbutil.expect_state_changes(
+            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
+        )
+
+        # LLDB should have responded in some way to all the qSymbol requests.
+        self.assertFalse(self.server.responder.wanted_symbols)
+
+        expected_results = dict(
+            [
+                ("main", 0x1000),
+                ("local_address", 0x1004),
+                # FIXME: Should return a value.
+                ("global_value", None),
+                # FIXME: Should return a value.
+                ("local_value", None),
+                ("not_a_symbol", None),
+            ]
+        )
+        self.assertEqual(expected_results, 
self.server.responder.symbol_results)

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml 
b/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml
new file mode 100644
index 0000000000000..10a2cb99ea27f
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/test_qsymbol.yaml
@@ -0,0 +1,33 @@
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_AARCH64
+Sections:
+  - Name:  .text
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address: 0x1000
+    Content: C0035FD6 # ret
+Symbols:
+  - Name: main
+    Type: STT_FUNC
+    Section: .text
+    Value: 0x1000
+    Size: 4
+    Binding: STB_GLOBAL
+  - Name: local_address
+    Type: STT_NOTYPE
+    Section: .text
+    Value: 0x1004
+  - Name: local_value
+    Type: STT_NOTYPE
+    Index: SHN_ABS
+    Value: 0xabcd
+  - Name: global_value
+    Type: STT_NOTYPE
+    Index: SHN_ABS
+    Value: 0x1234
+    Binding: STB_GLOBAL
+...


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to