Commit | Line | Data |
---|---|---|
015a42b4 JB |
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. */ | |
e933e538 AC |
83 | static struct value * |
84 | hpacc_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, | |
015a42b4 JB |
85 | struct type * type, int offset) |
86 | { | |
e933e538 | 87 | struct value *arg1 = *arg1p; |
015a42b4 JB |
88 | struct type *type1 = check_typedef (VALUE_TYPE (arg1)); |
89 | ||
90 | /* Deal with HP/Taligent runtime model for virtual functions */ | |
e933e538 AC |
91 | struct value *vp; |
92 | struct value *argp; /* arg1 cast to base */ | |
015a42b4 JB |
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) + | |
00a4c844 | 131 | HP_ACC_VFUNC_START)); |
015a42b4 JB |
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, | |
00a4c844 | 150 | coreptr + 4 * (HP_ACC_VFUNC_START + class_index)); |
015a42b4 JB |
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)); | |
00a4c844 | 156 | vp = value_at (builtin_type_int, coreptr); |
015a42b4 JB |
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 * | |
e933e538 | 178 | hpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc) |
015a42b4 JB |
179 | { |
180 | struct type *known_type; | |
181 | struct type *rtti_type; | |
182 | CORE_ADDR coreptr; | |
e933e538 | 183 | struct value *vp; |
015a42b4 JB |
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, | |
00a4c844 | 232 | coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET); |
015a42b4 JB |
233 | top_offset = value_as_long (vp); |
234 | if (top) | |
235 | *top = top_offset; | |
236 | ||
237 | /* Fetch the typeinfo pointer */ | |
238 | /* FIXME possible 32x64 problem with pointer size & arithmetic */ | |
00a4c844 | 239 | vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET); |
015a42b4 JB |
240 | /* Indirect through the typeinfo pointer and retrieve the pointer |
241 | * to the string name */ | |
242 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); | |
243 | if (!coreptr) | |
244 | error ("Retrieved null typeinfo pointer in trying to determine " | |
245 | "run-time type"); | |
246 | /* 4 -> offset of name field */ | |
00a4c844 | 247 | vp = value_at (builtin_type_int, coreptr + 4); |
015a42b4 JB |
248 | /* FIXME possible 32x64 problem */ |
249 | ||
250 | coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); | |
251 | ||
252 | read_memory_string (coreptr, rtti_type_name, 256); | |
253 | ||
254 | if (strlen (rtti_type_name) == 0) | |
255 | error ("Retrieved null type name from typeinfo"); | |
256 | ||
257 | /* search for type */ | |
258 | rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); | |
259 | ||
260 | if (!rtti_type) | |
261 | error ("Could not find run-time type: invalid type name %s in typeinfo??", | |
262 | rtti_type_name); | |
263 | CHECK_TYPEDEF (rtti_type); | |
264 | #if 0 | |
265 | printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), | |
266 | TYPE_TAG_NAME (rtti_type), full ? *full : -1); | |
267 | #endif | |
268 | /* Check whether we have the entire object */ | |
269 | if (full /* Non-null pointer passed */ | |
270 | && | |
271 | /* Either we checked on the whole object in hand and found the | |
272 | top offset to be zero */ | |
273 | (((top_offset == 0) && | |
274 | using_enclosing && | |
275 | TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type)) | |
276 | || | |
277 | /* Or we checked on the embedded object and top offset was the | |
278 | same as the embedded offset */ | |
279 | ((top_offset == VALUE_EMBEDDED_OFFSET (v)) && | |
280 | !using_enclosing && | |
281 | TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type)))) | |
282 | ||
283 | *full = 1; | |
284 | ||
285 | return rtti_type; | |
286 | } | |
287 | ||
1514d34e DJ |
288 | extern int gnuv2_baseclass_offset (struct type *type, int index, |
289 | char *valaddr, CORE_ADDR address); | |
015a42b4 JB |
290 | |
291 | static void | |
292 | init_hpacc_ops (void) | |
293 | { | |
294 | hpacc_abi_ops.shortname = "hpaCC"; | |
295 | hpacc_abi_ops.longname = "HP aCC ABI"; | |
296 | hpacc_abi_ops.doc = "HP aCC ABI"; | |
297 | hpacc_abi_ops.is_destructor_name = hpacc_is_destructor_name; | |
298 | hpacc_abi_ops.is_constructor_name = hpacc_is_constructor_name; | |
299 | hpacc_abi_ops.is_vtable_name = hpacc_is_vtable_name; | |
300 | hpacc_abi_ops.is_operator_name = hpacc_is_operator_name; | |
301 | hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field; | |
302 | hpacc_abi_ops.rtti_type = hpacc_value_rtti_type; | |
1514d34e DJ |
303 | /* It seems that this function is specific to GNU G++ < 3.0. |
304 | However, it is called for data members even in the HP | |
305 | case (although not for member functions). | |
306 | FIXME: Is that correct? */ | |
307 | hpacc_abi_ops.baseclass_offset = gnuv2_baseclass_offset; | |
015a42b4 JB |
308 | } |
309 | ||
b9362cc7 | 310 | extern initialize_file_ftype _initialize_hpacc_abi; /* -Wmissing-prototypes */ |
015a42b4 JB |
311 | |
312 | void | |
313 | _initialize_hpacc_abi (void) | |
314 | { | |
315 | init_hpacc_ops (); | |
316 | ||
317 | regcomp (&constructor_pattern, | |
318 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
319 | ||
320 | regcomp (&destructor_pattern, | |
321 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
322 | ||
323 | regcomp (&operator_pattern, | |
324 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
325 | ||
fe1f4a5e | 326 | register_cp_abi (&hpacc_abi_ops); |
015a42b4 | 327 | } |