[nto] Implement TARGET_OBJECT_AUXV.
authorAleksandar Ristovski <aristovski@qnx.com>
Tue, 20 Oct 2015 16:58:47 +0000 (12:58 -0400)
committerAleksandar Ristovski <aristovski@qnx.com>
Tue, 20 Oct 2015 17:02:33 +0000 (13:02 -0400)
Fix 'info auxv' for nto.

gdb/ChangeLog:

* nto-procfs.c (sys/auxv.h): Include.
(procfs_xfer_partial): Implement TARGET_OBJECT_AUXV.
* nto-tdep.c (nto_read_auxv_from_initial_stack): New function.
* nto-tdep.h (nto_read_auxv_from_initial_stack): New declaration.

gdb/ChangeLog
gdb/nto-procfs.c
gdb/nto-tdep.c
gdb/nto-tdep.h

index 1a49176e42af5a0c4f19b2473868539cfbcaf05d..919f81d010bea45d73474297fd1363c9bdcfa554 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-20  Aleksandar Ristovski  <aristovski@qnx.com>
+
+       * nto-procfs.c (sys/auxv.h): Include.
+       (procfs_xfer_partial): Implement TARGET_OBJECT_AUXV.
+       * nto-tdep.c (nto_read_auxv_from_initial_stack): New function.
+       * nto-tdep.h (nto_read_auxv_from_initial_stack): New declaration.
+
 2015-10-20  Aleksandar Ristovski  <aristovski@qnx.com>
 
        * nto-procfs.c (nto_procfs_path): Rename to...
index 264d88b40fd74e883222128a7425e259a41baea0..eb0f7bea154555c36263b50a6eba408cd1debcb0 100644 (file)
@@ -30,6 +30,8 @@
 #include <sys/syspage.h>
 #include <dirent.h>
 #include <sys/netmgr.h>
+#include <sys/auxv.h>
+
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
@@ -885,6 +887,38 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
     {
     case TARGET_OBJECT_MEMORY:
       return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
+    case TARGET_OBJECT_AUXV:
+      if (readbuf != NULL)
+       {
+         int err;
+         CORE_ADDR initial_stack;
+         debug_process_t procinfo;
+         /* For 32-bit architecture, size of auxv_t is 8 bytes.  */
+         const unsigned int sizeof_auxv_t = sizeof (auxv_t);
+         const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
+         int tempread;
+         gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
+
+         if (tempbuf == NULL)
+           return TARGET_XFER_E_IO;
+
+         err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
+                       sizeof procinfo, 0);
+         if (err != EOK)
+           return TARGET_XFER_E_IO;
+
+         initial_stack = procinfo.initial_stack;
+
+         /* procfs is always 'self-hosted', no byte-order manipulation.  */
+         tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
+                                                      sizeof_tempbuf,
+                                                      sizeof (auxv_t));
+         tempread = min (tempread, len) - offset;
+         memcpy (readbuf, tempbuf + offset, tempread);
+         *xfered_len = tempread;
+         return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
+       }
+       /* Fallthru */
     default:
       return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
                                            readbuf, writebuf, offset, len,
index 81ee7fbb77bc33255117421bda78eaacd061195b..62eb88afdb250ac73cd33a7321ed141fae4b233a 100644 (file)
@@ -394,3 +394,86 @@ nto_initialize_signals (void)
   signal_pass_update (SIGPHOTON, 1);
 #endif
 }
+
+/* Read AUXV from initial_stack.  */
+LONGEST
+nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
+                                  LONGEST len, size_t sizeof_auxv_t)
+{
+  gdb_byte targ32[4]; /* For 32 bit target values.  */
+  gdb_byte targ64[8]; /* For 64 bit target values.  */
+  CORE_ADDR data_ofs = 0;
+  ULONGEST anint;
+  LONGEST len_read = 0;
+  gdb_byte *buff;
+  enum bfd_endian byte_order;
+  int ptr_size;
+
+  if (sizeof_auxv_t == 16)
+    ptr_size = 8;
+  else
+    ptr_size = 4;
+
+  /* Skip over argc, argv and envp... Comment from ldd.c:
+
+     The startup frame is set-up so that we have:
+     auxv
+     NULL
+     ...
+     envp2
+     envp1 <----- void *frame + (argc + 2) * sizeof(char *)
+     NULL
+     ...
+     argv2
+     argv1
+     argc  <------ void * frame
+
+     On entry to ldd, frame gives the address of argc on the stack.  */
+  /* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little
+   * endian. So we just read first 4 bytes.  */
+  if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0)
+    return 0;
+
+  byte_order = gdbarch_byte_order (target_gdbarch ());
+
+  anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order);
+
+  /* Size of pointer is assumed to be 4 bytes (32 bit arch.) */
+  data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and
+                                                NULL terminating pointer in
+                                                argv.  */
+
+  /* Now loop over env table:  */
+  anint = 0;
+  while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size)
+         == 0)
+    {
+      if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0)
+       anint = 1; /* Keep looping until non-null entry is found.  */
+      else if (anint)
+       break;
+      data_ofs += ptr_size;
+    }
+  initial_stack += data_ofs;
+
+  memset (readbuf, 0, len);
+  buff = readbuf;
+  while (len_read <= len-sizeof_auxv_t)
+    {
+      if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t)
+         == 0)
+        {
+         /* Both 32 and 64 bit structures have int as the first field.  */
+          const ULONGEST a_type
+           = extract_unsigned_integer (buff, sizeof (targ32), byte_order);
+
+          if (a_type == AT_NULL)
+           break;
+         buff += sizeof_auxv_t;
+         len_read += sizeof_auxv_t;
+        }
+      else
+        break;
+    }
+  return len_read;
+}
index bd85d2a529b55e90ff33148d3b0e0c82665f3238..d029f073ddd9aecb835041cfbac155c6a02bcc15 100644 (file)
@@ -168,4 +168,7 @@ int nto_in_dynsym_resolve_code (CORE_ADDR pc);
 
 char *nto_extra_thread_info (struct target_ops *self, struct thread_info *);
 
+LONGEST nto_read_auxv_from_initial_stack (CORE_ADDR inital_stack,
+                                         gdb_byte *readbuf,
+                                         LONGEST len, size_t sizeof_auxv_t);
 #endif