ODR warning for "enum string_repr_result"
[binutils-gdb.git] / gdb / regcache.c
index 2d50f3efc85a105bf7274ea2e9e0ff6e1bf84320..037659ef8fae0d916d0d89132ca05fbef12f0440 100644 (file)
@@ -1,6 +1,6 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -620,15 +620,12 @@ template<typename T, typename>
 enum register_status
 readable_regcache::raw_read (int regnum, T *val)
 {
-  gdb_byte *buf;
-  enum register_status status;
-
   assert_regnum (regnum);
-  buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
-  status = raw_read (regnum, buf);
+  size_t len = m_descr->sizeof_register[regnum];
+  gdb_byte *buf = (gdb_byte *) alloca (len);
+  register_status status = raw_read (regnum, buf);
   if (status == REG_VALID)
-    *val = extract_integer<T> (buf,
-                              m_descr->sizeof_register[regnum],
+    *val = extract_integer<T> ({buf, len},
                               gdbarch_byte_order (m_descr->gdbarch));
   else
     *val = 0;
@@ -712,7 +709,7 @@ readable_regcache::cooked_read (int regnum, gdb_byte *buf)
       computed = gdbarch_pseudo_register_read_value (m_descr->gdbarch,
                                                     this, regnum);
       if (value_entirely_available (computed))
-       memcpy (buf, value_contents_raw (computed),
+       memcpy (buf, value_contents_raw (computed).data (),
                m_descr->sizeof_register[regnum]);
       else
        {
@@ -749,7 +746,7 @@ readable_regcache::cooked_read_value (int regnum)
         direction than in the other one, even though the value-based
         API is preferred.  */
       if (cooked_read (regnum,
-                      value_contents_raw (result)) == REG_UNAVAILABLE)
+                      value_contents_raw (result).data ()) == REG_UNAVAILABLE)
        mark_value_bytes_unavailable (result, 0,
                                      TYPE_LENGTH (value_type (result)));
 
@@ -772,14 +769,12 @@ template<typename T, typename>
 enum register_status
 readable_regcache::cooked_read (int regnum, T *val)
 {
-  enum register_status status;
-  gdb_byte *buf;
-
   gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
-  buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
-  status = cooked_read (regnum, buf);
+  size_t len = m_descr->sizeof_register[regnum];
+  gdb_byte *buf = (gdb_byte *) alloca (len);
+  register_status status = cooked_read (regnum, buf);
   if (status == REG_VALID)
-    *val = extract_integer<T> (buf, m_descr->sizeof_register[regnum],
+    *val = extract_integer<T> ({buf, len},
                               gdbarch_byte_order (m_descr->gdbarch));
   else
     *val = 0;
@@ -1169,7 +1164,12 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum,
        memset (out_buf + offs + reg_size, 0, slot_size - reg_size);
     }
   else if (in_buf != nullptr)
-    out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs);
+    {
+      /* Zero-extend the register value if the slot is smaller than the register.  */
+      if (slot_size < register_size (gdbarch, regnum))
+       out_regcache->raw_supply_zeroed (regnum);
+      out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs);
+    }
   else
     {
       /* Invalidate the register.  */
@@ -1264,6 +1264,33 @@ regcache::collect_regset (const struct regset *regset,
   transfer_regset (regset, nullptr, regnum, nullptr, (gdb_byte *) buf, size);
 }
 
+/* See regcache.h  */
+
+bool
+regcache_map_supplies (const struct regcache_map_entry *map, int regnum,
+                      struct gdbarch *gdbarch, size_t size)
+{
+  int offs = 0, count;
+
+  for (; (count = map->count) != 0; map++)
+    {
+      int regno = map->regno;
+      int slot_size = map->size;
+
+      if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
+       slot_size = register_size (gdbarch, regno);
+
+      if (regno != REGCACHE_MAP_SKIP && regnum >= regno
+         && regnum < regno + count)
+       return offs + (regnum - regno + 1) * slot_size <= size;
+
+      offs += count * slot_size;
+      if (offs >= size)
+       return false;
+    }
+  return false;
+}
+
 /* See gdbsupport/common-regcache.h.  */
 
 bool
@@ -1356,34 +1383,34 @@ regcache::debug_print_register (const char *func,  int regno)
 {
   struct gdbarch *gdbarch = arch ();
 
-  fprintf_unfiltered (gdb_stdlog, "%s ", func);
+  gdb_printf (gdb_stdlog, "%s ", func);
   if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
       && gdbarch_register_name (gdbarch, regno) != NULL
       && gdbarch_register_name (gdbarch, regno)[0] != '\0')
-    fprintf_unfiltered (gdb_stdlog, "(%s)",
-                       gdbarch_register_name (gdbarch, regno));
+    gdb_printf (gdb_stdlog, "(%s)",
+               gdbarch_register_name (gdbarch, regno));
   else
-    fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
+    gdb_printf (gdb_stdlog, "(%d)", regno);
   if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
     {
       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
       int size = register_size (gdbarch, regno);
       gdb_byte *buf = register_buffer (regno);
 
-      fprintf_unfiltered (gdb_stdlog, " = ");
+      gdb_printf (gdb_stdlog, " = ");
       for (int i = 0; i < size; i++)
        {
-         fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
+         gdb_printf (gdb_stdlog, "%02x", buf[i]);
        }
       if (size <= sizeof (LONGEST))
        {
          ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
 
-         fprintf_unfiltered (gdb_stdlog, " %s %s",
-                             core_addr_to_string_nz (val), plongest (val));
+         gdb_printf (gdb_stdlog, " %s %s",
+                     core_addr_to_string_nz (val), plongest (val));
        }
     }
-  fprintf_unfiltered (gdb_stdlog, "\n");
+  gdb_printf (gdb_stdlog, "\n");
 }
 
 /* Implement 'maint flush register-cache' command.  */
@@ -1394,7 +1421,7 @@ reg_flush_command (const char *command, int from_tty)
   /* Force-flush the register cache.  */
   registers_changed ();
   if (from_tty)
-    printf_filtered (_("Register cache flushed.\n"));
+    gdb_printf (_("Register cache flushed.\n"));
 }
 
 void
