mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
(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:
parent
20b8570d73
commit
015a42b4cf
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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))
|
||||
|
@ -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
99
gdb/cp-abi.c
Normal 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
131
gdb/cp-abi.h
Normal 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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
332
gdb/gnu-v2-abi.c
Normal 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
321
gdb/hpacc-abi.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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 ");
|
||||
|
10
gdb/symtab.c
10
gdb/symtab.c
@ -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));
|
||||
|
24
gdb/symtab.h
24
gdb/symtab.h
@ -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 */
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "gdbcmd.h"
|
||||
#include "target.h"
|
||||
#include "language.h"
|
||||
#include "cp-abi.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
#include <errno.h>
|
||||
|
221
gdb/valops.c
221
gdb/valops.c
@ -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()
|
||||
|
@ -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);
|
||||
|
||||
|
192
gdb/values.c
192
gdb/values.c
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user