[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.