(Changes from Daniel Berlin, with revisions by Jim Blandy.)

Abstract out operations specific to particular C++ ABI's, and
invoke them through a function table.  This removes the C++ ABI
dependencies scattered throughout the code, and allows us to
cleanly add support for new C++ ABI's.
* cp-abi.h, cp-abi.h, gnu-v2-abi.c, hpacc-abi.c: New files.
* c-typeprint.c, c-valprint.c, dbxread.c, eval.c, gdbtypes.c,
jv-typeprint.c, linespec.c, symtab.c, typeprint.c, valops.c:
#include "cp-abi.h".  These files all use functions now declared
there.
* symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P):
Deleted.  These services are now provided by functions declared in
cp-abi.h.
* value.h (value_rtti_type, value_virtual_fn_field): Same.
* values.c (value_virtual_fn_field): Same, for this definition.
* valops.c (value_rtti_type): Same.
* c-typeprint.c (c_type_print_base): Use the functions from
"cp-abi.h", instead of the old macros, or hard-coded ABI-specific
tests.
* dbxread.c (record_minimal_symbol): Same.
* gdbtypes.c (get_destructor_fn_field, virtual_base_index,
virtual_base_index_skip_primaries): Same.
* jv-typeprint.c (java_type_print_base): Same.
* linespec.c (find_methods, decode_line_1): Same.
* symtab.c (gdb_mangle_name): Same.
* Makefile.in (SFILES): Add the new .c files mentioned above.
(cp_abi_h): New variable.
(COMMON_OBS): Add gnu-v2-abi.o, hpacc-abi.o, and cp-abi.o.
(cp-abi.o, gnu-v2-abi.o, hpacc-abi.o): New targets.
(c-typeprint.o, c-valprint.o, dbxread.o, eval.o, gdbtypes.o,
jv-typeprint.o, symtab.o, linespec.o, typeprint.o, valops.o): Add
dependency on $(cp_abi_h).
This commit is contained in:
Jim Blandy 2001-04-27 00:19:09 +00:00
parent 20b8570d73
commit 015a42b4cf
19 changed files with 972 additions and 478 deletions

View File

@ -1,3 +1,39 @@
2001-04-26 Jim Blandy <jimb@redhat.com>
(Changes from Daniel Berlin, with revisions by Jim Blandy.)
Abstract out operations specific to particular C++ ABI's, and
invoke them through a function table. This removes the C++ ABI
dependencies scattered throughout the code, and allows us to
cleanly add support for new C++ ABI's.
* cp-abi.h, cp-abi.h, gnu-v2-abi.c, hpacc-abi.c: New files.
* c-typeprint.c, c-valprint.c, dbxread.c, eval.c, gdbtypes.c,
jv-typeprint.c, linespec.c, symtab.c, typeprint.c, valops.c:
#include "cp-abi.h". These files all use functions now declared
there.
* symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P):
Deleted. These services are now provided by functions declared in
cp-abi.h.
* value.h (value_rtti_type, value_virtual_fn_field): Same.
* values.c (value_virtual_fn_field): Same, for this definition.
* valops.c (value_rtti_type): Same.
* c-typeprint.c (c_type_print_base): Use the functions from
"cp-abi.h", instead of the old macros, or hard-coded ABI-specific
tests.
* dbxread.c (record_minimal_symbol): Same.
* gdbtypes.c (get_destructor_fn_field, virtual_base_index,
virtual_base_index_skip_primaries): Same.
* jv-typeprint.c (java_type_print_base): Same.
* linespec.c (find_methods, decode_line_1): Same.
* symtab.c (gdb_mangle_name): Same.
* Makefile.in (SFILES): Add the new .c files mentioned above.
(cp_abi_h): New variable.
(COMMON_OBS): Add gnu-v2-abi.o, hpacc-abi.o, and cp-abi.o.
(cp-abi.o, gnu-v2-abi.o, hpacc-abi.o): New targets.
(c-typeprint.o, c-valprint.o, dbxread.o, eval.o, gdbtypes.o,
jv-typeprint.o, symtab.o, linespec.o, typeprint.o, valops.o): Add
dependency on $(cp_abi_h).
2001-04-26 Michael Snyder <msnyder@redhat.com>
* thread-db.c (_initialize_thread_db): Add set/show command

View File