@@ -1414,7 +1441,7 @@ register_dump::dump (ui_file *file)
     {
       /* Name.  */
       if (regnum < 0)
-       fprintf_unfiltered (file, " %-10s", "Name");
+       gdb_printf (file, " %-10s", "Name");
       else
        {
          const char *p = gdbarch_register_name (m_gdbarch, regnum);
@@ -1423,31 +1450,31 @@ register_dump::dump (ui_file *file)
            p = "";
          else if (p[0] == '\0')
            p = "''";
-         fprintf_unfiltered (file, " %-10s", p);
+         gdb_printf (file, " %-10s", p);
        }
 
       /* Number.  */
       if (regnum < 0)
-       fprintf_unfiltered (file, " %4s", "Nr");
+       gdb_printf (file, " %4s", "Nr");
       else
-       fprintf_unfiltered (file, " %4d", regnum);
+       gdb_printf (file, " %4d", regnum);
 
       /* Relative number.  */
       if (regnum < 0)
-       fprintf_unfiltered (file, " %4s", "Rel");
+       gdb_printf (file, " %4s", "Rel");
       else if (regnum < gdbarch_num_regs (m_gdbarch))
-       fprintf_unfiltered (file, " %4d", regnum);
+       gdb_printf (file, " %4d", regnum);
       else
-       fprintf_unfiltered (file, " %4d",
-                           (regnum - gdbarch_num_regs (m_gdbarch)));
+       gdb_printf (file, " %4d",
+                   (regnum - gdbarch_num_regs (m_gdbarch)));
 
       /* Offset.  */
       if (regnum < 0)
-       fprintf_unfiltered (file, " %6s  ", "Offset");
+       gdb_printf (file, " %6s  ", "Offset");
       else
        {
-         fprintf_unfiltered (file, " %6ld",
-                             descr->register_offset[regnum]);
+         gdb_printf (file, " %6ld",
+                     descr->register_offset[regnum]);
          if (register_offset != descr->register_offset[regnum]
              || (regnum > 0
                  && (descr->register_offset[regnum]
@@ -1457,19 +1484,19 @@ register_dump::dump (ui_file *file)
            {
              if (!footnote_register_offset)
                footnote_register_offset = ++footnote_nr;
-             fprintf_unfiltered (file, "*%d", footnote_register_offset);
+             gdb_printf (file, "*%d", footnote_register_offset);
            }
          else
-           fprintf_unfiltered (file, "  ");
+           gdb_printf (file, "  ");
          register_offset = (descr->register_offset[regnum]
                             + descr->sizeof_register[regnum]);
        }
 
       /* Size.  */
       if (regnum < 0)
-       fprintf_unfiltered (file, " %5s ", "Size");
+       gdb_printf (file, " %5s ", "Size");
       else
-       fprintf_unfiltered (file, " %5ld", descr->sizeof_register[regnum]);
+       gdb_printf (file, " %5ld", descr->sizeof_register[regnum]);
 
       /* Type.  */
       {
@@ -1495,24 +1522,24 @@ register_dump::dump (ui_file *file)
            if (startswith (t, blt))
              t += strlen (blt);
          }
-       fprintf_unfiltered (file, " %-15s", t);
+       gdb_printf (file, " %-15s", t);
       }
 
       /* Leading space always present.  */
-      fprintf_unfiltered (file, " ");
+      gdb_printf (file, " ");
 
       dump_reg (file, regnum);
 
-      fprintf_unfiltered (file, "\n");
+      gdb_printf (file, "\n");
     }
 
   if (footnote_register_offset)
-    fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
-                       footnote_register_offset);
+    gdb_printf (file, "*%d: Inconsistent register offsets.\n",
+               footnote_register_offset);
   if (footnote_register_type_name_null)
-    fprintf_unfiltered (file,
-                       "*%d: Register type's name NULL.\n",
-                       footnote_register_type_name_null);
+    gdb_printf (file,
+               "*%d: Register type's name NULL.\n",
+               footnote_register_type_name_null);
 }
 
 #if GDB_SELF_TEST
