Update comments to to_xfer_partial implementations.
[deliverable/binutils-gdb.git] / gdb / auxv.c
index e2aeb214388a636f9a434e873fab158201d77618..2f4acf3da30d2a0c855db61fa8574a98a8ca00f4 100644 (file)
@@ -1,6 +1,6 @@
 /* Auxiliary vector support for GDB, the GNU debugger.
 
-   Copyright (C) 2004-2012 Free Software Foundation, Inc.
+   Copyright (C) 2004-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,6 +26,7 @@
 #include "gdb_assert.h"
 #include "gdbcore.h"
 #include "observer.h"
+#include "filestuff.h"
 
 #include "auxv.h"
 #include "elf/common.h"
 #include <fcntl.h>
 
 
-/* This function handles access via /proc/PID/auxv, which is a common
-   method for native targets.  */
+/* Implement the to_xfer_partial target_ops method.  This function
+   handles access via /proc/PID/auxv, which is a common method for
+   native targets.  */
 
-static LONGEST
+static enum target_xfer_status
 procfs_xfer_auxv (gdb_byte *readbuf,
                  const gdb_byte *writebuf,
                  ULONGEST offset,
-                 LONGEST len)
+                 ULONGEST len,
+                 ULONGEST *xfered_len)
 {
   char *pathname;
   int fd;
-  LONGEST n;
+  ssize_t l;
 
-  pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
-  fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
+  pathname = xstrprintf ("/proc/%d/auxv", ptid_get_pid (inferior_ptid));
+  fd = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
   xfree (pathname);
   if (fd < 0)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   if (offset != (ULONGEST) 0
       && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
-    n = -1;
+    l = -1;
   else if (readbuf != NULL)
-    n = read (fd, readbuf, len);
+    l = read (fd, readbuf, (size_t) len);
   else
-    n = write (fd, writebuf, len);
+    l = write (fd, writebuf, (size_t) len);
 
   (void) close (fd);
 
-  return n;
+  if (l < 0)
+    return TARGET_XFER_E_IO;
+  else if (l == 0)
+    return TARGET_XFER_EOF;
+  else
+    {
+      *xfered_len = (ULONGEST) l;
+      return TARGET_XFER_OK;
+    }
 }
 
 /* This function handles access via ld.so's symbol `_dl_auxv'.  */
 
-static LONGEST
+static enum target_xfer_status
 ld_so_xfer_auxv (gdb_byte *readbuf,
                 const gdb_byte *writebuf,
                 ULONGEST offset,
-                LONGEST len)
+                ULONGEST len, ULONGEST *xfered_len)
 {
   struct minimal_symbol *msym;
   CORE_ADDR data_address, pointer_address;
@@ -85,10 +96,10 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
 
   msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
   if (msym == NULL)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   if (MSYMBOL_SIZE (msym) != ptr_size)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   /* POINTER_ADDRESS is a location where the `_dl_auxv' variable
      resides.  DATA_ADDRESS is the inferior value present in
@@ -117,23 +128,26 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
      11440.  */
 
   if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   data_address = extract_typed_address (ptr_buf, ptr_type);
 
   /* Possibly still not initialized such as during an inferior
      startup.  */
   if (data_address == 0)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   data_address += offset;
 
   if (writebuf != NULL)
     {
       if (target_write_memory (data_address, writebuf, len) == 0)
-       return len;
+       {
+         *xfered_len = (ULONGEST) len;
+         return TARGET_XFER_OK;
+       }
       else
-       return -1;
+       return TARGET_XFER_E_IO;
     }
 
   /* Stop if trying to read past the existing AUXV block.  The final
@@ -143,10 +157,10 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
     {
       if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
                              ptr_size) != 0)
-       return -1;
+       return TARGET_XFER_E_IO;
 
       if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
-       return 0;
+       return TARGET_XFER_EOF;
     }
 
   retval = 0;
@@ -165,12 +179,12 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
 
       block &= -auxv_pair_size;
       if (block == 0)
-       return retval;
+       break;
 
       if (target_read_memory (data_address, readbuf, block) != 0)
        {
          if (block <= auxv_pair_size)
-           return retval;
+           break;
 
          block = auxv_pair_size;
          continue;
@@ -188,27 +202,31 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
          retval += auxv_pair_size;
 
          if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
-           return retval;
+           {
+             *xfered_len = (ULONGEST) retval;
+             return TARGET_XFER_OK;
+           }
 
          readbuf += auxv_pair_size;
          block -= auxv_pair_size;
        }
     }
 
-  return retval;
+  *xfered_len = (ULONGEST) retval;
+  return TARGET_XFER_OK;
 }
 
-/* This function is called like a to_xfer_partial hook, but must be
-   called with TARGET_OBJECT_AUXV.  It handles access to AUXV.  */
+/* Implement the to_xfer_partial target_ops method for
+   TARGET_OBJECT_AUXV.  It handles access to AUXV.  */
 
-LONGEST
+enum target_xfer_status
 memory_xfer_auxv (struct target_ops *ops,
                  enum target_object object,
                  const char *annex,
                  gdb_byte *readbuf,
                  const gdb_byte *writebuf,
                  ULONGEST offset,
-                 LONGEST len)
+                 ULONGEST len, ULONGEST *xfered_len)
 {
   gdb_assert (object == TARGET_OBJECT_AUXV);
   gdb_assert (readbuf || writebuf);
@@ -222,14 +240,14 @@ memory_xfer_auxv (struct target_ops *ops,
 
   if (current_inferior ()->attach_flag != 0)
     {
-      LONGEST retval;
+      enum target_xfer_status ret;
 
-      retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
-      if (retval != -1)
-       return retval;
+      ret = ld_so_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
+      if (ret != TARGET_XFER_E_IO)
+       return ret;
     }
 
-  return procfs_xfer_auxv (readbuf, writebuf, offset, len);
+  return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
 }
 
 /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
@@ -340,7 +358,7 @@ get_auxv_inferior_data (struct target_ops *ops)
   info = inferior_data (inf, auxv_inferior_data);
   if (info == NULL)
     {
-      info = XZALLOC (struct auxv_info);
+      info = XCNEW (struct auxv_info);
       info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV,
                                        NULL, &info->data);
       set_inferior_data (inf, auxv_inferior_data, info);
@@ -441,6 +459,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
          TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
          TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
          TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
+         TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex);
          TAG (AT_EXECFN, _("File name of executable"), str);
          TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
          TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
This page took 0.028905 seconds and 4 git commands to generate.