2002-01-04 Daniel Jacobowitz <drow@mvista.com>
authorDaniel Jacobowitz <drow@false.org>
Fri, 4 Jan 2002 18:20:19 +0000 (18:20 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 4 Jan 2002 18:20:19 +0000 (18:20 +0000)
        * cp-abi.c: Fix whitespace.
        (baseclass_offset): New wrapper function.
        * cp-abi.h (baseclass_offset): Add prototype.
        (struct cp_abi_ops): Add baseclass_offset pointer.

        * valops.c (vb_match): Move to...
        * gnu-v2-abi.c (vb_match): here.
        * valops.c (baseclass_offset): Move to...
        * gnu-v2-abi.c (gnuv2_baseclass_offset): here, and rename.

        * gnu-v3-abi.c (gnuv3_baseclass_offset): New function.

        * gnu-v2-abi.c (init_gnuv2_ops): Initialize baseclass_offset.
        * gnu-v3-abi.c (init_gnuv3_ops): Likewise.
        * hpacc-abi.c (init_hpacc_ops): Likewise.

gdb/ChangeLog
gdb/cp-abi.c
gdb/cp-abi.h
gdb/gnu-v2-abi.c
gdb/gnu-v3-abi.c
gdb/hpacc-abi.c
gdb/value.h
gdb/values.c

index 0f2c835..27ecf63 100644 (file)
@@ -1,5 +1,23 @@
 2002-01-04  Daniel Jacobowitz  <drow@mvista.com>
 
+       * cp-abi.c: Fix whitespace.
+       (baseclass_offset): New wrapper function.
+       * cp-abi.h (baseclass_offset): Add prototype.
+       (struct cp_abi_ops): Add baseclass_offset pointer.
+
+       * valops.c (vb_match): Move to...
+       * gnu-v2-abi.c (vb_match): here.
+       * valops.c (baseclass_offset): Move to...
+       * gnu-v2-abi.c (gnuv2_baseclass_offset): here, and rename.
+
+       * gnu-v3-abi.c (gnuv3_baseclass_offset): New function.
+
+       * gnu-v2-abi.c (init_gnuv2_ops): Initialize baseclass_offset.
+       * gnu-v3-abi.c (init_gnuv3_ops): Likewise.
+       * hpacc-abi.c (init_hpacc_ops): Likewise.
+
+2002-01-04  Daniel Jacobowitz  <drow@mvista.com>
+
        * valops.c (find_overload_match): Accept obj as a
        reference parameter.  Update it before returning.
        * value.h (find_overload_match): Update prototype.
index b9dac53..d4eb0a0 100644 (file)
@@ -60,6 +60,15 @@ is_operator_name (const char *name)
   return (*current_cp_abi.is_operator_name) (name);
 }
 
+int
+baseclass_offset (struct type *type, int index, char *valaddr,
+                 CORE_ADDR address)
+{
+  if (current_cp_abi.baseclass_offset == NULL)
+    error ("ABI doesn't define required function baseclass_offset");
+  return (*current_cp_abi.baseclass_offset) (type, index, valaddr, address);
+}
+
 struct value *
 value_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j,
                        struct type * type, int offset)
@@ -68,6 +77,7 @@ value_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j,
     return NULL;
   return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
 }
