gdb: make extract_integer take an array_view
authorSimon Marchi <simon.marchi@polymtl.ca>
Tue, 26 Oct 2021 03:29:34 +0000 (23:29 -0400)
committerSimon Marchi <simon.marchi@polymtl.ca>
Fri, 3 Dec 2021 21:41:38 +0000 (16:41 -0500)
I think it would make sense for extract_integer, extract_signed_integer
and extract_unsigned_integer to take an array_view.  This way, when we
extract an integer, we can validate that we don't overflow the buffer
passed by the caller (e.g. ask to extract a 4-byte integer but pass a
2-byte buffer).

 - Change extract_integer to take an array_view
 - Add overloads of extract_signed_integer and extract_unsigned_integer
   that take array_views.  Keep the existing versions so we don't
   need to change all callers, but make them call the array_view
   versions.

This shortens some places like:

  result = extract_unsigned_integer (value_contents (result_val).data (),
     TYPE_LENGTH (value_type (result_val)),
     byte_order);

into

  result = extract_unsigned_integer (value_contents (result_val), byte_order);

value_contents returns an array view that is of length
`TYPE_LENGTH (value_type (result_val))` already, so the length is
implicitly communicated through the array view.

Change-Id: Ic1c1f98c88d5c17a8486393af316f982604d6c95

14 files changed:
gdb/amd64-linux-tdep.c
gdb/defs.h
gdb/dwarf2/expr.c
gdb/fbsd-tdep.c
gdb/findvar.c
gdb/frame.c
gdb/frv-tdep.c
gdb/hppa-bsd-tdep.c
gdb/hppa-linux-tdep.c
gdb/i386-linux-tdep.c
gdb/ia64-tdep.c
gdb/regcache.c
gdb/unittests/gmp-utils-selftests.c
gdb/valops.c

index 817a197ceaaef81e1a8b74e213350b2097213533..3fe3d3949328b8d94d189ed552644eae0c796db3 100644 (file)
@@ -237,7 +237,7 @@ amd64_linux_get_syscall_number (struct gdbarch *gdbarch,
      is stored at %rax register.  */
   regcache->cooked_read (AMD64_LINUX_ORIG_RAX_REGNUM, buf);
 
-  ret = extract_signed_integer (buf, 8, byte_order);
+  ret = extract_signed_integer (buf, byte_order);
 
   return ret;
 }
index f7e09eca9db18a154d9c67e1dd299037230130dc..3b6a0e63905e0f3585403edcfa2d0fb8371c2ea3 100644 (file)
@@ -63,6 +63,7 @@
 
 #include "gdbsupport/host-defs.h"
 #include "gdbsupport/enum-flags.h"
+#include "gdbsupport/array-view.h"
 
 /* Scope types enumerator.  List the types of scopes the compiler will
    accept.  */
@@ -500,20 +501,36 @@ enum symbol_needs_kind
 /* In findvar.c.  */
 
 template<typename T, typename = RequireLongest<T>>
-T extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order);
+T extract_integer (gdb::array_view<const gdb_byte>, enum bfd_endian byte_order);
+
+static inline LONGEST
+extract_signed_integer (gdb::array_view<const gdb_byte> buf,
+                       enum bfd_endian byte_order)
+{
+  return extract_integer<LONGEST> (buf, byte_order);
+}
 
 static inline LONGEST
 extract_signed_integer (const gdb_byte *addr, int len,
                        enum bfd_endian byte_order)
 {
-  return extract_integer<LONGEST> (addr, len, byte_order);
+  return extract_signed_integer (gdb::array_view<const gdb_byte> (addr, len),
+                                byte_order);
+}
+
+static inline ULONGEST
+extract_unsigned_integer (gdb::array_view<const gdb_byte> buf,
+                         enum bfd_endian byte_order)
+{
+  return extract_integer<ULONGEST> (buf, byte_order);
 }
 
 static inline ULONGEST
 extract_unsigned_integer (const gdb_byte *addr, int len,
                          enum bfd_endian byte_order)
 {
-  return extract_integer<ULONGEST> (addr, len, byte_order);
+  return extract_unsigned_integer (gdb::array_view<const gdb_byte> (addr, len),
+                                  byte_order);
 }
 
 extern int extract_long_unsigned_integer (const gdb_byte *, int,
index 592dbe19d562c9e71597da0af64c3b5c024a5ef9..b267785ef51ae5c3b47520bea7d9f93ea81b118f 100644 (file)
@@ -577,8 +577,7 @@ indirect_pieced_value (value *value)
      encode address spaces and other things in CORE_ADDR.  */
   bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (frame));
   LONGEST byte_offset
