X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgnu-v2-abi.c;h=9f7dd0ac12f076e7afe592ece43a8e068da778fe;hb=2106ed9baf1098a5d76469ecde30813065c46c68;hp=fd9aad5fdc774d72f569f82427357b7f4a58d1ef;hpb=30c98d84cd2c82265d56de5e3bc6a25b291ff65c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c index fd9aad5fdc..9f7dd0ac12 100644 --- a/gdb/gnu-v2-abi.c +++ b/gdb/gnu-v2-abi.c @@ -1,14 +1,14 @@ /* Abstraction of GNU v2 abi. + + Copyright (C) 2001-2020 Free Software Foundation, Inc. + 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 + 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,18 +17,16 @@ 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. */ + along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" #include "symtab.h" #include "gdbtypes.h" #include "value.h" #include "demangle.h" +#include "gdb-demangle.h" #include "cp-abi.h" - +#include "cp-support.h" #include struct cp_abi_ops gnu_v2_abi_ops; @@ -39,10 +37,10 @@ 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) + || startswith (name, "__dt__")) return complete_object_dtor; else - return 0; + return (enum dtor_kinds) 0; } static enum ctor_kinds @@ -50,10 +48,10 @@ gnuv2_is_constructor_name (const char *name) { if ((name[0] == '_' && name[1] == '_' && (isdigit (name[2]) || strchr ("Qt", name[2]))) - || strncmp (name, "__ct__", 6) == 0) + || startswith (name, "__ct__")) return complete_object_ctor; else - return 0; + return (enum ctor_kinds) 0; } static int @@ -70,7 +68,7 @@ gnuv2_is_vtable_name (const char *name) static int gnuv2_is_operator_name (const char *name) { - return strncmp (name, "operator", 8) == 0; + return startswith (name, CP_OPERATOR_STR); } @@ -82,24 +80,26 @@ gnuv2_is_operator_name (const char *name) 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, +static struct value * +gnuv2_virtual_fn_field (struct value **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 value *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 value *entry; + struct value *vfn; + struct value *vtbl; + LONGEST vi = (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j); struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j); struct type *context; + struct type *context_vptr_basetype; + int context_vptr_fieldno; + 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. @@ -110,10 +110,10 @@ gnuv2_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j, /* 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; + struct value *tmp = value_cast (context, value_addr (arg1)); + arg1 = value_ind (tmp); - type1 = check_typedef (VALUE_TYPE (arg1)); + type1 = check_typedef (value_type (arg1)); } context = type1; @@ -122,21 +122,21 @@ gnuv2_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j, /* 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); + context_vptr_fieldno = get_vptr_fieldno (context, &context_vptr_basetype); + /* FIXME: What to do if vptr_fieldno is still -1? */ /* 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)); + vtbl = value_primitive_field (arg1, 0, context_vptr_fieldno, + context_vptr_basetype); /* 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) + of structures. Nowadays it points directly to the structure. */ + if (value_type (vtbl)->code () == TYPE_CODE_PTR + && TYPE_TARGET_TYPE (value_type (vtbl))->code () == TYPE_CODE_ARRAY) { /* Handle the case where the vtbl field points to an - array of structures. */ + array of structures. */ vtbl = value_ind (vtbl); /* Index into the virtual function table. This is hard-coded because @@ -147,53 +147,53 @@ gnuv2_virtual_fn_field (value_ptr * arg1p, struct fn_field * f, int j, } else { - /* Handle the case where the vtbl field points directly to a structure. */ - vtbl = value_add (vtbl, vi); + /* Handle the case where the vtbl field points directly to a + structure. */ + vtbl = value_ptradd (vtbl, vi); entry = value_ind (vtbl); } - entry_type = check_typedef (VALUE_TYPE (entry)); + entry_type = check_typedef (value_type (entry)); - if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT) + if (entry_type->code () == TYPE_CODE_STRUCT) { - /* Move the `this' pointer according to the virtual function table. */ - VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)); + /* Move the `this' pointer according to the virtual function table. */ + set_value_offset (arg1, value_offset (arg1) + + value_as_long (value_field (entry, 0))); - if (!VALUE_LAZY (arg1)) + if (!value_lazy (arg1)) { - VALUE_LAZY (arg1) = 1; + set_value_lazy (arg1, 1); value_fetch_lazy (arg1); } vfn = value_field (entry, 2); } - else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR) + else if (entry_type->code () == TYPE_CODE_PTR) vfn = entry; else - error ("I'm confused: virtual function table has bad type"); + 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)); + deprecated_set_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) +static struct type * +gnuv2_value_rtti_type (struct value *v, int *full, LONGEST *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 bound_minimal_symbol minsym; + char *demangled_name, *p; + const char *linkage_name; struct type *btype; + struct type *known_type_vptr_basetype; + int known_type_vptr_fieldno; if (full) *full = 0; @@ -202,11 +202,11 @@ gnuv2_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc) 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) + /* Get declared type. */ + known_type = value_type (v); + known_type = check_typedef (known_type); + /* RTTI works only or class objects. */ + if (known_type->code () != TYPE_CODE_STRUCT) return NULL; /* Plan on this changing in the future as i get around to setting @@ -214,74 +214,56 @@ gnuv2_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc) 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); + /* Try to get the vptr basetype, fieldno. */ + known_type_vptr_fieldno = get_vptr_fieldno (known_type, + &known_type_vptr_basetype); - /* If we still can't find one, give up */ - if (TYPE_VPTR_FIELDNO(known_type) < 0) + /* If we can't find it, give up. */ + if (known_type_vptr_fieldno < 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); + so we can get at the vtable properly. */ + btype = known_type_vptr_basetype; + btype = 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) + /* 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, known_type_vptr_fieldno)) == 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; - } + vtbl = value_as_address (value_field (v, known_type_vptr_fieldno)); - /* Try to find a symbol that is the vtable */ + /* 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)) + if (minsym.minsym==NULL + || (linkage_name=minsym.minsym->linkage_name ())==NULL + || !is_vtable_name (linkage_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; + /* If we just skip the prefix, we get screwed by namespaces. */ + demangled_name=gdb_demangle(linkage_name,DMGL_PARAMS|DMGL_ANSI); + p = strchr (demangled_name, ' '); + if (p) + *p = '\0'; - /* Lookup the type for the name */ - rtti_type=lookup_typename(demangled_name, (struct block *)0,1); - - if (rtti_type==NULL) + /* Lookup the type for the name. */ + /* FIXME: chastain/2003-11-26: block=NULL is bogus. See pr gdb/1465. */ + rtti_type = cp_lookup_rtti_type (demangled_name, NULL); + 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; + *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)) @@ -301,12 +283,120 @@ gnuv2_value_rtti_type (value_ptr v, int *full, int *top, int *using_enc) if (full) *full=1; } - if (using_enc) - *using_enc=using_enclosing; return rtti_type; } +/* Return true if the INDEXth field of TYPE is a virtual baseclass + pointer which is for the base class whose type is BASECLASS. */ + +static int +vb_match (struct type *type, int index, struct type *basetype) +{ + struct type *fieldtype; + const char *name = TYPE_FIELD_NAME (type, index); + const char *field_class_name = NULL; + + if (*name != '_') + return 0; + /* gcc 2.4 uses _vb$. */ + if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3])) + field_class_name = name + 4; + /* gcc 2.5 will use __vb_. */ + if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_') + field_class_name = name + 5; + + if (field_class_name == NULL) + /* This field is not a virtual base class pointer. */ + return 0; + + /* It's a virtual baseclass pointer, now we just need to find out whether + it is for this baseclass. */ + fieldtype = type->field (index).type (); + if (fieldtype == NULL + || fieldtype->code () != TYPE_CODE_PTR) + /* "Can't happen". */ + return 0; + + /* What we check for is that either the types are equal (needed for + nameless types) or have the same name. This is ugly, and a more + elegant solution should be devised (which would probably just push + the ugliness into symbol reading unless we change the stabs format). */ + if (TYPE_TARGET_TYPE (fieldtype) == basetype) + return 1; + + if (basetype->name () != NULL + && TYPE_TARGET_TYPE (fieldtype)->name () != NULL + && strcmp (basetype->name (), + TYPE_TARGET_TYPE (fieldtype)->name ()) == 0) + return 1; + return 0; +} + +/* Compute the offset of the baseclass which is the INDEXth baseclass + of class TYPE, for value at VALADDR (in host) at ADDRESS (in + target). The result is the offset of the baseclass value relative + to (the address of)(ARG) + OFFSET. */ + +static int +gnuv2_baseclass_offset (struct type *type, int index, + const bfd_byte *valaddr, LONGEST embedded_offset, + CORE_ADDR address, const struct value *val) +{ + struct type *basetype = TYPE_BASECLASS (type, index); + + if (BASETYPE_VIA_VIRTUAL (type, index)) + { + /* Must hunt for the pointer to this virtual baseclass. */ + int i, len = type->num_fields (); + int n_baseclasses = TYPE_N_BASECLASSES (type); + + /* First look for the virtual baseclass pointer + in the fields. */ + for (i = n_baseclasses; i < len; i++) + { + if (vb_match (type, i, basetype)) + { + struct type *field_type; + LONGEST field_offset; + int field_length; + CORE_ADDR addr; + + field_type = check_typedef (type->field (i).type ()); + field_offset = TYPE_FIELD_BITPOS (type, i) / 8; + field_length = TYPE_LENGTH (field_type); + + if (!value_bytes_available (val, embedded_offset + field_offset, + field_length)) + throw_error (NOT_AVAILABLE_ERROR, + _("Virtual baseclass pointer is not available")); + + addr = unpack_pointer (field_type, + valaddr + embedded_offset + field_offset); + + return addr - (LONGEST) address + embedded_offset; + } + } + /* Not in the fields, so try looking through the baseclasses. */ + for (i = index + 1; i < n_baseclasses; i++) + { + /* Don't go through baseclass_offset, as that wraps + exceptions, thus, inner exceptions would be wrapped more + than once. */ + int boffset = + gnuv2_baseclass_offset (type, i, valaddr, + embedded_offset, address, val); + + if (boffset) + return boffset; + } + + error (_("Baseclass offset not found")); + } + + /* Baseclass is easily computed. */ + return TYPE_BASECLASS_BITPOS (type, index) / 8; +} static void init_gnuv2_ops (void) @@ -320,12 +410,13 @@ init_gnuv2_ops (void) 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; + gnu_v2_abi_ops.baseclass_offset = gnuv2_baseclass_offset; } +void _initialize_gnu_v2_abi (); void -_initialize_gnu_v2_abi (void) +_initialize_gnu_v2_abi () { init_gnuv2_ops (); - register_cp_abi (gnu_v2_abi_ops); - switch_to_cp_abi ("gnu-v2"); + register_cp_abi (&gnu_v2_abi_ops); }