]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/findvar.c
gdb: add back declarations for _initialize functions
[thirdparty/binutils-gdb.git] / gdb / findvar.c
index 6e28a296de06cd4337df9aaefc78fe9c6660e481..5cf1cd4137b8bdaf8621e03845a8ad9674cdc625 100644 (file)
@@ -1,6 +1,6 @@
 /* Find a variable's value in memory, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2016 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,7 +25,6 @@
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
-#include "floatformat.h"
 #include "symfile.h"           /* for overlay functions */
 #include "regcache.h"
 #include "user-regs.h"
@@ -33,6 +32,7 @@
 #include "objfiles.h"
 #include "language.h"
 #include "dwarf2loc.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
 you lose
 #endif
 
-LONGEST
-extract_signed_integer (const gdb_byte *addr, int len,
-                       enum bfd_endian byte_order)
+template<typename T, typename>
+T
+extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order)
 {
-  LONGEST retval;
+  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 (LONGEST))
+  if (len > (int) sizeof (T))
     error (_("\
 That operation is not available on integers of more than %d bytes."),
-          (int) sizeof (LONGEST));
+          (int) sizeof (T));
 
   /* Start at the most significant end of the integer, and work towards
      the least significant.  */
   if (byte_order == BFD_ENDIAN_BIG)
     {
       p = startaddr;
-      /* Do the sign extension once at the start.  */
-      retval = ((LONGEST) * p ^ 0x80) - 0x80;
-      for (++p; p < endaddr; ++p)
+      if (std::is_signed<T>::value)
+       {
+         /* Do the sign extension once at the start.  */
+         retval = ((LONGEST) * p ^ 0x80) - 0x80;
+         ++p;
+       }
+      for (; p < endaddr; ++p)
        retval = (retval << 8) | *p;
     }
   else
     {
       p = endaddr - 1;
-      /* Do the sign extension once at the start.  */
-      retval = ((LONGEST) * p ^ 0x80) - 0x80;
-      for (--p; p >= startaddr; --p)
+      if (std::is_signed<T>::value)
+       {
+         /* Do the sign extension once at the start.  */
+         retval = ((LONGEST) * p ^ 0x80) - 0x80;
+         --p;
+       }
+      for (; p >= startaddr; --p)
        retval = (retval << 8) | *p;
     }
   return retval;
 }
 
