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