diff mbox series

[v2] gdbstub: add support to Xfer:auxv:read: packet

Message ID 20200730193932.3654677-1-yuanzi@google.com (mailing list archive)
State New, archived
Headers show
Series [v2] gdbstub: add support to Xfer:auxv:read: packet | expand

Commit Message

Lirong Yuan July 30, 2020, 7:39 p.m. UTC
This allows gdb to access the target’s auxiliary vector,
which can be helpful for telling system libraries important details
about the hardware, operating system, and process.

Signed-off-by: Lirong Yuan <yuanzi@google.com>
---
Changelog since v1:
 - Added a multiarch gdbstub test to verify this is working properly.
---
 gdbstub.c                                     | 54 ++++++++++++++++
 tests/tcg/multiarch/Makefile.target           |  9 ++-
 .../multiarch/gdbstub/test-qxfer-auxv-read.py | 64 +++++++++++++++++++
 3 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py

Comments

Alex Bennée Aug. 3, 2020, 11:26 a.m. UTC | #1
Lirong Yuan <yuanzi@google.com> writes:

> This allows gdb to access the target’s auxiliary vector,
> which can be helpful for telling system libraries important details
> about the hardware, operating system, and process.
>
> Signed-off-by: Lirong Yuan <yuanzi@google.com>

I cleaned up the test a little:

modified   tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
@@ -22,13 +22,9 @@ def report(cond, msg):
 def run_test():
     "Run through the tests one by one"
 
-    cond = True
-    try:
-      gdb.execute("info auxv")
-    except (gdb.error, AttributeError):
-      cond = False
-
-    report(cond, "Display the auxiliary vector of the inferior.")
+    auxv = gdb.execute("info auxv", False, True)
+    report(isinstance(auxv, str), "Fetched auxv from inferior")
+    report(auxv.find("sha1"), "Found test binary name in auxv")
 
 #
 # This runs as the script it sourced (via -x, via run-test.py)


Queued to gdbstub/next, thanks.
Lirong Yuan Aug. 3, 2020, 5:05 p.m. UTC | #2
On Mon, Aug 3, 2020 at 4:27 AM Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Lirong Yuan <yuanzi@google.com> writes:
>
> > This allows gdb to access the target’s auxiliary vector,
> > which can be helpful for telling system libraries important details
> > about the hardware, operating system, and process.
> >
> > Signed-off-by: Lirong Yuan <yuanzi@google.com>
>
> I cleaned up the test a little:
>
> modified   tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
> @@ -22,13 +22,9 @@ def report(cond, msg):
>  def run_test():
>      "Run through the tests one by one"
>
> -    cond = True
> -    try:
> -      gdb.execute("info auxv")
> -    except (gdb.error, AttributeError):
> -      cond = False
> -
> -    report(cond, "Display the auxiliary vector of the inferior.")
> +    auxv = gdb.execute("info auxv", False, True)
> +    report(isinstance(auxv, str), "Fetched auxv from inferior")
> +    report(auxv.find("sha1"), "Found test binary name in auxv")
>
>  #
>  # This runs as the script it sourced (via -x, via run-test.py)
>
>
> Queued to gdbstub/next, thanks.
>
> --
> Alex Bennée

Awesome, thank you Alex for the review and cleanup!

Regards,
Lirong
diff mbox series

Patch

diff --git a/gdbstub.c b/gdbstub.c
index f3a318cd7f..e1e1a2c1e6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2124,6 +2124,12 @@  static void handle_query_supported(GdbCmdContext *gdb_ctx, void *user_ctx)
         g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+");
     }
 
+#ifdef CONFIG_USER_ONLY
+    if (gdbserver_state.c_cpu->opaque) {
+        g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+");
+    }
+#endif
+
     if (gdb_ctx->num_params &&
         strstr(gdb_ctx->params[0].data, "multiprocess+")) {
         gdbserver_state.multiprocess = true;
@@ -2185,6 +2191,46 @@  static void handle_query_xfer_features(GdbCmdContext *gdb_ctx, void *user_ctx)
                       gdbserver_state.str_buf->len, true);
 }
 
