do_target_wait_1: Clear TARGET_WNOHANG if the target isn't async.
[binutils-gdb.git] / gdb / auxv.c
index 5e0ff26ab1a9ce32a05d06d09067b842b2e87511..36ef51f3aed2d3394aadef2eaa65b643ad292fae 100644 (file)
@@ -1,6 +1,6 @@
 /* Auxiliary vector support for GDB, the GNU debugger.
 
-   Copyright (C) 2004-2019 Free Software Foundation, Inc.
+   Copyright (C) 2004-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,7 +25,7 @@
 #include "valprint.h"
 #include "gdbcore.h"
 #include "observable.h"
-#include "common/filestuff.h"
+#include "gdbsupport/filestuff.h"
 #include "objfiles.h"
 
 #include "auxv.h"
@@ -46,23 +46,21 @@ procfs_xfer_auxv (gdb_byte *readbuf,
                  ULONGEST len,
                  ULONGEST *xfered_len)
 {
-  int fd;
   ssize_t l;
 
   std::string pathname = string_printf ("/proc/%d/auxv", inferior_ptid.pid ());
-  fd = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
-  if (fd < 0)
+  scoped_fd fd
+    = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
+  if (fd.get () < 0)
     return TARGET_XFER_E_IO;
 
   if (offset != (ULONGEST) 0
-      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+      && lseek (fd.get (), (off_t) offset, SEEK_SET) != (off_t) offset)
     l = -1;
   else if (readbuf != NULL)
-    l = read (fd, readbuf, (size_t) len);
+    l = read (fd.get (), readbuf, (size_t) len);
   else
-    l = write (fd, writebuf, (size_t) len);
-
-  (void) close (fd);
+    l = write (fd.get (), writebuf, (size_t) len);
 
   if (l < 0)
     return TARGET_XFER_E_IO;
@@ -192,8 +190,8 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
       len -= block;
 
       /* Check terminal AT_NULL.  This function is being called
-         indefinitely being extended its READBUF until it returns EOF
-         (0).  */
+        indefinitely being extended its READBUF until it returns EOF
+        (0).  */
 
       while (block >= auxv_pair_size)
        {
@@ -248,34 +246,65 @@ memory_xfer_auxv (struct target_ops *ops,
   return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
 }
 
-/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
-   Return 0 if *READPTR is already at the end of the buffer.
-   Return -1 if there is insufficient buffer for a whole entry.
-   Return 1 if an entry was read into *TYPEP and *VALP.  */
-int
-default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
-                  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+/* This function compared to other auxv_parse functions: it takes the size of
+   the auxv type field as a parameter.  */
+
+static int
+generic_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr,
+                   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp,
+                   int sizeof_auxv_type)
 {
-  const int sizeof_auxv_field = gdbarch_ptr_bit (target_gdbarch ())
-                               / TARGET_CHAR_BIT;
-  const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  const int sizeof_auxv_val = TYPE_LENGTH (ptr_type);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte *ptr = *readptr;
 
   if (endptr == ptr)
     return 0;
 
-  if (endptr - ptr < sizeof_auxv_field * 2)
+  if (endptr - ptr < 2 * sizeof_auxv_val)
     return -1;
 
-  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
-  ptr += sizeof_auxv_field;
-  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
-  ptr += sizeof_auxv_field;
+  *typep = extract_unsigned_integer (ptr, sizeof_auxv_type, byte_order);
+  /* Even if the auxv type takes less space than an auxv value, there is
+     padding after the type such that the value is aligned on a multiple of
+     its size (and this is why we advance by `sizeof_auxv_val` and not
+     `sizeof_auxv_type`).  */
+  ptr += sizeof_auxv_val;
+  *valp = extract_unsigned_integer (ptr, sizeof_auxv_val, byte_order);
+  ptr += sizeof_auxv_val;
 
   *readptr = ptr;
   return 1;
 }
 