-    = extract_signed_integer (value_contents (value).data (),
-                             TYPE_LENGTH (type), byte_order);
+    = extract_signed_integer (value_contents (value), byte_order);
   byte_offset += piece->v.ptr.offset;
 
   return indirect_synthetic_pointer (piece->v.ptr.die_sect_off,
@@ -1157,9 +1156,7 @@ dwarf_expr_context::fetch_address (int n)
   ULONGEST result;
 
   dwarf_require_integral (value_type (result_val));
-  result = extract_unsigned_integer (value_contents (result_val).data (),
-                                    TYPE_LENGTH (value_type (result_val)),
-                                    byte_order);
+  result = extract_unsigned_integer (value_contents (result_val), byte_order);
 
   /* For most architectures, calling extract_unsigned_integer() alone
      is sufficient for extracting an address.  However, some
index 07cd844c818faf9407062232f2b2f23131f3fc5d..4da7798544b95a0c1d1739cd382b18e86adeba91 100644 (file)
@@ -611,7 +611,7 @@ fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
                                 LWPINFO_OFFSET + LWPINFO_PL_FLAGS, 4))
     return -1;
 
-  int pl_flags = extract_signed_integer (buf, 4, gdbarch_byte_order (gdbarch));
+  int pl_flags = extract_signed_integer (buf, gdbarch_byte_order (gdbarch));
   if (!(pl_flags & PL_FLAG_SI))
     return -1;
 
@@ -1933,7 +1933,7 @@ fbsd_read_integer_by_name (struct gdbarch *gdbarch, const char *name)
   if (target_read_memory (BMSYMBOL_VALUE_ADDRESS (ms), buf, sizeof buf) != 0)
     error (_("Unable to read value of '%s'"), name);
 
-  return extract_signed_integer (buf, sizeof buf, gdbarch_byte_order (gdbarch));
+  return extract_signed_integer (buf, gdbarch_byte_order (gdbarch));
 }
 
 /* Lookup offsets of fields in the runtime linker's 'Obj_Entry'
@@ -2004,7 +2004,7 @@ fbsd_get_tls_index (struct gdbarch *gdbarch, CORE_ADDR lm_addr)
     throw_error (TLS_GENERIC_ERROR,
                 _("Cannot find thread-local variables on this target"));
 
-  return extract_signed_integer (buf, sizeof buf, gdbarch_byte_order (gdbarch));
+  return extract_signed_integer (buf, gdbarch_byte_order (gdbarch));
 }
 
 /* See fbsd-tdep.h.  */
index f7e632809d07d881ed145c94d3ce732039fd18da..a0031d2dadd95e12480608c3f5d0793af1bbef11 100644 (file)
@@ -48,14 +48,11 @@ you lose
 
 template<typename T, typename>
 T
-extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order)
+extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order)
 {
   typename std::make_unsigned<T>::type retval = 0;
-  const unsigned char *p;
-  const unsigned char *startaddr = addr;
-  const unsigned char *endaddr = startaddr + len;
 
-  if (len > (int) sizeof (T))
+  if (buf.size () > (int) sizeof (T))
     error (_("\
 That operation is not available on integers of more than %d bytes."),
           (int) sizeof (T));
@@ -64,36 +61,38 @@ That operation is not available on integers of more than %d bytes."),
      the least significant.  */
   if (byte_order == BFD_ENDIAN_BIG)
     {
-      p = startaddr;
+      size_t i = 0;
+
       if (std::is_signed<T>::value)
        {
          /* Do the sign extension once at the start.  */
-         retval = ((LONGEST) * p ^ 0x80) - 0x80;
-         ++p;
+         retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+         ++i;
        }
-      for (; p < endaddr; ++p)
-       retval = (retval << 8) | *p;
+      for (; i < buf.size (); ++i)
+       retval = (retval << 8) | buf[i];
     }
   else
     {
-      p = endaddr - 1;
+      ssize_t i = buf.size () - 1;
+
       if (std::is_signed<T>::value)
        {
          /* Do the sign extension once at the start.  */
-         retval = ((LONGEST) * p ^ 0x80) - 0x80;
-         --p;
+         retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+         --i;
        }
-      for (; p >= startaddr; --p)
-       retval = (retval << 8) | *p;
+      for (; i >= 0; --i)
+       retval = (retval << 8) | buf[i];
     }
   return retval;
 }
 
 /* Explicit instantiations.  */
