[PATCH v4 08/44] gdb: add a new extract_integer variant that takes two array_views

Markus Metzger <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
From: Tankut Baris Aktemur <[email protected]>

Add a new variant of extract integer that takes both the source and
the destination values as array_view parameter.  The existing
templated extract_integer then becomes a wrapper around the new
variant.  The new variant gives flexibility and ease of use in cases
where the destination buffer and length are runtime values.
---
 gdb/extract-store-integer.c | 53 ++++++++++++++++++++++++-------------
 gdb/extract-store-integer.h |  8 ++++++
 2 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/gdb/extract-store-integer.c b/gdb/extract-store-integer.c
index 67e4534a27d..41116d6cd3c 100644
--- a/gdb/extract-store-integer.c
+++ b/gdb/extract-store-integer.c
@@ -20,26 +20,27 @@
 #include "gdbarch.h"
 #include "gdbsupport/selftest.h"
 
-template<typename T, typename>
-T
-extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order)
-{
-  typename std::make_unsigned<T>::type retval = 0;
+/* See extract-store-integer.h.  */
 
-  /* It is ok if BUF is wider than T, but only if the value is
+void
+extract_integer (gdb::array_view<gdb_byte> dst,
+		 gdb::array_view<const gdb_byte> buf,
+		 enum bfd_endian byte_order,
+		 bool is_signed)
+{
+  /* It is ok if BUF is wider than DST, but only if the value is
      representable.  */
   bool bad_repr = false;
-  if (buf.size () > (int) sizeof (T))
+  if (buf.size () > dst.size ())
     {
-      const size_t end = buf.size () - sizeof (T);
+      const size_t end = buf.size () - dst.size ();
       if (byte_order == BFD_ENDIAN_BIG)
 	{
 	  for (size_t i = 0; i < end; ++i)
 	    {
 	      /* High bytes == 0 are always ok, and high bytes == 0xff
 		 are ok when the type is signed.  */
-	      if ((buf[i] == 0
-		   || (std::is_signed<T>::value && buf[i] == 0xff))
+	      if ((buf[i] == 0 || (is_signed && buf[i] == 0xff))
 		  /* All the high bytes must be the same, no
 		     alternating 0 and 0xff.  */
 		  && (i == 0 || buf[i - 1] == buf[i]))
@@ -61,8 +62,7 @@ extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order
 	    {
 	      /* High bytes == 0 are always ok, and high bytes == 0xff
 		 are ok when the type is signed.  */
-	      if ((buf[i] == 0
-		   || (std::is_signed<T>::value && buf[i] == 0xff))
+	      if ((buf[i] == 0 || (is_signed && buf[i] == 0xff))
 		  /* All the high bytes must be the same, no
 		     alternating 0 and 0xff.  */
 		  && (i == bufsz || buf[i] == buf[i + 1]))
@@ -81,7 +81,7 @@ extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order
 
   if (bad_repr)
     error (_("Value cannot be represented as integer of %d bytes."),
-	   (int) sizeof (T));
+	   (int) dst.size ());
 
   /* Start at the most significant end of the integer, and work towards
      the least significant.  */
@@ -89,28 +89,43 @@ extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order
     {
       size_t i = 0;
 
-      if (std::is_signed<T>::value)
+      if (is_signed)
 	{
 	  /* Do the sign extension once at the start.  */
-	  retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+	  dst[buf.size () - 1] = ((LONGEST) buf[i] ^ 0x80) - 0x80;
 	  ++i;
 	}
       for (; i < buf.size (); ++i)
-	retval = (retval << 8) | buf[i];
+	dst[buf.size () - 1 - i] = buf[i];
     }
   else
     {
       ssize_t i = buf.size () - 1;
 
-      if (std::is_signed<T>::value)
+      if (is_signed)
 	{
 	  /* Do the sign extension once at the start.  */
-	  retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+	  dst[i] = ((LONGEST) buf[i] ^ 0x80) - 0x80;
 	  --i;
 	}
       for (; i >= 0; --i)
-	retval = (retval << 8) | buf[i];
+	dst[i] = buf[i];
     }
+
+  /* Extend the upper bytes when DST is wider than BUF.  */
+  if (is_signed && (dst[buf.size () - 1] & 0x80) != 0)
+    for (size_t i = buf.size (); i < dst.size (); ++i)
+      dst[i] = 0xff;
+}
+
+template<typename T, typename>
+T
+extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order)
+{
+  typename std::make_unsigned<T>::type retval = 0;
+  gdb::array_view<gdb_byte> dst ((gdb_byte *) &retval, sizeof (T));
+  extract_integer (dst, buf, byte_order, std::is_signed<T>::value);
+
   return retval;
 }
 
diff --git a/gdb/extract-store-integer.h b/gdb/extract-store-integer.h
index b6f734d23a7..5d9d95e7036 100644
--- a/gdb/extract-store-integer.h
+++ b/gdb/extract-store-integer.h
@@ -20,6 +20,14 @@
 
 #include <type_traits>
 
+/* Convert the target-format buffer SRC into the host-format buffer
+   DST, according to BYTE_ORDER and taking IS_SIGNED into account.  */
+
+void extract_integer (gdb::array_view<gdb_byte> dst,
+		      gdb::array_view<const gdb_byte> src,
+		      enum bfd_endian byte_order,
+		      bool is_signed);
+
 template<typename T, typename = std::is_integral<T>>
 T extract_integer (gdb::array_view<const gdb_byte>, enum bfd_endian byte_order);
 
-- 
2.43.0

________________________________________
Intel Deutschland GmbH 

Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany 

Tel: +49 (89) 99143-0 

www.intel.de 

Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman

Chairperson of the Supervisory Board: Sonja Pierer

Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.