* 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.
This commit is contained in:
Pedro Alves 2011-02-14 11:35:45 +00:00
parent 1b28d0b3be
commit 8af8e3bc81
16 changed files with 385 additions and 146 deletions

View file

@ -1,3 +1,56 @@
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

View 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 *

View 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.
/* 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. */
-1 is returned on error. */
extern int baseclass_offset (struct type *type,
int index, const gdb_byte *valaddr,
int embedded_offset,
CORE_ADDR address,
const struct value *val);
extern int baseclass_offset (struct type *type, int index,
const bfd_byte *valaddr,
CORE_ADDR address);
/* 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);

View 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));
/* 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 (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);
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;

View 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
};

View 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;
}

View 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;
return addr - (LONGEST) address;
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"));
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. */

View 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));

View file

@ -38,6 +38,7 @@
#include "p-lang.h"
#include "cp-abi.h"
#include "cp-support.h"
#include "exceptions.h"
/* 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,

View file

@ -1,3 +1,13 @@
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.

View 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. */

View 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"

View 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. */

View 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

View 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

View 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 *