gdb/
authorPedro Alves <palves@redhat.com>
Mon, 14 Feb 2011 11:35:45 +0000 (11:35 +0000)
committerPedro Alves <palves@redhat.com>
Mon, 14 Feb 2011 11:35:45 +0000 (11:35 +0000)
* exceptions.h (NOT_AVAILABLE_ERROR): New error.
* value.c: Include "exceptions.h".
(require_available): Throw NOT_AVAILABLE_ERROR instead of a
generic error.
* cp-abi.c: Include gdb_assert.h.
(baseclass_offset): Add `embedded_offset' and `val' parameters.
Assert the method is implemented.  Wrap NOT_AVAILABLE_ERROR
errors.
* cp-abi.h (baseclass_offset): Add `embedded_offset' and `val'
parameters.  No longer returns -1 on error.
(struct cp_abi_ops) <baseclass_offset>: Add `embedded_offset' and
`val' parameters.
* cp-valprint.c: Include exceptions.h.
(cp_print_value): Handle NOT_AVAILABLE_ERROR errors when fetching
the baseclass_offset.  Handle unavailable base classes.  Use
val_print_invalid_address.
* p-valprint.c: Include exceptions.h.
(pascal_object_print_value): Handle NOT_AVAILABLE_ERROR errors
when fetching the baseclass_offset.  No longer expect
baseclass_offset returning -1.  Handle unavailable base classes.
Use val_print_invalid_address.
* valops.c (dynamic_cast_check_1): Rename `contents' parameter to
`valaddr' parameter, and change its type to gdb_byte pointer.  Add
`embedded_offset' and `val' parameters.  Adjust.
(dynamic_cast_check_2): Rename `contents' parameter to `valaddr'
parameter, and change its type to gdb_byte pointer.  Add
`embedded_offset' and `val' parameters.  Adjust.  No longer expect
baseclass_offset returning -1.
(value_dynamic_cast): Use value_contents_for_printing rather than
value_contents.  Adjust.
(search_struct_field): No longer expect baseclass_offset returning
-1.
(search_struct_method): If reading memory from the target is
necessary, wrap it in a new value to pass to baseclass_offset.  No
longer expect baseclass_offset returning -1.
(find_method_list): No longer expect baseclass_offset returning
-1.  Use value_contents_for_printing rather than value_contents.
* valprint.c (val_print_invalid_address): New function.
* valprint.h (val_print_invalid_address): Declare.
* gdbtypes.c (is_unique_ancestor_worker): New `embedded_offset'
and `val' parameters.  No longer expect baseclass_offset returning
-1.  Adjust.
* gnu-v2-abi.c: Include "exceptions.h".
(gnuv2_baseclass_offset): Add `embedded_offset' and `val'
parameters.  Handle unavailable memory.  Recurse through
gnuv2_baseclass_offset directly, rather than through
baseclass_offset.  No longer returns -1 on not found, instead
throw an error.
* gnu-v3-abi.c (gnuv3_baseclass_offset): Add `embedded_offset' and
`val' parameters.  Adjust.

gdb/testsuite/
* gdb.trace/unavailable.cc (class Base, class Middle, class
Derived): New types.
(derived_unavail, derived_partial, derived_whole): New globals.
(virtual_partial): New global.
(virtualp): Point at virtual_partial.
* gdb.trace/unavailable.exp (gdb_collect_globals_test): Add tests
related to unavailable vptr.

16 files changed:
gdb/ChangeLog
gdb/cp-abi.c
gdb/cp-abi.h
gdb/cp-valprint.c
gdb/exceptions.h
gdb/gdbtypes.c
gdb/gnu-v2-abi.c
gdb/gnu-v3-abi.c
gdb/p-valprint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.trace/unavailable.cc
gdb/testsuite/gdb.trace/unavailable.exp
gdb/valops.c
gdb/valprint.c
gdb/valprint.h
gdb/value.c

index f7099b4..bfef2e2 100644 (file)
@@ -1,5 +1,58 @@
 2011-02-14  Pedro Alves  <pedro@codesourcery.com>
 
