Use an accessor function for general_symbol_info::language
[deliverable/binutils-gdb.git] / gdb / findvar.c
index 80c709a9861f329dc940eb1c298eee063ac810f8..18dd3cd04f5254247d22f9e8e1ba0fd715565b53 100644 (file)
@@ -1,6 +1,6 @@
 /* Find a variable's value in memory, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 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);
@@ -285,8 +286,7 @@ value_of_register_lazy (struct frame_info *frame, int regnum)
   struct value *reg_val;
   struct frame_info *next_frame;
 
-  gdb_assert (regnum < (gdbarch_num_regs (gdbarch)
-                       + gdbarch_num_pseudo_regs (gdbarch)));
+  gdb_assert (regnum < gdbarch_num_cooked_regs (gdbarch));
 
   gdb_assert (frame != NULL);
 
@@ -309,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);
 }
@@ -318,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);
 }
@@ -329,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);
 }
@@ -338,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);
 }
@@ -446,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
@@ -566,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"));
@@ -601,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);
@@ -620,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;
@@ -630,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));
@@ -668,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;
 
@@ -680,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);
@@ -694,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:
@@ -721,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);
          }
@@ -731,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;
          }
       }
@@ -747,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),
@@ -767,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
@@ -787,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;
     }
 
@@ -805,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);
@@ -838,7 +840,7 @@ default_value_from_register (struct gdbarch *gdbarch, struct type *type,
      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);
@@ -953,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,
@@ -1002,8 +1003,97 @@ 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)
+{
+#if GDB_SELF_TEST
+  selftests::register_test
+    ("copy_integer_to_size",
+     selftests::findvar_tests::copy_integer_to_size_test);
+#endif
+}
This page took 0.04569 seconds and 4 git commands to generate.