-template LONGEST extract_integer<LONGEST> (const gdb_byte *addr, int len,
+template LONGEST extract_integer<LONGEST> (gdb::array_view<const gdb_byte> buf,
                                           enum bfd_endian byte_order);
-template ULONGEST extract_integer<ULONGEST> (const gdb_byte *addr, int len,
-                                            enum bfd_endian byte_order);
+template ULONGEST extract_integer<ULONGEST>
+  (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order);
 
 /* Sometimes a long long unsigned integer can be extracted as a
    LONGEST value.  This is done so that we can print these values
index 2a899fc494f247d895389fc43c3ae5599a7646c9..7944d1edef8d5f1a97f40754ffd939e0313c5763 100644 (file)
@@ -1288,7 +1288,6 @@ frame_unwind_register_signed (frame_info *next_frame, int regnum)
 {
   struct gdbarch *gdbarch = frame_unwind_arch (next_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  int size = register_size (gdbarch, regnum);
   struct value *value = frame_unwind_register_value (next_frame, regnum);
 
   gdb_assert (value != NULL);
@@ -1304,8 +1303,7 @@ frame_unwind_register_signed (frame_info *next_frame, int regnum)
                   _("Register %d is not available"), regnum);
     }
 
-  LONGEST r = extract_signed_integer (value_contents_all (value).data (), size,
-                                     byte_order);
+  LONGEST r = extract_signed_integer (value_contents_all (value), byte_order);
 
   release_value (value);
   return r;
index 09274d54a0e581c0b0f36e2938f6ba7581761050..3e2729f6c9189ea7f1a1b09615b7ae3a93c33aee 100644 (file)
@@ -596,7 +596,7 @@ frv_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
 
       if (target_read_memory (pc, buf, sizeof buf) != 0)
        break;
-      op = extract_signed_integer (buf, sizeof buf, byte_order);
+      op = extract_signed_integer (buf, byte_order);
 
       next_pc = pc + 4;
 
index f4567b48f8263d9d926cdf7a14f98bb6ace68437..9021414a460ec5be57c4ac611fe318dee7c00e12 100644 (file)
@@ -75,7 +75,7 @@ hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function)
              if (target_read_memory (addr, buf, sizeof buf) != 0)
                break;
 
-             tag = extract_signed_integer (buf, sizeof buf, byte_order);
+             tag = extract_signed_integer (buf, byte_order);
              if (tag == DT_PLTGOT)
                {
                  CORE_ADDR pltgot;
index 1dd6993ab09bc0ead35c520982c3b9321d4106c2..6bb8580aa62edf3cbe67a7958ea803d34147b787 100644 (file)
@@ -384,7 +384,7 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch,
              status = target_read_memory (addr, buf, sizeof (buf));
              if (status != 0)
                break;
-             tag = extract_signed_integer (buf, sizeof (buf), byte_order);
+             tag = extract_signed_integer (buf, byte_order);
 
              if (tag == DT_PLTGOT)
                {
index 898b73f632c464895c90d5e09e65d5a2eb6889b3..7c6274589c9b444bb49b69d19231ee4b6bd2339f 100644 (file)
@@ -549,7 +549,7 @@ i386_linux_get_syscall_number_from_regcache (struct regcache *regcache)
      is stored at %eax register.  */
   regcache->cooked_read (I386_LINUX_ORIG_EAX_REGNUM, buf);
 
-  ret = extract_signed_integer (buf, 4, byte_order);
+  ret = extract_signed_integer (buf, byte_order);
 
   return ret;
 }
index 829909dab186cbd694b4fe32bb1f21b29ee9f512..f1af7cb0fec8826512ae8cf0d32a5603aec34841 100644 (file)
@@ -3450,7 +3450,7 @@ ia64_find_global_pointer_from_dynamic_section (struct gdbarch *gdbarch,
              status = target_read_memory (addr, buf, sizeof (buf));
              if (status != 0)
                break;
-             tag = extract_signed_integer (buf, sizeof (buf), byte_order);
+             tag = extract_signed_integer (buf, byte_order);
 
              if (tag == DT_PLTGOT)
                {
@@ -3531,7 +3531,7 @@ find_extant_func_descr (struct gdbarch *gdbarch, CORE_ADDR faddr)
              status = target_read_memory (addr, buf, sizeof (buf));
              if (status != 0)
                break;
-             faddr2 = extract_signed_integer (buf, sizeof (buf), byte_order);
+             faddr2 = extract_signed_integer (buf, byte_order);
 
              if (faddr == faddr2)
                return addr;
index 8457284c12a1483bbbe797a93e44f120a90250d6..b3ecba2fbe62231775a46bae1c185c9eace74de3 100644 (file)
@@ -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;
@@ -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;
index f40666e4cd5688d3dc52e2951b0a25f5a4008377..e48bb39166e7d9da985e9822bcc82fc3a61dd789 100644 (file)
@@ -299,7 +299,7 @@ write_and_extract (T val, size_t buf_len, enum bfd_endian byte_order)
   gdb_byte *buf = (gdb_byte *) alloca (buf_len);
   v.write ({buf, buf_len}, byte_order, !std::is_signed<T>::value);
 
-  return extract_integer<T> (buf, buf_len, byte_order);
+  return extract_integer<T> ({buf, buf_len}, byte_order);
 }
 
 /* Test the gdb_mpz::write method over a reasonable range of values.
index ca71c128de9cf471482381fbfe40033eacd1e528..779ca93edd7df016cf9e93c09e1e74e485713b35 100644 (file)
@@ -587,8 +587,7 @@ value_cast (struct type *type, struct value *arg2)
         bits.  */
       if (code2 == TYPE_CODE_PTR)
        longest = extract_unsigned_integer
-                   (value_contents (arg2).data (), TYPE_LENGTH (type2),
-                    type_byte_order (type2));
+                   (value_contents (arg2), type_byte_order (type2));
       else
        longest = value_as_long (arg2);
       return value_from_longest (to_type, convert_to_boolean ?