+       * exceptions.h (NOT_AVAILABLE_ERROR): New error.
+       * value.c: Include "exceptions.h".
+       (require_available): Throw NOT_AVAILABLE_ERROR instead of a
+       generic error.
+       * cp-abi.c: Include gdb_assert.h.
+       (baseclass_offset): Add `embedded_offset' and `val' parameters.
+       Assert the method is implemented.  Wrap NOT_AVAILABLE_ERROR
+       errors.
+       * cp-abi.h (baseclass_offset): Add `embedded_offset' and `val'
+       parameters.  No longer returns -1 on error.
+       (struct cp_abi_ops) <baseclass_offset>: Add `embedded_offset' and
+       `val' parameters.
+       * cp-valprint.c: Include exceptions.h.
+       (cp_print_value): Handle NOT_AVAILABLE_ERROR errors when fetching
+       the baseclass_offset.  Handle unavailable base classes.  Use
+       val_print_invalid_address.
+       * p-valprint.c: Include exceptions.h.
+       (pascal_object_print_value): Handle NOT_AVAILABLE_ERROR errors
+       when fetching the baseclass_offset.  No longer expect
+       baseclass_offset returning -1.  Handle unavailable base classes.
+       Use val_print_invalid_address.
+       * valops.c (dynamic_cast_check_1): Rename `contents' parameter to
+       `valaddr' parameter, and change its type to gdb_byte pointer.  Add
+       `embedded_offset' and `val' parameters.  Adjust.
+       (dynamic_cast_check_2): Rename `contents' parameter to `valaddr'
+       parameter, and change its type to gdb_byte pointer.  Add
+       `embedded_offset' and `val' parameters.  Adjust.  No longer expect
+       baseclass_offset returning -1.
+       (value_dynamic_cast): Use value_contents_for_printing rather than
+       value_contents.  Adjust.
+       (search_struct_field): No longer expect baseclass_offset returning
+       -1.
+       (search_struct_method): If reading memory from the target is
+       necessary, wrap it in a new value to pass to baseclass_offset.  No
+       longer expect baseclass_offset returning -1.
+       (find_method_list): No longer expect baseclass_offset returning
+       -1.  Use value_contents_for_printing rather than value_contents.
+       * valprint.c (val_print_invalid_address): New function.
+       * valprint.h (val_print_invalid_address): Declare.
+       * gdbtypes.c (is_unique_ancestor_worker): New `embedded_offset'
+       and `val' parameters.  No longer expect baseclass_offset returning
+       -1.  Adjust.
+       * gnu-v2-abi.c: Include "exceptions.h".
+       (gnuv2_baseclass_offset): Add `embedded_offset' and `val'
+       parameters.  Handle unavailable memory.  Recurse through
+       gnuv2_baseclass_offset directly, rather than through
+       baseclass_offset.  No longer returns -1 on not found, instead
+       throw an error.
+       * gnu-v3-abi.c (gnuv3_baseclass_offset): Add `embedded_offset' and
+       `val' parameters.  Adjust.
+
+2011-02-14  Pedro Alves  <pedro@codesourcery.com>
+
        * tracepoint.c (memrange_sortmerge): Don't merge ranges that are
        almost but not quite adjacent.
 
index 0c21f91..040962e 100644 (file)
@@ -25,7 +25,7 @@
 #include "exceptions.h"
 #include "gdbcmd.h"
 #include "ui-out.h"
-
+#include "gdb_assert.h"
 #include "gdb_string.h"
 
 static struct cp_abi_ops *find_cp_abi (const char *short_name);
@@ -70,14 +70,30 @@ is_operator_name (const char *name)
 }
 
 int
-baseclass_offset (struct type *type, int index,
-                 const bfd_byte *valaddr,
-                 CORE_ADDR address)
+baseclass_offset (struct type *type, int index, const gdb_byte *valaddr,
+                 int embedded_offset, CORE_ADDR address,
+                 const struct value *val)
 {
-  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);
+  volatile struct gdb_exception ex;
+  int res = 0;
+
+  gdb_assert (current_cp_abi.baseclass_offset != NULL);
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      res = (*current_cp_abi.baseclass_offset) (type, index, valaddr,
+                                               embedded_offset,
+                                               address, val);
+    }
+
+  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+    throw_error (NOT_AVAILABLE_ERROR,
+                _("Cannot determine virtual baseclass offset "
+                  "of incomplete object"));
+  else if (ex.reason < 0)
+    throw_exception (ex);
+  else
+    return res;
 }
 
 struct value *
index 53c8f93..9bfa1b0 100644 (file)
@@ -139,18 +139,18 @@ 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,
-                            const bfd_byte *valaddr,
-                            CORE_ADDR address);
-                  
+/* Compute the offset of the baseclass which is the INDEXth baseclass
+   of class TYPE, for value at VALADDR (in host) at ADDRESS (in
+   target), offset by EMBEDDED_OFFSET.  VALADDR points to the raw
+   contents of VAL.  The result is the offset of the baseclass value
+   relative to (the address of)(ARG) + OFFSET.  */
+
+extern int baseclass_offset (struct type *type,
+                            int index, const gdb_byte *valaddr,
+                            int embedded_offset,
+                            CORE_ADDR address,
+                            const struct value *val);
+
 /* Describe the target of a pointer to method.  CONTENTS is the byte
    pattern representing the pointer to method.  TYPE is the pointer to
    method type.  STREAM is the stream to print it to.  */