-ULONGEST
-extract_unsigned_integer (const gdb_byte *addr, int len,
-                         enum bfd_endian byte_order)
-{
-  ULONGEST retval;
-  const unsigned char *p;
-  const unsigned char *startaddr = addr;
-  const unsigned char *endaddr = startaddr + len;
-
-  if (len > (int) sizeof (ULONGEST))
-    error (_("\
-That operation is not available on integers of more than %d bytes."),
-          (int) sizeof (ULONGEST));
-
-  /* Start at the most significant end of the integer, and work towards
-     the least significant.  */
-  retval = 0;
-  if (byte_order == BFD_ENDIAN_BIG)
-    {
-      for (p = startaddr; p < endaddr; ++p)
-       retval = (retval << 8) | *p;
-    }
-  else
-    {
-      for (p = endaddr - 1; p >= startaddr; --p)
-       retval = (retval << 8) | *p;
-    }
-  return retval;
-}
+/* Explicit instantiations.  */
+template LONGEST extract_integer<LONGEST> (const gdb_byte *addr, int len,
+                                          enum bfd_endian byte_order);
+template ULONGEST extract_integer<ULONGEST> (const gdb_byte *addr, int len,
+                                            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
@@ -169,8 +153,7 @@ extract_long_unsigned_integer (const gdb_byte *addr, int orig_len,
 CORE_ADDR
 extract_typed_address (const gdb_byte *buf, struct type *type)
 {
-  if (TYPE_CODE (type) != TYPE_CODE_PTR
-      && TYPE_CODE (type) != TYPE_CODE_REF)
+  if (TYPE_CODE (type) != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type))
     internal_error (__FILE__, __LINE__,
                    _("extract_typed_address: "
                    "type is not a pointer or reference"));
@@ -180,10 +163,10 @@ extract_typed_address (const gdb_byte *buf, struct type *type)
 
 /* 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_signed_integer (gdb_byte *addr, int len,
-                     enum bfd_endian byte_order, LONGEST val)
+store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+              T val)
 {
   gdb_byte *p;
   gdb_byte *startaddr = addr;
@@ -209,41 +192,21 @@ store_signed_integer (gdb_byte *addr, int len,
     }
 }
 
-void
-store_unsigned_integer (gdb_byte *addr, int len,
-                       enum bfd_endian byte_order, ULONGEST val)
-{
-  unsigned char *p;
-  unsigned char *startaddr = (unsigned char *) addr;
-  unsigned char *endaddr = startaddr + len;
+/* Explicit instantiations.  */
+template void store_integer (gdb_byte *addr, int len,
+                            enum bfd_endian byte_order,
+                            LONGEST val);
 
-  /* 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;
-       }
-    }
-}
+template void store_integer (gdb_byte *addr, int len,
+                            enum 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)
 {
-  if (TYPE_CODE (type) != TYPE_CODE_PTR
-      && TYPE_CODE (type) != TYPE_CODE_REF)
+  if (TYPE_CODE (type) != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type))
     internal_error (__FILE__, __LINE__,
                    _("store_typed_address: "
                    "type is not a pointer or reference"));
@@ -251,7 +214,46 @@ store_typed_address (gdb_byte *buf, struct type *type, CORE_ADDR addr)
   gdbarch_address_to_pointer (get_type_arch (type), 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);
+    }
+}
 
 /* Return a `value' with the contents of (virtual or cooked) register
    REGNUM as found in the specified FRAME.  The register's type is
@@ -265,8 +267,7 @@ value_of_register (int regnum, struct frame_info *frame)
 
   /* User registers lie completely outside of the range of normal
      registers.  Catch them early so that the target never sees them.  */
-  if (regnum >= gdbarch_num_regs (gdbarch)
-               + gdbarch_num_pseudo_regs (gdbarch))
+  if (regnum >= gdbarch_num_cooked_regs (gdbarch))
     return value_of_user_reg (regnum, frame);
 
   reg_val = value_of_register_lazy (frame, regnum);
@@ -283,17 +284,22 @@ value_of_register_lazy (struct frame_info *frame, int regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct value *reg_val;
+  struct frame_info *next_frame;
+
+  gdb_assert (regnum < gdbarch_num_cooked_regs (gdbarch));
 
-  gdb_assert (regnum < (gdbarch_num_regs (gdbarch)
-                       + gdbarch_num_pseudo_regs (gdbarch)));
+  gdb_assert (frame != NULL);
 
-  /* We should have a valid (i.e. non-sentinel) frame.  */
-  gdb_assert (frame_id_p (get_frame_id (frame)));
+  next_frame = get_next_frame_sentinel_okay (frame);
+
+  /* We should have a valid next frame.  */
+  gdb_assert (frame_id_p (get_frame_id (next_frame)));
 
   reg_val = allocate_value_lazy (register_type (gdbarch, regnum));
   VALUE_LVAL (reg_val) = lval_register;
   VALUE_REGNUM (reg_val) = regnum;
-  VALUE_FRAME_ID (reg_val) = get_frame_id (frame);
+  VALUE_NEXT_FRAME_ID (reg_val) = get_frame_id (next_frame);
+
   return reg_val;
 }
 
@@ -303,7 +309,7 @@ CORE_ADDR
 unsigned_pointer_to_address (struct gdbarch *gdbarch,
                             struct type *type, const gdb_byte *buf)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (type);
 
   return extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
 }
@@ -312,7 +318,7 @@ CORE_ADDR
 signed_pointer_to_address (struct gdbarch *gdbarch,
                           struct type *type, const gdb_byte *buf)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (type);
 
   return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order);
 }
@@ -323,7 +329,7 @@ void
 unsigned_address_to_pointer (struct gdbarch *gdbarch, struct type *type,
                             gdb_byte *buf, CORE_ADDR addr)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (type);
 
   store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, addr);
 }
@@ -332,7 +338,7 @@ void
 address_to_signed_pointer (struct gdbarch *gdbarch, struct type *type,
                           gdb_byte *buf, CORE_ADDR addr)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (type);
 
   store_signed_integer (buf, TYPE_LENGTH (type), byte_order, addr);
 }