+
 struct type *
 value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
 {
index ae62478..7c1e952 100644 (file)
@@ -132,7 +132,17 @@ extern struct value *value_virtual_fn_field (struct value **valuep,
 extern struct type *value_rtti_type (struct value *value,
                                      int *full, int *top, int *using_enc);
 
+/* Compute the offset of the baseclass which is
+   the INDEXth baseclass of class TYPE,
+   for value at VALADDR (in host) at ADDRESS (in target).
+   The result is the offset of the baseclass value relative
+   to (the address of)(ARG) + OFFSET.
 
+   -1 is returned on error. */
+
+extern int baseclass_offset (struct type *type, int index, char *valaddr,
+                            CORE_ADDR address);
+                  
 struct cp_abi_ops
 {
   const char *shortname;
@@ -148,6 +158,8 @@ struct cp_abi_ops
                                     int j, struct type * type, int offset);
   struct type *(*rtti_type) (struct value *v, int *full, int *top,
                             int *using_enc);
+  int (*baseclass_offset) (struct type *type, int index, char *valaddr,
+                          CORE_ADDR address);
 };
 
 
index ef46055..2b086c5 100644 (file)
@@ -34,6 +34,8 @@
 struct cp_abi_ops gnu_v2_abi_ops;
 
 static int vb_match (struct type *, int, struct type *);
+int gnuv2_baseclass_offset (struct type *type, int index, char *valaddr,
+                           CORE_ADDR address);
 
 static enum dtor_kinds
 gnuv2_is_destructor_name (const char *name)
@@ -308,6 +310,100 @@ gnuv2_value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
   return rtti_type;
 }
 
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+   pointer which is for the base class whose type is BASECLASS.  */
+
+static int
+vb_match (struct type *type, int index, struct type *basetype)
+{
+  struct type *fieldtype;
+  char *name = TYPE_FIELD_NAME (type, index);
+  char *field_class_name = NULL;
+
+  if (*name != '_')
+    return 0;
+  /* gcc 2.4 uses _vb$.  */
+  if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
+    field_class_name = name + 4;
+  /* gcc 2.5 will use __vb_.  */
+  if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
+    field_class_name = name + 5;
+
+  if (field_class_name == NULL)
+    /* This field is not a virtual base class pointer.  */
+    return 0;
+
+  /* It's a virtual baseclass pointer, now we just need to find out whether
+     it is for this baseclass.  */
+  fieldtype = TYPE_FIELD_TYPE (type, index);
+  if (fieldtype == NULL
+      || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
+    /* "Can't happen".  */
+    return 0;
+
+  /* What we check for is that either the types are equal (needed for
+     nameless types) or have the same name.  This is ugly, and a more
+     elegant solution should be devised (which would probably just push
+     the ugliness into symbol reading unless we change the stabs format).  */
+  if (TYPE_TARGET_TYPE (fieldtype) == basetype)
+    return 1;
+
+  if (TYPE_NAME (basetype) != NULL
+      && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
+      && STREQ (TYPE_NAME (basetype),
+               TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
+    return 1;
+  return 0;
+}
+
+/* Compute the offset of the baseclass which is
+   the INDEXth baseclass of class TYPE,
+   for value at VALADDR (in host) at ADDRESS (in target).
+   The result is the offset of the baseclass value relative
+   to (the address of)(ARG) + OFFSET.
+
+   -1 is returned on error. */
+
+int
+gnuv2_baseclass_offset (struct type *type, int index, char *valaddr,
+                 CORE_ADDR address)
+{
+  struct type *basetype = TYPE_BASECLASS (type, index);
+
+  if (BASETYPE_VIA_VIRTUAL (type, index))
+    {
+      /* Must hunt for the pointer to this virtual baseclass.  */
+      register int i, len = TYPE_NFIELDS (type);
+      register int n_baseclasses = TYPE_N_BASECLASSES (type);
+
+      /* First look for the virtual baseclass pointer
+         in the fields.  */
+      for (i = n_baseclasses; i < len; i++)
+       {
+         if (vb_match (type, i, basetype))
+           {
+             CORE_ADDR addr
+             = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+                               valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+             return addr - (LONGEST) address;
+           }
+       }
+      /* Not in the fields, so try looking through the baseclasses.  */
+      for (i = index + 1; i < n_baseclasses; i++)
+       {
+         int boffset =
+         baseclass_offset (type, i, valaddr, address);
+         if (boffset)
+           return boffset;
+       }
+      /* Not found.  */
+      return -1;
+    }
+
+  /* Baseclass is easily computed.  */
+  return TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
 
 static void
 init_gnuv2_ops (void)
@@ -321,6 +417,7 @@ init_gnuv2_ops (void)
   gnu_v2_abi_ops.is_operator_name = gnuv2_is_operator_name;
   gnu_v2_abi_ops.virtual_fn_field = gnuv2_virtual_fn_field;
   gnu_v2_abi_ops.rtti_type = gnuv2_value_rtti_type;
+  gnu_v2_abi_ops.baseclass_offset = gnuv2_baseclass_offset;
 }
 
 void
index b9cc0db..93bc995 100644 (file)
@@ -339,6 +339,66 @@ gnuv3_virtual_fn_field (struct value **value_p,
   return vfn;
 }
 
+/* Compute the offset of the baseclass which is
+   the INDEXth baseclass of class TYPE,
+   for value at VALADDR (in host) at ADDRESS (in target).
+   The result is the offset of the baseclass value relative
+   to (the address of)(ARG) + OFFSET.
+
+   -1 is returned on error. */
+int
+gnuv3_baseclass_offset (struct type *type, int index, char *valaddr,
+                       CORE_ADDR address)
+{
+  struct type *vtable_type = gdbarch_data (vtable_type_gdbarch_data);
+  struct type *basetype = TYPE_BASECLASS (type, index);
+  struct value *full_object, *vbase_object, *orig_object;
+  struct value *vtable, *orig_typeinfo, *orig_base_info;
+  struct type *orig_type, *vbasetype;
+  struct value *offset_val, *vbase_array;
+  CORE_ADDR vtable_address;
+  long int cur_base_offset, base_offset;
+  int to_top;
+  int baseclasses, i;
+
+  /* If it isn't a virtual base, this is easy.  The offset is in the
+     type definition.  */
+  if (!BASETYPE_VIA_VIRTUAL (type, index))
+    return TYPE_BASECLASS_BITPOS (type, index) / 8;
+
+  /* To access a virtual base, we need to use the vbase offset stored in
+     our vtable.  Recent GCC versions provide this information.  If it isn't
+     available, we could get what we needed from RTTI, or from drawing the
+     complete inheritance graph based on the debug info.  Neither is
+     worthwhile.  */
+  cur_base_offset = TYPE_BASECLASS_BITPOS (type, index) / 8;
+  if (cur_base_offset >= - vtable_address_point_offset ())
+    error ("Expected a negative vbase offset (old compiler?)");
+
+  cur_base_offset = cur_base_offset + vtable_address_point_offset ();
+  if ((- cur_base_offset) % TYPE_LENGTH (builtin_type_void_data_ptr) != 0)
+    error ("Misaligned vbase offset.");
+  cur_base_offset = cur_base_offset
+    / ((int) TYPE_LENGTH (builtin_type_void_data_ptr));
+
+  /* We're now looking for the cur_base_offset'th entry (negative index)
+     in the vcall_and_vbase_offsets array.  */
+
+  orig_object = value_at_lazy (type, address, NULL);
+  vbasetype = TYPE_VPTR_BASETYPE (VALUE_TYPE (orig_object));
+  vbase_object = value_cast (vbasetype, orig_object);
+
+  vtable_address
+    = value_as_address (value_field (vbase_object,
+                                    TYPE_VPTR_FIELDNO (vbasetype)));
+  vtable = value_at_lazy (vtable_type,
+                          vtable_address - vtable_address_point_offset (),
+                          NULL);
+  offset_val = value_from_longest(builtin_type_int, cur_base_offset);
+  vbase_array = value_field (vtable, vtable_field_vcall_and_vbase_offsets);
+  base_offset = value_as_long (value_subscript (vbase_array, offset_val));
+  return base_offset;
+}
 
 static void
 init_gnuv3_ops (void)
@@ -354,6 +414,7 @@ init_gnuv3_ops (void)
   gnu_v3_abi_ops.is_operator_name = gnuv3_is_operator_name;
   gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type;
   gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field;
+  gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset;
 }
 
 
index 4dcb1c3..6753cd7 100644 (file)
@@ -287,6 +287,8 @@ hpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
   return rtti_type;
 }
 
+extern int gnuv2_baseclass_offset (struct type *type, int index,
+                                  char *valaddr, CORE_ADDR address);
 
 static void
 init_hpacc_ops (void)
@@ -300,6 +302,11 @@ init_hpacc_ops (void)
   hpacc_abi_ops.is_operator_name = hpacc_is_operator_name;
   hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field;
   hpacc_abi_ops.rtti_type = hpacc_value_rtti_type;
+  /* It seems that this function is specific to GNU G++ < 3.0.
+     However, it is called for data members even in the HP
+     case (although not for member functions).
+     FIXME: Is that correct?  */
+  hpacc_abi_ops.baseclass_offset = gnuv2_baseclass_offset;
 }
 
 
