| 1 | /* Abstraction of HP aCC ABI. |
| 2 | Contributed by Daniel Berlin <dberlin@redhat.com> |
| 3 | Most of the real code is from HP, i've just fiddled it to fit in |
| 4 | the C++ ABI abstraction framework. |
| 5 | |
| 6 | Copyright 2001 Free Software Foundation, Inc. |
| 7 | |
| 8 | This file is part of GDB. |
| 9 | |
| 10 | This program is free software; you can redistribute it and/or |
| 11 | modify |
| 12 | it under the terms of the GNU General Public License as published |
| 13 | by |
| 14 | the Free Software Foundation; either version 2 of the License, or |
| 15 | (at your option) any later version. |
| 16 | |
| 17 | This program is distributed in the hope that it will be useful, |
| 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | GNU General Public License for more details. |
| 21 | |
| 22 | You should have received a copy of the GNU General Public License |
| 23 | along with this program; if not, write to the Free Software |
| 24 | Foundation, Inc., 59 Temple Place - Suite 330, |
| 25 | Boston, MA 02111-1307, USA. */ |
| 26 | |
| 27 | #include "defs.h" |
| 28 | #include "value.h" |
| 29 | #include "gdb_regex.h" |
| 30 | #include "gdb_string.h" |
| 31 | #include "gdbtypes.h" |
| 32 | #include "gdbcore.h" |
| 33 | #include "cp-abi.h" |
| 34 | |
| 35 | struct cp_abi_ops hpacc_abi_ops; |
| 36 | |
| 37 | /* It appears the is_*_name stuff is never used when we try the hpACC |
| 38 | * ABI. As such, I have no clue what the real answers are. Shouldn't |
| 39 | * have any more effect than it does now. */ |
| 40 | static regex_t constructor_pattern; |
| 41 | static regex_t destructor_pattern; |
| 42 | static regex_t operator_pattern; |
| 43 | |
| 44 | static enum dtor_kinds |
| 45 | hpacc_is_destructor_name (const char *name) |
| 46 | { |
| 47 | if (regexec (&destructor_pattern, name, 0, 0, 0) == 0) |
| 48 | return complete_object_dtor; |
| 49 | else |
| 50 | return 0; |
| 51 | } |
| 52 | |
| 53 | static enum ctor_kinds |
| 54 | hpacc_is_constructor_name (const char *name) |
| 55 | { |
| 56 | if (regexec (&constructor_pattern, name, 0, 0, 0) == 0) |
| 57 | return complete_object_ctor; |
| 58 | else |
| 59 | return 0; |
| 60 | } |
| 61 | |
| 62 | static int |
| 63 | hpacc_is_operator_name (const char *name) |
| 64 | { |
| 65 | return regexec (&operator_pattern, name, 0, 0, 0) == 0; |
| 66 | } |
| 67 | |
| 68 | static int |
| 69 | hpacc_is_vtable_name (const char *name) |
| 70 | { |
| 71 | return strcmp (name, |
| 72 | "This will never match anything, please fill it in") == 0; |
| 73 | } |
| 74 | |
| 75 | /* Return a virtual function as a value. |
| 76 | ARG1 is the object which provides the virtual function |
| 77 | table pointer. *ARG1P is side-effected in calling this function. |
| 78 | F is the list of member functions which contains the desired virtual |
| 79 | function. |
| 80 | J is an index into F which provides the desired virtual function. |
| 81 | |
| 82 | TYPE is the type in which F is located. */ |
| 83 | static struct value * |
| 84 | hpacc_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, |
| 85 | struct type * type, int offset) |
| 86 | { |
| 87 | struct value *arg1 = *arg1p; |
| 88 | struct type *type1 = check_typedef (VALUE_TYPE (arg1)); |
| 89 | |
| 90 | /* Deal with HP/Taligent runtime model for virtual functions */ |
| 91 | struct value *vp; |
| 92 | struct value *argp; /* arg1 cast to base */ |
| 93 | CORE_ADDR coreptr; /* pointer to target address */ |
| 94 | int class_index; /* which class segment pointer to use */ |
| 95 | struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */ |
| 96 | |
| 97 | argp = value_cast (type, *arg1p); |
| 98 | |
| 99 | if (VALUE_ADDRESS (argp) == 0) |
| 100 | error ("Address of object is null; object may not have been created."); |
| 101 | |
| 102 | /* pai: FIXME -- 32x64 possible problem? */ |
| 103 | /* First word (4 bytes) in object layout is the vtable pointer */ |
| 104 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */ |
| 105 | /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */ |
| 106 | |
| 107 | if (!coreptr) |
| 108 | error |
| 109 | ("Virtual table pointer is null for object; object may not have been created."); |
| 110 | |
| 111 | /* pai/1997-05-09 |
| 112 | * FIXME: The code here currently handles only |
| 113 | * the non-RRBC case of the Taligent/HP runtime spec; when RRBC |
| 114 | * is introduced, the condition for the "if" below will have to |
| 115 | * be changed to be a test for the RRBC case. */ |
| 116 | |
| 117 | if (1) |
| 118 | { |
| 119 | /* Non-RRBC case; the virtual function pointers are stored at fixed |
| 120 | * offsets in the virtual table. */ |
| 121 | |
| 122 | /* Retrieve the offset in the virtual table from the debug |
| 123 | * info. The offset of the vfunc's entry is in words from |
| 124 | * the beginning of the vtable; but first we have to adjust |
| 125 | * by HP_ACC_VFUNC_START to account for other entries */ |
| 126 | |
| 127 | /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in |
| 128 | * which case the multiplier should be 8 and values should be long */ |
| 129 | vp = value_at (builtin_type_int, |
| 130 | coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + |
| 131 | HP_ACC_VFUNC_START), NULL); |
| 132 | |
| 133 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); |
| 134 | /* coreptr now contains the address of the virtual function */ |
| 135 | /* (Actually, it contains the pointer to the plabel for the function. */ |
| 136 | } |
| 137 | else |
| 138 | { |
| 139 | /* RRBC case; the virtual function pointers are found by double |
| 140 | * indirection through the class segment tables. */ |
| 141 | |
| 142 | /* Choose class segment depending on type we were passed */ |
| 143 | class_index = class_index_in_primary_list (type); |
| 144 | |
| 145 | /* Find class segment pointer. These are in the vtable slots after |
| 146 | * some other entries, so adjust by HP_ACC_VFUNC_START for that. */ |
| 147 | /* pai: FIXME 32x64 problem here, if words are 8 bytes long |
| 148 | * the multiplier below has to be 8 and value should be long. */ |
| 149 | vp = value_at (builtin_type_int, |
| 150 | coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL); |
| 151 | /* Indirect once more, offset by function index */ |
| 152 | /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */ |
| 153 | coreptr = |
| 154 | *(CORE_ADDR *) (VALUE_CONTENTS (vp) + |
| 155 | 4 * TYPE_FN_FIELD_VOFFSET (f, j)); |
| 156 | vp = value_at (builtin_type_int, coreptr, NULL); |
| 157 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); |
| 158 | |
| 159 | /* coreptr now contains the address of the virtual function */ |
| 160 | /* (Actually, it contains the pointer to the plabel for the function.) */ |
| 161 | |
| 162 | } |
| 163 | |
| 164 | if (!coreptr) |
| 165 | error ("Address of virtual function is null; error in virtual table?"); |
| 166 | |
| 167 | /* Wrap this addr in a value and return pointer */ |
| 168 | vp = allocate_value (ftype); |
| 169 | VALUE_TYPE (vp) = ftype; |
| 170 | VALUE_ADDRESS (vp) = coreptr; |
| 171 | |
| 172 | /* pai: (temp) do we need the value_ind stuff in value_fn_field? */ |
| 173 | return vp; |
| 174 | } |
| 175 | |
| 176 | |
| 177 | static struct type * |
| 178 | hpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc) |
| 179 | { |
| 180 | struct type *known_type; |
| 181 | struct type *rtti_type; |
| 182 | CORE_ADDR coreptr; |
| 183 | struct value *vp; |
| 184 | int using_enclosing = 0; |
| 185 | long top_offset = 0; |
| 186 | char rtti_type_name[256]; |
| 187 | |
| 188 | if (full) |
| 189 | *full = 0; |
| 190 | if (top) |
| 191 | *top = -1; |
| 192 | if (using_enc) |
| 193 | *using_enc = 0; |
| 194 | |
| 195 | /* Get declared type */ |
| 196 | known_type = VALUE_TYPE (v); |
| 197 | CHECK_TYPEDEF (known_type); |
| 198 | /* RTTI works only or class objects */ |
| 199 | if (TYPE_CODE (known_type) != TYPE_CODE_CLASS) |
| 200 | return NULL; |
| 201 | |
| 202 | /* If neither the declared type nor the enclosing type of the |
| 203 | * value structure has a HP ANSI C++ style virtual table, |
| 204 | * we can't do anything. */ |
| 205 | if (!TYPE_HAS_VTABLE (known_type)) |
| 206 | { |
| 207 | known_type = VALUE_ENCLOSING_TYPE (v); |
| 208 | CHECK_TYPEDEF (known_type); |
| 209 | if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) || |
| 210 | !TYPE_HAS_VTABLE (known_type)) |
| 211 | return NULL; /* No RTTI, or not HP-compiled types */ |
| 212 | CHECK_TYPEDEF (known_type); |
| 213 | using_enclosing = 1; |
| 214 | } |
| 215 | |
| 216 | if (using_enclosing && using_enc) |
| 217 | *using_enc = 1; |
| 218 | |
| 219 | /* First get the virtual table address */ |
| 220 | coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v)) |
| 221 | + VALUE_OFFSET (v) |
| 222 | + (using_enclosing |
| 223 | ? 0 |
| 224 | : VALUE_EMBEDDED_OFFSET (v))); |
| 225 | if (coreptr == 0) |
| 226 | /* return silently -- maybe called on gdb-generated value */ |
| 227 | return NULL; |
| 228 | |
| 229 | /* Fetch the top offset of the object */ |
| 230 | /* FIXME possible 32x64 problem with pointer size & arithmetic */ |
| 231 | vp = value_at (builtin_type_int, |
| 232 | coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET, |
| 233 | VALUE_BFD_SECTION (v)); |
| 234 | top_offset = value_as_long (vp); |
| 235 | if (top) |
| 236 | *top = top_offset; |
| 237 | |
| 238 | /* Fetch the typeinfo pointer */ |
| 239 | /* FIXME possible 32x64 problem with pointer size & arithmetic */ |
| 240 | vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, |
| 241 | VALUE_BFD_SECTION (v)); |
| 242 | /* Indirect through the typeinfo pointer and retrieve the pointer |
| 243 | * to the string name */ |
| 244 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); |
| 245 | if (!coreptr) |
| 246 | error ("Retrieved null typeinfo pointer in trying to determine " |
| 247 | "run-time type"); |
| 248 | /* 4 -> offset of name field */ |
| 249 | vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); |
| 250 | /* FIXME possible 32x64 problem */ |
| 251 | |
| 252 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); |
| 253 | |
| 254 | read_memory_string (coreptr, rtti_type_name, 256); |
| 255 | |
| 256 | if (strlen (rtti_type_name) == 0) |
| 257 | error ("Retrieved null type name from typeinfo"); |
| 258 | |
| 259 | /* search for type */ |
| 260 | rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); |
| 261 | |
| 262 | if (!rtti_type) |
| 263 | error ("Could not find run-time type: invalid type name %s in typeinfo??", |
| 264 | rtti_type_name); |
| 265 | CHECK_TYPEDEF (rtti_type); |
| 266 | #if 0 |
| 267 | printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), |
| 268 | TYPE_TAG_NAME (rtti_type), full ? *full : -1); |
| 269 | #endif |
| 270 | /* Check whether we have the entire object */ |
| 271 | if (full /* Non-null pointer passed */ |
| 272 | && |
| 273 | /* Either we checked on the whole object in hand and found the |
| 274 | top offset to be zero */ |
| 275 | (((top_offset == 0) && |
| 276 | using_enclosing && |
| 277 | TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type)) |
| 278 | || |
| 279 | /* Or we checked on the embedded object and top offset was the |
| 280 | same as the embedded offset */ |
| 281 | ((top_offset == VALUE_EMBEDDED_OFFSET (v)) && |
| 282 | !using_enclosing && |
| 283 | TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type)))) |
| 284 | |
| 285 | *full = 1; |
| 286 | |
| 287 | return rtti_type; |
| 288 | } |
| 289 | |
| 290 | extern int gnuv2_baseclass_offset (struct type *type, int index, |
| 291 | char *valaddr, CORE_ADDR address); |
| 292 | |
| 293 | static void |
| 294 | init_hpacc_ops (void) |
| 295 | { |
| 296 | hpacc_abi_ops.shortname = "hpaCC"; |
| 297 | hpacc_abi_ops.longname = "HP aCC ABI"; |
| 298 | hpacc_abi_ops.doc = "HP aCC ABI"; |
| 299 | hpacc_abi_ops.is_destructor_name = hpacc_is_destructor_name; |
| 300 | hpacc_abi_ops.is_constructor_name = hpacc_is_constructor_name; |
| 301 | hpacc_abi_ops.is_vtable_name = hpacc_is_vtable_name; |
| 302 | hpacc_abi_ops.is_operator_name = hpacc_is_operator_name; |
| 303 | hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field; |
| 304 | hpacc_abi_ops.rtti_type = hpacc_value_rtti_type; |
| 305 | /* It seems that this function is specific to GNU G++ < 3.0. |
| 306 | However, it is called for data members even in the HP |
| 307 | case (although not for member functions). |
| 308 | FIXME: Is that correct? */ |
| 309 | hpacc_abi_ops.baseclass_offset = gnuv2_baseclass_offset; |
| 310 | } |
| 311 | |
| 312 | |
| 313 | void |
| 314 | _initialize_hpacc_abi (void) |
| 315 | { |
| 316 | init_hpacc_ops (); |
| 317 | |
| 318 | regcomp (&constructor_pattern, |
| 319 | "^This will never match anything, please fill it in$", REG_NOSUB); |
| 320 | |
| 321 | regcomp (&destructor_pattern, |
| 322 | "^This will never match anything, please fill it in$", REG_NOSUB); |
| 323 | |
| 324 | regcomp (&operator_pattern, |
| 325 | "^This will never match anything, please fill it in$", REG_NOSUB); |
| 326 | |
| 327 | register_cp_abi (hpacc_abi_ops); |
| 328 | } |