@@ -440,7 +446,7 @@ follow_static_link (struct frame_info *frame,
       QUIT;
 
       /* If we don't know how to compute FRAME's base address, don't give up:
-        maybe the frame we are looking for is upper in the stace frame.  */
+        maybe the frame we are looking for is upper in the stack frame.  */
       if (framefunc != NULL
          && SYMBOL_BLOCK_OPS (framefunc) != NULL
          && SYMBOL_BLOCK_OPS (framefunc)->get_frame_base != NULL
@@ -560,9 +566,9 @@ get_hosting_frame (struct symbol *var, const struct block *var_block,
        {
          if (BLOCK_FUNCTION (var_block)
              && !block_inlined_p (var_block)
-             && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)))
+             && BLOCK_FUNCTION (var_block)->print_name ())
            error (_("No frame is currently executing in block %s."),
-                  SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)));
+                  BLOCK_FUNCTION (var_block)->print_name ());
          else
            error (_("No frame is currently executing in specified"
                     " block"));
@@ -595,7 +601,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
   if (sym_need == SYMBOL_NEEDS_FRAME)
     gdb_assert (frame != NULL);
   else if (sym_need == SYMBOL_NEEDS_REGISTERS && !target_has_registers)
-    error (_("Cannot read `%s' without registers"), SYMBOL_PRINT_NAME (var));
+    error (_("Cannot read `%s' without registers"), var->print_name ());
 
   if (frame != NULL)
     frame = get_hosting_frame (var, var_block, frame);
@@ -614,7 +620,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
       /* Put the constant back in target format. */
       v = allocate_value (type);
       store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type),
-                           gdbarch_byte_order (get_type_arch (type)),
+                           type_byte_order (type),
                            (LONGEST) SYMBOL_VALUE (var));
       VALUE_LVAL (v) = not_lval;
       return v;
@@ -624,7 +630,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
       v = allocate_value (type);
       if (overlay_debugging)
        {
-         CORE_ADDR addr
+         addr
            = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
                                        SYMBOL_OBJ_SECTION (symbol_objfile (var),
                                                            var));
@@ -662,7 +668,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
       addr = get_frame_args_address (frame);
       if (!addr)
        error (_("Unknown argument list address for `%s'."),
-              SYMBOL_PRINT_NAME (var));
+              var->print_name ());
       addr += SYMBOL_VALUE (var);
       break;
 
@@ -674,7 +680,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
        argref = get_frame_args_address (frame);
        if (!argref)
          error (_("Unknown argument list address for `%s'."),
-                SYMBOL_PRINT_NAME (var));
+                var->print_name ());
        argref += SYMBOL_VALUE (var);
        ref = value_at (lookup_pointer_type (type), argref);
        addr = value_as_address (ref);
@@ -688,16 +694,16 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
 
     case LOC_TYPEDEF:
       error (_("Cannot look up value of a typedef `%s'."),
-            SYMBOL_PRINT_NAME (var));
+            var->print_name ());
       break;
 
     case LOC_BLOCK:
       if (overlay_debugging)
        addr = symbol_overlayed_address
-         (BLOCK_START (SYMBOL_BLOCK_VALUE (var)),
+         (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (var)),
           SYMBOL_OBJ_SECTION (symbol_objfile (var), var));
       else
-       addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+       addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (var));
       break;
 
     case LOC_REGISTER:
@@ -715,7 +721,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
 
            if (regval == NULL)
              error (_("Value of register variable not available for `%s'."),
-                    SYMBOL_PRINT_NAME (var));
+                    var->print_name ());
 
            addr = value_as_address (regval);
          }
@@ -725,7 +731,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
 
            if (regval == NULL)
              error (_("Value of register variable not available for `%s'."),
-                    SYMBOL_PRINT_NAME (var));
+                    var->print_name ());
            return regval;
          }
       }
@@ -741,7 +747,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
        struct obj_section *obj_section;
 
        memset (&lookup_data, 0, sizeof (lookup_data));
