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) + | |
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 * | |
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, | |
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 | ||
1514d34e DJ |
290 | extern int gnuv2_baseclass_offset (struct type *type, int index, |
291 | char *valaddr, CORE_ADDR address); | |
015a42b4 JB |
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; | |
1514d34e DJ |
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; | |
015a42b4 JB |
310 | } |
311 | ||
b9362cc7 | 312 | extern initialize_file_ftype _initialize_hpacc_abi; /* -Wmissing-prototypes */ |
015a42b4 JB |
313 | |
314 | void | |
315 | _initialize_hpacc_abi (void) | |
316 | { | |
317 | init_hpacc_ops (); | |
318 | ||
319 | regcomp (&constructor_pattern, | |
320 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
321 | ||
322 | regcomp (&destructor_pattern, | |
323 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
324 | ||
325 | regcomp (&operator_pattern, | |
326 | "^This will never match anything, please fill it in$", REG_NOSUB); | |
327 | ||
fe1f4a5e | 328 | register_cp_abi (&hpacc_abi_ops); |
015a42b4 | 329 | } |