+/* See auxv.h.  */
+
+int
+default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+                   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  struct gdbarch *gdbarch = target_gdbarch ();
+  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  const int sizeof_auxv_type = TYPE_LENGTH (ptr_type);
+
+  return generic_auxv_parse (gdbarch, readptr, endptr, typep, valp,
+                            sizeof_auxv_type);
+}
+
+/* See auxv.h.  */
+
+int
+svr4_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr,
+                gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  struct type *int_type = builtin_type (gdbarch)->builtin_int;
+  const int sizeof_auxv_type = TYPE_LENGTH (int_type);
+
+  return generic_auxv_parse (gdbarch, readptr, endptr, typep, valp,
+                            sizeof_auxv_type);
+}
+
 /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
    Return 0 if *READPTR is already at the end of the buffer.
    Return -1 if there is insufficient buffer for a whole entry.
@@ -289,7 +318,8 @@ target_auxv_parse (gdb_byte **readptr,
   if (gdbarch_auxv_parse_p (gdbarch))
     return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
 
-  return current_top_target ()->auxv_parse (readptr, endptr, typep, valp);
+  return current_inferior ()->top_target ()->auxv_parse (readptr, endptr,
+                                                        typep, valp);
 }
 
 
@@ -458,9 +488,21 @@ default_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
           AUXV_FORMAT_HEX);
       TAG (AT_L1I_CACHESHAPE, _("L1 Instruction cache information"),
           AUXV_FORMAT_HEX);
+      TAG (AT_L1I_CACHESIZE, _("L1 Instruction cache size"), AUXV_FORMAT_HEX);
+      TAG (AT_L1I_CACHEGEOMETRY, _("L1 Instruction cache geometry"),
+          AUXV_FORMAT_HEX);
       TAG (AT_L1D_CACHESHAPE, _("L1 Data cache information"), AUXV_FORMAT_HEX);
+      TAG (AT_L1D_CACHESIZE, _("L1 Data cache size"), AUXV_FORMAT_HEX);
+      TAG (AT_L1D_CACHEGEOMETRY, _("L1 Data cache geometry"),
+          AUXV_FORMAT_HEX);
       TAG (AT_L2_CACHESHAPE, _("L2 cache information"), AUXV_FORMAT_HEX);
+      TAG (AT_L2_CACHESIZE, _("L2 cache size"), AUXV_FORMAT_HEX);
+      TAG (AT_L2_CACHEGEOMETRY, _("L2 cache geometry"), AUXV_FORMAT_HEX);
       TAG (AT_L3_CACHESHAPE, _("L3 cache information"), AUXV_FORMAT_HEX);
+      TAG (AT_L3_CACHESIZE, _("L3 cache size"), AUXV_FORMAT_HEX);
+      TAG (AT_L3_CACHEGEOMETRY, _("L3 cache geometry"), AUXV_FORMAT_HEX);
+      TAG (AT_MINSIGSTKSZ, _("Minimum stack size for signal delivery"),
+          AUXV_FORMAT_HEX);
       TAG (AT_SUN_UID, _("Effective user ID"), AUXV_FORMAT_DEC);
       TAG (AT_SUN_RUID, _("Real user ID"), AUXV_FORMAT_DEC);
       TAG (AT_SUN_GID, _("Effective group ID"), AUXV_FORMAT_DEC);
@@ -533,11 +575,12 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
 static void
 info_auxv_command (const char *cmd, int from_tty)
 {
-  if (! target_has_stack)
+  if (! target_has_stack ())
     error (_("The program has no auxiliary information now."));
   else
     {
-      int ents = fprint_target_auxv (gdb_stdout, current_top_target ());
+      int ents = fprint_target_auxv (gdb_stdout,
+                                    current_inferior ()->top_target ());
 
       if (ents < 0)
        error (_("No auxiliary vector found, or failed reading it."));
@@ -546,15 +589,16 @@ info_auxv_command (const char *cmd, int from_tty)
     }
 }
 
+void _initialize_auxv ();
 void
-_initialize_auxv (void)
+_initialize_auxv ()
 {
   add_info ("auxv", info_auxv_command,
            _("Display the inferior's auxiliary vector.\n\
 This is information provided by the operating system at program startup."));
 
   /* Observers used to invalidate the auxv cache when needed.  */
-  gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf);
-  gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf);
-  gdb::observers::executable_changed.attach (invalidate_auxv_cache);
+  gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf, "auxv");
+  gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf, "auxv");
+  gdb::observers::executable_changed.attach (invalidate_auxv_cache, "auxv");
 }