-       lookup_data.name = SYMBOL_LINKAGE_NAME (var);
+       lookup_data.name = var->linkage_name ();
 
        gdbarch_iterate_over_objfiles_in_search_order
          (symbol_arch (var),
@@ -761,7 +767,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
               can't be NULL.  */
            gdb_assert (flavour_name != NULL);
            error (_("Missing %s symbol \"%s\"."),
-                  flavour_name, SYMBOL_LINKAGE_NAME (var));
+                  flavour_name, var->linkage_name ());
          }
        obj_section = MSYMBOL_OBJ_SECTION (lookup_data.result.objfile, msym);
        /* Relocate address, unless there is no section or the variable is
@@ -781,11 +787,13 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
       break;
 
     case LOC_OPTIMIZED_OUT:
+      if (is_dynamic_type (type))
+       type = resolve_dynamic_type (type, NULL, /* Unused address.  */ 0);
       return allocate_optimized_out_value (type);
 
     default:
       error (_("Cannot look up value of a botched symbol `%s'."),
-            SYMBOL_PRINT_NAME (var));
+            var->print_name ());
       break;
     }
 
@@ -799,7 +807,7 @@ struct value *
 read_var_value (struct symbol *var, const struct block *var_block,
                struct frame_info *frame)
 {
-  const struct language_defn *lang = language_def (SYMBOL_LANGUAGE (var));
+  const struct language_defn *lang = language_def (var->language ());
 
   gdb_assert (lang != NULL);
   gdb_assert (lang->la_read_var_value != NULL);
@@ -815,16 +823,24 @@ default_value_from_register (struct gdbarch *gdbarch, struct type *type,
 {
   int len = TYPE_LENGTH (type);
   struct value *value = allocate_value (type);
+  struct frame_info *frame;
 
   VALUE_LVAL (value) = lval_register;
-  VALUE_FRAME_ID (value) = frame_id;
+  frame = frame_find_by_id (frame_id);
+
+  if (frame == NULL)
+    frame_id = null_frame_id;
+  else
+    frame_id = get_frame_id (get_next_frame_sentinel_okay (frame));
+
+  VALUE_NEXT_FRAME_ID (value) = frame_id;
   VALUE_REGNUM (value) = regnum;
 
   /* Any structure stored in more than one register will always be
      an integral number of registers.  Otherwise, you need to do
      some fiddling with the last register copied here for little
      endian machines.  */
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
+  if (type_byte_order (type) == BFD_ENDIAN_BIG
       && len < register_size (gdbarch, regnum))
     /* Big-endian, and we want less than full size.  */
     set_value_offset (value, register_size (gdbarch, regnum) - len);
@@ -902,7 +918,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
          including the location.  */
       v = allocate_value (type);
       VALUE_LVAL (v) = lval_register;
-      VALUE_FRAME_ID (v) = get_frame_id (frame);
+      VALUE_NEXT_FRAME_ID (v) = get_frame_id (get_next_frame_sentinel_okay (frame));
       VALUE_REGNUM (v) = regnum;
       ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
                                      value_contents_raw (v), &optim,
@@ -939,8 +955,7 @@ address_from_register (int regnum, struct frame_info *frame)
   struct type *type = builtin_type (gdbarch)->builtin_data_ptr;
   struct value *value;
   CORE_ADDR result;
-  int regnum_max_excl = (gdbarch_num_regs (gdbarch)
-                        + gdbarch_num_pseudo_regs (gdbarch));
+  int regnum_max_excl = gdbarch_num_cooked_regs (gdbarch);
 
   if (regnum < 0 || regnum >= regnum_max_excl)
     error (_("Invalid register #%d, expecting 0 <= # < %d"), regnum,
@@ -950,7 +965,7 @@ address_from_register (int regnum, struct frame_info *frame)
      where the ID of FRAME is not yet known.  Calling value_from_register
      would therefore abort in get_frame_id.  However, since we only need
      a temporary value that is never used as lvalue, we actually do not
-     really need to set its VALUE_FRAME_ID.  Therefore, we re-implement
+     really need to set its VALUE_NEXT_FRAME_ID.  Therefore, we re-implement
      the core of value_from_register, but use the null_frame_id.  */
 
   /* Some targets require a special conversion routine even for plain
@@ -988,8 +1003,98 @@ address_from_register (int regnum, struct frame_info *frame)
 
   result = value_as_address (value);
   release_value (value);
-  value_free (value);
 
   return result;
 }
 
+#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
+}