diff options
Diffstat (limited to 'gdb/findvar.c')
-rw-r--r-- | gdb/findvar.c | 239 |
1 files changed, 1 insertions, 238 deletions
diff --git a/gdb/findvar.c b/gdb/findvar.c index 7344949..660eb11 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "extract-store-integer.h" #include "symtab.h" #include "gdbtypes.h" #include "frame.h" @@ -30,7 +31,6 @@ #include "block.h" #include "objfiles.h" #include "language.h" -#include "gdbsupport/selftest.h" /* Basic byte-swapping routines. All 'extract' functions return a host-format integer from a target-format integer at ADDR which is @@ -44,151 +44,6 @@ you lose #endif -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; - - if (buf.size () > (int) sizeof (T)) - error (_("\ -That operation is not available on integers of more than %d bytes."), - (int) sizeof (T)); - - /* Start at the most significant end of the integer, and work towards - the least significant. */ - if (byte_order == BFD_ENDIAN_BIG) - { - size_t i = 0; - - if (std::is_signed<T>::value) - { - /* Do the sign extension once at the start. */ - retval = ((LONGEST) buf[i] ^ 0x80) - 0x80; - ++i; - } - for (; i < buf.size (); ++i) - retval = (retval << 8) | buf[i]; - } - else - { - ssize_t i = buf.size () - 1; - - if (std::is_signed<T>::value) - { - /* Do the sign extension once at the start. */ - retval = ((LONGEST) buf[i] ^ 0x80) - 0x80; - --i; - } - for (; i >= 0; --i) - retval = (retval << 8) | buf[i]; - } - return retval; -} - -/* Explicit instantiations. */ -template LONGEST extract_integer<LONGEST> (gdb::array_view<const gdb_byte> buf, - enum bfd_endian byte_order); -template ULONGEST extract_integer<ULONGEST> - (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order); - -/* Treat the bytes at BUF as a pointer of type TYPE, and return the - address it represents. */ -CORE_ADDR -extract_typed_address (const gdb_byte *buf, struct type *type) -{ - gdb_assert (type->is_pointer_or_reference ()); - return gdbarch_pointer_to_address (type->arch (), type, buf); -} - -/* All 'store' functions accept a host-format integer and store a - target-format integer at ADDR which is LEN bytes long. */ -template<typename T, typename> -void -store_integer (gdb::array_view<gdb_byte> dst, enum bfd_endian byte_order, - T val) -{ - gdb_byte *p; - gdb_byte *startaddr = dst.data (); - gdb_byte *endaddr = startaddr + dst.size (); - - /* Start at the least significant end of the integer, and work towards - the most significant. */ - if (byte_order == BFD_ENDIAN_BIG) - { - for (p = endaddr - 1; p >= startaddr; --p) - { - *p = val & 0xff; - val >>= 8; - } - } - else - { - for (p = startaddr; p < endaddr; ++p) - { - *p = val & 0xff; - val >>= 8; - } - } -} - -/* Explicit instantiations. */ -template void store_integer (gdb::array_view<gdb_byte> dst, - bfd_endian byte_order, LONGEST val); - -template void store_integer (gdb::array_view<gdb_byte> dst, - bfd_endian byte_order, ULONGEST val); - -/* Store the address ADDR as a pointer of type TYPE at BUF, in target - form. */ -void -store_typed_address (gdb_byte *buf, struct type *type, CORE_ADDR addr) -{ - gdb_assert (type->is_pointer_or_reference ()); - gdbarch_address_to_pointer (type->arch (), type, buf, addr); -} - -/* Copy a value from SOURCE of size SOURCE_SIZE bytes to DEST of size DEST_SIZE - bytes. If SOURCE_SIZE is greater than DEST_SIZE, then truncate the most - significant bytes. If SOURCE_SIZE is less than DEST_SIZE then either sign - or zero extended according to IS_SIGNED. Values are stored in memory with - endianness BYTE_ORDER. */ - -void -copy_integer_to_size (gdb_byte *dest, int dest_size, const gdb_byte *source, - int source_size, bool is_signed, - enum bfd_endian byte_order) -{ - signed int size_diff = dest_size - source_size; - - /* Copy across everything from SOURCE that can fit into DEST. */ - - if (byte_order == BFD_ENDIAN_BIG && size_diff > 0) - memcpy (dest + size_diff, source, source_size); - else if (byte_order == BFD_ENDIAN_BIG && size_diff < 0) - memcpy (dest, source - size_diff, dest_size); - else - memcpy (dest, source, std::min (source_size, dest_size)); - - /* Fill the remaining space in DEST by either zero extending or sign - extending. */ - - if (size_diff > 0) - { - gdb_byte extension = 0; - if (is_signed - && ((byte_order != BFD_ENDIAN_BIG && source[source_size - 1] & 0x80) - || (byte_order == BFD_ENDIAN_BIG && source[0] & 0x80))) - extension = 0xff; - - /* Extend into MSBs of SOURCE. */ - if (byte_order == BFD_ENDIAN_BIG) - memset (dest, extension, size_diff); - else - memset (dest + source_size, extension, size_diff); - } -} - /* See value.h. */ value * @@ -800,95 +655,3 @@ address_from_register (int regnum, const frame_info_ptr &frame) return value_as_address (v.get ()); } - -#if GDB_SELF_TEST -namespace selftests { -namespace findvar_tests { - -/* Function to test copy_integer_to_size. Store SOURCE_VAL with size - SOURCE_SIZE to a buffer, making sure no sign extending happens at this - stage. Copy buffer to a new buffer using copy_integer_to_size. Extract - copied value and compare to DEST_VALU. Copy again with a signed - copy_integer_to_size and compare to DEST_VALS. Do everything for both - LITTLE and BIG target endians. Use unsigned values throughout to make - sure there are no implicit sign extensions. */ - -static void -do_cint_test (ULONGEST dest_valu, ULONGEST dest_vals, int dest_size, - ULONGEST src_val, int src_size) -{ - for (int i = 0; i < 2 ; i++) - { - gdb_byte srcbuf[sizeof (ULONGEST)] = {}; - gdb_byte destbuf[sizeof (ULONGEST)] = {}; - enum bfd_endian byte_order = i ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; - - /* Fill the src buffer (and later the dest buffer) with non-zero junk, - to ensure zero extensions aren't hidden. */ - memset (srcbuf, 0xaa, sizeof (srcbuf)); - - /* Store (and later extract) using unsigned to ensure there are no sign - extensions. */ - store_unsigned_integer (srcbuf, src_size, byte_order, src_val); - - /* Test unsigned. */ - memset (destbuf, 0xaa, sizeof (destbuf)); - copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, false, - byte_order); - SELF_CHECK (dest_valu == extract_unsigned_integer (destbuf, dest_size, - byte_order)); - - /* Test signed. */ - memset (destbuf, 0xaa, sizeof (destbuf)); - copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, true, - byte_order); - SELF_CHECK (dest_vals == extract_unsigned_integer (destbuf, dest_size, - byte_order)); - } -} - -static void -copy_integer_to_size_test () -{ - /* Destination is bigger than the source, which has the signed bit unset. */ - do_cint_test (0x12345678, 0x12345678, 8, 0x12345678, 4); - do_cint_test (0x345678, 0x345678, 8, 0x12345678, 3); - - /* Destination is bigger than the source, which has the signed bit set. */ - do_cint_test (0xdeadbeef, 0xffffffffdeadbeef, 8, 0xdeadbeef, 4); - do_cint_test (0xadbeef, 0xffffffffffadbeef, 8, 0xdeadbeef, 3); - - /* Destination is smaller than the source. */ - do_cint_test (0x5678, 0x5678, 2, 0x12345678, 3); - do_cint_test (0xbeef, 0xbeef, 2, 0xdeadbeef, 3); - - /* Destination and source are the same size. */ - do_cint_test (0x8765432112345678, 0x8765432112345678, 8, 0x8765432112345678, - 8); - do_cint_test (0x432112345678, 0x432112345678, 6, 0x8765432112345678, 6); - do_cint_test (0xfeedbeaddeadbeef, 0xfeedbeaddeadbeef, 8, 0xfeedbeaddeadbeef, - 8); - do_cint_test (0xbeaddeadbeef, 0xbeaddeadbeef, 6, 0xfeedbeaddeadbeef, 6); - - /* Destination is bigger than the source. Source is bigger than 32bits. */ - do_cint_test (0x3412345678, 0x3412345678, 8, 0x3412345678, 6); - do_cint_test (0xff12345678, 0xff12345678, 8, 0xff12345678, 6); - do_cint_test (0x432112345678, 0x432112345678, 8, 0x8765432112345678, 6); - do_cint_test (0xff2112345678, 0xffffff2112345678, 8, 0xffffff2112345678, 6); -} - -} // namespace findvar_test -} // namespace selftests - -#endif - -void _initialize_findvar (); -void -_initialize_findvar () -{ -#if GDB_SELF_TEST - selftests::register_test - ("copy_integer_to_size", - selftests::findvar_tests::copy_integer_to_size_test); -#endif -} |