@@ -204,8 +204,8 @@ struct cp_abi_ops
   struct type *(*rtti_type) (struct value *v, int *full,
                             int *top, int *using_enc);
   int (*baseclass_offset) (struct type *type, int index,
-                          const bfd_byte *valaddr,
-                          CORE_ADDR address);
+                          const bfd_byte *valaddr, int embedded_offset,
+                          CORE_ADDR address, const struct value *val);
   void (*print_method_ptr) (const gdb_byte *contents,
                            struct type *type,
                            struct ui_file *stream);
index 1a171ea..255e9ce 100644 (file)
@@ -37,6 +37,7 @@
 #include "cp-support.h"
 #include "language.h"
 #include "python/python.h"
+#include "exceptions.h"
 
 /* Controls printing of vtbl's.  */
 static void
@@ -482,12 +483,13 @@ cp_print_value (struct type *type, struct type *real_type,
 
   for (i = 0; i < n_baseclasses; i++)
     {
-      int boffset;
+      int boffset = 0;
       int skip;
       struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
       char *basename = TYPE_NAME (baseclass);
-      const gdb_byte *base_valaddr;
-      const struct value *base_val;
+      const gdb_byte *base_valaddr = NULL;
+      const struct value *base_val = NULL;
+      volatile struct gdb_exception ex;
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
        {
@@ -507,34 +509,47 @@ cp_print_value (struct type *type, struct type *real_type,
       thisoffset = offset;
       thistype = real_type;
 
-      boffset = baseclass_offset (type, i, valaddr + offset,
-                                 address + offset);
-      skip = ((boffset == -1) || (boffset + offset) < 0);
-
-      if (BASETYPE_VIA_VIRTUAL (type, i))
+      TRY_CATCH (ex, RETURN_MASK_ERROR)
        {
-         /* The virtual base class pointer might have been clobbered
-            by the user program.  Make sure that it still points to a
-            valid memory location.  */
+         boffset = baseclass_offset (type, i, valaddr, offset, address, val);
+       }
+      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+       skip = -1;
+      else if (ex.reason < 0)
+       skip = 1;
+      else
+       {
+         skip = 0;
 
-         if (boffset != -1
-             && ((boffset + offset) < 0
-                 || (boffset + offset) >= TYPE_LENGTH (real_type)))
+         if (BASETYPE_VIA_VIRTUAL (type, i))
            {
-             /* FIXME (alloca): unsafe if baseclass is really really
-                large.  */
-             gdb_byte *buf = alloca (TYPE_LENGTH (baseclass));
-
-             if (target_read_memory (address + boffset, buf,
-                                     TYPE_LENGTH (baseclass)) != 0)
-               skip = 1;
-             base_val = value_from_contents_and_address (baseclass,
-                                                         buf,
-                                                         address + boffset);
-             thisoffset = 0;
-             boffset = 0;
-             thistype = baseclass;
-             base_valaddr = value_contents_for_printing_const (base_val);
+             /* The virtual base class pointer might have been
+                clobbered by the user program. Make sure that it
+                still points to a valid memory location.  */
+
+             if ((boffset + offset) < 0
+                 || (boffset + offset) >= TYPE_LENGTH (real_type))
+               {
+                 /* FIXME (alloca): unsafe if baseclass is really
+                    really large.  */
+                 gdb_byte *buf = alloca (TYPE_LENGTH (baseclass));
+
+                 if (target_read_memory (address + boffset, buf,
+                                         TYPE_LENGTH (baseclass)) != 0)
+                   skip = 1;
+                 base_val = value_from_contents_and_address (baseclass,
+                                                             buf,
+                                                             address + boffset);
+                 thisoffset = 0;
+                 boffset = 0;
+                 thistype = baseclass;
+                 base_valaddr = value_contents_for_printing_const (base_val);
+               }
+             else
+               {
+                 base_valaddr = valaddr;
+                 base_val = val;
+               }
            }
          else
            {
@@ -542,11 +557,6 @@ cp_print_value (struct type *type, struct type *real_type,
              base_val = val;
            }
        }
-      else
-       {
-         base_valaddr = valaddr;
-         base_val = val;
-       }
 
       /* Now do the printing.  */
       if (options->pretty)
@@ -560,9 +570,10 @@ cp_print_value (struct type *type, struct type *real_type,
       fputs_filtered (basename ? basename : "", stream);
       fputs_filtered ("> = ", stream);
 
-
-      if (skip)
-       fprintf_filtered (stream, "<invalid address>");
+      if (skip < 0)
+       val_print_unavailable (stream);
+      else if (skip > 0)
+       val_print_invalid_address (stream);
       else
        {
          int result = 0;
index 81f3f4b..b1c4587 100644 (file)
@@ -49,9 +49,12 @@ typedef int return_mask;
 
 enum errors {
   GDB_NO_ERROR,
+
   /* Any generic error, the corresponding text is in
      exception.message.  */
   GENERIC_ERROR,
+
+  /* Something requested was not found.  */
   NOT_FOUND_ERROR,
 
   /* Thread library lacks support necessary for finding thread local
@@ -78,6 +81,10 @@ enum errors {
   /* Feature is not supported in this copy of GDB.  */
   UNSUPPORTED_ERROR,
 
+  /* Value not available.  E.g., a register was not collected in a
+     traceframe.  */
+  NOT_AVAILABLE_ERROR,
+
   /* Add more errors here.  */
   NR_ERRORS
 };
index 2cf1b4d..91fafa2 100644 (file)
@@ -2101,7 +2101,8 @@ is_public_ancestor (struct type *base, struct type *dclass)
 static int
 is_unique_ancestor_worker (struct type *base, struct type *dclass,
                           int *offset,
-                          const bfd_byte *contents, CORE_ADDR address)
+                          const gdb_byte *valaddr, int embedded_offset,
+                          CORE_ADDR address, struct value *val)
 {
   int i, count = 0;
 
@@ -2110,11 +2111,13 @@ is_unique_ancestor_worker (struct type *base, struct type *dclass,
 
   for (i = 0; i < TYPE_N_BASECLASSES (dclass) && count < 2; ++i)
     {
-      struct type *iter = check_typedef (TYPE_BASECLASS (dclass, i));
-      int this_offset = baseclass_offset (dclass, i, contents, address);
+      struct type *iter;
+      int this_offset;
 
-      if (this_offset == -1)
-       error (_("virtual baseclass botch"));
+      iter = check_typedef (TYPE_BASECLASS (dclass, i));
+
+      this_offset = baseclass_offset (dclass, i, valaddr, embedded_offset,
+                                     address, val);
 
       if (class_types_same_p (base, iter))
        {
@@ -2136,8 +2139,9 @@ is_unique_ancestor_worker (struct type *base, struct type *dclass,
        }
       else
        count += is_unique_ancestor_worker (base, iter, offset,
-                                           contents + this_offset,
-                                           address + this_offset);
+                                           valaddr,
+                                           embedded_offset + this_offset,
+                                           address, val);
     }
 
   return count;
@@ -2152,8 +2156,9 @@ is_unique_ancestor (struct type *base, struct value *val)
   int offset = -1;
 
   return is_unique_ancestor_worker (base, value_type (val), &offset,
-                                   value_contents (val),
-                                   value_address (val)) == 1;
+                                   value_contents_for_printing (val),
+                                   value_embedded_offset (val),
+                                   value_address (val), val) == 1;
 }
 
 \f
index effac40..3d49a06 100644 (file)
@@ -28,6 +28,7 @@
 #include "demangle.h"
 #include "cp-abi.h"
 #include "cp-support.h"
+#include "exceptions.h"
 
 #include <ctype.h>
 
@@ -334,17 +335,15 @@ vb_match (struct type *type, int index, struct type *basetype)
   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.  */
+/* 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.  */
 
 static int
 gnuv2_baseclass_offset (struct type *type, int index,
-                       const bfd_byte *valaddr, CORE_ADDR address)
+                       const bfd_byte *valaddr, int embedded_offset,
+                       CORE_ADDR address, const struct value *val)
 {
   struct type *basetype = TYPE_BASECLASS (type, index);
 
@@ -360,24 +359,41 @@ gnuv2_baseclass_offset (struct type *type, int index,
        {
          if (vb_match (type, i, basetype))
            {
-             CORE_ADDR addr
-               = unpack_pointer (TYPE_FIELD_TYPE (type, i),
-                                 valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+             struct type *field_type;
+             int field_offset;
+             int field_length;
+             CORE_ADDR addr;
+
+             field_type = check_typedef (TYPE_FIELD_TYPE (type, i));
+             field_offset = TYPE_FIELD_BITPOS (type, i) / 8;
+             field_length = TYPE_LENGTH (field_type);
+
+             if (!value_bytes_available (val, embedded_offset + field_offset,
+                                         field_length))
+               throw_error (NOT_AVAILABLE_ERROR,
+                            _("Virtual baseclass pointer is not available"));
 
-             return addr - (LONGEST) address;
+             addr = unpack_pointer (field_type,
+                                    valaddr + embedded_offset + field_offset);
+
+             return addr - (LONGEST) address + embedded_offset;
            }
        }
       /* Not in the fields, so try looking through the baseclasses.  */
       for (i = index + 1; i < n_baseclasses; i++)
        {
+         /* Don't go through baseclass_offset, as that wraps
+            exceptions, thus, inner exceptions would be wrapped more
+            than once.  */
          int boffset =
-           baseclass_offset (type, i, valaddr, address);
+           gnuv2_baseclass_offset (type, i, valaddr,
+                                   embedded_offset, address, val);
 
          if (boffset)
            return boffset;
        }
-      /* Not found.  */
-      return -1;
+
+      error (_("Baseclass offset not found"));
     }
 
   /* Baseclass is easily computed.  */
index 0b80571..25a437b 100644 (file)
@@ -411,8 +411,9 @@ gnuv3_virtual_fn_field (struct value **value_p,
    -1 is returned on error.  */
 
 static int
-gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
-                       CORE_ADDR address)
+gnuv3_baseclass_offset (struct type *type, int index,
+                       const bfd_byte *valaddr, int embedded_offset,
+                       CORE_ADDR address, const struct value *val)
 {
   struct gdbarch *gdbarch;
   struct type *ptr_type;
@@ -443,7 +444,7 @@ gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
     error (_("Misaligned vbase offset."));
   cur_base_offset = cur_base_offset / ((int) TYPE_LENGTH (ptr_type));
 
-  vtable = gnuv3_get_vtable (gdbarch, type, address);
+  vtable = gnuv3_get_vtable (gdbarch, type, address + embedded_offset);
   gdb_assert (vtable != NULL);
   vbase_array = value_field (vtable, vtable_field_vcall_and_vbase_offsets);
   base_offset = value_as_long (value_subscript (vbase_array, cur_base_offset));
index 7031a77..fc50e2a 100644 (file)
@@ -38,6 +38,7 @@
 #include "p-lang.h"
 #include "cp-abi.h"
 #include "cp-support.h"
+#include "exceptions.h"
 \f
 
 /* See val_print for a description of the various parameters of this
@@ -900,11 +901,13 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
 
   for (i = 0; i < n_baseclasses; i++)
     {
-      int boffset;
+      int boffset = 0;
       struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
       char *basename = type_name_no_tag (baseclass);
-      const gdb_byte *base_valaddr;
+      const gdb_byte *base_valaddr = NULL;
       int thisoffset;
+      volatile struct gdb_exception ex;
+      int skip = 0;
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
        {
@@ -923,7 +926,38 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
 
       thisoffset = offset;
 
-      boffset = baseclass_offset (type, i, valaddr + offset, address + offset);
+      TRY_CATCH (ex, RETURN_MASK_ERROR)
+       {
+         boffset = baseclass_offset (type, i, valaddr, offset, address, val);
+       }
+      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+       skip = -1;
+      else if (ex.reason < 0)
+       skip = 1;
+      else
+       {
+         skip = 0;
+
+         /* The virtual base class pointer might have been clobbered by the
+            user program. Make sure that it still points to a valid memory
+            location.  */
+
+         if (boffset < 0 || boffset >= TYPE_LENGTH (type))
+           {
+             /* FIXME (alloc): not safe is baseclass is really really big. */
+             gdb_byte *buf = alloca (TYPE_LENGTH (baseclass));
+
+             base_valaddr = buf;
+             if (target_read_memory (address + boffset, buf,
+                                     TYPE_LENGTH (baseclass)) != 0)
+               skip = 1;
+             address = address + boffset;
+             thisoffset = 0;
+             boffset = 0;
+           }
+         else
+           base_valaddr = valaddr;
+       }
 
       if (options->pretty)
        {
@@ -937,28 +971,10 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
       fputs_filtered (basename ? basename : "", stream);
       fputs_filtered ("> = ", stream);
 
-      /* The virtual base class pointer might have been clobbered by the
-         user program.  Make sure that it still points to a valid memory
-         location.  */
-
-      if (boffset != -1 && (boffset < 0 || boffset >= TYPE_LENGTH (type)))
-       {
-         /* FIXME (alloc): not safe is baseclass is really really big.  */
-         gdb_byte *buf = alloca (TYPE_LENGTH (baseclass));
-
-         base_valaddr = buf;
-         if (target_read_memory (address + boffset, buf,
-                                 TYPE_LENGTH (baseclass)) != 0)
-           boffset = -1;
-         address = address + boffset;
-         thisoffset = 0;
-         boffset = 0;
-       }
-      else
-       base_valaddr = valaddr;
-
-      if (boffset == -1)
-       fprintf_filtered (stream, "<invalid address>");
+      if (skip < 0)
+       val_print_unavailable (stream);
+      else if (skip > 0)
+       val_print_invalid_address (stream);
       else
        pascal_object_print_value_fields (baseclass, base_valaddr,
                                          thisoffset + boffset, address,
index 0fab274..eb00301 100644 (file)
@@ -1,5 +1,15 @@
 2011-02-14  Pedro Alves  <pedro@codesourcery.com>
 
+       * gdb.trace/unavailable.cc (class Base, class Middle, class
+       Derived): New types.
+       (derived_unavail, derived_partial, derived_whole): New globals.
+       (virtual_partial): New global.
+       (virtualp): Point at virtual_partial.
+       * gdb.trace/unavailable.exp (gdb_collect_globals_test): Add tests
+       related to unavailable vptr.
+
+2011-02-14  Pedro Alves  <pedro@codesourcery.com>
+
        * gdb.trace/unavailable.cc (a, b, c): New globals.
        (main): Set and clear them.
        * gdb.trace/unavailable.exp (gdb_collect_globals_test): Collect
index 7b4a2b2..36b7455 100644 (file)
@@ -133,13 +133,44 @@ struct StructA StructB::static_struct_a;
 StructRef g_structref(0x12345678);
 StructRef *g_structref_p = &g_structref;
 
+class Base
+{
+protected:
+  int x;
+
+public:
+  Base(void) { x = 2; };
+};
+
+class Middle: public virtual Base
+{
+protected:
+  int y;
+
+public:
+  Middle(void): Base() { y = 3; };
+};
+
+class Derived: public virtual Middle {
+protected:
+  int z;
+
+public:
+  Derived(void): Middle() { z = 4; };
+};
+
+Derived derived_unavail;
+Derived derived_partial;
+Derived derived_whole;
+
 struct Virtual {
   int z;
 
   virtual ~Virtual() {}
 };
 
-Virtual *virtualp;
+Virtual virtual_partial;
+Virtual *virtualp = &virtual_partial;
 
 /* Test functions.  */
 
index 8ec6343..ab8fe97 100644 (file)
@@ -87,6 +87,9 @@ proc gdb_collect_globals_test { } {
            "Tracepoint \[0-9\]+ at .*" \
            "set tracepoint"
 
+    # We collect the initial sizeof(pointer) bytes of derived_partial
+    # in an attempt of collecting the vptr.  Not portable, but should
+    # work everywhere we need to care.
     gdb_trace_setactions "define actions" \
        "" \
        "collect struct_b.struct_a.array\[2\]" "^$" \
@@ -106,7 +109,12 @@ proc gdb_collect_globals_test { } {
        "collect g_string_partial\[1\]" "^$" \
        "collect g_string_partial\[2\]" "^$" \
        \
-       "collect g_structref_p" "^$"
+       "collect g_structref_p" "^$" \
+       \
+       "collect *((char *)&derived_partial)@sizeof\(void *\)" "^$" \
+       "collect derived_whole" "^$" \
+       \
+       "collect virtual_partial.z" "^$"
 
     # Begin the test.
     run_trace_experiment globals_test_func
@@ -256,14 +264,54 @@ proc gdb_collect_globals_test { } {
 
     gdb_test_no_output "set print object on"
 
+    set old_pf_prefix_2 $pf_prefix
+    set pf_prefix "$pf_prefix print object on:"
+
     # With print object on, printing a pointer may need to fetch the
     # pointed-to object, to check its run-time type.  Make sure that
     # fails gracefully and transparently when the pointer itself is
     # unavailable.
     gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
 
+    # no vtable pointer available
+    gdb_test "print derived_unavail" \
+       " = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z = <unavailable>}"
+
+    # vtable pointer available, but nothing else
+    gdb_test "print derived_partial" \
+       " = \\(Derived\\) {<Middle> = {<Base> = <unavailable>, _vptr.Middle = <unavailable>, y = <unavailable>}, _vptr.Derived = $hex, z = <unavailable>}"
+
+    # whole object available
+    gdb_test "print derived_whole" \
+       " = \\(Derived\\) {<Middle> = {<Base> = {x = 2}, _vptr.Middle = $hex, y = 3}, _vptr.Derived = $hex, z = 4}"
+
+    set pf_prefix $old_pf_prefix_2
+
     gdb_test_no_output "set print object off"
 
+    set pf_prefix "$pf_prefix print object off:"
+
+    gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
+
+    # no vtable pointer available
+    gdb_test "print derived_unavail" \
+       " = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z = <unavailable>}"
+
+    # vtable pointer available, but nothing else
+    gdb_test "print derived_partial" \
+       " = {<Middle> = {<Base> = <unavailable>, _vptr.Middle = <unavailable>, y = <unavailable>}, _vptr.Derived = $hex, z = <unavailable>}"
+
+    # whole object available
+    gdb_test "print derived_whole" \
+       " = {<Middle> = {<Base> = {x = 2}, _vptr.Middle = $hex, y = 3}, _vptr.Derived = $hex, z = 4}"
+
+    set pf_prefix $old_pf_prefix_2
+
+    # An instance of a virtual class where we collected everything but
+    # the vptr.
+    gdb_test "print virtual_partial" \
+       " = {_vptr.Virtual = <unavailable>, z = 0}"
+
     gdb_test "tfind none" \
        "#0  end .*" \
        "cease trace debugging"
index 1f25a32..5465aba 100644 (file)
@@ -652,8 +652,10 @@ value_reinterpret_cast (struct type *type, struct value *arg)
 
 static int
 dynamic_cast_check_1 (struct type *desired_type,
-                     const bfd_byte *contents,
+                     const gdb_byte *valaddr,
+                     int embedded_offset,
                      CORE_ADDR address,
+                     struct value *val,
                      struct type *search_type,
                      CORE_ADDR arg_addr,
                      struct type *arg_type,
@@ -663,25 +665,25 @@ dynamic_cast_check_1 (struct type *desired_type,
 
   for (i = 0; i < TYPE_N_BASECLASSES (search_type) && result_count < 2; ++i)
     {
-      int offset = baseclass_offset (search_type, i, contents, address);
+      int offset = baseclass_offset (search_type, i, valaddr, embedded_offset,
+                                    address, val);
 
-      if (offset == -1)
-       error (_("virtual baseclass botch"));
       if (class_types_same_p (desired_type, TYPE_BASECLASS (search_type, i)))
        {
-         if (address + offset >= arg_addr
-             && address + offset < arg_addr + TYPE_LENGTH (arg_type))
+         if (address + embedded_offset + offset >= arg_addr
+             && address + embedded_offset + offset < arg_addr + TYPE_LENGTH (arg_type))
            {
              ++result_count;
              if (!*result)
                *result = value_at_lazy (TYPE_BASECLASS (search_type, i),
-                                        address + offset);
+                                        address + embedded_offset + offset);
            }
        }
       else
        result_count += dynamic_cast_check_1 (desired_type,
-                                             contents + offset,
-                                             address + offset,
+                                             valaddr,
+                                             embedded_offset + offset,
+                                             address, val,
                                              TYPE_BASECLASS (search_type, i),
                                              arg_addr,
                                              arg_type,
@@ -697,8 +699,10 @@ dynamic_cast_check_1 (struct type *desired_type,
 
 static int
 dynamic_cast_check_2 (struct type *desired_type,
-                     const bfd_byte *contents,
+                     const gdb_byte *valaddr,
+                     int embedded_offset,
                      CORE_ADDR address,
+                     struct value *val,
                      struct type *search_type,
                      struct value **result)
 {
@@ -711,20 +715,20 @@ dynamic_cast_check_2 (struct type *desired_type,
       if (! BASETYPE_VIA_PUBLIC (search_type, i))
        continue;
 
-      offset = baseclass_offset (search_type, i, contents, address);
-      if (offset == -1)
-       error (_("virtual baseclass botch"));
+      offset = baseclass_offset (search_type, i, valaddr, embedded_offset,
+                                address, val);
       if (class_types_same_p (desired_type, TYPE_BASECLASS (search_type, i)))
        {
          ++result_count;
          if (*result == NULL)
            *result = value_at_lazy (TYPE_BASECLASS (search_type, i),
-                                    address + offset);
+                                    address + embedded_offset + offset);
        }
       else
        result_count += dynamic_cast_check_2 (desired_type,
-                                             contents + offset,
-                                             address + offset,
+                                             valaddr,
+                                             embedded_offset + offset,
+                                             address, val,
                                              TYPE_BASECLASS (search_type, i),
                                              result);
     }
@@ -822,7 +826,9 @@ value_dynamic_cast (struct type *type, struct value *arg)
        return tem;
       result = NULL;
       if (dynamic_cast_check_1 (TYPE_TARGET_TYPE (resolved_type),
-                               value_contents (tem), value_address (tem),
+                               value_contents_for_printing (tem),
+                               value_embedded_offset (tem),
+                               value_address (tem), tem,
                                rtti_type, addr,
                                arg_type,
                                &result) == 1)
@@ -834,7 +840,9 @@ value_dynamic_cast (struct type *type, struct value *arg)
   result = NULL;
   if (is_public_ancestor (arg_type, rtti_type)
       && dynamic_cast_check_2 (TYPE_TARGET_TYPE (resolved_type),
-                              value_contents (tem), value_address (tem),
+                              value_contents_for_printing (tem),
+                              value_embedded_offset (tem),
+                              value_address (tem), tem,
                               rtti_type, &result) == 1)
     return value_cast (type,
                       is_ref ? value_ref (result) : value_addr (result));
@@ -1323,6 +1331,7 @@ value_assign (struct value *toval, struct value *fromval)
                int offset = value_offset (parent) + value_offset (toval);
                int changed_len;
                gdb_byte buffer[sizeof (LONGEST)];
+               int optim, unavail;
 
                changed_len = (value_bitpos (toval)
                               + value_bitsize (toval)
@@ -2075,12 +2084,10 @@ search_struct_field (const char *name, struct value *arg1, int offset,
          struct value *v2;
 
          boffset = baseclass_offset (type, i,
-                                     value_contents (arg1) + offset,
-                                     value_address (arg1)
-                                     + value_embedded_offset (arg1)
-                                     + offset);
-         if (boffset == -1)
-           error (_("virtual baseclass botch"));
+                                     value_contents_for_printing (arg1),
+                                     value_embedded_offset (arg1) + offset,
+                                     value_address (arg1),
+                                     arg1);
 
          /* The virtual base class pointer might have been clobbered
             by the user program.  Make sure that it still points to a
@@ -2202,10 +2209,13 @@ search_struct_method (const char *name, struct value **arg1p,
   for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
     {
       int base_offset;
+      int skip = 0;
+      int this_offset;
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
        {
          struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+         struct value *base_val;
          const gdb_byte *base_valaddr;
 
          /* The virtual base class pointer might have been
@@ -2215,19 +2225,28 @@ search_struct_method (const char *name, struct value **arg1p,
          if (offset < 0 || offset >= TYPE_LENGTH (type))
            {
              gdb_byte *tmp = alloca (TYPE_LENGTH (baseclass));
+             CORE_ADDR address = value_address (*arg1p);
 
-             if (target_read_memory (value_address (*arg1p) + offset,
+             if (target_read_memory (address + offset,
                                      tmp, TYPE_LENGTH (baseclass)) != 0)
                error (_("virtual baseclass botch"));
-             base_valaddr = tmp;
+
+             base_val = value_from_contents_and_address (baseclass,
+                                                         tmp,
+                                                         address + offset);
+             base_valaddr = value_contents_for_printing (base_val);
+             this_offset = 0;
            }
          else
-           base_valaddr = value_contents (*arg1p) + offset;
+           {
+             base_val = *arg1p;
+             base_valaddr = value_contents_for_printing (*arg1p);
+             this_offset = offset;
+           }
 
          base_offset = baseclass_offset (type, i, base_valaddr,
-                                         value_address (*arg1p) + offset);
-         if (base_offset == -1)
-           error (_("virtual baseclass botch"));
+                                         this_offset, value_address (base_val),
+                                         base_val);
        }
       else
        {
@@ -2405,12 +2424,10 @@ find_method_list (struct value **argp, const char *method,
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
        {
-         base_offset = value_offset (*argp) + offset;
          base_offset = baseclass_offset (type, i,
-                                         value_contents (*argp) + base_offset,
-                                         value_address (*argp) + base_offset);
-         if (base_offset == -1)
-           error (_("virtual baseclass botch"));
+                                         value_contents_for_printing (*argp),
+                                         value_offset (*argp) + offset,
+                                         value_address (*argp), *argp);
        }
       else /* Non-virtual base, simply use bit position from debug
              info.  */
index fd573c2..286ef9e 100644 (file)
@@ -305,6 +305,12 @@ val_print_unavailable (struct ui_file *stream)
   fprintf_filtered (stream, _("<unavailable>"));
 }
 
+void
+val_print_invalid_address (struct ui_file *stream)
+{
+  fprintf_filtered (stream, _("<invalid address>"));
+}
+
 /* Print using the given LANGUAGE the data of type TYPE located at
    VALADDR + EMBEDDED_OFFSET (within GDB), which came from the
    inferior at address ADDRESS + EMBEDDED_OFFSET, onto stdio stream
index 542a13a..b6ea7a9 100644 (file)
@@ -156,4 +156,6 @@ extern void val_print_optimized_out (struct ui_file *stream);
 
 extern void val_print_unavailable (struct ui_file *stream);
 
+extern void val_print_invalid_address (struct ui_file *stream);
+
 #endif
index 236b42f..3b4d23a 100644 (file)
@@ -39,7 +39,7 @@
 #include "objfiles.h"
 #include "valprint.h"
 #include "cli/cli-decode.h"
-
+#include "exceptions.h"
 #include "python/python.h"
 
 #include "tracepoint.h"
@@ -826,7 +826,7 @@ static void
 require_available (const struct value *value)
 {
   if (!VEC_empty (range_s, value->unavailable))
-    error (_("value is not available"));
+    throw_error (NOT_AVAILABLE_ERROR, _("value is not available"));
 }
 
 const gdb_byte *