Commit | Line | Data |
---|---|---|
015a42b4 | 1 | /* Abstraction of HP aCC ABI. |
6b08edad | 2 | |
015a42b4 JB |
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 | ||
197e01b6 | 7 | Copyright (C) 2001, 2005 Free Software Foundation, Inc. |
015a42b4 JB |
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 | |
197e01b6 EZ |
25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, |
26 | Boston, MA 02110-1301, USA. */ | |
015a42b4 JB |
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" | |
6b08edad | 35 | #include "gnu-v2-abi.h" |
015a42b4 JB |
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. */ | |
e933e538 AC |
85 | static struct value * |
86 | hpacc_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, | |
015a42b4 JB |
87 | struct type * type, int offset) |
88 | { | |
e933e538 | 89 | struct value *arg1 = *arg1p; |
df407dfe | 90 | struct type *type1 = check_typedef (value_type (arg1)); |
015a42b4 JB |
91 | |
92 | /* Deal with HP/Taligent runtime model for virtual functions */ | |
e933e538 AC |
93 | struct value *vp; |
94 | struct value *argp; /* arg1 cast to base */ | |
015a42b4 JB |
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) | |
8a3fe4f8 | 102 | error (_("Address of object is null; object may not have been created.")); |
015a42b4 JB |
103 | |
104 | /* pai: FIXME -- 32x64 possible problem? */ | |
105 | /* First word (4 bytes) in object layout is the vtable pointer */ | |
0fd88904 | 106 | coreptr = *(CORE_ADDR *) (value_contents (argp)); /* pai: (temp) */ |
13c3b5f5 | 107 | /* + offset + value_embedded_offset (argp)); */ |
015a42b4 JB |
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) + | |
00a4c844 | 133 | HP_ACC_VFUNC_START)); |
015a42b4 | 134 | |
0fd88904 | 135 | coreptr = *(CORE_ADDR *) (value_contents (vp)); |
015a42b4 JB |
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, | |
00a4c844 | 152 | coreptr + 4 * (HP_ACC_VFUNC_START + class_index)); |
015a42b4 JB |
153 | /* Indirect once more, offset by function index */ |
154 | /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */ | |
155 | coreptr = | |
0fd88904 | 156 | *(CORE_ADDR *) (value_contents (vp) + |
015a42b4 | 157 | 4 * TYPE_FN_FIELD_VOFFSET (f, j)); |
00a4c844 | 158 | vp = value_at (builtin_type_int, coreptr); |
0fd88904 | 159 | coreptr = *(CORE_ADDR *) (value_contents (vp)); |
015a42b4 JB |
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) | |
8a3fe4f8 | 167 | error (_("Address of virtual function is null; error in virtual table?")); |
015a42b4 JB |
168 | |
169 | /* Wrap this addr in a value and return pointer */ | |
170 | vp = allocate_value (ftype); | |
04624583 | 171 | deprecated_set_value_type (vp, ftype); |
015a42b4 JB |
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 * | |
e933e538 | 180 | hpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc) |
015a42b4 JB |
181 | { |
182 | struct type *known_type; | |
183 | struct type *rtti_type; | |
184 | CORE_ADDR coreptr; | |
e933e538 | 185 | struct value *vp; |
015a42b4 JB |
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 */ | |
df407dfe | 198 | known_type = value_type (v); |
015a42b4 JB |
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 | { | |
4754a64e | 209 | known_type = value_enclosing_type (v); |
015a42b4 JB |
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 */ | |
46615f07 | 222 | coreptr = *(CORE_ADDR *) ((value_contents_all (v)) |
df407dfe | 223 | + value_offset (v) |
015a42b4 JB |
224 | + (using_enclosing |
225 | ? 0 | |
13c3b5f5 | 226 | : value_embedded_offset (v))); |
015a42b4 JB |
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, | |
00a4c844 | 234 | coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET); |
015a42b4 JB |
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 */ | |
00a4c844 | 241 | vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET); |
015a42b4 JB |
242 | /* Indirect through the typeinfo pointer and retrieve the pointer |
243 | * to the string name */ | |
0fd88904 | 244 | coreptr = *(CORE_ADDR *) (value_contents (vp)); |
015a42b4 | 245 | if (!coreptr) |
8a3fe4f8 AC |
246 | error (_("Retrieved null typeinfo pointer in trying to determine " |
247 | "run-time type")); | |
015a42b4 | 248 | /* 4 -> offset of name field */ |
00a4c844 | 249 | vp = value_at (builtin_type_int, coreptr + 4); |
015a42b4 JB |
250 | /* FIXME possible 32x64 problem */ |
251 | ||
0fd88904 | 252 | coreptr = *(CORE_ADDR *) (value_contents (vp)); |
015a42b4 JB |
253 | |
254 | read_memory_string (coreptr, rtti_type_name, 256); | |
255 | ||
256 | if (strlen (rtti_type_name) == 0) | |
8a3fe4f8 | 257 | error (_("Retrieved null type name from typeinfo")); |
015a42b4 JB |
258 | |
259 | /* search for type */ | |
260 | rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); | |
261 | ||
262 | if (!rtti_type) | |
8a3fe4f8 | 263 | error (_("Could not find run-time type: invalid type name %s in typeinfo??"), |
015a42b4 JB |
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 */ | |
13c3b5f5 | 281 | ((top_offset == value_embedded_offset (v)) && |
015a42b4 | 282 | !using_enclosing && |
4754a64e | 283 | TYPE_LENGTH (value_enclosing_type (v)) == TYPE_LENGTH (rtti_type)))) |
015a42b4 JB |
284 | |
285 | *full = 1; | |
286 | ||
287 | return rtti_type; | |
288 | } | |
289 | ||
015a42b4 JB |
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; | |
1514d34e DJ |
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; | |
015a42b4 JB |
307 | } |
308 | ||
b9362cc7 | 309 | extern initialize_file_ftype _initialize_hpacc_abi; /* -Wmissing-prototypes */ |
015a42b4 JB |
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 | ||
fe1f4a5e | 325 | register_cp_abi (&hpacc_abi_ops); |
015a42b4 | 326 | } |