From 015a42b4cf96cadcb996b6474ab61eca781fdde6 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 27 Apr 2001 00:19:09 +0000 Subject: [PATCH] (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). --- gdb/ChangeLog | 36 +++++ gdb/Makefile.in | 36 +++-- gdb/c-typeprint.c | 10 +- gdb/c-valprint.c | 2 + gdb/cp-abi.c | 99 ++++++++++++++ gdb/cp-abi.h | 131 ++++++++++++++++++ gdb/dbxread.c | 3 +- gdb/eval.c | 1 + gdb/gdbtypes.c | 11 +- gdb/gnu-v2-abi.c | 332 +++++++++++++++++++++++++++++++++++++++++++++ gdb/hpacc-abi.c | 321 +++++++++++++++++++++++++++++++++++++++++++ gdb/jv-typeprint.c | 10 +- gdb/linespec.c | 5 +- gdb/symtab.c | 10 +- gdb/symtab.h | 24 ---- gdb/typeprint.c | 1 + gdb/valops.c | 221 +----------------------------- gdb/value.h | 5 - gdb/values.c | 192 -------------------------- 19 files changed, 972 insertions(+), 478 deletions(-) create mode 100644 gdb/cp-abi.c create mode 100644 gdb/cp-abi.h create mode 100644 gdb/gnu-v2-abi.c create mode 100644 gdb/hpacc-abi.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7f1161fae82..69fdc41c1d2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2001-04-26 Jim Blandy + + (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 * thread-db.c (_initialize_thread_db): Add set/show command diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 687456153bd..ecc5b321b34 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 \ diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index ab9abc70c0c..789d5f0b2df 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -33,6 +33,7 @@ #include "demangle.h" #include "c-lang.h" #include "typeprint.h" +#include "cp-abi.h" #include "gdb_string.h" #include @@ -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)) diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index a4bcfb43ca6..e1e8b8211b4 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -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. */ diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c new file mode 100644 index 00000000000..eb31270367e --- /dev/null +++ b/gdb/cp-abi.c @@ -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; +} + diff --git a/gdb/cp-abi.h b/gdb/cp-abi.h new file mode 100644 index 00000000000..059816a9f7b --- /dev/null +++ b/gdb/cp-abi.h @@ -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 + 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 + diff --git a/gdb/dbxread.c b/gdb/dbxread.c index cdb165762e8..d3a1489bc81 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -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); diff --git a/gdb/eval.c b/gdb/eval.c index ceed262543e..fad995ee35c 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -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; diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 86499e2b683..f3cff63501f 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -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; diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c new file mode 100644 index 00000000000..ad73165345a --- /dev/null +++ b/gdb/gnu-v2-abi.c @@ -0,0 +1,332 @@ +/* Abstraction of GNU v2 abi. + Contributed by Daniel Berlin + 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 + +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"); +} diff --git a/gdb/hpacc-abi.c b/gdb/hpacc-abi.c new file mode 100644 index 00000000000..f9ec31745f3 --- /dev/null +++ b/gdb/hpacc-abi.c @@ -0,0 +1,321 @@ +/* Abstraction of HP aCC ABI. + Contributed by Daniel Berlin + 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); +} diff --git a/gdb/jv-typeprint.c b/gdb/jv-typeprint.c index 4fdd84c2fbe..c0d9ec92903 100644 --- a/gdb/jv-typeprint.c +++ b/gdb/jv-typeprint.c @@ -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; diff --git a/gdb/linespec.c b/gdb/linespec.c index 35f225cf2da..e23479035d3 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -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 "); diff --git a/gdb/symtab.c b/gdb/symtab.c index 6cb8e963de4..aecf362d472 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -45,6 +45,7 @@ #include "gdb_string.h" #include "gdb_stat.h" #include +#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)); diff --git a/gdb/symtab.h b/gdb/symtab.h index a4f224d6872..bbde658f091 100644 --- a/gdb/symtab.h +++ b/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 */ diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 444c78b7bfd..7ea7098c819 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -31,6 +31,7 @@ #include "gdbcmd.h" #include "target.h" #include "language.h" +#include "cp-abi.h" #include "gdb_string.h" #include diff --git a/gdb/valops.c b/gdb/valops.c index 0ab0ae6e916..0e7e7e14056 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -31,6 +31,7 @@ #include "language.h" #include "gdbcmd.h" #include "regcache.h" +#include "cp-abi.h" #include #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() diff --git a/gdb/value.h b/gdb/value.h index 064a261d312..50abe0ebfe7 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -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); diff --git a/gdb/values.c b/gdb/values.c index eec1178d1db..8a93be9f1f7 100644 --- a/gdb/values.c +++ b/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). -- 2.39.2