aboutsummaryrefslogtreecommitdiff
path: root/gdb/findvar.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/findvar.c')
-rw-r--r--gdb/findvar.c239
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
-}