@ -539,7 +539,8 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c \
ui-file.h ui-file.c \
frame.c
frame.c \
gnu-v2-abi.c hpacc-abi.c cp-abi.c
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@ -613,6 +614,8 @@ cli_script_h = $(srcdir)/cli/cli-script.h
cli_setshow_h = $(srcdir)/cli/cli-setshow.h
cli_utils_h = $(srcdir)/cli/cli-utils.h
cp_abi_h = cp-abi.h
# Header files that need to have srcdir added. Note that in the cases
# where we use a macro like $(gdbcmd_h), things are carefully arranged
# so that each .h file is listed exactly once (M-x tags-search works
@ -686,7 +689,8 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
ui-file.o tui-file.o \
frame.o
frame.o \
gnu-v2-abi.o hpacc-abi.o cp-abi.o
OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
@ -1222,10 +1226,10 @@ c-lang.o: c-lang.c c-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
c-typeprint.o: c-typeprint.c c-lang.h $(defs_h) $(expression_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
target.h typeprint.h $(value_h) gdb_string.h
target.h typeprint.h $(value_h) gdb_string.h $(cp_abi_h)
c-valprint.o: c-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
language.h $(symtab_h) valprint.h $(value_h)
language.h $(symtab_h) valprint.h $(value_h) $(cp_abi_h)
f-lang.o: f-lang.c f-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
language.h parser-defs.h $(symtab_h) gdb_string.h
@ -1278,6 +1282,8 @@ corefile.o: corefile.c $(dis-asm_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
corelow.o: corelow.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
target.h gdbthread.h gdb_string.h $(regcache_h)
cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h)
cp-valprint.o: cp-valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h
@ -1287,7 +1293,7 @@ dcache.o: dcache.c $(dcache_h) $(defs_h) $(gdbcmd_h) gdb_string.h \
dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
$(gdbtypes_h) language.h objfiles.h partial-stab.h stabsread.h \
symfile.h $(symtab_h) target.h gdb_string.h
symfile.h $(symtab_h) target.h gdb_string.h $(cp_abi_h)
delta68-nat.o: delta68-nat.c $(defs_h)
@ -1317,7 +1323,7 @@ environ.o: environ.c $(defs_h) environ.h $(gdbcore_h) gdb_string.h
eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
$(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
gdb_string.h
gdb_string.h $(cp_abi_h)
event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_h) $(event_top_h)
@ -1446,7 +1452,7 @@ arch-utils.o: arch-utils.c $(defs_h) $(bfd_h) $(gdbcmd_h) \
gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
$(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
$(value_h) gdb_string.h wrapper.h
$(value_h) gdb_string.h wrapper.h $(cp_abi_h)
go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) gdb_wait.h $(gdbcore_h) \
$(command_h) $(floatformat_h) target.h i387-nat.h $(regcache_h)
@ -1454,6 +1460,9 @@ go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) gdb_wait.h $(gdbcore_h) \
gnu-nat.o: process_reply_S.h exc_request_S.h notify_S.h msg_reply_S.h \
exc_request_U.h msg_U.h gnu-nat.h
gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(cp_abi_h) gdb_string.h $(symtab_h) \
$(gdbtypes_h) $(value_h)
h8300-tdep.o: h8300-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(regcache_h)
h8500-tdep.o: h8500-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) \
@ -1462,6 +1471,9 @@ h8500-tdep.o: h8500-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) \
hp300ux-nat.o: hp300ux-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)
hpacc-abi.o: hpacc-abi.c $(defs_h) $(cp_abi_h) gdb_string.h $(gdbtypes_h) \
$(value_h) $(gdbcore_h)
hppa-tdep.o: hppa-tdep.c gdb_wait.h $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) objfiles.h symfile.h target.h $(regcache_h)
@ -1551,7 +1563,7 @@ jv-lang.o: jv-lang.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
jv-typeprint.o: jv-typeprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(demangle_h) jv-lang.h gdb_string.h \
typeprint.h c-lang.h
typeprint.h c-lang.h $(cp_abi_h)
jv-valprint.o: jv-valprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(value_h) $(demangle_h) valprint.h \
@ -1958,11 +1970,11 @@ symmisc.o: symmisc.c $(bfd_h) $(breakpoint_h) $(command_h) $(defs_h) \
symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \
$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) \
gdb_string.h linespec.h
gdb_string.h linespec.h $(cp_abi_h)
linespec.o: linespec.c linespec.h $(defs_h) $(frame_h) $(value_h) \
objfiles.h symfile.h completer.h $(symtab_h) \
$(demangle_h) command.h
$(demangle_h) command.h $(cp_abi_h)
tic80-tdep.o: tic80-tdep.c $(defs_h) $(regcache_h)
@ -1981,7 +1993,7 @@ top.o: top.c top.h $(bfd_h) $(getopt_h) $(readline_headers) call-cmds.h \
typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
$(value_h) gdb_string.h
$(value_h) gdb_string.h $(cp_abi.h)
# OBSOLETE ultra3-nat.o: ultra3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)
@ -1998,7 +2010,7 @@ valarith.o: valarith.c $(bfd_h) $(defs_h) $(expression_h) \
gdb_string.h
valops.o: valops.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
gdb_string.h $(regcache_h)
gdb_string.h $(regcache_h) $(cp_abi_h)
valprint.o: valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \

View File