index a6a517c..78f615f 100644 (file)
@@ -547,8 +547,6 @@ extern void clear_internalvars (void);
 
 extern struct value *value_copy (struct value *);
 
-extern int baseclass_offset (struct type *, int, char *, CORE_ADDR);
-
 /* From valops.c */
 
 extern struct value *varying_to_slice (struct value *);
index 4546622..68230e6 100644 (file)
@@ -1098,101 +1098,6 @@ value_from_vtable_info (struct value *arg, struct type *type)
 
   return value_headof (arg, 0, type);
 }
-
-/* Return true if the INDEXth field of TYPE is a virtual baseclass
-   pointer which is for the base class whose type is BASECLASS.  */
-
-static int
-vb_match (struct type *type, int index, struct type *basetype)
-{
-  struct type *fieldtype;
-  char *name = TYPE_FIELD_NAME (type, index);
-  char *field_class_name = NULL;
-
-  if (*name != '_')
-    return 0;
-  /* gcc 2.4 uses _vb$.  */
-  if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
-    field_class_name = name + 4;
-  /* gcc 2.5 will use __vb_.  */
-  if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
-    field_class_name = name + 5;
-
-  if (field_class_name == NULL)
-    /* This field is not a virtual base class pointer.  */
-    return 0;
-
-  /* It's a virtual baseclass pointer, now we just need to find out whether
-     it is for this baseclass.  */
-  fieldtype = TYPE_FIELD_TYPE (type, index);
-  if (fieldtype == NULL
-      || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
-    /* "Can't happen".  */
-    return 0;
-
-  /* What we check for is that either the types are equal (needed for
-     nameless types) or have the same name.  This is ugly, and a more
-     elegant solution should be devised (which would probably just push
-     the ugliness into symbol reading unless we change the stabs format).  */
-  if (TYPE_TARGET_TYPE (fieldtype) == basetype)
-    return 1;
-
-  if (TYPE_NAME (basetype) != NULL
-      && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
-      && STREQ (TYPE_NAME (basetype),
-               TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
-    return 1;
-  return 0;
-}
-
-/* Compute the offset of the baseclass which is
-   the INDEXth baseclass of class TYPE,
-   for value at VALADDR (in host) at ADDRESS (in target).
-   The result is the offset of the baseclass value relative
-   to (the address of)(ARG) + OFFSET.
-
-   -1 is returned on error. */
-
-int
-baseclass_offset (struct type *type, int index, char *valaddr,
-                 CORE_ADDR address)
-{
-  struct type *basetype = TYPE_BASECLASS (type, index);
-
-  if (BASETYPE_VIA_VIRTUAL (type, index))
-    {
-      /* Must hunt for the pointer to this virtual baseclass.  */
-      register int i, len = TYPE_NFIELDS (type);
-      register int n_baseclasses = TYPE_N_BASECLASSES (type);
-
-      /* First look for the virtual baseclass pointer
-         in the fields.  */
-      for (i = n_baseclasses; i < len; i++)
-       {
-         if (vb_match (type, i, basetype))
-           {
-             CORE_ADDR addr
-             = unpack_pointer (TYPE_FIELD_TYPE (type, i),
-                               valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
-
-             return addr - (LONGEST) address;
-           }
-       }
-      /* Not in the fields, so try looking through the baseclasses.  */
-      for (i = index + 1; i < n_baseclasses; i++)
-       {
-         int boffset =
-         baseclass_offset (type, i, valaddr, address);
-         if (boffset)
-           return boffset;
-       }
-      /* Not found.  */
-      return -1;
-    }
-
-  /* Baseclass is easily computed.  */
-  return TYPE_BASECLASS_BITPOS (type, index) / 8;
-}
 \f
 /* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
    VALADDR.