@@ -1917,30 +1944,9 @@ cooked_read_test (struct gdbarch *gdbarch)
 static void
 cooked_write_test (struct gdbarch *gdbarch)
 {
-  /* Error out if debugging something, because we're going to push the
-     test target, which would pop any existing target.  */
-  if (current_inferior ()->top_target ()->stratum () >= process_stratum)
-    error (_("target already pushed"));
-
   /* Create a mock environment.  A process_stratum target pushed.  */
-
-  target_ops_no_register mock_target;
-
-  /* Push the process_stratum target so we can mock accessing
-     registers.  */
-  current_inferior ()->push_target (&mock_target);
-
-  /* Pop it again on exit (return/exception).  */
-  struct on_exit
-  {
-    ~on_exit ()
-    {
-      pop_all_targets_at_and_above (process_stratum);
-    }
-  } pop_targets;
-
-  readwrite_regcache readwrite (&mock_target, gdbarch);
-
+  scoped_mock_context<target_ops_no_register> ctx (gdbarch);
+  readwrite_regcache readwrite (&ctx.mock_target, gdbarch);
   const int num_regs = gdbarch_num_cooked_regs (gdbarch);
 
   for (auto regnum = 0; regnum < num_regs; regnum++)
@@ -2038,15 +2044,19 @@ regcache_thread_ptid_changed ()
   /* Prepare two targets with one thread each, with the same ptid.  */
   scoped_mock_context<test_target_ops> target1 (arch);
   scoped_mock_context<test_target_ops> target2 (arch);
-  target2.mock_inferior.next = &target1.mock_inferior;
 
   ptid_t old_ptid (111, 222);
   ptid_t new_ptid (111, 333);
 
   target1.mock_inferior.pid = old_ptid.pid ();
   target1.mock_thread.ptid = old_ptid;
+  target1.mock_inferior.ptid_thread_map.clear ();
+  target1.mock_inferior.ptid_thread_map[old_ptid] = &target1.mock_thread;
+
   target2.mock_inferior.pid = old_ptid.pid ();
   target2.mock_thread.ptid = old_ptid;
+  target2.mock_inferior.ptid_thread_map.clear ();
+  target2.mock_inferior.ptid_thread_map[old_ptid] = &target2.mock_thread;
 
   gdb_assert (regcaches.empty ());
 
@@ -2102,13 +2112,13 @@ _initialize_regcache ()
 
 #if GDB_SELF_TEST
   selftests::register_test ("get_thread_arch_aspace_regcache",
-                           selftests::get_thread_arch_aspace_regcache_test);
+                           selftests::get_thread_arch_aspace_regcache_test);
   selftests::register_test ("registers_changed_ptid_all",
                            selftests::registers_changed_ptid_all_test);
   selftests::register_test ("registers_changed_ptid_target",
-                           selftests::registers_changed_ptid_target_test);
+                           selftests::registers_changed_ptid_target_test);
   selftests::register_test ("registers_changed_ptid_target_pid",
-                           selftests::registers_changed_ptid_target_pid_test);
+                           selftests::registers_changed_ptid_target_pid_test);
   selftests::register_test ("registers_changed_ptid_target_ptid",
                            selftests::registers_changed_ptid_target_ptid_test);