@ -33,6 +33,7 @@
#include "demangle.h"
#include "c-lang.h"
#include "typeprint.h"
#include "cp-abi.h"
#include "gdb_string.h"
#include <errno.h>
@ -904,11 +905,10 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
{
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
int is_full_physname_constructor =
((physname[0] == '_' && physname[1] == '_'
&& strchr ("0123456789Qt", physname[2]))
|| STREQN (physname, "__ct__", 6)
|| DESTRUCTOR_PREFIX_P (physname)
|| STREQN (physname, "__dt__", 6));
is_constructor_name (physname)
|| is_destructor_name (physname)
|| method_name[0] == '~';
QUIT;
if (TYPE_FN_FIELD_PROTECTED (f, j))

View File

@ -28,6 +28,7 @@
#include "valprint.h"
#include "language.h"
#include "c-lang.h"
#include "cp-abi.h"
/* Print function pointer with inferior address ADDRESS onto stdio
@ -303,6 +304,7 @@ c_val_print (struct type *type, char *valaddr, int embedded_offset,
}
/* Fall through. */
case TYPE_CODE_STRUCT:
/*FIXME: Abstract this away */
if (vtblprint && cp_is_vtbl_ptr_type (type))
{
/* Print the unmangled name if desired. */

99
gdb/cp-abi.c Normal file
View File

@ -0,0 +1,99 @@
/* Generic code for supporting multiple C++ ABI's
Copyright 2001 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "value.h"
#include "cp-abi.h"
struct cp_abi_ops current_cp_abi;
struct cp_abi_ops *cp_abis;
int num_cp_abis = 0;
enum ctor_kinds
is_constructor_name (const char *name)
{
if ((current_cp_abi.is_constructor_name) == NULL)
error ("ABI doesn't define required function is_constructor_name");
return (*current_cp_abi.is_constructor_name) (name);
}
enum dtor_kinds
is_destructor_name (const char *name)
{
if ((current_cp_abi.is_destructor_name) == NULL)
error ("ABI doesn't define required function is_destructor_name");
return (*current_cp_abi.is_destructor_name) (name);
}
int
is_vtable_name (const char *name)
{
if ((current_cp_abi.is_vtable_name) == NULL)
error ("ABI doesn't define required function is_vtable_name");
return (*current_cp_abi.is_vtable_name) (name);
}
int
is_operator_name (const char *name)
{
if ((current_cp_abi.is_operator_name) == NULL)
error ("ABI doesn't define required function is_operator_name");
return (*current_cp_abi.is_operator_name) (name);
}
value_ptr
value_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
struct type * type, int offset)
{
if ((current_cp_abi.virtual_fn_field) == NULL)
return NULL;
return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
}
struct type *
value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
{
if ((current_cp_abi.rtti_type) == NULL)
return NULL;
return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
}
int
register_cp_abi (struct cp_abi_ops abi)
{
cp_abis =
xrealloc (cp_abis, (num_cp_abis + 1) * sizeof (struct cp_abi_ops));
cp_abis[num_cp_abis++] = abi;
return 1;
}
int
switch_to_cp_abi (const char *short_name)
{
int i;
for (i = 0; i < num_cp_abis; i++)
if (strcmp (cp_abis[i].shortname, short_name) == 0)
current_cp_abi = cp_abis[i];
return 1;
}

131
gdb/cp-abi.h Normal file
View File

@ -0,0 +1,131 @@
/* Abstraction of various C++ ABI's we support, and the info we need
to get from them.
Contributed by Daniel Berlin <dberlin@redhat.com>
Copyright 2001 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or
modify
it under the terms of the GNU General Public License as published
by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef CP_ABI_H_
#define CP_ABI_H_ 1
/* Kinds of constructors. All these values are guaranteed to be
non-zero. */
enum ctor_kinds {
/* Initialize a complete object, including virtual bases, using
memory provided by caller. */
complete_object_ctor = 1,
/* Initialize a base object of some larger object. */
base_object_ctor,
/* An allocating complete-object constructor. */
complete_object_allocating_ctor
};
/* Kinds of destructors. All these values are guaranteed to be
non-zero. */
enum dtor_kinds {
/* A destructor which finalizes the entire object, and then calls
`delete' on its storage. */
deleting_dtor = 1,
/* A destructor which finalizes the entire object, but does not call
`delete'. */
complete_object_dtor,
/* A destructor which finalizes a subobject of some larger object. */
base_object_dtor
};
struct cp_abi_ops
{
const char *shortname;
const char *longname;
const char *doc;
/* The functions here that attempt to determine what sort of thing a
mangled name refers to may well be revised in the future. It
would certainly be cleaner to carry this information explicitly
in GDB's data structures than to derive it from the mangled name. */
/* Return non-zero iff NAME is the mangled name of a constructor.
Actually, return an `enum ctor_kind' value describing what *kind*
of constructor it is. */
enum ctor_kinds (*is_constructor_name) (const char *name);
/* Return non-zero iff NAME is the mangled name of a destructor.
Actually, return an `enum dtor_kind' value describing what *kind*
of destructor it is. */
enum dtor_kinds (*is_destructor_name) (const char *name);
/* Return non-zero iff NAME is the mangled name of a vtable. */
int (*is_vtable_name) (const char *name);
/* Return non-zero iff NAME is the un-mangled name of an operator,
perhaps scoped within some class. */
int (*is_operator_name) (const char *name);
value_ptr (*virtual_fn_field) (value_ptr * arg1p, struct fn_field * f,
int j, struct type * type, int offset);
/* Find the real run-time type of a value using RTTI.
* V is a pointer to the value.
* A pointer to the struct type entry of the run-time type
* is returneed.
* FULL is a flag that is set only if the value V includes
* the entire contents of an object of the RTTI type.
* TOP is the offset to the top of the enclosing object of
* the real run-time type. This offset may be for the embedded
* object, or for the enclosing object of V.
* USING_ENC is the flag that distinguishes the two cases.
* If it is 1, then the offset is for the enclosing object,
* otherwise for the embedded object.
*
*/
struct type *(*rtti_type) (value_ptr v, int *full, int *top,
int *using_enc);
};
extern struct cp_abi_ops *cp_abis;
extern int num_cp_abis;
extern struct cp_abi_ops current_cp_abi;
extern enum ctor_kinds is_constructor_name (const char *name);
extern enum dtor_kinds is_destructor_name (const char *name);
extern int is_vtable_name (const char *name);
extern int is_operator_name (const char *name);
extern value_ptr value_virtual_fn_field (value_ptr * arg1p,
struct fn_field *f, int j,
struct type *type, int offset);
extern struct type *value_rtti_type (value_ptr v, int *full, int *top,
int *using_enc);
extern int register_cp_abi (struct cp_abi_ops abi);
extern int switch_to_cp_abi (const char *short_name);
#endif

View File

@ -57,6 +57,7 @@
#include "demangle.h"
#include "language.h" /* Needed inside partial-stab.h */
#include "complaints.h"
#include "cp-abi.h"
#include "aout/aout64.h"
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
@ -514,7 +515,7 @@ record_minimal_symbol (char *name, CORE_ADDR address, int type,
char *tempstring = name;
if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
++tempstring;
if (VTBL_PREFIX_P ((tempstring)))
if (is_vtable_name (tempstring))
ms_type = mst_data;
}
section = SECT_OFF_DATA (objfile);

View File

@ -30,6 +30,7 @@
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
#include "cp-abi.h"
/* Defined in symtab.c */
extern int hp_som_som_object_present;

View File

@ -35,6 +35,7 @@
#include "complaints.h"
#include "gdbcmd.h"
#include "wrapper.h"
#include "cp-abi.h"
/* These variables point to the objects
representing the predefined C data types. */
@ -1027,7 +1028,7 @@ get_destructor_fn_field (struct type *t, int *method_indexp, int *field_indexp)
for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (t, i); j++)
{
if (DESTRUCTOR_PREFIX_P (TYPE_FN_FIELD_PHYSNAME (f, j)))
if (is_destructor_name (TYPE_FN_FIELD_PHYSNAME (f, j)) != 0)
{
*method_indexp = i;
*field_indexp = j;
@ -1902,12 +1903,12 @@ virtual_base_index (struct type *base, struct type *dclass)
return -1;
i = 0;
vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[0];
vbase = virtual_base_list (dclass)[0];
while (vbase)
{
if (vbase == base)
break;
vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[++i];
vbase = virtual_base_list (dclass)[++i];
}
return vbase ? i : -1;
@ -1936,14 +1937,14 @@ virtual_base_index_skip_primaries (struct type *base, struct type *dclass)
j = -1;
i = 0;
vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[0];
vbase = virtual_base_list (dclass)[0];
while (vbase)
{
if (!primary || (virtual_base_index_skip_primaries (vbase, primary) < 0))
j++;
if (vbase == base)
break;
vbase = TYPE_VIRTUAL_BASE_LIST (dclass)[++i];
vbase = virtual_base_list (dclass)[++i];
}
return vbase ? j : -1;

332
gdb/gnu-v2-abi.c Normal file
View File

@ -0,0 +1,332 @@
/* Abstraction of GNU v2 abi.
Contributed by Daniel Berlin <dberlin@redhat.com>
Copyright 2001 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or
modify
it under the terms of the GNU General Public License as published
by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdb_regex.h"
#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "demangle.h"
#include "cp-abi.h"
#include <ctype.h>
struct cp_abi_ops gnu_v2_abi_ops;
static int vb_match (struct type *, int, struct type *);
static enum dtor_kinds
gnuv2_is_destructor_name (const char *name)
{
if ((name[0] == '_' && is_cplus_marker (name[1]) && name[2] == '_')
|| strncmp (name, "__dt__", 6) == 0)
return complete_object_dtor;
else
return 0;
}
static enum ctor_kinds
gnuv2_is_constructor_name (const char *name)
{
if ((name[0] == '_' && name[1] == '_'
&& (isdigit (name[2]) || strchr ("Qt", name[2])))
|| strncmp (name, "__ct__", 6) == 0)
return complete_object_ctor;
else
return 0;
}
static int
gnuv2_is_vtable_name (const char *name)
{
return (((name)[0] == '_'
&& (((name)[1] == 'V' && (name)[2] == 'T')
|| ((name)[1] == 'v' && (name)[2] == 't'))
&& is_cplus_marker ((name)[3])) ||
((name)[0] == '_' && (name)[1] == '_'
&& (name)[2] == 'v' && (name)[3] == 't' && (name)[4] == '_'));
}
static int
gnuv2_is_operator_name (const char *name)
{
return strncmp (name, "operator", 8) == 0;
}
/* Return a virtual function as a value.
ARG1 is the object which provides the virtual function
table pointer. *ARG1P is side-effected in calling this function.
F is the list of member functions which contains the desired virtual
function.
J is an index into F which provides the desired virtual function.
TYPE is the type in which F is located. */
static value_ptr
gnuv2_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
struct type * type, int offset)
{
value_ptr arg1 = *arg1p;
struct type *type1 = check_typedef (VALUE_TYPE (arg1));
struct type *entry_type;
/* First, get the virtual function table pointer. That comes
with a strange type, so cast it to type `pointer to long' (which
should serve just fine as a function type). Then, index into
the table, and convert final value to appropriate function type. */
value_ptr entry, vfn, vtbl;
value_ptr vi = value_from_longest (builtin_type_int,
(LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
struct type *context;
if (fcontext == NULL)
/* We don't have an fcontext (e.g. the program was compiled with
g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
This won't work right for multiple inheritance, but at least we
should do as well as GDB 3.x did. */
fcontext = TYPE_VPTR_BASETYPE (type);
context = lookup_pointer_type (fcontext);
/* Now context is a pointer to the basetype containing the vtbl. */
if (TYPE_TARGET_TYPE (context) != type1)
{
value_ptr tmp = value_cast (context, value_addr (arg1));
VALUE_POINTED_TO_OFFSET (tmp) = 0;
arg1 = value_ind (tmp);
type1 = check_typedef (VALUE_TYPE (arg1));
}
context = type1;
/* Now context is the basetype containing the vtbl. */
/* This type may have been defined before its virtual function table
was. If so, fill in the virtual function table entry for the
type now. */
if (TYPE_VPTR_FIELDNO (context) < 0)
fill_in_vptr_fieldno (context);
/* The virtual function table is now an array of structures
which have the form { int16 offset, delta; void *pfn; }. */
vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
TYPE_VPTR_BASETYPE (context));
/* With older versions of g++, the vtbl field pointed to an array
of structures. Nowadays it points directly to the structure. */
if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
{
/* Handle the case where the vtbl field points to an
array of structures. */
vtbl = value_ind (vtbl);
/* Index into the virtual function table. This is hard-coded because
looking up a field is not cheap, and it may be important to save
time, e.g. if the user has set a conditional breakpoint calling
a virtual function. */
entry = value_subscript (vtbl, vi);
}
else
{
/* Handle the case where the vtbl field points directly to a structure. */
vtbl = value_add (vtbl, vi);
entry = value_ind (vtbl);
}
entry_type = check_typedef (VALUE_TYPE (entry));
if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
{
/* Move the `this' pointer according to the virtual function table. */
VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
if (!VALUE_LAZY (arg1))
{
VALUE_LAZY (arg1) = 1;
value_fetch_lazy (arg1);
}
vfn = value_field (entry, 2);
}
else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
vfn = entry;
else
error ("I'm confused: virtual function table has bad type");
/* Reinstantiate the function pointer with the correct type. */
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
*arg1p = arg1;
return vfn;
}
struct type *
gnuv2_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
{
struct type *known_type;
struct type *rtti_type;
CORE_ADDR coreptr;
value_ptr vp;
int using_enclosing = 0;
long top_offset = 0;
char rtti_type_name[256];
CORE_ADDR vtbl;
struct minimal_symbol *minsym;
struct symbol *sym;
char *demangled_name;
struct type *btype;
if (full)
*full = 0;
if (top)
*top = -1;
if (using_enc)
*using_enc = 0;
/* Get declared type */
known_type = VALUE_TYPE (v);
CHECK_TYPEDEF (known_type);
/* RTTI works only or class objects */
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL;
/* Plan on this changing in the future as i get around to setting
the vtables properly for G++ compiled stuff. Also, I'll be using
the type info functions, which are always right. Deal with it
until then. */
/* If the type has no vptr fieldno, try to get it filled in */
if (TYPE_VPTR_FIELDNO(known_type) < 0)
fill_in_vptr_fieldno(known_type);
/* If we still can't find one, give up */
if (TYPE_VPTR_FIELDNO(known_type) < 0)
return NULL;
/* Make sure our basetype and known type match, otherwise, cast
so we can get at the vtable properly.
*/
btype = TYPE_VPTR_BASETYPE (known_type);
CHECK_TYPEDEF (btype);
if (btype != known_type )
{
v = value_cast (btype, v);
if (using_enc)
*using_enc=1;
}
/*
We can't use value_ind here, because it would want to use RTTI, and
we'd waste a bunch of time figuring out we already know the type.
Besides, we don't care about the type, just the actual pointer
*/
if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
return NULL;
/*
If we are enclosed by something that isn't us, adjust the
address properly and set using_enclosing.
*/
if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
{
value_ptr tempval;
int bitpos = TYPE_BASECLASS_BITPOS (known_type,
TYPE_VPTR_FIELDNO (known_type));
tempval=value_field (v, TYPE_VPTR_FIELDNO(known_type));
VALUE_ADDRESS(tempval) += bitpos / 8;
vtbl=value_as_pointer (tempval);
using_enclosing=1;
}
else
{
vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
using_enclosing=0;
}
/* Try to find a symbol that is the vtable */
minsym=lookup_minimal_symbol_by_pc(vtbl);
if (minsym==NULL
|| (demangled_name=SYMBOL_NAME(minsym))==NULL
|| !is_vtable_name (demangled_name))
return NULL;
/* If we just skip the prefix, we get screwed by namespaces */
demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
*(strchr(demangled_name,' '))=0;
/* Lookup the type for the name */
rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
if (rtti_type==NULL)
return NULL;
if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
{
if (top)
*top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
if (top && ((*top) >0))
{
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
{
if (full)
*full=0;
}
else
{
if (full)
*full=1;
}
}
}
else
{
if (full)
*full=1;
}
if (using_enc)
*using_enc=using_enclosing;
return rtti_type;
}
static void
init_gnuv2_ops (void)
{
gnu_v2_abi_ops.shortname = "gnu-v2";
gnu_v2_abi_ops.longname = "GNU G++ Version 2 ABI";
gnu_v2_abi_ops.doc = "G++ Version 2 ABI";
gnu_v2_abi_ops.is_destructor_name = gnuv2_is_destructor_name;
gnu_v2_abi_ops.is_constructor_name = gnuv2_is_constructor_name;
gnu_v2_abi_ops.is_vtable_name = gnuv2_is_vtable_name;
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;
}
void
_initialize_gnu_v2_abi (void)
{
init_gnuv2_ops ();
register_cp_abi (gnu_v2_abi_ops);
switch_to_cp_abi ("gnu-v2");
}

321
gdb/hpacc-abi.c Normal file
View File

@ -0,0 +1,321 @@
/* Abstraction of HP aCC ABI.
Contributed by Daniel Berlin <dberlin@redhat.com>
Most of the real code is from HP, i've just fiddled it to fit in
the C++ ABI abstraction framework.
Copyright 2001 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or
modify
it under the terms of the GNU General Public License as published
by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "value.h"
#include "gdb_regex.h"
#include "gdb_string.h"
#include "gdbtypes.h"
#include "gdbcore.h"
#include "cp-abi.h"
struct cp_abi_ops hpacc_abi_ops;
/* It appears the is_*_name stuff is never used when we try the hpACC
* ABI. As such, I have no clue what the real answers are. Shouldn't
* have any more effect than it does now. */
static regex_t constructor_pattern;
static regex_t destructor_pattern;
static regex_t operator_pattern;
static enum dtor_kinds
hpacc_is_destructor_name (const char *name)
{
if (regexec (&destructor_pattern, name, 0, 0, 0) == 0)
return complete_object_dtor;
else
return 0;
}
static enum ctor_kinds
hpacc_is_constructor_name (const char *name)
{
if (regexec (&constructor_pattern, name, 0, 0, 0) == 0)
return complete_object_ctor;
else
return 0;
}
static int
hpacc_is_operator_name (const char *name)
{
return regexec (&operator_pattern, name, 0, 0, 0) == 0;
}
static int
hpacc_is_vtable_name (const char *name)
{
return strcmp (name,
"This will never match anything, please fill it in") == 0;
}
/* Return a virtual function as a value.
ARG1 is the object which provides the virtual function
table pointer. *ARG1P is side-effected in calling this function.
F is the list of member functions which contains the desired virtual
function.
J is an index into F which provides the desired virtual function.
TYPE is the type in which F is located. */
static value_ptr
hpacc_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j,
struct type * type, int offset)
{
value_ptr arg1 = *arg1p;
struct type *type1 = check_typedef (VALUE_TYPE (arg1));
/* Deal with HP/Taligent runtime model for virtual functions */
value_ptr vp;
value_ptr argp; /* arg1 cast to base */
CORE_ADDR coreptr; /* pointer to target address */
int class_index; /* which class segment pointer to use */
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
argp = value_cast (type, *arg1p);
if (VALUE_ADDRESS (argp) == 0)
error ("Address of object is null; object may not have been created.");
/* pai: FIXME -- 32x64 possible problem? */
/* First word (4 bytes) in object layout is the vtable pointer */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
/* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
if (!coreptr)
error
("Virtual table pointer is null for object; object may not have been created.");
/* pai/1997-05-09
* FIXME: The code here currently handles only
* the non-RRBC case of the Taligent/HP runtime spec; when RRBC
* is introduced, the condition for the "if" below will have to
* be changed to be a test for the RRBC case. */
if (1)
{
/* Non-RRBC case; the virtual function pointers are stored at fixed
* offsets in the virtual table. */
/* Retrieve the offset in the virtual table from the debug
* info. The offset of the vfunc's entry is in words from
* the beginning of the vtable; but first we have to adjust
* by HP_ACC_VFUNC_START to account for other entries */
/* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
* which case the multiplier should be 8 and values should be long */
vp = value_at (builtin_type_int,
coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) +
HP_ACC_VFUNC_START), NULL);
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
/* coreptr now contains the address of the virtual function */
/* (Actually, it contains the pointer to the plabel for the function. */
}
else
{
/* RRBC case; the virtual function pointers are found by double
* indirection through the class segment tables. */
/* Choose class segment depending on type we were passed */
class_index = class_index_in_primary_list (type);
/* Find class segment pointer. These are in the vtable slots after
* some other entries, so adjust by HP_ACC_VFUNC_START for that. */
/* pai: FIXME 32x64 problem here, if words are 8 bytes long
* the multiplier below has to be 8 and value should be long. */
vp = value_at (builtin_type_int,
coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
/* Indirect once more, offset by function index */
/* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
coreptr =
*(CORE_ADDR *) (VALUE_CONTENTS (vp) +
4 * TYPE_FN_FIELD_VOFFSET (f, j));
vp = value_at (builtin_type_int, coreptr, NULL);
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
/* coreptr now contains the address of the virtual function */
/* (Actually, it contains the pointer to the plabel for the function.) */
}
if (!coreptr)
error ("Address of virtual function is null; error in virtual table?");
/* Wrap this addr in a value and return pointer */
vp = allocate_value (ftype);
VALUE_TYPE (vp) = ftype;
VALUE_ADDRESS (vp) = coreptr;
/* pai: (temp) do we need the value_ind stuff in value_fn_field? */
return vp;
}
static struct type *
hpacc_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
{
struct type *known_type;
struct type *rtti_type;
CORE_ADDR coreptr;
value_ptr vp;
int using_enclosing = 0;
long top_offset = 0;
char rtti_type_name[256];
if (full)
*full = 0;
if (top)
*top = -1;
if (using_enc)
*using_enc = 0;
/* Get declared type */
known_type = VALUE_TYPE (v);
CHECK_TYPEDEF (known_type);
/* RTTI works only or class objects */
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL;
/* If neither the declared type nor the enclosing type of the
* value structure has a HP ANSI C++ style virtual table,
* we can't do anything. */
if (!TYPE_HAS_VTABLE (known_type))
{
known_type = VALUE_ENCLOSING_TYPE (v);
CHECK_TYPEDEF (known_type);
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
!TYPE_HAS_VTABLE (known_type))
return NULL; /* No RTTI, or not HP-compiled types */
CHECK_TYPEDEF (known_type);
using_enclosing = 1;
}
if (using_enclosing && using_enc)
*using_enc = 1;
/* First get the virtual table address */
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ VALUE_OFFSET (v)
+ (using_enclosing
? 0
: VALUE_EMBEDDED_OFFSET (v)));
if (coreptr == 0)
/* return silently -- maybe called on gdb-generated value */
return NULL;
/* Fetch the top offset of the object */
/* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int,
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
VALUE_BFD_SECTION (v));
top_offset = value_as_long (vp);
if (top)
*top = top_offset;
/* Fetch the typeinfo pointer */
/* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET,
VALUE_BFD_SECTION (v));
/* Indirect through the typeinfo pointer and retrieve the pointer
* to the string name */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
if (!coreptr)
error ("Retrieved null typeinfo pointer in trying to determine "
"run-time type");
/* 4 -> offset of name field */
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v));
/* FIXME possible 32x64 problem */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
read_memory_string (coreptr, rtti_type_name, 256);
if (strlen (rtti_type_name) == 0)
error ("Retrieved null type name from typeinfo");
/* search for type */
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
if (!rtti_type)
error ("Could not find run-time type: invalid type name %s in typeinfo??",
rtti_type_name);
CHECK_TYPEDEF (rtti_type);
#if 0
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type),
TYPE_TAG_NAME (rtti_type), full ? *full : -1);
#endif
/* Check whether we have the entire object */
if (full /* Non-null pointer passed */
&&
/* Either we checked on the whole object in hand and found the
top offset to be zero */
(((top_offset == 0) &&
using_enclosing &&
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
||
/* Or we checked on the embedded object and top offset was the
same as the embedded offset */
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
!using_enclosing &&
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
*full = 1;
return rtti_type;
}
static void
init_hpacc_ops (void)
{
hpacc_abi_ops.shortname = "hpaCC";
hpacc_abi_ops.longname = "HP aCC ABI";
hpacc_abi_ops.doc = "HP aCC ABI";
hpacc_abi_ops.is_destructor_name = hpacc_is_destructor_name;
hpacc_abi_ops.is_constructor_name = hpacc_is_constructor_name;
hpacc_abi_ops.is_vtable_name = hpacc_is_vtable_name;
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;
}
void
_initialize_hpacc_abi (void)
{
init_hpacc_ops ();
regcomp (&constructor_pattern,
"^This will never match anything, please fill it in$", REG_NOSUB);
regcomp (&destructor_pattern,
"^This will never match anything, please fill it in$", REG_NOSUB);
regcomp (&operator_pattern,
"^This will never match anything, please fill it in$", REG_NOSUB);
register_cp_abi (hpacc_abi_ops);
}

View File

@ -28,6 +28,7 @@
#include "gdb_string.h"
#include "typeprint.h"
#include "c-lang.h"
#include "cp-abi.h"
/* Local functions */
@ -224,12 +225,9 @@ java_type_print_base (struct type *type, struct ui_file *stream, int show,
physname = TYPE_FN_FIELD_PHYSNAME (f, j);
is_full_physname_constructor =
((physname[0] == '_' && physname[1] == '_'
&& strchr ("0123456789Qt", physname[2]))
|| STREQN (physname, "__ct__", 6)
|| DESTRUCTOR_PREFIX_P (physname)
|| STREQN (physname, "__dt__", 6));
is_full_physname_constructor
= (is_constructor_name (physname)
|| is_destructor_name (physname));
QUIT;

View File

@ -29,6 +29,7 @@
#include "demangle.h"
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
/* Prototype for one function in parser-defs.h,
instead of including that entire file. */
@ -166,7 +167,7 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
/* Destructor is handled by caller, dont add it to the list */
if (DESTRUCTOR_PREFIX_P (phys_name))
if (is_destructor_name (phys_name) != 0)
continue;
sym_arr[i1] = lookup_symbol (phys_name,
@ -801,7 +802,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
{
char *tmp;
if (OPNAME_PREFIX_P (copy))
if (is_operator_name (copy))
{
tmp = (char *) alloca (strlen (copy + 3) + 9);
strcpy (tmp, "operator ");

View File

@ -45,6 +45,7 @@
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
#include "cp-abi.h"
/* Prototype for one function in parser-defs.h,
instead of including that entire file. */
@ -288,20 +289,17 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
int is_full_physname_constructor;
int is_constructor;
int is_destructor = DESTRUCTOR_PREFIX_P (physname);
int is_destructor = is_destructor_name (physname);
/* Need a new type prefix. */
char *const_prefix = method->is_const ? "C" : "";
char *volatile_prefix = method->is_volatile ? "V" : "";
char buf[20];
int len = (newname == NULL ? 0 : strlen (newname));
if (OPNAME_PREFIX_P (field_name))
if (is_operator_name (field_name))
return xstrdup (physname);
is_full_physname_constructor =
((physname[0] == '_' && physname[1] == '_' &&
(isdigit (physname[2]) || physname[2] == 'Q' || physname[2] == 't'))
|| (strncmp (physname, "__ct", 4) == 0));
is_full_physname_constructor = is_constructor_name (physname);
is_constructor =
is_full_physname_constructor || (newname && STREQ (field_name, newname));

View File

@ -1046,30 +1046,6 @@ struct partial_symtab
#define VTBL_FNADDR_OFFSET 2
/* Macro that yields non-zero value iff NAME is the prefix for C++ operator
names. If you leave out the parenthesis here you will lose! */
#define OPNAME_PREFIX_P(NAME) \
(!strncmp (NAME, "operator", 8))
/* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl
names. Note that this macro is g++ specific (FIXME).
'_vt$' is the old cfront-style vtables; '_VT$' is the new
style, using thunks (where '$' is really CPLUS_MARKER). */
#define VTBL_PREFIX_P(NAME) \
(((NAME)[0] == '_' \
&& (((NAME)[1] == 'V' && (NAME)[2] == 'T') \
|| ((NAME)[1] == 'v' && (NAME)[2] == 't')) \
&& is_cplus_marker ((NAME)[3])) || ((NAME)[0]=='_' && (NAME)[1]=='_' \
&& (NAME)[2]=='v' && (NAME)[3]=='t' && (NAME)[4]=='_'))
/* Macro that yields non-zero value iff NAME is the prefix for C++ destructor
names. Note that this macro is g++ specific (FIXME). */
#define DESTRUCTOR_PREFIX_P(NAME) \
((NAME)[0] == '_' && is_cplus_marker ((NAME)[1]) && (NAME)[2] == '_')
/* External variables and functions for the objects described above. */
/* This symtab variable specifies the current file for printing source lines */

View File

@ -31,6 +31,7 @@
#include "gdbcmd.h"
#include "target.h"
#include "language.h"
#include "cp-abi.h"
#include "gdb_string.h"
#include <errno.h>

View File

@ -31,6 +31,7 @@
#include "language.h"
#include "gdbcmd.h"
#include "regcache.h"
#include "cp-abi.h"
#include <errno.h>
#include "gdb_string.h"
@ -3111,226 +3112,6 @@ value_struct_elt_for_reference (struct type *domain, int offset,
}
/* Find the real run-time type of a value using RTTI.
* V is a pointer to the value.
* A pointer to the struct type entry of the run-time type
* is returneed.
* FULL is a flag that is set only if the value V includes
* the entire contents of an object of the RTTI type.
* TOP is the offset to the top of the enclosing object of
* the real run-time type. This offset may be for the embedded
* object, or for the enclosing object of V.
* USING_ENC is the flag that distinguishes the two cases.
* If it is 1, then the offset is for the enclosing object,
* otherwise for the embedded object.
*
*/
struct type *
value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
{
struct type *known_type;
struct type *rtti_type;
CORE_ADDR coreptr;
value_ptr vp;
int using_enclosing = 0;
long top_offset = 0;
char rtti_type_name[256];
if (full)
*full = 0;
if (top)
*top = -1;
if (using_enc)
*using_enc = 0;
/* Get declared type */
known_type = VALUE_TYPE (v);
CHECK_TYPEDEF (known_type);
/* RTTI works only or class objects */
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL;
if (TYPE_HAS_VTABLE(known_type))
{
/* If neither the declared type nor the enclosing type of the
* value structure has a HP ANSI C++ style virtual table,
* we can't do anything. */
if (!TYPE_HAS_VTABLE (known_type))
{
known_type = VALUE_ENCLOSING_TYPE (v);
CHECK_TYPEDEF (known_type);
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
!TYPE_HAS_VTABLE (known_type))
return NULL; /* No RTTI, or not HP-compiled types */
CHECK_TYPEDEF (known_type);
using_enclosing = 1;
}
if (using_enclosing && using_enc)
*using_enc = 1;
/* First get the virtual table address */
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ VALUE_OFFSET (v)
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
if (coreptr == 0)
return NULL; /* return silently -- maybe called on gdb-generated value */
/* Fetch the top offset of the object */
/* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int,
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
VALUE_BFD_SECTION (v));
top_offset = value_as_long (vp);
if (top)
*top = top_offset;
/* Fetch the typeinfo pointer */
/* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
/* Indirect through the typeinfo pointer and retrieve the pointer
* to the string name */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
if (!coreptr)
error ("Retrieved null typeinfo pointer in trying to determine run-time type");
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
/* FIXME possible 32x64 problem */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
read_memory_string (coreptr, rtti_type_name, 256);
if (strlen (rtti_type_name) == 0)
error ("Retrieved null type name from typeinfo");
/* search for type */
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
if (!rtti_type)
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
CHECK_TYPEDEF (rtti_type);
#if 0
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
#endif
/* Check whether we have the entire object */
if (full /* Non-null pointer passed */
&&
/* Either we checked on the whole object in hand and found the
top offset to be zero */
(((top_offset == 0) &&
using_enclosing &&
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
||
/* Or we checked on the embedded object and top offset was the
same as the embedded offset */
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
!using_enclosing &&
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
*full = 1;
}
else
/*
Right now this is G++ RTTI. Plan on this changing in the
future as i get around to setting the vtables properly for G++
compiled stuff. Also, i'll be using the type info functions,
which are always right. Deal with it until then.
*/
{
CORE_ADDR vtbl;
struct minimal_symbol *minsym;
struct symbol *sym;
char *demangled_name;
struct type *btype;
/* If the type has no vptr fieldno, try to get it filled in */
if (TYPE_VPTR_FIELDNO(known_type) < 0)
fill_in_vptr_fieldno(known_type);
/* If we still can't find one, give up */
if (TYPE_VPTR_FIELDNO(known_type) < 0)
return NULL;
/* Make sure our basetype and known type match, otherwise, cast
so we can get at the vtable properly.
*/
btype = TYPE_VPTR_BASETYPE (known_type);
CHECK_TYPEDEF (btype);
if (btype != known_type )
{
v = value_cast (btype, v);
if (using_enc)
*using_enc=1;
}
/*
We can't use value_ind here, because it would want to use RTTI, and
we'd waste a bunch of time figuring out we already know the type.
Besides, we don't care about the type, just the actual pointer
*/
if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
return NULL;
/*
If we are enclosed by something that isn't us, adjust the
address properly and set using_enclosing.
*/
if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
{
value_ptr tempval;
tempval=value_field(v,TYPE_VPTR_FIELDNO(known_type));
VALUE_ADDRESS(tempval)+=(TYPE_BASECLASS_BITPOS(known_type,TYPE_VPTR_FIELDNO(known_type))/8);
vtbl=value_as_pointer(tempval);
using_enclosing=1;
}
else
{
vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
using_enclosing=0;
}
/* Try to find a symbol that is the vtable */
minsym=lookup_minimal_symbol_by_pc(vtbl);
if (minsym==NULL || (demangled_name=SYMBOL_NAME(minsym))==NULL || !VTBL_PREFIX_P(demangled_name))
return NULL;
/* If we just skip the prefix, we get screwed by namespaces */
demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
*(strchr(demangled_name,' '))=0;
/* Lookup the type for the name */
rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
if (rtti_type==NULL)
return NULL;
if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
{
if (top)
*top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
if (top && ((*top) >0))
{
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
{
if (full)
*full=0;
}
else
{
if (full)
*full=1;
}
}
}
else
{
if (full)
*full=1;
}
if (using_enc)
*using_enc=using_enclosing;
}
return rtti_type;
}
/* Given a pointer value V, find the real (RTTI) type
of the object it points to.
Other parameters FULL, TOP, USING_ENC as with value_rtti_type()

View File

@ -367,7 +367,6 @@ extern value_ptr value_field (value_ptr arg1, int fieldno);
extern value_ptr value_primitive_field (value_ptr arg1, int offset,
int fieldno, struct type *arg_type);
extern struct type *value_rtti_type (value_ptr, int *, int *, int *);
extern struct type *value_rtti_target_type (value_ptr, int *, int *, int *);
@ -447,10 +446,6 @@ extern value_ptr value_x_unop (value_ptr arg1, enum exp_opcode op,
extern value_ptr value_fn_field (value_ptr * arg1p, struct fn_field *f,
int j, struct type *type, int offset);
extern value_ptr value_virtual_fn_field (value_ptr * arg1p,
struct fn_field *f, int j,
struct type *type, int offset);
extern int binop_user_defined_p (enum exp_opcode op,
value_ptr arg1, value_ptr arg2);

View File

@ -45,7 +45,6 @@ static void show_values (char *, int);
static void show_convenience (char *, int);
static int vb_match (struct type *, int, struct type *);
/* The value-history records all the values printed
by print commands during this session. Each chunk
@ -890,197 +889,6 @@ value_fn_field (value_ptr *arg1p, struct fn_field *f, int j, struct type *type,
return v;
}
/* Return a virtual function as a value.
ARG1 is the object which provides the virtual function
table pointer. *ARG1P is side-effected in calling this function.
F is the list of member functions which contains the desired virtual
function.
J is an index into F which provides the desired virtual function.
TYPE is the type in which F is located. */
value_ptr
value_virtual_fn_field (value_ptr *arg1p, struct fn_field *f, int j,
struct type *type, int offset)
{
value_ptr arg1 = *arg1p;
struct type *type1 = check_typedef (VALUE_TYPE (arg1));
if (TYPE_HAS_VTABLE (type))
{
/* Deal with HP/Taligent runtime model for virtual functions */
value_ptr vp;
value_ptr argp; /* arg1 cast to base */
CORE_ADDR coreptr; /* pointer to target address */
int class_index; /* which class segment pointer to use */
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
argp = value_cast (type, *arg1p);
if (VALUE_ADDRESS (argp) == 0)
error ("Address of object is null; object may not have been created.");
/* pai: FIXME -- 32x64 possible problem? */
/* First word (4 bytes) in object layout is the vtable pointer */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
/* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
if (!coreptr)
error ("Virtual table pointer is null for object; object may not have been created.");
/* pai/1997-05-09
* FIXME: The code here currently handles only
* the non-RRBC case of the Taligent/HP runtime spec; when RRBC
* is introduced, the condition for the "if" below will have to
* be changed to be a test for the RRBC case. */
if (1)
{
/* Non-RRBC case; the virtual function pointers are stored at fixed
* offsets in the virtual table. */
/* Retrieve the offset in the virtual table from the debug
* info. The offset of the vfunc's entry is in words from
* the beginning of the vtable; but first we have to adjust
* by HP_ACC_VFUNC_START to account for other entries */
/* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
* which case the multiplier should be 8 and values should be long */
vp = value_at (builtin_type_int,
coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL);
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
/* coreptr now contains the address of the virtual function */
/* (Actually, it contains the pointer to the plabel for the function. */
}
else
{
/* RRBC case; the virtual function pointers are found by double
* indirection through the class segment tables. */
/* Choose class segment depending on type we were passed */
class_index = class_index_in_primary_list (type);
/* Find class segment pointer. These are in the vtable slots after
* some other entries, so adjust by HP_ACC_VFUNC_START for that. */
/* pai: FIXME 32x64 problem here, if words are 8 bytes long
* the multiplier below has to be 8 and value should be long. */
vp = value_at (builtin_type_int,
coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
/* Indirect once more, offset by function index */
/* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j));
vp = value_at (builtin_type_int, coreptr, NULL);
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
/* coreptr now contains the address of the virtual function */
/* (Actually, it contains the pointer to the plabel for the function.) */
}
if (!coreptr)
error ("Address of virtual function is null; error in virtual table?");
/* Wrap this addr in a value and return pointer */
vp = allocate_value (ftype);
VALUE_TYPE (vp) = ftype;
VALUE_ADDRESS (vp) = coreptr;
/* pai: (temp) do we need the value_ind stuff in value_fn_field? */
return vp;
}
else
{ /* Not using HP/Taligent runtime conventions; so try to
* use g++ conventions for virtual table */
struct type *entry_type;
/* First, get the virtual function table pointer. That comes
with a strange type, so cast it to type `pointer to long' (which
should serve just fine as a function type). Then, index into
the table, and convert final value to appropriate function type. */
value_ptr entry, vfn, vtbl;
value_ptr vi = value_from_longest (builtin_type_int,
(LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
struct type *context;
if (fcontext == NULL)
/* We don't have an fcontext (e.g. the program was compiled with
g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
This won't work right for multiple inheritance, but at least we
should do as well as GDB 3.x did. */
fcontext = TYPE_VPTR_BASETYPE (type);
context = lookup_pointer_type (fcontext);
/* Now context is a pointer to the basetype containing the vtbl. */
if (TYPE_TARGET_TYPE (context) != type1)
{
value_ptr tmp = value_cast (context, value_addr (arg1));
VALUE_POINTED_TO_OFFSET (tmp) = 0;
arg1 = value_ind (tmp);
type1 = check_typedef (VALUE_TYPE (arg1));
}
context = type1;
/* Now context is the basetype containing the vtbl. */
/* This type may have been defined before its virtual function table
was. If so, fill in the virtual function table entry for the
type now. */
if (TYPE_VPTR_FIELDNO (context) < 0)
fill_in_vptr_fieldno (context);
/* The virtual function table is now an array of structures
which have the form { int16 offset, delta; void *pfn; }. */
vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
TYPE_VPTR_BASETYPE (context));
/* With older versions of g++, the vtbl field pointed to an array
of structures. Nowadays it points directly to the structure. */
if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
{
/* Handle the case where the vtbl field points to an
array of structures. */
vtbl = value_ind (vtbl);
/* Index into the virtual function table. This is hard-coded because
looking up a field is not cheap, and it may be important to save
time, e.g. if the user has set a conditional breakpoint calling
a virtual function. */
entry = value_subscript (vtbl, vi);
}
else
{
/* Handle the case where the vtbl field points directly to a structure. */
vtbl = value_add (vtbl, vi);
entry = value_ind (vtbl);
}
entry_type = check_typedef (VALUE_TYPE (entry));
if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
{
/* Move the `this' pointer according to the virtual function table. */
VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
if (!VALUE_LAZY (arg1))
{
VALUE_LAZY (arg1) = 1;
value_fetch_lazy (arg1);
}
vfn = value_field (entry, 2);
}
else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
vfn = entry;
else
error ("I'm confused: virtual function table has bad type");
/* Reinstantiate the function pointer with the correct type. */
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
*arg1p = arg1;
return vfn;
}
}
/* ARG is a pointer to an object we know to be at least
a DTYPE. BTYPE is the most derived basetype that has
already been searched (and need not be searched again).