198944Sobrien/* Abstraction of HP aCC ABI. 298944Sobrien Contributed by Daniel Berlin <dberlin@redhat.com> 398944Sobrien Most of the real code is from HP, i've just fiddled it to fit in 498944Sobrien the C++ ABI abstraction framework. 598944Sobrien 698944Sobrien Copyright 2001 Free Software Foundation, Inc. 798944Sobrien 898944Sobrien This file is part of GDB. 998944Sobrien 1098944Sobrien This program is free software; you can redistribute it and/or 1198944Sobrien modify 1298944Sobrien it under the terms of the GNU General Public License as published 1398944Sobrien by 1498944Sobrien the Free Software Foundation; either version 2 of the License, or 1598944Sobrien (at your option) any later version. 1698944Sobrien 1798944Sobrien This program is distributed in the hope that it will be useful, 1898944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1998944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2098944Sobrien GNU General Public License for more details. 2198944Sobrien 2298944Sobrien You should have received a copy of the GNU General Public License 2398944Sobrien along with this program; if not, write to the Free Software 2498944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2598944Sobrien Boston, MA 02111-1307, USA. */ 2698944Sobrien 2798944Sobrien#include "defs.h" 2898944Sobrien#include "value.h" 2998944Sobrien#include "gdb_regex.h" 3098944Sobrien#include "gdb_string.h" 3198944Sobrien#include "gdbtypes.h" 3298944Sobrien#include "gdbcore.h" 3398944Sobrien#include "cp-abi.h" 3498944Sobrien 3598944Sobrienstruct cp_abi_ops hpacc_abi_ops; 3698944Sobrien 3798944Sobrien/* It appears the is_*_name stuff is never used when we try the hpACC 3898944Sobrien * ABI. As such, I have no clue what the real answers are. Shouldn't 3998944Sobrien * have any more effect than it does now. */ 4098944Sobrienstatic regex_t constructor_pattern; 4198944Sobrienstatic regex_t destructor_pattern; 4298944Sobrienstatic regex_t operator_pattern; 4398944Sobrien 4498944Sobrienstatic enum dtor_kinds 4598944Sobrienhpacc_is_destructor_name (const char *name) 4698944Sobrien{ 4798944Sobrien if (regexec (&destructor_pattern, name, 0, 0, 0) == 0) 4898944Sobrien return complete_object_dtor; 4998944Sobrien else 5098944Sobrien return 0; 5198944Sobrien} 5298944Sobrien 5398944Sobrienstatic enum ctor_kinds 5498944Sobrienhpacc_is_constructor_name (const char *name) 5598944Sobrien{ 5698944Sobrien if (regexec (&constructor_pattern, name, 0, 0, 0) == 0) 5798944Sobrien return complete_object_ctor; 5898944Sobrien else 5998944Sobrien return 0; 6098944Sobrien} 6198944Sobrien 6298944Sobrienstatic int 6398944Sobrienhpacc_is_operator_name (const char *name) 6498944Sobrien{ 6598944Sobrien return regexec (&operator_pattern, name, 0, 0, 0) == 0; 6698944Sobrien} 6798944Sobrien 6898944Sobrienstatic int 6998944Sobrienhpacc_is_vtable_name (const char *name) 7098944Sobrien{ 7198944Sobrien return strcmp (name, 7298944Sobrien "This will never match anything, please fill it in") == 0; 7398944Sobrien} 7498944Sobrien 7598944Sobrien/* Return a virtual function as a value. 7698944Sobrien ARG1 is the object which provides the virtual function 7798944Sobrien table pointer. *ARG1P is side-effected in calling this function. 7898944Sobrien F is the list of member functions which contains the desired virtual 7998944Sobrien function. 8098944Sobrien J is an index into F which provides the desired virtual function. 8198944Sobrien 8298944Sobrien TYPE is the type in which F is located. */ 8398944Sobrienstatic struct value * 8498944Sobrienhpacc_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, 8598944Sobrien struct type * type, int offset) 8698944Sobrien{ 8798944Sobrien struct value *arg1 = *arg1p; 8898944Sobrien struct type *type1 = check_typedef (VALUE_TYPE (arg1)); 8998944Sobrien 9098944Sobrien /* Deal with HP/Taligent runtime model for virtual functions */ 9198944Sobrien struct value *vp; 9298944Sobrien struct value *argp; /* arg1 cast to base */ 9398944Sobrien CORE_ADDR coreptr; /* pointer to target address */ 9498944Sobrien int class_index; /* which class segment pointer to use */ 9598944Sobrien struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */ 9698944Sobrien 9798944Sobrien argp = value_cast (type, *arg1p); 9898944Sobrien 9998944Sobrien if (VALUE_ADDRESS (argp) == 0) 10098944Sobrien error ("Address of object is null; object may not have been created."); 10198944Sobrien 10298944Sobrien /* pai: FIXME -- 32x64 possible problem? */ 10398944Sobrien /* First word (4 bytes) in object layout is the vtable pointer */ 10498944Sobrien coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */ 10598944Sobrien /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */ 10698944Sobrien 10798944Sobrien if (!coreptr) 10898944Sobrien error 10998944Sobrien ("Virtual table pointer is null for object; object may not have been created."); 11098944Sobrien 11198944Sobrien /* pai/1997-05-09 11298944Sobrien * FIXME: The code here currently handles only 11398944Sobrien * the non-RRBC case of the Taligent/HP runtime spec; when RRBC 11498944Sobrien * is introduced, the condition for the "if" below will have to 11598944Sobrien * be changed to be a test for the RRBC case. */ 11698944Sobrien 11798944Sobrien if (1) 11898944Sobrien { 11998944Sobrien /* Non-RRBC case; the virtual function pointers are stored at fixed 12098944Sobrien * offsets in the virtual table. */ 12198944Sobrien 12298944Sobrien /* Retrieve the offset in the virtual table from the debug 12398944Sobrien * info. The offset of the vfunc's entry is in words from 12498944Sobrien * the beginning of the vtable; but first we have to adjust 12598944Sobrien * by HP_ACC_VFUNC_START to account for other entries */ 12698944Sobrien 12798944Sobrien /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in 12898944Sobrien * which case the multiplier should be 8 and values should be long */ 12998944Sobrien vp = value_at (builtin_type_int, 13098944Sobrien coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + 13198944Sobrien HP_ACC_VFUNC_START), NULL); 13298944Sobrien 13398944Sobrien coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); 13498944Sobrien /* coreptr now contains the address of the virtual function */ 13598944Sobrien /* (Actually, it contains the pointer to the plabel for the function. */ 13698944Sobrien } 13798944Sobrien else 13898944Sobrien { 13998944Sobrien /* RRBC case; the virtual function pointers are found by double 14098944Sobrien * indirection through the class segment tables. */ 14198944Sobrien 14298944Sobrien /* Choose class segment depending on type we were passed */ 14398944Sobrien class_index = class_index_in_primary_list (type); 14498944Sobrien 14598944Sobrien /* Find class segment pointer. These are in the vtable slots after 14698944Sobrien * some other entries, so adjust by HP_ACC_VFUNC_START for that. */ 14798944Sobrien /* pai: FIXME 32x64 problem here, if words are 8 bytes long 14898944Sobrien * the multiplier below has to be 8 and value should be long. */ 14998944Sobrien vp = value_at (builtin_type_int, 15098944Sobrien coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL); 15198944Sobrien /* Indirect once more, offset by function index */ 15298944Sobrien /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */ 15398944Sobrien coreptr = 15498944Sobrien *(CORE_ADDR *) (VALUE_CONTENTS (vp) + 15598944Sobrien 4 * TYPE_FN_FIELD_VOFFSET (f, j)); 15698944Sobrien vp = value_at (builtin_type_int, coreptr, NULL); 15798944Sobrien coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); 15898944Sobrien 15998944Sobrien /* coreptr now contains the address of the virtual function */ 16098944Sobrien /* (Actually, it contains the pointer to the plabel for the function.) */ 16198944Sobrien 16298944Sobrien } 16398944Sobrien 16498944Sobrien if (!coreptr) 16598944Sobrien error ("Address of virtual function is null; error in virtual table?"); 16698944Sobrien 16798944Sobrien /* Wrap this addr in a value and return pointer */ 16898944Sobrien vp = allocate_value (ftype); 16998944Sobrien VALUE_TYPE (vp) = ftype; 17098944Sobrien VALUE_ADDRESS (vp) = coreptr; 17198944Sobrien 17298944Sobrien /* pai: (temp) do we need the value_ind stuff in value_fn_field? */ 17398944Sobrien return vp; 17498944Sobrien} 17598944Sobrien 17698944Sobrien 17798944Sobrienstatic struct type * 17898944Sobrienhpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc) 17998944Sobrien{ 18098944Sobrien struct type *known_type; 18198944Sobrien struct type *rtti_type; 18298944Sobrien CORE_ADDR coreptr; 18398944Sobrien struct value *vp; 18498944Sobrien int using_enclosing = 0; 18598944Sobrien long top_offset = 0; 18698944Sobrien char rtti_type_name[256]; 18798944Sobrien 18898944Sobrien if (full) 18998944Sobrien *full = 0; 19098944Sobrien if (top) 19198944Sobrien *top = -1; 19298944Sobrien if (using_enc) 19398944Sobrien *using_enc = 0; 19498944Sobrien 19598944Sobrien /* Get declared type */ 19698944Sobrien known_type = VALUE_TYPE (v); 19798944Sobrien CHECK_TYPEDEF (known_type); 19898944Sobrien /* RTTI works only or class objects */ 19998944Sobrien if (TYPE_CODE (known_type) != TYPE_CODE_CLASS) 20098944Sobrien return NULL; 20198944Sobrien 20298944Sobrien /* If neither the declared type nor the enclosing type of the 20398944Sobrien * value structure has a HP ANSI C++ style virtual table, 20498944Sobrien * we can't do anything. */ 20598944Sobrien if (!TYPE_HAS_VTABLE (known_type)) 20698944Sobrien { 20798944Sobrien known_type = VALUE_ENCLOSING_TYPE (v); 20898944Sobrien CHECK_TYPEDEF (known_type); 20998944Sobrien if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) || 21098944Sobrien !TYPE_HAS_VTABLE (known_type)) 21198944Sobrien return NULL; /* No RTTI, or not HP-compiled types */ 21298944Sobrien CHECK_TYPEDEF (known_type); 21398944Sobrien using_enclosing = 1; 21498944Sobrien } 21598944Sobrien 21698944Sobrien if (using_enclosing && using_enc) 21798944Sobrien *using_enc = 1; 21898944Sobrien 21998944Sobrien /* First get the virtual table address */ 22098944Sobrien coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v)) 22198944Sobrien + VALUE_OFFSET (v) 22298944Sobrien + (using_enclosing 22398944Sobrien ? 0 22498944Sobrien : VALUE_EMBEDDED_OFFSET (v))); 22598944Sobrien if (coreptr == 0) 22698944Sobrien /* return silently -- maybe called on gdb-generated value */ 22798944Sobrien return NULL; 22898944Sobrien 22998944Sobrien /* Fetch the top offset of the object */ 23098944Sobrien /* FIXME possible 32x64 problem with pointer size & arithmetic */ 23198944Sobrien vp = value_at (builtin_type_int, 23298944Sobrien coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET, 23398944Sobrien VALUE_BFD_SECTION (v)); 23498944Sobrien top_offset = value_as_long (vp); 23598944Sobrien if (top) 23698944Sobrien *top = top_offset; 23798944Sobrien 23898944Sobrien /* Fetch the typeinfo pointer */ 23998944Sobrien /* FIXME possible 32x64 problem with pointer size & arithmetic */ 24098944Sobrien vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, 24198944Sobrien VALUE_BFD_SECTION (v)); 24298944Sobrien /* Indirect through the typeinfo pointer and retrieve the pointer 24398944Sobrien * to the string name */ 24498944Sobrien coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); 24598944Sobrien if (!coreptr) 24698944Sobrien error ("Retrieved null typeinfo pointer in trying to determine " 24798944Sobrien "run-time type"); 24898944Sobrien /* 4 -> offset of name field */ 24998944Sobrien vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); 25098944Sobrien /* FIXME possible 32x64 problem */ 25198944Sobrien 25298944Sobrien coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); 25398944Sobrien 25498944Sobrien read_memory_string (coreptr, rtti_type_name, 256); 25598944Sobrien 25698944Sobrien if (strlen (rtti_type_name) == 0) 25798944Sobrien error ("Retrieved null type name from typeinfo"); 25898944Sobrien 25998944Sobrien /* search for type */ 26098944Sobrien rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); 26198944Sobrien 26298944Sobrien if (!rtti_type) 26398944Sobrien error ("Could not find run-time type: invalid type name %s in typeinfo??", 26498944Sobrien rtti_type_name); 26598944Sobrien CHECK_TYPEDEF (rtti_type); 26698944Sobrien#if 0 26798944Sobrien printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), 26898944Sobrien TYPE_TAG_NAME (rtti_type), full ? *full : -1); 26998944Sobrien#endif 27098944Sobrien /* Check whether we have the entire object */ 27198944Sobrien if (full /* Non-null pointer passed */ 27298944Sobrien && 27398944Sobrien /* Either we checked on the whole object in hand and found the 27498944Sobrien top offset to be zero */ 27598944Sobrien (((top_offset == 0) && 27698944Sobrien using_enclosing && 27798944Sobrien TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type)) 27898944Sobrien || 27998944Sobrien /* Or we checked on the embedded object and top offset was the 28098944Sobrien same as the embedded offset */ 28198944Sobrien ((top_offset == VALUE_EMBEDDED_OFFSET (v)) && 28298944Sobrien !using_enclosing && 28398944Sobrien TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type)))) 28498944Sobrien 28598944Sobrien *full = 1; 28698944Sobrien 28798944Sobrien return rtti_type; 28898944Sobrien} 28998944Sobrien 29098944Sobrienextern int gnuv2_baseclass_offset (struct type *type, int index, 29198944Sobrien char *valaddr, CORE_ADDR address); 29298944Sobrien 29398944Sobrienstatic void 29498944Sobrieninit_hpacc_ops (void) 29598944Sobrien{ 29698944Sobrien hpacc_abi_ops.shortname = "hpaCC"; 29798944Sobrien hpacc_abi_ops.longname = "HP aCC ABI"; 29898944Sobrien hpacc_abi_ops.doc = "HP aCC ABI"; 29998944Sobrien hpacc_abi_ops.is_destructor_name = hpacc_is_destructor_name; 30098944Sobrien hpacc_abi_ops.is_constructor_name = hpacc_is_constructor_name; 30198944Sobrien hpacc_abi_ops.is_vtable_name = hpacc_is_vtable_name; 30298944Sobrien hpacc_abi_ops.is_operator_name = hpacc_is_operator_name; 30398944Sobrien hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field; 30498944Sobrien hpacc_abi_ops.rtti_type = hpacc_value_rtti_type; 30598944Sobrien /* It seems that this function is specific to GNU G++ < 3.0. 30698944Sobrien However, it is called for data members even in the HP 30798944Sobrien case (although not for member functions). 30898944Sobrien FIXME: Is that correct? */ 30998944Sobrien hpacc_abi_ops.baseclass_offset = gnuv2_baseclass_offset; 31098944Sobrien} 31198944Sobrien 312130803Smarcelextern initialize_file_ftype _initialize_hpacc_abi; /* -Wmissing-prototypes */ 31398944Sobrien 31498944Sobrienvoid 31598944Sobrien_initialize_hpacc_abi (void) 31698944Sobrien{ 31798944Sobrien init_hpacc_ops (); 31898944Sobrien 31998944Sobrien regcomp (&constructor_pattern, 32098944Sobrien "^This will never match anything, please fill it in$", REG_NOSUB); 32198944Sobrien 32298944Sobrien regcomp (&destructor_pattern, 32398944Sobrien "^This will never match anything, please fill it in$", REG_NOSUB); 32498944Sobrien 32598944Sobrien regcomp (&operator_pattern, 32698944Sobrien "^This will never match anything, please fill it in$", REG_NOSUB); 32798944Sobrien 328130803Smarcel register_cp_abi (&hpacc_abi_ops); 32998944Sobrien} 330