Skip to contentSkip to conversation

gdbstub: Support AUXV packet for debugging PIE executables.

PATCH In review Wei-cheng, Wang 2 participants 3 messages Nov 23, 2014 – Dec 25, 2014

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 gdbstub: Support AUXV packet for debugging PIE executables.

Hi,

This patch adds support for sending AUXV packet.
This is required for debugging Linux position independent executables. Otherwise, gdb client cannot find out where the executable is loaded.

---
 gdbstub.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
gdbstub.c +41 -0
index d1b5afd..30f3bbc 100644
@@ -1127,6 +1127,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             if (cc->gdb_core_xml_file != NULL) {
                 pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
             }
+            pstrcat(buf, sizeof(buf), ";qXfer:auxv:read+");
             put_packet(s, buf);
             break;
         }
@@ -1173,6 +1174,46 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             put_packet_binary(s, buf, len + 1);
             break;
         }
+#ifdef CONFIG_USER_ONLY
+        if (strncmp(p, "Xfer:auxv:read:", 15) == 0) {
+            TaskState *ts = s->c_cpu->opaque;
+            target_ulong auxv = ts->info->saved_auxv;
+            target_ulong auxv_len = ts->info->auxv_len;
+            char *ptr;
+
+            p += 15;
+            while (*p && *p != ':')
+                p++;
+            p++;
+
+            addr = strtoul(p, (char **)&p, 16);
+            if (*p == ',')
+                p++;
+            len = strtoul(p, (char **)&p, 16);
+
+            ptr = lock_user(VERIFY_READ, auxv, auxv_len, 0);
+            if (ptr == NULL) {
+                break;
+            }
+
+            if (addr > len) {
+                snprintf(buf, sizeof(buf), "E00");
+                put_packet(s, buf);
+                break;
+            }
+            if (len > (MAX_PACKET_LENGTH - 5) / 2)
+                len = (MAX_PACKET_LENGTH - 5) / 2;
+            if (len < auxv_len - addr) {
+                buf[0] = 'm';
+                len = memtox(buf + 1, ptr + addr, len);
+            } else {
+                buf[0] = 'l';
+                len = memtox(buf + 1, ptr + addr, auxv_len - addr);
+            }
+            put_packet_binary(s, buf, len + 1);
+            unlock_user(ptr, auxv, len);
+        }
+#endif /* !CONFIG_USER_ONLY */
         /* Unrecognised 'q' command.  */
         goto unknown_command;
 
Signature · 1 line
1.9.1
#1 lore raw

CCing Riku Voipio for a review.

Paolo

Quoted 72 lines · Wang

Hi,

This patch adds support for sending AUXV packet.
This is required for debugging Linux position independent executables. Otherwise, gdb client cannot find out where the executable is loaded.

---
 gdbstub.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
gdbstub.c +1 -0
index d1b5afd..30f3bbc 100644
@@ -1127,6 +1127,7 @@ static int gdb_handle_packet(GDBState *s, const
 char *line_buf)
             if (cc->gdb_core_xml_file != NULL) {
                 pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
             }
+            pstrcat(buf, sizeof(buf), ";qXfer:auxv:read+");
             put_packet(s, buf);
             break;
         }
gdbstub.c +40 -0
@@ -1173,6 +1174,46 @@ static int gdb_handle_packet(GDBState *s, const
 char *line_buf)
             put_packet_binary(s, buf, len + 1);
             break;
         }
+#ifdef CONFIG_USER_ONLY
+        if (strncmp(p, "Xfer:auxv:read:", 15) == 0) {
+            TaskState *ts = s->c_cpu->opaque;
+            target_ulong auxv = ts->info->saved_auxv;
+            target_ulong auxv_len = ts->info->auxv_len;
+            char *ptr;
+
+            p += 15;
+            while (*p && *p != ':')
+                p++;
+            p++;
+
+            addr = strtoul(p, (char **)&p, 16);
+            if (*p == ',')
+                p++;
+            len = strtoul(p, (char **)&p, 16);
+
+            ptr = lock_user(VERIFY_READ, auxv, auxv_len, 0);
+            if (ptr == NULL) {
+                break;
+            }
+
+            if (addr > len) {
+                snprintf(buf, sizeof(buf), "E00");
+                put_packet(s, buf);
+                break;
+            }
+            if (len > (MAX_PACKET_LENGTH - 5) / 2)
+                len = (MAX_PACKET_LENGTH - 5) / 2;
+            if (len < auxv_len - addr) {
+                buf[0] = 'm';
+                len = memtox(buf + 1, ptr + addr, len);
+            } else {
+                buf[0] = 'l';
+                len = memtox(buf + 1, ptr + addr, auxv_len - addr);
+            }
+            put_packet_binary(s, buf, len + 1);
+            unlock_user(ptr, auxv, len);
+        }
+#endif /* !CONFIG_USER_ONLY */
         /* Unrecognised 'q' command.  */
         goto unknown_command;
#2 lore raw

Ping :)

Thanks,
Wei-cheng

Quoted 77 lines · Paolo Bonzini

CCing Riku Voipio for a review.

Paolo

Quoted 72 lines · Wang

Hi,

This patch adds support for sending AUXV packet.
This is required for debugging Linux position independent executables. Otherwise, gdb client cannot find out where the executable is loaded.

---
  gdbstub.c | 41 +++++++++++++++++++++++++++++++++++++++++
  1 file changed, 41 insertions(+)
gdbstub.c +1 -0
index d1b5afd..30f3bbc 100644
@@ -1127,6 +1127,7 @@ static int gdb_handle_packet(GDBState *s, const
 char *line_buf)
              if (cc->gdb_core_xml_file != NULL) {
                  pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
              }
+            pstrcat(buf, sizeof(buf), ";qXfer:auxv:read+");
              put_packet(s, buf);
              break;
          }
gdbstub.c +40 -0
@@ -1173,6 +1174,46 @@ static int gdb_handle_packet(GDBState *s, const
 char *line_buf)
              put_packet_binary(s, buf, len + 1);
              break;
          }
+#ifdef CONFIG_USER_ONLY
+        if (strncmp(p, "Xfer:auxv:read:", 15) == 0) {
+            TaskState *ts = s->c_cpu->opaque;
+            target_ulong auxv = ts->info->saved_auxv;
+            target_ulong auxv_len = ts->info->auxv_len;
+            char *ptr;
+
+            p += 15;
+            while (*p && *p != ':')
+                p++;
+            p++;
+
+            addr = strtoul(p, (char **)&p, 16);
+            if (*p == ',')
+                p++;
+            len = strtoul(p, (char **)&p, 16);
+
+            ptr = lock_user(VERIFY_READ, auxv, auxv_len, 0);
+            if (ptr == NULL) {
+                break;
+            }
+
+            if (addr > len) {
+                snprintf(buf, sizeof(buf), "E00");
+                put_packet(s, buf);
+                break;
+            }
+            if (len > (MAX_PACKET_LENGTH - 5) / 2)
+                len = (MAX_PACKET_LENGTH - 5) / 2;
+            if (len < auxv_len - addr) {
+                buf[0] = 'm';
+                len = memtox(buf + 1, ptr + addr, len);
+            } else {
+                buf[0] = 'l';
+                len = memtox(buf + 1, ptr + addr, auxv_len - addr);
+            }
+            put_packet_binary(s, buf, len + 1);
+            unlock_user(ptr, auxv, len);
+        }
+#endif /* !CONFIG_USER_ONLY */
          /* Unrecognised 'q' command.  */
          goto unknown_command;