+#ifdef CONFIG_USER_ONLY
+static void handle_query_xfer_auxv(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+    TaskState *ts;
+    unsigned long offset, len, saved_auxv, auxv_len;
+    const char *mem;
+
+    if (gdb_ctx->num_params < 2) {
+        put_packet("E22");
+        return;
+    }
+
+    offset = gdb_ctx->params[0].val_ul;
+    len = gdb_ctx->params[1].val_ul;
+    ts = gdbserver_state.c_cpu->opaque;
+    saved_auxv = ts->info->saved_auxv;
+    auxv_len = ts->info->auxv_len;
+    mem = (const char *)(saved_auxv + offset);
+    if (offset > auxv_len) {
+        put_packet("E00");
+        return;
+    }
+
+    if (len > (MAX_PACKET_LENGTH - 5) / 2) {
+        len = (MAX_PACKET_LENGTH - 5) / 2;
+    }
+
+    if (len < auxv_len - offset) {
+        g_string_assign(gdbserver_state.str_buf, "m");
+        memtox(gdbserver_state.str_buf, mem, len);
+    } else {
+        g_string_assign(gdbserver_state.str_buf, "l");
+        memtox(gdbserver_state.str_buf, mem, auxv_len - offset);
+    }
+
+    put_packet_binary(gdbserver_state.str_buf->str,
+                      gdbserver_state.str_buf->len, true);
+}
+#endif
+
 static void handle_query_attached(GdbCmdContext *gdb_ctx, void *user_ctx)
 {
     put_packet(GDB_ATTACHED);
@@ -2290,6 +2336,14 @@  static GdbCmdParseEntry gdb_gen_query_table[] = {
         .cmd_startswith = 1,
         .schema = "s:l,l0"
     },
+#ifdef CONFIG_USER_ONLY
+    {
+        .handler = handle_query_xfer_auxv,
+        .cmd = "Xfer:auxv:read::",
+        .cmd_startswith = 1,
+        .schema = "l,l0"
+    },
+#endif
     {
         .handler = handle_query_attached,
         .cmd = "Attached:",
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target
index cb49cc9ccb..c8cdb1e04d 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -54,7 +54,14 @@  run-gdbstub-sha1: sha1
 		--bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \
 	"basic gdbstub support")
 
-EXTRA_RUNS += run-gdbstub-sha1
+run-gdbstub-qxfer-auxv-read: sha1
+	$(call run-test, $@, $(GDB_SCRIPT) \
+		--gdb $(HAVE_GDB_BIN) \
+		--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
+		--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
+	"basic gdbstub qXfer:auxv:read support")
+
+EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
 endif
 
 
diff --git a/tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py b/tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
new file mode 100644
index 0000000000..88049dd330
--- /dev/null
+++ b/tests/tcg/multiarch/gdbstub/test-qxfer-auxv-read.py
@@ -0,0 +1,64 @@ 
+from __future__ import print_function
+#
+# Test the SVE ZReg reports the right amount of data. It uses the
+from __future__ import print_function
+#
+# Test auxiliary vector is loaded via gdbstub
+#
+# This is launched via tests/guest-debug/run-test.py
+#
+
+import gdb
+import sys
+
+failcount = 0
+
+def report(cond, msg):
+    "Report success/fail of test"
+    if cond:
+        print ("PASS: %s" % (msg))
+    else:
+        print ("FAIL: %s" % (msg))
+        global failcount
+        failcount += 1
+
+def run_test():
+    "Run through the tests one by one"
+
+    cond = True
+    try:
+      gdb.execute("info auxv")
+    except (gdb.error, AttributeError):
+      cond = False
+
+    report(cond, "Display the auxiliary vector of the inferior.")
+
+#
+# This runs as the script it sourced (via -x, via run-test.py)
+#
+try:
+    inferior = gdb.selected_inferior()
+    arch = inferior.architecture()
+    print("ATTACHED: %s" % arch.name())
+except (gdb.error, AttributeError):
+    print("SKIPPING (not connected)", file=sys.stderr)
+    exit(0)
+
+if gdb.parse_and_eval('$pc') == 0:
+    print("SKIP: PC not set")
+    exit(0)
+
+try:
+    # These are not very useful in scripts
+    gdb.execute("set pagination off")
+    gdb.execute("set confirm off")
+
+    # Run the actual tests
+    run_test()
+except (gdb.error):
+    print ("GDB Exception: %s" % (sys.exc_info()[0]))
+    failcount += 1
+    pass
+
+print("All tests complete: %d failures" % failcount)
+exit(failcount)