File: | src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c |
Warning: | line 2355, column 12 Potential leak of memory pointed to by 'method_name' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* prdbg.c -- Print out generic debugging information. | |||
2 | Copyright 1995, 1996, 1999, 2002, 2003, 2004 | |||
3 | Free Software Foundation, Inc. | |||
4 | Written by Ian Lance Taylor <ian@cygnus.com>. | |||
5 | Tags style generation written by Salvador E. Tropea <set@computer.org>. | |||
6 | ||||
7 | This file is part of GNU Binutils. | |||
8 | ||||
9 | This program is free software; you can redistribute it and/or modify | |||
10 | it under the terms of the GNU General Public License as published by | |||
11 | the Free Software Foundation; either version 2 of the License, or | |||
12 | (at your option) any later version. | |||
13 | ||||
14 | This program is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
17 | GNU General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU General Public License | |||
20 | along with this program; if not, write to the Free Software | |||
21 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA | |||
22 | 02110-1301, USA. */ | |||
23 | ||||
24 | /* This file prints out the generic debugging information, by | |||
25 | supplying a set of routines to debug_write. */ | |||
26 | ||||
27 | #include <stdio.h> | |||
28 | #include <assert.h> | |||
29 | ||||
30 | #include "bfd.h" | |||
31 | #include "bucomm.h" | |||
32 | #include "libiberty.h" | |||
33 | #include "debug.h" | |||
34 | #include "budbg.h" | |||
35 | ||||
36 | /* This is the structure we use as a handle for these routines. */ | |||
37 | ||||
38 | struct pr_handle | |||
39 | { | |||
40 | /* File to print information to. */ | |||
41 | FILE *f; | |||
42 | /* Current indentation level. */ | |||
43 | unsigned int indent; | |||
44 | /* Type stack. */ | |||
45 | struct pr_stack *stack; | |||
46 | /* Parameter number we are about to output. */ | |||
47 | int parameter; | |||
48 | /* The following are used only by the tags code (tg_). */ | |||
49 | /* Name of the file we are using. */ | |||
50 | char *filename; | |||
51 | /* The BFD. */ | |||
52 | bfd *abfd; | |||
53 | /* The symbols table for this BFD. */ | |||
54 | asymbol **syms; | |||
55 | /* Pointer to a function to demangle symbols. */ | |||
56 | char *(*demangler) (bfd *, const char *); | |||
57 | }; | |||
58 | ||||
59 | /* The type stack. */ | |||
60 | ||||
61 | struct pr_stack | |||
62 | { | |||
63 | /* Next element on the stack. */ | |||
64 | struct pr_stack *next; | |||
65 | /* This element. */ | |||
66 | char *type; | |||
67 | /* Current visibility of fields if this is a class. */ | |||
68 | enum debug_visibility visibility; | |||
69 | /* Name of the current method we are handling. */ | |||
70 | const char *method; | |||
71 | /* The following are used only by the tags code (tg_). */ | |||
72 | /* Type for the container (struct, union, class, union class). */ | |||
73 | const char *flavor; | |||
74 | /* A comma separated list of parent classes. */ | |||
75 | char *parents; | |||
76 | /* How many parents contains parents. */ | |||
77 | int num_parents; | |||
78 | }; | |||
79 | ||||
80 | static void indent (struct pr_handle *); | |||
81 | static bfd_boolean push_type (struct pr_handle *, const char *); | |||
82 | static bfd_boolean prepend_type (struct pr_handle *, const char *); | |||
83 | static bfd_boolean append_type (struct pr_handle *, const char *); | |||
84 | static bfd_boolean substitute_type (struct pr_handle *, const char *); | |||
85 | static bfd_boolean indent_type (struct pr_handle *); | |||
86 | static char *pop_type (struct pr_handle *); | |||
87 | static void print_vma (bfd_vma, char *, bfd_boolean, bfd_boolean); | |||
88 | static bfd_boolean pr_fix_visibility | |||
89 | (struct pr_handle *, enum debug_visibility); | |||
90 | static bfd_boolean pr_start_compilation_unit (void *, const char *); | |||
91 | static bfd_boolean pr_start_source (void *, const char *); | |||
92 | static bfd_boolean pr_empty_type (void *); | |||
93 | static bfd_boolean pr_void_type (void *); | |||
94 | static bfd_boolean pr_int_type (void *, unsigned int, bfd_boolean); | |||
95 | static bfd_boolean pr_float_type (void *, unsigned int); | |||
96 | static bfd_boolean pr_complex_type (void *, unsigned int); | |||
97 | static bfd_boolean pr_bool_type (void *, unsigned int); | |||
98 | static bfd_boolean pr_enum_type | |||
99 | (void *, const char *, const char **, bfd_signed_vma *); | |||
100 | static bfd_boolean pr_pointer_type (void *); | |||
101 | static bfd_boolean pr_function_type (void *, int, bfd_boolean); | |||
102 | static bfd_boolean pr_reference_type (void *); | |||
103 | static bfd_boolean pr_range_type (void *, bfd_signed_vma, bfd_signed_vma); | |||
104 | static bfd_boolean pr_array_type | |||
105 | (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean); | |||
106 | static bfd_boolean pr_set_type (void *, bfd_boolean); | |||
107 | static bfd_boolean pr_offset_type (void *); | |||
108 | static bfd_boolean pr_method_type (void *, bfd_boolean, int, bfd_boolean); | |||
109 | static bfd_boolean pr_const_type (void *); | |||
110 | static bfd_boolean pr_volatile_type (void *); | |||
111 | static bfd_boolean pr_start_struct_type | |||
112 | (void *, const char *, unsigned int, bfd_boolean, unsigned int); | |||
113 | static bfd_boolean pr_struct_field | |||
114 | (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); | |||
115 | static bfd_boolean pr_end_struct_type (void *); | |||
116 | static bfd_boolean pr_start_class_type | |||
117 | (void *, const char *, unsigned int, bfd_boolean, unsigned int, | |||
118 | bfd_boolean, bfd_boolean); | |||
119 | static bfd_boolean pr_class_static_member | |||
120 | (void *, const char *, const char *, enum debug_visibility); | |||
121 | static bfd_boolean pr_class_baseclass | |||
122 | (void *, bfd_vma, bfd_boolean, enum debug_visibility); | |||
123 | static bfd_boolean pr_class_start_method (void *, const char *); | |||
124 | static bfd_boolean pr_class_method_variant | |||
125 | (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, | |||
126 | bfd_vma, bfd_boolean); | |||
127 | static bfd_boolean pr_class_static_method_variant | |||
128 | (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean); | |||
129 | static bfd_boolean pr_class_end_method (void *); | |||
130 | static bfd_boolean pr_end_class_type (void *); | |||
131 | static bfd_boolean pr_typedef_type (void *, const char *); | |||
132 | static bfd_boolean pr_tag_type | |||
133 | (void *, const char *, unsigned int, enum debug_type_kind); | |||
134 | static bfd_boolean pr_typdef (void *, const char *); | |||
135 | static bfd_boolean pr_tag (void *, const char *); | |||
136 | static bfd_boolean pr_int_constant (void *, const char *, bfd_vma); | |||
137 | static bfd_boolean pr_float_constant (void *, const char *, double); | |||
138 | static bfd_boolean pr_typed_constant (void *, const char *, bfd_vma); | |||
139 | static bfd_boolean pr_variable | |||
140 | (void *, const char *, enum debug_var_kind, bfd_vma); | |||
141 | static bfd_boolean pr_start_function (void *, const char *, bfd_boolean); | |||
142 | static bfd_boolean pr_function_parameter | |||
143 | (void *, const char *, enum debug_parm_kind, bfd_vma); | |||
144 | static bfd_boolean pr_start_block (void *, bfd_vma); | |||
145 | static bfd_boolean pr_end_block (void *, bfd_vma); | |||
146 | static bfd_boolean pr_end_function (void *); | |||
147 | static bfd_boolean pr_lineno (void *, const char *, unsigned long, bfd_vma); | |||
148 | static bfd_boolean append_parent (struct pr_handle *, const char *); | |||
149 | /* Only used by tg_ code. */ | |||
150 | static bfd_boolean tg_fix_visibility | |||
151 | (struct pr_handle *, enum debug_visibility); | |||
152 | static void find_address_in_section (bfd *, asection *, void *); | |||
153 | static void translate_addresses (bfd *, char *, FILE *, asymbol **); | |||
154 | static const char *visibility_name (enum debug_visibility); | |||
155 | /* Tags style replacements. */ | |||
156 | static bfd_boolean tg_start_compilation_unit (void *, const char *); | |||
157 | static bfd_boolean tg_start_source (void *, const char *); | |||
158 | static bfd_boolean tg_enum_type | |||
159 | (void *, const char *, const char **, bfd_signed_vma *); | |||
160 | static bfd_boolean tg_start_struct_type | |||
161 | (void *, const char *, unsigned int, bfd_boolean, unsigned int); | |||
162 | static bfd_boolean pr_struct_field | |||
163 | (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); | |||
164 | static bfd_boolean tg_struct_field | |||
165 | (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); | |||
166 | static bfd_boolean tg_struct_field | |||
167 | (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); | |||
168 | static bfd_boolean tg_end_struct_type (void *); | |||
169 | static bfd_boolean tg_start_class_type | |||
170 | (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, bfd_boolean); | |||
171 | static bfd_boolean tg_class_static_member | |||
172 | (void *, const char *, const char *, enum debug_visibility); | |||
173 | static bfd_boolean tg_class_baseclass | |||
174 | (void *, bfd_vma, bfd_boolean, enum debug_visibility); | |||
175 | static bfd_boolean tg_class_method_variant | |||
176 | (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean); | |||
177 | static bfd_boolean tg_class_static_method_variant | |||
178 | (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean); | |||
179 | static bfd_boolean tg_end_class_type (void *); | |||
180 | static bfd_boolean tg_tag_type | |||
181 | (void *, const char *, unsigned int, enum debug_type_kind); | |||
182 | static bfd_boolean tg_typdef (void *, const char *); | |||
183 | static bfd_boolean tg_tag (void *, const char *); | |||
184 | static bfd_boolean tg_int_constant (void *, const char *, bfd_vma); | |||
185 | static bfd_boolean tg_float_constant (void *, const char *, double); | |||
186 | static bfd_boolean tg_typed_constant (void *, const char *, bfd_vma); | |||
187 | static bfd_boolean tg_variable | |||
188 | (void *, const char *, enum debug_var_kind, bfd_vma); | |||
189 | static bfd_boolean tg_start_function (void *, const char *, bfd_boolean); | |||
190 | static bfd_boolean tg_function_parameter | |||
191 | (void *, const char *, enum debug_parm_kind, bfd_vma); | |||
192 | static bfd_boolean tg_start_block (void *, bfd_vma); | |||
193 | static bfd_boolean tg_end_block (void *, bfd_vma); | |||
194 | static bfd_boolean tg_lineno (void *, const char *, unsigned long, bfd_vma); | |||
195 | ||||
196 | static const struct debug_write_fns pr_fns = | |||
197 | { | |||
198 | pr_start_compilation_unit, | |||
199 | pr_start_source, | |||
200 | pr_empty_type, | |||
201 | pr_void_type, | |||
202 | pr_int_type, | |||
203 | pr_float_type, | |||
204 | pr_complex_type, | |||
205 | pr_bool_type, | |||
206 | pr_enum_type, | |||
207 | pr_pointer_type, | |||
208 | pr_function_type, | |||
209 | pr_reference_type, | |||
210 | pr_range_type, | |||
211 | pr_array_type, | |||
212 | pr_set_type, | |||
213 | pr_offset_type, | |||
214 | pr_method_type, | |||
215 | pr_const_type, | |||
216 | pr_volatile_type, | |||
217 | pr_start_struct_type, | |||
218 | pr_struct_field, | |||
219 | pr_end_struct_type, | |||
220 | pr_start_class_type, | |||
221 | pr_class_static_member, | |||
222 | pr_class_baseclass, | |||
223 | pr_class_start_method, | |||
224 | pr_class_method_variant, | |||
225 | pr_class_static_method_variant, | |||
226 | pr_class_end_method, | |||
227 | pr_end_class_type, | |||
228 | pr_typedef_type, | |||
229 | pr_tag_type, | |||
230 | pr_typdef, | |||
231 | pr_tag, | |||
232 | pr_int_constant, | |||
233 | pr_float_constant, | |||
234 | pr_typed_constant, | |||
235 | pr_variable, | |||
236 | pr_start_function, | |||
237 | pr_function_parameter, | |||
238 | pr_start_block, | |||
239 | pr_end_block, | |||
240 | pr_end_function, | |||
241 | pr_lineno | |||
242 | }; | |||
243 | ||||
244 | static const struct debug_write_fns tg_fns = | |||
245 | { | |||
246 | tg_start_compilation_unit, | |||
247 | tg_start_source, | |||
248 | pr_empty_type, /* Same, push_type. */ | |||
249 | pr_void_type, /* Same, push_type. */ | |||
250 | pr_int_type, /* Same, push_type. */ | |||
251 | pr_float_type, /* Same, push_type. */ | |||
252 | pr_complex_type, /* Same, push_type. */ | |||
253 | pr_bool_type, /* Same, push_type. */ | |||
254 | tg_enum_type, | |||
255 | pr_pointer_type, /* Same, changes to pointer. */ | |||
256 | pr_function_type, /* Same, push_type. */ | |||
257 | pr_reference_type, /* Same, changes to reference. */ | |||
258 | pr_range_type, /* FIXME: What's that?. */ | |||
259 | pr_array_type, /* Same, push_type. */ | |||
260 | pr_set_type, /* FIXME: What's that?. */ | |||
261 | pr_offset_type, /* FIXME: What's that?. */ | |||
262 | pr_method_type, /* Same. */ | |||
263 | pr_const_type, /* Same, changes to const. */ | |||
264 | pr_volatile_type, /* Same, changes to volatile. */ | |||
265 | tg_start_struct_type, | |||
266 | tg_struct_field, | |||
267 | tg_end_struct_type, | |||
268 | tg_start_class_type, | |||
269 | tg_class_static_member, | |||
270 | tg_class_baseclass, | |||
271 | pr_class_start_method, /* Same, remembers that's a method. */ | |||
272 | tg_class_method_variant, | |||
273 | tg_class_static_method_variant, | |||
274 | pr_class_end_method, /* Same, forgets that's a method. */ | |||
275 | tg_end_class_type, | |||
276 | pr_typedef_type, /* Same, just push type. */ | |||
277 | tg_tag_type, | |||
278 | tg_typdef, | |||
279 | tg_tag, | |||
280 | tg_int_constant, /* Untested. */ | |||
281 | tg_float_constant, /* Untested. */ | |||
282 | tg_typed_constant, /* Untested. */ | |||
283 | tg_variable, | |||
284 | tg_start_function, | |||
285 | tg_function_parameter, | |||
286 | tg_start_block, | |||
287 | tg_end_block, | |||
288 | pr_end_function, /* Same, does nothing. */ | |||
289 | tg_lineno | |||
290 | }; | |||
291 | ||||
292 | /* Print out the generic debugging information recorded in dhandle. */ | |||
293 | ||||
294 | bfd_boolean | |||
295 | print_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms, | |||
296 | void *demangler, bfd_boolean as_tags) | |||
297 | { | |||
298 | struct pr_handle info; | |||
299 | ||||
300 | info.f = f; | |||
301 | info.indent = 0; | |||
302 | info.stack = NULL((void*)0); | |||
303 | info.parameter = 0; | |||
304 | info.filename = NULL((void*)0); | |||
305 | info.abfd = abfd; | |||
306 | info.syms = syms; | |||
307 | info.demangler = demangler; | |||
308 | ||||
309 | if (as_tags) | |||
310 | { | |||
311 | fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f); | |||
312 | fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f); | |||
313 | fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f); | |||
314 | fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f); | |||
315 | } | |||
316 | ||||
317 | return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info) | |||
318 | : debug_write (dhandle, &pr_fns, (void *) & info); | |||
319 | } | |||
320 | ||||
321 | /* Indent to the current indentation level. */ | |||
322 | ||||
323 | static void | |||
324 | indent (struct pr_handle *info) | |||
325 | { | |||
326 | unsigned int i; | |||
327 | ||||
328 | for (i = 0; i < info->indent; i++) | |||
329 | putc (' ', info->f)(!__isthreaded ? __sputc(' ', info->f) : (putc)(' ', info-> f)); | |||
330 | } | |||
331 | ||||
332 | /* Push a type on the type stack. */ | |||
333 | ||||
334 | static bfd_boolean | |||
335 | push_type (struct pr_handle *info, const char *type) | |||
336 | { | |||
337 | struct pr_stack *n; | |||
338 | ||||
339 | if (type == NULL((void*)0)) | |||
340 | return FALSE0; | |||
341 | ||||
342 | n = (struct pr_stack *) xmalloc (sizeof *n); | |||
343 | memset (n, 0, sizeof *n); | |||
344 | ||||
345 | n->type = xstrdup (type); | |||
346 | n->visibility = DEBUG_VISIBILITY_IGNORE; | |||
347 | n->method = NULL((void*)0); | |||
348 | n->next = info->stack; | |||
349 | info->stack = n; | |||
350 | ||||
351 | return TRUE1; | |||
352 | } | |||
353 | ||||
354 | /* Prepend a string onto the type on the top of the type stack. */ | |||
355 | ||||
356 | static bfd_boolean | |||
357 | prepend_type (struct pr_handle *info, const char *s) | |||
358 | { | |||
359 | char *n; | |||
360 | ||||
361 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 361, __func__, "info->stack != NULL")); | |||
362 | ||||
363 | n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1); | |||
364 | sprintf (n, "%s%s", s, info->stack->type); | |||
365 | free (info->stack->type); | |||
366 | info->stack->type = n; | |||
367 | ||||
368 | return TRUE1; | |||
369 | } | |||
370 | ||||
371 | /* Append a string to the type on the top of the type stack. */ | |||
372 | ||||
373 | static bfd_boolean | |||
374 | append_type (struct pr_handle *info, const char *s) | |||
375 | { | |||
376 | unsigned int len; | |||
377 | ||||
378 | if (s == NULL((void*)0)) | |||
379 | return FALSE0; | |||
380 | ||||
381 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 381, __func__, "info->stack != NULL")); | |||
382 | ||||
383 | len = strlen (info->stack->type); | |||
384 | info->stack->type = (char *) xrealloc (info->stack->type, | |||
385 | len + strlen (s) + 1); | |||
386 | strcpy (info->stack->type + len, s); | |||
387 | ||||
388 | return TRUE1; | |||
389 | } | |||
390 | ||||
391 | /* Append a string to the parents on the top of the type stack. */ | |||
392 | ||||
393 | static bfd_boolean | |||
394 | append_parent (struct pr_handle *info, const char *s) | |||
395 | { | |||
396 | unsigned int len; | |||
397 | ||||
398 | if (s == NULL((void*)0)) | |||
399 | return FALSE0; | |||
400 | ||||
401 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 401, __func__, "info->stack != NULL")); | |||
402 | ||||
403 | len = info->stack->parents ? strlen (info->stack->parents) : 0; | |||
404 | info->stack->parents = (char *) xrealloc (info->stack->parents, | |||
405 | len + strlen (s) + 1); | |||
406 | strcpy (info->stack->parents + len, s); | |||
407 | ||||
408 | return TRUE1; | |||
409 | } | |||
410 | ||||
411 | /* We use an underscore to indicate where the name should go in a type | |||
412 | string. This function substitutes a string for the underscore. If | |||
413 | there is no underscore, the name follows the type. */ | |||
414 | ||||
415 | static bfd_boolean | |||
416 | substitute_type (struct pr_handle *info, const char *s) | |||
417 | { | |||
418 | char *u; | |||
419 | ||||
420 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 420, __func__, "info->stack != NULL")); | |||
421 | ||||
422 | u = strchr (info->stack->type, '|'); | |||
423 | if (u != NULL((void*)0)) | |||
424 | { | |||
425 | char *n; | |||
426 | ||||
427 | n = (char *) xmalloc (strlen (info->stack->type) + strlen (s)); | |||
428 | ||||
429 | memcpy (n, info->stack->type, u - info->stack->type); | |||
430 | strcpy (n + (u - info->stack->type), s); | |||
431 | strcat (n, u + 1); | |||
432 | ||||
433 | free (info->stack->type); | |||
434 | info->stack->type = n; | |||
435 | ||||
436 | return TRUE1; | |||
437 | } | |||
438 | ||||
439 | if (strchr (s, '|') != NULL((void*)0) | |||
440 | && (strchr (info->stack->type, '{') != NULL((void*)0) | |||
441 | || strchr (info->stack->type, '(') != NULL((void*)0))) | |||
442 | { | |||
443 | if (! prepend_type (info, "(") | |||
444 | || ! append_type (info, ")")) | |||
445 | return FALSE0; | |||
446 | } | |||
447 | ||||
448 | if (*s == '\0') | |||
449 | return TRUE1; | |||
450 | ||||
451 | return (append_type (info, " ") | |||
452 | && append_type (info, s)); | |||
453 | } | |||
454 | ||||
455 | /* Indent the type at the top of the stack by appending spaces. */ | |||
456 | ||||
457 | static bfd_boolean | |||
458 | indent_type (struct pr_handle *info) | |||
459 | { | |||
460 | unsigned int i; | |||
461 | ||||
462 | for (i = 0; i < info->indent; i++) | |||
463 | { | |||
464 | if (! append_type (info, " ")) | |||
465 | return FALSE0; | |||
466 | } | |||
467 | ||||
468 | return TRUE1; | |||
469 | } | |||
470 | ||||
471 | /* Pop a type from the type stack. */ | |||
472 | ||||
473 | static char * | |||
474 | pop_type (struct pr_handle *info) | |||
475 | { | |||
476 | struct pr_stack *o; | |||
477 | char *ret; | |||
478 | ||||
479 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 479, __func__, "info->stack != NULL")); | |||
480 | ||||
481 | o = info->stack; | |||
482 | info->stack = o->next; | |||
483 | ret = o->type; | |||
484 | free (o); | |||
485 | ||||
486 | return ret; | |||
487 | } | |||
488 | ||||
489 | /* Print a VMA value into a string. */ | |||
490 | ||||
491 | static void | |||
492 | print_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp) | |||
493 | { | |||
494 | if (sizeof (vma) <= sizeof (unsigned long)) | |||
495 | { | |||
496 | if (hexp) | |||
497 | sprintf (buf, "0x%lx", (unsigned long) vma); | |||
498 | else if (unsignedp) | |||
499 | sprintf (buf, "%lu", (unsigned long) vma); | |||
500 | else | |||
501 | sprintf (buf, "%ld", (long) vma); | |||
502 | } | |||
503 | else | |||
504 | { | |||
505 | buf[0] = '0'; | |||
506 | buf[1] = 'x'; | |||
507 | sprintf_vma (buf + 2, vma)sprintf (buf + 2, "%016lx", vma); | |||
508 | } | |||
509 | } | |||
510 | ||||
511 | /* Start a new compilation unit. */ | |||
512 | ||||
513 | static bfd_boolean | |||
514 | pr_start_compilation_unit (void *p, const char *filename) | |||
515 | { | |||
516 | struct pr_handle *info = (struct pr_handle *) p; | |||
517 | ||||
518 | assert (info->indent == 0)((info->indent == 0) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 518, __func__, "info->indent == 0")); | |||
519 | ||||
520 | fprintf (info->f, "%s:\n", filename); | |||
521 | ||||
522 | return TRUE1; | |||
523 | } | |||
524 | ||||
525 | /* Start a source file within a compilation unit. */ | |||
526 | ||||
527 | static bfd_boolean | |||
528 | pr_start_source (void *p, const char *filename) | |||
529 | { | |||
530 | struct pr_handle *info = (struct pr_handle *) p; | |||
531 | ||||
532 | assert (info->indent == 0)((info->indent == 0) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 532, __func__, "info->indent == 0")); | |||
533 | ||||
534 | fprintf (info->f, " %s:\n", filename); | |||
535 | ||||
536 | return TRUE1; | |||
537 | } | |||
538 | ||||
539 | /* Push an empty type onto the type stack. */ | |||
540 | ||||
541 | static bfd_boolean | |||
542 | pr_empty_type (void *p) | |||
543 | { | |||
544 | struct pr_handle *info = (struct pr_handle *) p; | |||
545 | ||||
546 | return push_type (info, "<undefined>"); | |||
547 | } | |||
548 | ||||
549 | /* Push a void type onto the type stack. */ | |||
550 | ||||
551 | static bfd_boolean | |||
552 | pr_void_type (void *p) | |||
553 | { | |||
554 | struct pr_handle *info = (struct pr_handle *) p; | |||
555 | ||||
556 | return push_type (info, "void"); | |||
557 | } | |||
558 | ||||
559 | /* Push an integer type onto the type stack. */ | |||
560 | ||||
561 | static bfd_boolean | |||
562 | pr_int_type (void *p, unsigned int size, bfd_boolean unsignedp) | |||
563 | { | |||
564 | struct pr_handle *info = (struct pr_handle *) p; | |||
565 | char ab[10]; | |||
566 | ||||
567 | sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8); | |||
568 | return push_type (info, ab); | |||
569 | } | |||
570 | ||||
571 | /* Push a floating type onto the type stack. */ | |||
572 | ||||
573 | static bfd_boolean | |||
574 | pr_float_type (void *p, unsigned int size) | |||
575 | { | |||
576 | struct pr_handle *info = (struct pr_handle *) p; | |||
577 | char ab[10]; | |||
578 | ||||
579 | if (size == 4) | |||
580 | return push_type (info, "float"); | |||
581 | else if (size == 8) | |||
582 | return push_type (info, "double"); | |||
583 | ||||
584 | sprintf (ab, "float%d", size * 8); | |||
585 | return push_type (info, ab); | |||
586 | } | |||
587 | ||||
588 | /* Push a complex type onto the type stack. */ | |||
589 | ||||
590 | static bfd_boolean | |||
591 | pr_complex_type (void *p, unsigned int size) | |||
592 | { | |||
593 | struct pr_handle *info = (struct pr_handle *) p; | |||
594 | ||||
595 | if (! pr_float_type (p, size)) | |||
596 | return FALSE0; | |||
597 | ||||
598 | return prepend_type (info, "complex "); | |||
599 | } | |||
600 | ||||
601 | /* Push a bfd_boolean type onto the type stack. */ | |||
602 | ||||
603 | static bfd_boolean | |||
604 | pr_bool_type (void *p, unsigned int size) | |||
605 | { | |||
606 | struct pr_handle *info = (struct pr_handle *) p; | |||
607 | char ab[10]; | |||
608 | ||||
609 | sprintf (ab, "bool%d", size * 8); | |||
610 | ||||
611 | return push_type (info, ab); | |||
612 | } | |||
613 | ||||
614 | /* Push an enum type onto the type stack. */ | |||
615 | ||||
616 | static bfd_boolean | |||
617 | pr_enum_type (void *p, const char *tag, const char **names, | |||
618 | bfd_signed_vma *values) | |||
619 | { | |||
620 | struct pr_handle *info = (struct pr_handle *) p; | |||
621 | unsigned int i; | |||
622 | bfd_signed_vma val; | |||
623 | ||||
624 | if (! push_type (info, "enum ")) | |||
625 | return FALSE0; | |||
626 | if (tag != NULL((void*)0)) | |||
627 | { | |||
628 | if (! append_type (info, tag) | |||
629 | || ! append_type (info, " ")) | |||
630 | return FALSE0; | |||
631 | } | |||
632 | if (! append_type (info, "{ ")) | |||
633 | return FALSE0; | |||
634 | ||||
635 | if (names == NULL((void*)0)) | |||
636 | { | |||
637 | if (! append_type (info, "/* undefined */")) | |||
638 | return FALSE0; | |||
639 | } | |||
640 | else | |||
641 | { | |||
642 | val = 0; | |||
643 | for (i = 0; names[i] != NULL((void*)0); i++) | |||
644 | { | |||
645 | if (i > 0) | |||
646 | { | |||
647 | if (! append_type (info, ", ")) | |||
648 | return FALSE0; | |||
649 | } | |||
650 | ||||
651 | if (! append_type (info, names[i])) | |||
652 | return FALSE0; | |||
653 | ||||
654 | if (values[i] != val) | |||
655 | { | |||
656 | char ab[20]; | |||
657 | ||||
658 | print_vma (values[i], ab, FALSE0, FALSE0); | |||
659 | if (! append_type (info, " = ") | |||
660 | || ! append_type (info, ab)) | |||
661 | return FALSE0; | |||
662 | val = values[i]; | |||
663 | } | |||
664 | ||||
665 | ++val; | |||
666 | } | |||
667 | } | |||
668 | ||||
669 | return append_type (info, " }"); | |||
670 | } | |||
671 | ||||
672 | /* Turn the top type on the stack into a pointer. */ | |||
673 | ||||
674 | static bfd_boolean | |||
675 | pr_pointer_type (void *p) | |||
676 | { | |||
677 | struct pr_handle *info = (struct pr_handle *) p; | |||
678 | char *s; | |||
679 | ||||
680 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 680, __func__, "info->stack != NULL")); | |||
681 | ||||
682 | s = strchr (info->stack->type, '|'); | |||
683 | if (s != NULL((void*)0) && s[1] == '[') | |||
684 | return substitute_type (info, "(*|)"); | |||
685 | return substitute_type (info, "*|"); | |||
686 | } | |||
687 | ||||
688 | /* Turn the top type on the stack into a function returning that type. */ | |||
689 | ||||
690 | static bfd_boolean | |||
691 | pr_function_type (void *p, int argcount, bfd_boolean varargs) | |||
692 | { | |||
693 | struct pr_handle *info = (struct pr_handle *) p; | |||
694 | char **arg_types; | |||
695 | unsigned int len; | |||
696 | char *s; | |||
697 | ||||
698 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 698, __func__, "info->stack != NULL")); | |||
699 | ||||
700 | len = 10; | |||
701 | ||||
702 | if (argcount <= 0) | |||
703 | { | |||
704 | arg_types = NULL((void*)0); | |||
705 | len += 15; | |||
706 | } | |||
707 | else | |||
708 | { | |||
709 | int i; | |||
710 | ||||
711 | arg_types = (char **) xmalloc (argcount * sizeof *arg_types); | |||
712 | for (i = argcount - 1; i >= 0; i--) | |||
713 | { | |||
714 | if (! substitute_type (info, "")) | |||
715 | return FALSE0; | |||
716 | arg_types[i] = pop_type (info); | |||
717 | if (arg_types[i] == NULL((void*)0)) | |||
718 | return FALSE0; | |||
719 | len += strlen (arg_types[i]) + 2; | |||
720 | } | |||
721 | if (varargs) | |||
722 | len += 5; | |||
723 | } | |||
724 | ||||
725 | /* Now the return type is on the top of the stack. */ | |||
726 | ||||
727 | s = (char *) xmalloc (len); | |||
728 | strcpy (s, "(|) ("); | |||
729 | ||||
730 | if (argcount < 0) | |||
731 | strcat (s, "/* unknown */"); | |||
732 | else | |||
733 | { | |||
734 | int i; | |||
735 | ||||
736 | for (i = 0; i < argcount; i++) | |||
737 | { | |||
738 | if (i > 0) | |||
739 | strcat (s, ", "); | |||
740 | strcat (s, arg_types[i]); | |||
741 | } | |||
742 | if (varargs) | |||
743 | { | |||
744 | if (i > 0) | |||
745 | strcat (s, ", "); | |||
746 | strcat (s, "..."); | |||
747 | } | |||
748 | if (argcount > 0) | |||
749 | free (arg_types); | |||
750 | } | |||
751 | ||||
752 | strcat (s, ")"); | |||
753 | ||||
754 | if (! substitute_type (info, s)) | |||
755 | return FALSE0; | |||
756 | ||||
757 | free (s); | |||
758 | ||||
759 | return TRUE1; | |||
760 | } | |||
761 | ||||
762 | /* Turn the top type on the stack into a reference to that type. */ | |||
763 | ||||
764 | static bfd_boolean | |||
765 | pr_reference_type (void *p) | |||
766 | { | |||
767 | struct pr_handle *info = (struct pr_handle *) p; | |||
768 | ||||
769 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 769, __func__, "info->stack != NULL")); | |||
770 | ||||
771 | return substitute_type (info, "&|"); | |||
772 | } | |||
773 | ||||
774 | /* Make a range type. */ | |||
775 | ||||
776 | static bfd_boolean | |||
777 | pr_range_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper) | |||
778 | { | |||
779 | struct pr_handle *info = (struct pr_handle *) p; | |||
780 | char abl[20], abu[20]; | |||
781 | ||||
782 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 782, __func__, "info->stack != NULL")); | |||
783 | ||||
784 | if (! substitute_type (info, "")) | |||
785 | return FALSE0; | |||
786 | ||||
787 | print_vma (lower, abl, FALSE0, FALSE0); | |||
788 | print_vma (upper, abu, FALSE0, FALSE0); | |||
789 | ||||
790 | return (prepend_type (info, "range (") | |||
791 | && append_type (info, "):") | |||
792 | && append_type (info, abl) | |||
793 | && append_type (info, ":") | |||
794 | && append_type (info, abu)); | |||
795 | } | |||
796 | ||||
797 | /* Make an array type. */ | |||
798 | ||||
799 | static bfd_boolean | |||
800 | pr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper, | |||
801 | bfd_boolean stringp) | |||
802 | { | |||
803 | struct pr_handle *info = (struct pr_handle *) p; | |||
804 | char *range_type; | |||
805 | char abl[20], abu[20], ab[50]; | |||
806 | ||||
807 | range_type = pop_type (info); | |||
808 | if (range_type == NULL((void*)0)) | |||
809 | return FALSE0; | |||
810 | ||||
811 | if (lower == 0) | |||
812 | { | |||
813 | if (upper == -1) | |||
814 | sprintf (ab, "|[]"); | |||
815 | else | |||
816 | { | |||
817 | print_vma (upper + 1, abu, FALSE0, FALSE0); | |||
818 | sprintf (ab, "|[%s]", abu); | |||
819 | } | |||
820 | } | |||
821 | else | |||
822 | { | |||
823 | print_vma (lower, abl, FALSE0, FALSE0); | |||
824 | print_vma (upper, abu, FALSE0, FALSE0); | |||
825 | sprintf (ab, "|[%s:%s]", abl, abu); | |||
826 | } | |||
827 | ||||
828 | if (! substitute_type (info, ab)) | |||
829 | return FALSE0; | |||
830 | ||||
831 | if (strcmp (range_type, "int") != 0) | |||
832 | { | |||
833 | if (! append_type (info, ":") | |||
834 | || ! append_type (info, range_type)) | |||
835 | return FALSE0; | |||
836 | } | |||
837 | ||||
838 | if (stringp) | |||
839 | { | |||
840 | if (! append_type (info, " /* string */")) | |||
841 | return FALSE0; | |||
842 | } | |||
843 | ||||
844 | return TRUE1; | |||
845 | } | |||
846 | ||||
847 | /* Make a set type. */ | |||
848 | ||||
849 | static bfd_boolean | |||
850 | pr_set_type (void *p, bfd_boolean bitstringp) | |||
851 | { | |||
852 | struct pr_handle *info = (struct pr_handle *) p; | |||
853 | ||||
854 | if (! substitute_type (info, "")) | |||
855 | return FALSE0; | |||
856 | ||||
857 | if (! prepend_type (info, "set { ") | |||
858 | || ! append_type (info, " }")) | |||
859 | return FALSE0; | |||
860 | ||||
861 | if (bitstringp) | |||
862 | { | |||
863 | if (! append_type (info, "/* bitstring */")) | |||
864 | return FALSE0; | |||
865 | } | |||
866 | ||||
867 | return TRUE1; | |||
868 | } | |||
869 | ||||
870 | /* Make an offset type. */ | |||
871 | ||||
872 | static bfd_boolean | |||
873 | pr_offset_type (void *p) | |||
874 | { | |||
875 | struct pr_handle *info = (struct pr_handle *) p; | |||
876 | char *t; | |||
877 | ||||
878 | if (! substitute_type (info, "")) | |||
879 | return FALSE0; | |||
880 | ||||
881 | t = pop_type (info); | |||
882 | if (t == NULL((void*)0)) | |||
883 | return FALSE0; | |||
884 | ||||
885 | return (substitute_type (info, "") | |||
886 | && prepend_type (info, " ") | |||
887 | && prepend_type (info, t) | |||
888 | && append_type (info, "::|")); | |||
889 | } | |||
890 | ||||
891 | /* Make a method type. */ | |||
892 | ||||
893 | static bfd_boolean | |||
894 | pr_method_type (void *p, bfd_boolean domain, int argcount, bfd_boolean varargs) | |||
895 | { | |||
896 | struct pr_handle *info = (struct pr_handle *) p; | |||
897 | unsigned int len; | |||
898 | char *domain_type; | |||
899 | char **arg_types; | |||
900 | char *s; | |||
901 | ||||
902 | len = 10; | |||
903 | ||||
904 | if (! domain) | |||
905 | domain_type = NULL((void*)0); | |||
906 | else | |||
907 | { | |||
908 | if (! substitute_type (info, "")) | |||
909 | return FALSE0; | |||
910 | domain_type = pop_type (info); | |||
911 | if (domain_type == NULL((void*)0)) | |||
912 | return FALSE0; | |||
913 | if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0 | |||
914 | && strchr (domain_type + sizeof "class " - 1, ' ') == NULL((void*)0)) | |||
915 | domain_type += sizeof "class " - 1; | |||
916 | else if (strncmp (domain_type, "union class ", | |||
917 | sizeof "union class ") == 0 | |||
918 | && (strchr (domain_type + sizeof "union class " - 1, ' ') | |||
919 | == NULL((void*)0))) | |||
920 | domain_type += sizeof "union class " - 1; | |||
921 | len += strlen (domain_type); | |||
922 | } | |||
923 | ||||
924 | if (argcount <= 0) | |||
925 | { | |||
926 | arg_types = NULL((void*)0); | |||
927 | len += 15; | |||
928 | } | |||
929 | else | |||
930 | { | |||
931 | int i; | |||
932 | ||||
933 | arg_types = (char **) xmalloc (argcount * sizeof *arg_types); | |||
934 | for (i = argcount - 1; i >= 0; i--) | |||
935 | { | |||
936 | if (! substitute_type (info, "")) | |||
937 | return FALSE0; | |||
938 | arg_types[i] = pop_type (info); | |||
939 | if (arg_types[i] == NULL((void*)0)) | |||
940 | return FALSE0; | |||
941 | len += strlen (arg_types[i]) + 2; | |||
942 | } | |||
943 | if (varargs) | |||
944 | len += 5; | |||
945 | } | |||
946 | ||||
947 | /* Now the return type is on the top of the stack. */ | |||
948 | ||||
949 | s = (char *) xmalloc (len); | |||
950 | if (! domain) | |||
951 | *s = '\0'; | |||
952 | else | |||
953 | strcpy (s, domain_type); | |||
954 | strcat (s, "::| ("); | |||
955 | ||||
956 | if (argcount < 0) | |||
957 | strcat (s, "/* unknown */"); | |||
958 | else | |||
959 | { | |||
960 | int i; | |||
961 | ||||
962 | for (i = 0; i < argcount; i++) | |||
963 | { | |||
964 | if (i > 0) | |||
965 | strcat (s, ", "); | |||
966 | strcat (s, arg_types[i]); | |||
967 | } | |||
968 | if (varargs) | |||
969 | { | |||
970 | if (i > 0) | |||
971 | strcat (s, ", "); | |||
972 | strcat (s, "..."); | |||
973 | } | |||
974 | if (argcount > 0) | |||
975 | free (arg_types); | |||
976 | } | |||
977 | ||||
978 | strcat (s, ")"); | |||
979 | ||||
980 | if (! substitute_type (info, s)) | |||
981 | return FALSE0; | |||
982 | ||||
983 | free (s); | |||
984 | ||||
985 | return TRUE1; | |||
986 | } | |||
987 | ||||
988 | /* Make a const qualified type. */ | |||
989 | ||||
990 | static bfd_boolean | |||
991 | pr_const_type (void *p) | |||
992 | { | |||
993 | struct pr_handle *info = (struct pr_handle *) p; | |||
994 | ||||
995 | return substitute_type (info, "const |"); | |||
996 | } | |||
997 | ||||
998 | /* Make a volatile qualified type. */ | |||
999 | ||||
1000 | static bfd_boolean | |||
1001 | pr_volatile_type (void *p) | |||
1002 | { | |||
1003 | struct pr_handle *info = (struct pr_handle *) p; | |||
1004 | ||||
1005 | return substitute_type (info, "volatile |"); | |||
1006 | } | |||
1007 | ||||
1008 | /* Start accumulating a struct type. */ | |||
1009 | ||||
1010 | static bfd_boolean | |||
1011 | pr_start_struct_type (void *p, const char *tag, unsigned int id, | |||
1012 | bfd_boolean structp, unsigned int size) | |||
1013 | { | |||
1014 | struct pr_handle *info = (struct pr_handle *) p; | |||
1015 | ||||
1016 | info->indent += 2; | |||
1017 | ||||
1018 | if (! push_type (info, structp ? "struct " : "union ")) | |||
1019 | return FALSE0; | |||
1020 | if (tag != NULL((void*)0)) | |||
1021 | { | |||
1022 | if (! append_type (info, tag)) | |||
1023 | return FALSE0; | |||
1024 | } | |||
1025 | else | |||
1026 | { | |||
1027 | char idbuf[20]; | |||
1028 | ||||
1029 | sprintf (idbuf, "%%anon%u", id); | |||
1030 | if (! append_type (info, idbuf)) | |||
1031 | return FALSE0; | |||
1032 | } | |||
1033 | ||||
1034 | if (! append_type (info, " {")) | |||
1035 | return FALSE0; | |||
1036 | if (size != 0 || tag != NULL((void*)0)) | |||
1037 | { | |||
1038 | char ab[30]; | |||
1039 | ||||
1040 | if (! append_type (info, " /*")) | |||
1041 | return FALSE0; | |||
1042 | ||||
1043 | if (size != 0) | |||
1044 | { | |||
1045 | sprintf (ab, " size %u", size); | |||
1046 | if (! append_type (info, ab)) | |||
1047 | return FALSE0; | |||
1048 | } | |||
1049 | if (tag != NULL((void*)0)) | |||
1050 | { | |||
1051 | sprintf (ab, " id %u", id); | |||
1052 | if (! append_type (info, ab)) | |||
1053 | return FALSE0; | |||
1054 | } | |||
1055 | if (! append_type (info, " */")) | |||
1056 | return FALSE0; | |||
1057 | } | |||
1058 | if (! append_type (info, "\n")) | |||
1059 | return FALSE0; | |||
1060 | ||||
1061 | info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; | |||
1062 | ||||
1063 | return indent_type (info); | |||
1064 | } | |||
1065 | ||||
1066 | /* Output the visibility of a field in a struct. */ | |||
1067 | ||||
1068 | static bfd_boolean | |||
1069 | pr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) | |||
1070 | { | |||
1071 | const char *s = NULL((void*)0); | |||
1072 | char *t; | |||
1073 | unsigned int len; | |||
1074 | ||||
1075 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1075, __func__, "info->stack != NULL")); | |||
1076 | ||||
1077 | if (info->stack->visibility == visibility) | |||
1078 | return TRUE1; | |||
1079 | ||||
1080 | switch (visibility) | |||
1081 | { | |||
1082 | case DEBUG_VISIBILITY_PUBLIC: | |||
1083 | s = "public"; | |||
1084 | break; | |||
1085 | case DEBUG_VISIBILITY_PRIVATE: | |||
1086 | s = "private"; | |||
1087 | break; | |||
1088 | case DEBUG_VISIBILITY_PROTECTED: | |||
1089 | s = "protected"; | |||
1090 | break; | |||
1091 | case DEBUG_VISIBILITY_IGNORE: | |||
1092 | s = "/* ignore */"; | |||
1093 | break; | |||
1094 | default: | |||
1095 | abort (); | |||
1096 | return FALSE0; | |||
1097 | } | |||
1098 | ||||
1099 | /* Trim off a trailing space in the struct string, to make the | |||
1100 | output look a bit better, then stick on the visibility string. */ | |||
1101 | ||||
1102 | t = info->stack->type; | |||
1103 | len = strlen (t); | |||
1104 | assert (t[len - 1] == ' ')((t[len - 1] == ' ') ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1104, __func__, "t[len - 1] == ' '")); | |||
1105 | t[len - 1] = '\0'; | |||
1106 | ||||
1107 | if (! append_type (info, s) | |||
1108 | || ! append_type (info, ":\n") | |||
1109 | || ! indent_type (info)) | |||
1110 | return FALSE0; | |||
1111 | ||||
1112 | info->stack->visibility = visibility; | |||
1113 | ||||
1114 | return TRUE1; | |||
1115 | } | |||
1116 | ||||
1117 | /* Add a field to a struct type. */ | |||
1118 | ||||
1119 | static bfd_boolean | |||
1120 | pr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize, | |||
1121 | enum debug_visibility visibility) | |||
1122 | { | |||
1123 | struct pr_handle *info = (struct pr_handle *) p; | |||
1124 | char ab[20]; | |||
1125 | char *t; | |||
1126 | ||||
1127 | if (! substitute_type (info, name)) | |||
1128 | return FALSE0; | |||
1129 | ||||
1130 | if (! append_type (info, "; /* ")) | |||
1131 | return FALSE0; | |||
1132 | ||||
1133 | if (bitsize != 0) | |||
1134 | { | |||
1135 | print_vma (bitsize, ab, TRUE1, FALSE0); | |||
1136 | if (! append_type (info, "bitsize ") | |||
1137 | || ! append_type (info, ab) | |||
1138 | || ! append_type (info, ", ")) | |||
1139 | return FALSE0; | |||
1140 | } | |||
1141 | ||||
1142 | print_vma (bitpos, ab, TRUE1, FALSE0); | |||
1143 | if (! append_type (info, "bitpos ") | |||
1144 | || ! append_type (info, ab) | |||
1145 | || ! append_type (info, " */\n") | |||
1146 | || ! indent_type (info)) | |||
1147 | return FALSE0; | |||
1148 | ||||
1149 | t = pop_type (info); | |||
1150 | if (t == NULL((void*)0)) | |||
1151 | return FALSE0; | |||
1152 | ||||
1153 | if (! pr_fix_visibility (info, visibility)) | |||
1154 | return FALSE0; | |||
1155 | ||||
1156 | return append_type (info, t); | |||
1157 | } | |||
1158 | ||||
1159 | /* Finish a struct type. */ | |||
1160 | ||||
1161 | static bfd_boolean | |||
1162 | pr_end_struct_type (void *p) | |||
1163 | { | |||
1164 | struct pr_handle *info = (struct pr_handle *) p; | |||
1165 | char *s; | |||
1166 | ||||
1167 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1167, __func__, "info->stack != NULL")); | |||
1168 | assert (info->indent >= 2)((info->indent >= 2) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1168, __func__, "info->indent >= 2")); | |||
1169 | ||||
1170 | info->indent -= 2; | |||
1171 | ||||
1172 | /* Change the trailing indentation to have a close brace. */ | |||
1173 | s = info->stack->type + strlen (info->stack->type) - 2; | |||
1174 | assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0')((s[0] == ' ' && s[1] == ' ' && s[2] == '\0') ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1174, __func__, "s[0] == ' ' && s[1] == ' ' && s[2] == '\\0'" )); | |||
1175 | ||||
1176 | *s++ = '}'; | |||
1177 | *s = '\0'; | |||
1178 | ||||
1179 | return TRUE1; | |||
1180 | } | |||
1181 | ||||
1182 | /* Start a class type. */ | |||
1183 | ||||
1184 | static bfd_boolean | |||
1185 | pr_start_class_type (void *p, const char *tag, unsigned int id, | |||
1186 | bfd_boolean structp, unsigned int size, | |||
1187 | bfd_boolean vptr, bfd_boolean ownvptr) | |||
1188 | { | |||
1189 | struct pr_handle *info = (struct pr_handle *) p; | |||
1190 | char *tv = NULL((void*)0); | |||
1191 | ||||
1192 | info->indent += 2; | |||
1193 | ||||
1194 | if (vptr && ! ownvptr) | |||
1195 | { | |||
1196 | tv = pop_type (info); | |||
1197 | if (tv == NULL((void*)0)) | |||
1198 | return FALSE0; | |||
1199 | } | |||
1200 | ||||
1201 | if (! push_type (info, structp ? "class " : "union class ")) | |||
1202 | return FALSE0; | |||
1203 | if (tag != NULL((void*)0)) | |||
1204 | { | |||
1205 | if (! append_type (info, tag)) | |||
1206 | return FALSE0; | |||
1207 | } | |||
1208 | else | |||
1209 | { | |||
1210 | char idbuf[20]; | |||
1211 | ||||
1212 | sprintf (idbuf, "%%anon%u", id); | |||
1213 | if (! append_type (info, idbuf)) | |||
1214 | return FALSE0; | |||
1215 | } | |||
1216 | ||||
1217 | if (! append_type (info, " {")) | |||
1218 | return FALSE0; | |||
1219 | if (size != 0 || vptr || ownvptr || tag != NULL((void*)0)) | |||
1220 | { | |||
1221 | if (! append_type (info, " /*")) | |||
1222 | return FALSE0; | |||
1223 | ||||
1224 | if (size != 0) | |||
1225 | { | |||
1226 | char ab[20]; | |||
1227 | ||||
1228 | sprintf (ab, "%u", size); | |||
1229 | if (! append_type (info, " size ") | |||
1230 | || ! append_type (info, ab)) | |||
1231 | return FALSE0; | |||
1232 | } | |||
1233 | ||||
1234 | if (vptr) | |||
1235 | { | |||
1236 | if (! append_type (info, " vtable ")) | |||
1237 | return FALSE0; | |||
1238 | if (ownvptr) | |||
1239 | { | |||
1240 | if (! append_type (info, "self ")) | |||
1241 | return FALSE0; | |||
1242 | } | |||
1243 | else | |||
1244 | { | |||
1245 | if (! append_type (info, tv) | |||
1246 | || ! append_type (info, " ")) | |||
1247 | return FALSE0; | |||
1248 | } | |||
1249 | } | |||
1250 | ||||
1251 | if (tag != NULL((void*)0)) | |||
1252 | { | |||
1253 | char ab[30]; | |||
1254 | ||||
1255 | sprintf (ab, " id %u", id); | |||
1256 | if (! append_type (info, ab)) | |||
1257 | return FALSE0; | |||
1258 | } | |||
1259 | ||||
1260 | if (! append_type (info, " */")) | |||
1261 | return FALSE0; | |||
1262 | } | |||
1263 | ||||
1264 | info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; | |||
1265 | ||||
1266 | return (append_type (info, "\n") | |||
1267 | && indent_type (info)); | |||
1268 | } | |||
1269 | ||||
1270 | /* Add a static member to a class. */ | |||
1271 | ||||
1272 | static bfd_boolean | |||
1273 | pr_class_static_member (void *p, const char *name, const char *physname, | |||
1274 | enum debug_visibility visibility) | |||
1275 | { | |||
1276 | struct pr_handle *info = (struct pr_handle *) p; | |||
1277 | char *t; | |||
1278 | ||||
1279 | if (! substitute_type (info, name)) | |||
1280 | return FALSE0; | |||
1281 | ||||
1282 | if (! prepend_type (info, "static ") | |||
1283 | || ! append_type (info, "; /* ") | |||
1284 | || ! append_type (info, physname) | |||
1285 | || ! append_type (info, " */\n") | |||
1286 | || ! indent_type (info)) | |||
1287 | return FALSE0; | |||
1288 | ||||
1289 | t = pop_type (info); | |||
1290 | if (t == NULL((void*)0)) | |||
1291 | return FALSE0; | |||
1292 | ||||
1293 | if (! pr_fix_visibility (info, visibility)) | |||
1294 | return FALSE0; | |||
1295 | ||||
1296 | return append_type (info, t); | |||
1297 | } | |||
1298 | ||||
1299 | /* Add a base class to a class. */ | |||
1300 | ||||
1301 | static bfd_boolean | |||
1302 | pr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual, | |||
1303 | enum debug_visibility visibility) | |||
1304 | { | |||
1305 | struct pr_handle *info = (struct pr_handle *) p; | |||
1306 | char *t; | |||
1307 | const char *prefix; | |||
1308 | char ab[20]; | |||
1309 | char *s, *l, *n; | |||
1310 | ||||
1311 | assert (info->stack != NULL && info->stack->next != NULL)((info->stack != ((void*)0) && info->stack-> next != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1311, __func__, "info->stack != NULL && info->stack->next != NULL" )); | |||
1312 | ||||
1313 | if (! substitute_type (info, "")) | |||
1314 | return FALSE0; | |||
1315 | ||||
1316 | t = pop_type (info); | |||
1317 | if (t == NULL((void*)0)) | |||
1318 | return FALSE0; | |||
1319 | ||||
1320 | if (strncmp (t, "class ", sizeof "class " - 1) == 0) | |||
1321 | t += sizeof "class " - 1; | |||
1322 | ||||
1323 | /* Push it back on to take advantage of the prepend_type and | |||
1324 | append_type routines. */ | |||
1325 | if (! push_type (info, t)) | |||
1326 | return FALSE0; | |||
1327 | ||||
1328 | if (virtual) | |||
1329 | { | |||
1330 | if (! prepend_type (info, "virtual ")) | |||
1331 | return FALSE0; | |||
1332 | } | |||
1333 | ||||
1334 | switch (visibility) | |||
1335 | { | |||
1336 | case DEBUG_VISIBILITY_PUBLIC: | |||
1337 | prefix = "public "; | |||
1338 | break; | |||
1339 | case DEBUG_VISIBILITY_PROTECTED: | |||
1340 | prefix = "protected "; | |||
1341 | break; | |||
1342 | case DEBUG_VISIBILITY_PRIVATE: | |||
1343 | prefix = "private "; | |||
1344 | break; | |||
1345 | default: | |||
1346 | prefix = "/* unknown visibility */ "; | |||
1347 | break; | |||
1348 | } | |||
1349 | ||||
1350 | if (! prepend_type (info, prefix)) | |||
1351 | return FALSE0; | |||
1352 | ||||
1353 | if (bitpos != 0) | |||
1354 | { | |||
1355 | print_vma (bitpos, ab, TRUE1, FALSE0); | |||
1356 | if (! append_type (info, " /* bitpos ") | |||
1357 | || ! append_type (info, ab) | |||
1358 | || ! append_type (info, " */")) | |||
1359 | return FALSE0; | |||
1360 | } | |||
1361 | ||||
1362 | /* Now the top of the stack is something like "public A / * bitpos | |||
1363 | 10 * /". The next element on the stack is something like "class | |||
1364 | xx { / * size 8 * /\n...". We want to substitute the top of the | |||
1365 | stack in before the {. */ | |||
1366 | s = strchr (info->stack->next->type, '{'); | |||
1367 | assert (s != NULL)((s != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1367, __func__, "s != NULL")); | |||
1368 | --s; | |||
1369 | ||||
1370 | /* If there is already a ':', then we already have a baseclass, and | |||
1371 | we must append this one after a comma. */ | |||
1372 | for (l = info->stack->next->type; l != s; l++) | |||
1373 | if (*l == ':') | |||
1374 | break; | |||
1375 | if (! prepend_type (info, l == s ? " : " : ", ")) | |||
1376 | return FALSE0; | |||
1377 | ||||
1378 | t = pop_type (info); | |||
1379 | if (t == NULL((void*)0)) | |||
1380 | return FALSE0; | |||
1381 | ||||
1382 | n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); | |||
1383 | memcpy (n, info->stack->type, s - info->stack->type); | |||
1384 | strcpy (n + (s - info->stack->type), t); | |||
1385 | strcat (n, s); | |||
1386 | ||||
1387 | free (info->stack->type); | |||
1388 | info->stack->type = n; | |||
1389 | ||||
1390 | free (t); | |||
1391 | ||||
1392 | return TRUE1; | |||
1393 | } | |||
1394 | ||||
1395 | /* Start adding a method to a class. */ | |||
1396 | ||||
1397 | static bfd_boolean | |||
1398 | pr_class_start_method (void *p, const char *name) | |||
1399 | { | |||
1400 | struct pr_handle *info = (struct pr_handle *) p; | |||
1401 | ||||
1402 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1402, __func__, "info->stack != NULL")); | |||
1403 | info->stack->method = name; | |||
1404 | return TRUE1; | |||
1405 | } | |||
1406 | ||||
1407 | /* Add a variant to a method. */ | |||
1408 | ||||
1409 | static bfd_boolean | |||
1410 | pr_class_method_variant (void *p, const char *physname, | |||
1411 | enum debug_visibility visibility, | |||
1412 | bfd_boolean constp, bfd_boolean volatilep, | |||
1413 | bfd_vma voffset, bfd_boolean context) | |||
1414 | { | |||
1415 | struct pr_handle *info = (struct pr_handle *) p; | |||
1416 | char *method_type; | |||
1417 | char *context_type; | |||
1418 | ||||
1419 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1419, __func__, "info->stack != NULL")); | |||
1420 | assert (info->stack->next != NULL)((info->stack->next != ((void*)0)) ? (void)0 : __assert2 ("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c", 1420, __func__, "info->stack->next != NULL")); | |||
1421 | ||||
1422 | /* Put the const and volatile qualifiers on the type. */ | |||
1423 | if (volatilep) | |||
1424 | { | |||
1425 | if (! append_type (info, " volatile")) | |||
1426 | return FALSE0; | |||
1427 | } | |||
1428 | if (constp) | |||
1429 | { | |||
1430 | if (! append_type (info, " const")) | |||
1431 | return FALSE0; | |||
1432 | } | |||
1433 | ||||
1434 | /* Stick the name of the method into its type. */ | |||
1435 | if (! substitute_type (info, | |||
1436 | (context | |||
1437 | ? info->stack->next->next->method | |||
1438 | : info->stack->next->method))) | |||
1439 | return FALSE0; | |||
1440 | ||||
1441 | /* Get the type. */ | |||
1442 | method_type = pop_type (info); | |||
1443 | if (method_type == NULL((void*)0)) | |||
1444 | return FALSE0; | |||
1445 | ||||
1446 | /* Pull off the context type if there is one. */ | |||
1447 | if (! context) | |||
1448 | context_type = NULL((void*)0); | |||
1449 | else | |||
1450 | { | |||
1451 | context_type = pop_type (info); | |||
1452 | if (context_type == NULL((void*)0)) | |||
1453 | return FALSE0; | |||
1454 | } | |||
1455 | ||||
1456 | /* Now the top of the stack is the class. */ | |||
1457 | ||||
1458 | if (! pr_fix_visibility (info, visibility)) | |||
1459 | return FALSE0; | |||
1460 | ||||
1461 | if (! append_type (info, method_type) | |||
1462 | || ! append_type (info, " /* ") | |||
1463 | || ! append_type (info, physname) | |||
1464 | || ! append_type (info, " ")) | |||
1465 | return FALSE0; | |||
1466 | if (context || voffset != 0) | |||
1467 | { | |||
1468 | char ab[20]; | |||
1469 | ||||
1470 | if (context) | |||
1471 | { | |||
1472 | if (! append_type (info, "context ") | |||
1473 | || ! append_type (info, context_type) | |||
1474 | || ! append_type (info, " ")) | |||
1475 | return FALSE0; | |||
1476 | } | |||
1477 | print_vma (voffset, ab, TRUE1, FALSE0); | |||
1478 | if (! append_type (info, "voffset ") | |||
1479 | || ! append_type (info, ab)) | |||
1480 | return FALSE0; | |||
1481 | } | |||
1482 | ||||
1483 | return (append_type (info, " */;\n") | |||
1484 | && indent_type (info)); | |||
1485 | } | |||
1486 | ||||
1487 | /* Add a static variant to a method. */ | |||
1488 | ||||
1489 | static bfd_boolean | |||
1490 | pr_class_static_method_variant (void *p, const char *physname, | |||
1491 | enum debug_visibility visibility, | |||
1492 | bfd_boolean constp, bfd_boolean volatilep) | |||
1493 | { | |||
1494 | struct pr_handle *info = (struct pr_handle *) p; | |||
1495 | char *method_type; | |||
1496 | ||||
1497 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1497, __func__, "info->stack != NULL")); | |||
1498 | assert (info->stack->next != NULL)((info->stack->next != ((void*)0)) ? (void)0 : __assert2 ("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c", 1498, __func__, "info->stack->next != NULL")); | |||
1499 | assert (info->stack->next->method != NULL)((info->stack->next->method != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 1499, __func__, "info->stack->next->method != NULL" )); | |||
1500 | ||||
1501 | /* Put the const and volatile qualifiers on the type. */ | |||
1502 | if (volatilep) | |||
1503 | { | |||
1504 | if (! append_type (info, " volatile")) | |||
1505 | return FALSE0; | |||
1506 | } | |||
1507 | if (constp) | |||
1508 | { | |||
1509 | if (! append_type (info, " const")) | |||
1510 | return FALSE0; | |||
1511 | } | |||
1512 | ||||
1513 | /* Mark it as static. */ | |||
1514 | if (! prepend_type (info, "static ")) | |||
1515 | return FALSE0; | |||
1516 | ||||
1517 | /* Stick the name of the method into its type. */ | |||
1518 | if (! substitute_type (info, info->stack->next->method)) | |||
1519 | return FALSE0; | |||
1520 | ||||
1521 | /* Get the type. */ | |||
1522 | method_type = pop_type (info); | |||
1523 | if (method_type == NULL((void*)0)) | |||
1524 | return FALSE0; | |||
1525 | ||||
1526 | /* Now the top of the stack is the class. */ | |||
1527 | ||||
1528 | if (! pr_fix_visibility (info, visibility)) | |||
1529 | return FALSE0; | |||
1530 | ||||
1531 | return (append_type (info, method_type) | |||
1532 | && append_type (info, " /* ") | |||
1533 | && append_type (info, physname) | |||
1534 | && append_type (info, " */;\n") | |||
1535 | && indent_type (info)); | |||
1536 | } | |||
1537 | ||||
1538 | /* Finish up a method. */ | |||
1539 | ||||
1540 | static bfd_boolean | |||
1541 | pr_class_end_method (void *p) | |||
1542 | { | |||
1543 | struct pr_handle *info = (struct pr_handle *) p; | |||
1544 | ||||
1545 | info->stack->method = NULL((void*)0); | |||
1546 | return TRUE1; | |||
1547 | } | |||
1548 | ||||
1549 | /* Finish up a class. */ | |||
1550 | ||||
1551 | static bfd_boolean | |||
1552 | pr_end_class_type (void *p) | |||
1553 | { | |||
1554 | return pr_end_struct_type (p); | |||
1555 | } | |||
1556 | ||||
1557 | /* Push a type on the stack using a typedef name. */ | |||
1558 | ||||
1559 | static bfd_boolean | |||
1560 | pr_typedef_type (void *p, const char *name) | |||
1561 | { | |||
1562 | struct pr_handle *info = (struct pr_handle *) p; | |||
1563 | ||||
1564 | return push_type (info, name); | |||
1565 | } | |||
1566 | ||||
1567 | /* Push a type on the stack using a tag name. */ | |||
1568 | ||||
1569 | static bfd_boolean | |||
1570 | pr_tag_type (void *p, const char *name, unsigned int id, | |||
1571 | enum debug_type_kind kind) | |||
1572 | { | |||
1573 | struct pr_handle *info = (struct pr_handle *) p; | |||
1574 | const char *t, *tag; | |||
1575 | char idbuf[20]; | |||
1576 | ||||
1577 | switch (kind) | |||
1578 | { | |||
1579 | case DEBUG_KIND_STRUCT: | |||
1580 | t = "struct "; | |||
1581 | break; | |||
1582 | case DEBUG_KIND_UNION: | |||
1583 | t = "union "; | |||
1584 | break; | |||
1585 | case DEBUG_KIND_ENUM: | |||
1586 | t = "enum "; | |||
1587 | break; | |||
1588 | case DEBUG_KIND_CLASS: | |||
1589 | t = "class "; | |||
1590 | break; | |||
1591 | case DEBUG_KIND_UNION_CLASS: | |||
1592 | t = "union class "; | |||
1593 | break; | |||
1594 | default: | |||
1595 | abort (); | |||
1596 | return FALSE0; | |||
1597 | } | |||
1598 | ||||
1599 | if (! push_type (info, t)) | |||
1600 | return FALSE0; | |||
1601 | if (name != NULL((void*)0)) | |||
1602 | tag = name; | |||
1603 | else | |||
1604 | { | |||
1605 | sprintf (idbuf, "%%anon%u", id); | |||
1606 | tag = idbuf; | |||
1607 | } | |||
1608 | ||||
1609 | if (! append_type (info, tag)) | |||
1610 | return FALSE0; | |||
1611 | if (name != NULL((void*)0) && kind != DEBUG_KIND_ENUM) | |||
1612 | { | |||
1613 | sprintf (idbuf, " /* id %u */", id); | |||
1614 | if (! append_type (info, idbuf)) | |||
1615 | return FALSE0; | |||
1616 | } | |||
1617 | ||||
1618 | return TRUE1; | |||
1619 | } | |||
1620 | ||||
1621 | /* Output a typedef. */ | |||
1622 | ||||
1623 | static bfd_boolean | |||
1624 | pr_typdef (void *p, const char *name) | |||
1625 | { | |||
1626 | struct pr_handle *info = (struct pr_handle *) p; | |||
1627 | char *s; | |||
1628 | ||||
1629 | if (! substitute_type (info, name)) | |||
1630 | return FALSE0; | |||
1631 | ||||
1632 | s = pop_type (info); | |||
1633 | if (s == NULL((void*)0)) | |||
1634 | return FALSE0; | |||
1635 | ||||
1636 | indent (info); | |||
1637 | fprintf (info->f, "typedef %s;\n", s); | |||
1638 | ||||
1639 | free (s); | |||
1640 | ||||
1641 | return TRUE1; | |||
1642 | } | |||
1643 | ||||
1644 | /* Output a tag. The tag should already be in the string on the | |||
1645 | stack, so all we have to do here is print it out. */ | |||
1646 | ||||
1647 | static bfd_boolean | |||
1648 | pr_tag (void *p, const char *name ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
1649 | { | |||
1650 | struct pr_handle *info = (struct pr_handle *) p; | |||
1651 | char *t; | |||
1652 | ||||
1653 | t = pop_type (info); | |||
1654 | if (t == NULL((void*)0)) | |||
1655 | return FALSE0; | |||
1656 | ||||
1657 | indent (info); | |||
1658 | fprintf (info->f, "%s;\n", t); | |||
1659 | ||||
1660 | free (t); | |||
1661 | ||||
1662 | return TRUE1; | |||
1663 | } | |||
1664 | ||||
1665 | /* Output an integer constant. */ | |||
1666 | ||||
1667 | static bfd_boolean | |||
1668 | pr_int_constant (void *p, const char *name, bfd_vma val) | |||
1669 | { | |||
1670 | struct pr_handle *info = (struct pr_handle *) p; | |||
1671 | char ab[20]; | |||
1672 | ||||
1673 | indent (info); | |||
1674 | print_vma (val, ab, FALSE0, FALSE0); | |||
1675 | fprintf (info->f, "const int %s = %s;\n", name, ab); | |||
1676 | return TRUE1; | |||
1677 | } | |||
1678 | ||||
1679 | /* Output a floating point constant. */ | |||
1680 | ||||
1681 | static bfd_boolean | |||
1682 | pr_float_constant (void *p, const char *name, double val) | |||
1683 | { | |||
1684 | struct pr_handle *info = (struct pr_handle *) p; | |||
1685 | ||||
1686 | indent (info); | |||
1687 | fprintf (info->f, "const double %s = %g;\n", name, val); | |||
1688 | return TRUE1; | |||
1689 | } | |||
1690 | ||||
1691 | /* Output a typed constant. */ | |||
1692 | ||||
1693 | static bfd_boolean | |||
1694 | pr_typed_constant (void *p, const char *name, bfd_vma val) | |||
1695 | { | |||
1696 | struct pr_handle *info = (struct pr_handle *) p; | |||
1697 | char *t; | |||
1698 | char ab[20]; | |||
1699 | ||||
1700 | t = pop_type (info); | |||
1701 | if (t == NULL((void*)0)) | |||
1702 | return FALSE0; | |||
1703 | ||||
1704 | indent (info); | |||
1705 | print_vma (val, ab, FALSE0, FALSE0); | |||
1706 | fprintf (info->f, "const %s %s = %s;\n", t, name, ab); | |||
1707 | ||||
1708 | free (t); | |||
1709 | ||||
1710 | return TRUE1; | |||
1711 | } | |||
1712 | ||||
1713 | /* Output a variable. */ | |||
1714 | ||||
1715 | static bfd_boolean | |||
1716 | pr_variable (void *p, const char *name, enum debug_var_kind kind, | |||
1717 | bfd_vma val) | |||
1718 | { | |||
1719 | struct pr_handle *info = (struct pr_handle *) p; | |||
1720 | char *t; | |||
1721 | char ab[20]; | |||
1722 | ||||
1723 | if (! substitute_type (info, name)) | |||
1724 | return FALSE0; | |||
1725 | ||||
1726 | t = pop_type (info); | |||
1727 | if (t == NULL((void*)0)) | |||
1728 | return FALSE0; | |||
1729 | ||||
1730 | indent (info); | |||
1731 | switch (kind) | |||
1732 | { | |||
1733 | case DEBUG_STATIC: | |||
1734 | case DEBUG_LOCAL_STATIC: | |||
1735 | fprintf (info->f, "static "); | |||
1736 | break; | |||
1737 | case DEBUG_REGISTER: | |||
1738 | fprintf (info->f, "register "); | |||
1739 | break; | |||
1740 | default: | |||
1741 | break; | |||
1742 | } | |||
1743 | print_vma (val, ab, TRUE1, TRUE1); | |||
1744 | fprintf (info->f, "%s /* %s */;\n", t, ab); | |||
1745 | ||||
1746 | free (t); | |||
1747 | ||||
1748 | return TRUE1; | |||
1749 | } | |||
1750 | ||||
1751 | /* Start outputting a function. */ | |||
1752 | ||||
1753 | static bfd_boolean | |||
1754 | pr_start_function (void *p, const char *name, bfd_boolean global) | |||
1755 | { | |||
1756 | struct pr_handle *info = (struct pr_handle *) p; | |||
1757 | char *t; | |||
1758 | ||||
1759 | if (! substitute_type (info, name)) | |||
1760 | return FALSE0; | |||
1761 | ||||
1762 | t = pop_type (info); | |||
1763 | if (t == NULL((void*)0)) | |||
1764 | return FALSE0; | |||
1765 | ||||
1766 | indent (info); | |||
1767 | if (! global) | |||
1768 | fprintf (info->f, "static "); | |||
1769 | fprintf (info->f, "%s (", t); | |||
1770 | ||||
1771 | info->parameter = 1; | |||
1772 | ||||
1773 | return TRUE1; | |||
1774 | } | |||
1775 | ||||
1776 | /* Output a function parameter. */ | |||
1777 | ||||
1778 | static bfd_boolean | |||
1779 | pr_function_parameter (void *p, const char *name, | |||
1780 | enum debug_parm_kind kind, bfd_vma val) | |||
1781 | { | |||
1782 | struct pr_handle *info = (struct pr_handle *) p; | |||
1783 | char *t; | |||
1784 | char ab[20]; | |||
1785 | ||||
1786 | if (kind == DEBUG_PARM_REFERENCE | |||
1787 | || kind == DEBUG_PARM_REF_REG) | |||
1788 | { | |||
1789 | if (! pr_reference_type (p)) | |||
1790 | return FALSE0; | |||
1791 | } | |||
1792 | ||||
1793 | if (! substitute_type (info, name)) | |||
1794 | return FALSE0; | |||
1795 | ||||
1796 | t = pop_type (info); | |||
1797 | if (t == NULL((void*)0)) | |||
1798 | return FALSE0; | |||
1799 | ||||
1800 | if (info->parameter != 1) | |||
1801 | fprintf (info->f, ", "); | |||
1802 | ||||
1803 | if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) | |||
1804 | fprintf (info->f, "register "); | |||
1805 | ||||
1806 | print_vma (val, ab, TRUE1, TRUE1); | |||
1807 | fprintf (info->f, "%s /* %s */", t, ab); | |||
1808 | ||||
1809 | free (t); | |||
1810 | ||||
1811 | ++info->parameter; | |||
1812 | ||||
1813 | return TRUE1; | |||
1814 | } | |||
1815 | ||||
1816 | /* Start writing out a block. */ | |||
1817 | ||||
1818 | static bfd_boolean | |||
1819 | pr_start_block (void *p, bfd_vma addr) | |||
1820 | { | |||
1821 | struct pr_handle *info = (struct pr_handle *) p; | |||
1822 | char ab[20]; | |||
1823 | ||||
1824 | if (info->parameter > 0) | |||
1825 | { | |||
1826 | fprintf (info->f, ")\n"); | |||
1827 | info->parameter = 0; | |||
1828 | } | |||
1829 | ||||
1830 | indent (info); | |||
1831 | print_vma (addr, ab, TRUE1, TRUE1); | |||
1832 | fprintf (info->f, "{ /* %s */\n", ab); | |||
1833 | ||||
1834 | info->indent += 2; | |||
1835 | ||||
1836 | return TRUE1; | |||
1837 | } | |||
1838 | ||||
1839 | /* Write out line number information. */ | |||
1840 | ||||
1841 | static bfd_boolean | |||
1842 | pr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr) | |||
1843 | { | |||
1844 | struct pr_handle *info = (struct pr_handle *) p; | |||
1845 | char ab[20]; | |||
1846 | ||||
1847 | indent (info); | |||
1848 | print_vma (addr, ab, TRUE1, TRUE1); | |||
1849 | fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab); | |||
1850 | ||||
1851 | return TRUE1; | |||
1852 | } | |||
1853 | ||||
1854 | /* Finish writing out a block. */ | |||
1855 | ||||
1856 | static bfd_boolean | |||
1857 | pr_end_block (void *p, bfd_vma addr) | |||
1858 | { | |||
1859 | struct pr_handle *info = (struct pr_handle *) p; | |||
1860 | char ab[20]; | |||
1861 | ||||
1862 | info->indent -= 2; | |||
1863 | ||||
1864 | indent (info); | |||
1865 | print_vma (addr, ab, TRUE1, TRUE1); | |||
1866 | fprintf (info->f, "} /* %s */\n", ab); | |||
1867 | ||||
1868 | return TRUE1; | |||
1869 | } | |||
1870 | ||||
1871 | /* Finish writing out a function. */ | |||
1872 | ||||
1873 | static bfd_boolean | |||
1874 | pr_end_function (void *p ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
1875 | { | |||
1876 | return TRUE1; | |||
1877 | } | |||
1878 | ||||
1879 | /* Tags style generation functions start here. */ | |||
1880 | ||||
1881 | /* Variables for address to line translation. */ | |||
1882 | static bfd_vma pc; | |||
1883 | static const char *filename; | |||
1884 | static const char *functionname; | |||
1885 | static unsigned int line; | |||
1886 | static bfd_boolean found; | |||
1887 | ||||
1888 | /* Look for an address in a section. This is called via | |||
1889 | bfd_map_over_sections. */ | |||
1890 | ||||
1891 | static void | |||
1892 | find_address_in_section (bfd *abfd, asection *section, void *data) | |||
1893 | { | |||
1894 | bfd_vma vma; | |||
1895 | bfd_size_type size; | |||
1896 | asymbol **syms = (asymbol **) data; | |||
1897 | ||||
1898 | if (found) | |||
1899 | return; | |||
1900 | ||||
1901 | if ((bfd_get_section_flags (abfd, section)((section)->flags + 0) & SEC_ALLOC0x001) == 0) | |||
1902 | return; | |||
1903 | ||||
1904 | vma = bfd_get_section_vma (abfd, section)((section)->vma + 0); | |||
1905 | if (pc < vma) | |||
1906 | return; | |||
1907 | ||||
1908 | size = bfd_get_section_size (section)((section)->size); | |||
1909 | if (pc >= vma + size) | |||
1910 | return; | |||
1911 | ||||
1912 | found = bfd_find_nearest_line (abfd, section, syms, pc - vma,((*((abfd)->xvec->_bfd_find_nearest_line)) (abfd, section , syms, pc - vma, &filename, &functionname, &line )) | |||
1913 | &filename, &functionname, &line)((*((abfd)->xvec->_bfd_find_nearest_line)) (abfd, section , syms, pc - vma, &filename, &functionname, &line )); | |||
1914 | } | |||
1915 | ||||
1916 | static void | |||
1917 | translate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms) | |||
1918 | { | |||
1919 | pc = bfd_scan_vma (addr_hex, NULL((void*)0), 16); | |||
1920 | found = FALSE0; | |||
1921 | bfd_map_over_sections (abfd, find_address_in_section, syms); | |||
1922 | ||||
1923 | if (! found) | |||
1924 | fprintf (f, "??"); | |||
1925 | else | |||
1926 | fprintf (f, "%u", line); | |||
1927 | } | |||
1928 | ||||
1929 | /* Start a new compilation unit. */ | |||
1930 | ||||
1931 | static bfd_boolean | |||
1932 | tg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
1933 | { | |||
1934 | struct pr_handle *info = (struct pr_handle *) p; | |||
1935 | ||||
1936 | fprintf (stderr(&__sF[2]), "New compilation unit: %s\n", filename); | |||
1937 | ||||
1938 | free (info->filename); | |||
1939 | /* Should it be relative? best way to do it here?. */ | |||
1940 | info->filename = strdup (filename); | |||
1941 | ||||
1942 | return TRUE1; | |||
1943 | } | |||
1944 | ||||
1945 | /* Start a source file within a compilation unit. */ | |||
1946 | ||||
1947 | static bfd_boolean | |||
1948 | tg_start_source (void *p, const char *filename) | |||
1949 | { | |||
1950 | struct pr_handle *info = (struct pr_handle *) p; | |||
1951 | ||||
1952 | free (info->filename); | |||
1953 | /* Should it be relative? best way to do it here?. */ | |||
1954 | info->filename = strdup (filename); | |||
1955 | ||||
1956 | return TRUE1; | |||
1957 | } | |||
1958 | ||||
1959 | /* Push an enum type onto the type stack. */ | |||
1960 | ||||
1961 | static bfd_boolean | |||
1962 | tg_enum_type (void *p, const char *tag, const char **names, | |||
1963 | bfd_signed_vma *values) | |||
1964 | { | |||
1965 | struct pr_handle *info = (struct pr_handle *) p; | |||
1966 | unsigned int i; | |||
1967 | const char *name; | |||
1968 | char ab[20]; | |||
1969 | ||||
1970 | if (! pr_enum_type (p, tag, names, values)) | |||
1971 | return FALSE0; | |||
1972 | ||||
1973 | name = tag ? tag : "unknown"; | |||
1974 | /* Generate an entry for the enum. */ | |||
1975 | if (tag) | |||
1976 | fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag, | |||
1977 | info->filename, info->stack->type); | |||
1978 | ||||
1979 | /* Generate entries for the values. */ | |||
1980 | if (names != NULL((void*)0)) | |||
1981 | { | |||
1982 | for (i = 0; names[i] != NULL((void*)0); i++) | |||
1983 | { | |||
1984 | print_vma (values[i], ab, FALSE0, FALSE0); | |||
1985 | fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n", | |||
1986 | names[i], info->filename, name, ab); | |||
1987 | } | |||
1988 | } | |||
1989 | ||||
1990 | return TRUE1; | |||
1991 | } | |||
1992 | ||||
1993 | /* Start accumulating a struct type. */ | |||
1994 | ||||
1995 | static bfd_boolean | |||
1996 | tg_start_struct_type (void *p, const char *tag, unsigned int id, | |||
1997 | bfd_boolean structp, | |||
1998 | unsigned int size ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
1999 | { | |||
2000 | struct pr_handle *info = (struct pr_handle *) p; | |||
2001 | const char *name; | |||
2002 | char idbuf[20]; | |||
2003 | ||||
2004 | if (tag != NULL((void*)0)) | |||
2005 | name = tag; | |||
2006 | else | |||
2007 | { | |||
2008 | name = idbuf; | |||
2009 | sprintf (idbuf, "%%anon%u", id); | |||
2010 | } | |||
2011 | ||||
2012 | if (! push_type (info, name)) | |||
2013 | return FALSE0; | |||
2014 | ||||
2015 | info->stack->flavor = structp ? "struct" : "union"; | |||
2016 | ||||
2017 | fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename, | |||
2018 | info->stack->flavor[0]); | |||
2019 | ||||
2020 | info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; | |||
2021 | ||||
2022 | return indent_type (info); | |||
2023 | } | |||
2024 | ||||
2025 | /* Output the visibility of a field in a struct. */ | |||
2026 | ||||
2027 | static bfd_boolean | |||
2028 | tg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) | |||
2029 | { | |||
2030 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2030, __func__, "info->stack != NULL")); | |||
2031 | ||||
2032 | if (info->stack->visibility == visibility) | |||
2033 | return TRUE1; | |||
2034 | ||||
2035 | assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE)((info->stack->visibility != DEBUG_VISIBILITY_IGNORE) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2035, __func__, "info->stack->visibility != DEBUG_VISIBILITY_IGNORE" )); | |||
2036 | ||||
2037 | info->stack->visibility = visibility; | |||
2038 | ||||
2039 | return TRUE1; | |||
2040 | } | |||
2041 | ||||
2042 | /* Add a field to a struct type. */ | |||
2043 | ||||
2044 | static bfd_boolean | |||
2045 | tg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2046 | bfd_vma bitsize ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2047 | enum debug_visibility visibility) | |||
2048 | { | |||
2049 | struct pr_handle *info = (struct pr_handle *) p; | |||
2050 | char *t; | |||
2051 | ||||
2052 | t = pop_type (info); | |||
2053 | if (t == NULL((void*)0)) | |||
2054 | return FALSE0; | |||
2055 | ||||
2056 | if (! tg_fix_visibility (info, visibility)) | |||
2057 | return FALSE0; | |||
2058 | ||||
2059 | /* It happens, a bug? */ | |||
2060 | if (! name[0]) | |||
2061 | return TRUE1; | |||
2062 | ||||
2063 | fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n", | |||
2064 | name, info->filename, t, info->stack->flavor, info->stack->type, | |||
2065 | visibility_name (visibility)); | |||
2066 | ||||
2067 | return TRUE1; | |||
2068 | } | |||
2069 | ||||
2070 | /* Finish a struct type. */ | |||
2071 | ||||
2072 | static bfd_boolean | |||
2073 | tg_end_struct_type (void *p ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2074 | { | |||
2075 | struct pr_handle *info = (struct pr_handle *) p; | |||
2076 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2076, __func__, "info->stack != NULL")); | |||
2077 | ||||
2078 | return TRUE1; | |||
2079 | } | |||
2080 | ||||
2081 | /* Start a class type. */ | |||
2082 | ||||
2083 | static bfd_boolean | |||
2084 | tg_start_class_type (void *p, const char *tag, unsigned int id, | |||
2085 | bfd_boolean structp, unsigned int size, | |||
2086 | bfd_boolean vptr, bfd_boolean ownvptr) | |||
2087 | { | |||
2088 | struct pr_handle *info = (struct pr_handle *) p; | |||
2089 | char *tv = NULL((void*)0); | |||
2090 | const char *name; | |||
2091 | ||||
2092 | info->indent += 2; | |||
2093 | ||||
2094 | if (vptr && ! ownvptr) | |||
2095 | { | |||
2096 | tv = pop_type (info); | |||
2097 | if (tv == NULL((void*)0)) | |||
2098 | return FALSE0; | |||
2099 | } | |||
2100 | ||||
2101 | if (tag != NULL((void*)0)) | |||
2102 | name = tag; | |||
2103 | else | |||
2104 | { | |||
2105 | char idbuf[20]; | |||
2106 | ||||
2107 | sprintf (idbuf, "%%anon%u", id); | |||
2108 | name = idbuf; | |||
2109 | } | |||
2110 | ||||
2111 | if (! push_type (info, name)) | |||
2112 | return FALSE0; | |||
2113 | ||||
2114 | info->stack->flavor = structp ? "class" : "union class"; | |||
2115 | info->stack->parents = NULL((void*)0); | |||
2116 | info->stack->num_parents = 0; | |||
2117 | ||||
2118 | if (size != 0 || vptr || ownvptr || tag != NULL((void*)0)) | |||
2119 | { | |||
2120 | if (vptr) | |||
2121 | { | |||
2122 | if (! append_type (info, " vtable ")) | |||
2123 | return FALSE0; | |||
2124 | if (ownvptr) | |||
2125 | { | |||
2126 | if (! append_type (info, "self ")) | |||
2127 | return FALSE0; | |||
2128 | } | |||
2129 | else | |||
2130 | { | |||
2131 | if (! append_type (info, tv) | |||
2132 | || ! append_type (info, " ")) | |||
2133 | return FALSE0; | |||
2134 | } | |||
2135 | } | |||
2136 | } | |||
2137 | ||||
2138 | info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; | |||
2139 | ||||
2140 | return TRUE1; | |||
2141 | } | |||
2142 | ||||
2143 | /* Add a static member to a class. */ | |||
2144 | ||||
2145 | static bfd_boolean | |||
2146 | tg_class_static_member (void *p, const char *name, | |||
2147 | const char *physname ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2148 | enum debug_visibility visibility) | |||
2149 | { | |||
2150 | struct pr_handle *info = (struct pr_handle *) p; | |||
2151 | char *t; | |||
2152 | int len_var, len_class; | |||
2153 | char *full_name; | |||
2154 | ||||
2155 | len_var = strlen (name); | |||
2156 | len_class = strlen (info->stack->next->type); | |||
2157 | full_name = (char *) xmalloc (len_var + len_class + 3); | |||
2158 | if (! full_name) | |||
2159 | return FALSE0; | |||
2160 | memcpy (full_name, info->stack->next->type, len_class); | |||
2161 | memcpy (full_name + len_class, "::", 2); | |||
2162 | memcpy (full_name + len_class + 2, name, len_var + 1); | |||
2163 | ||||
2164 | if (! substitute_type (info, full_name)) | |||
2165 | return FALSE0; | |||
2166 | ||||
2167 | if (! prepend_type (info, "static ")) | |||
2168 | return FALSE0; | |||
2169 | ||||
2170 | t = pop_type (info); | |||
2171 | if (t == NULL((void*)0)) | |||
2172 | return FALSE0; | |||
2173 | ||||
2174 | if (! tg_fix_visibility (info, visibility)) | |||
2175 | return FALSE0; | |||
2176 | ||||
2177 | fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n", | |||
2178 | name, info->filename, t, info->stack->type, | |||
2179 | visibility_name (visibility)); | |||
2180 | free (t); | |||
2181 | free (full_name); | |||
2182 | ||||
2183 | return TRUE1; | |||
2184 | } | |||
2185 | ||||
2186 | /* Add a base class to a class. */ | |||
2187 | ||||
2188 | static bfd_boolean | |||
2189 | tg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2190 | bfd_boolean virtual, enum debug_visibility visibility) | |||
2191 | { | |||
2192 | struct pr_handle *info = (struct pr_handle *) p; | |||
2193 | char *t; | |||
2194 | const char *prefix; | |||
2195 | ||||
2196 | assert (info->stack != NULL && info->stack->next != NULL)((info->stack != ((void*)0) && info->stack-> next != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2196, __func__, "info->stack != NULL && info->stack->next != NULL" )); | |||
2197 | ||||
2198 | t = pop_type (info); | |||
2199 | if (t == NULL((void*)0)) | |||
2200 | return FALSE0; | |||
2201 | ||||
2202 | if (strncmp (t, "class ", sizeof "class " - 1) == 0) | |||
2203 | t += sizeof "class " - 1; | |||
2204 | ||||
2205 | /* Push it back on to take advantage of the prepend_type and | |||
2206 | append_type routines. */ | |||
2207 | if (! push_type (info, t)) | |||
2208 | return FALSE0; | |||
2209 | ||||
2210 | if (virtual) | |||
2211 | { | |||
2212 | if (! prepend_type (info, "virtual ")) | |||
2213 | return FALSE0; | |||
2214 | } | |||
2215 | ||||
2216 | switch (visibility) | |||
2217 | { | |||
2218 | case DEBUG_VISIBILITY_PUBLIC: | |||
2219 | prefix = "public "; | |||
2220 | break; | |||
2221 | case DEBUG_VISIBILITY_PROTECTED: | |||
2222 | prefix = "protected "; | |||
2223 | break; | |||
2224 | case DEBUG_VISIBILITY_PRIVATE: | |||
2225 | prefix = "private "; | |||
2226 | break; | |||
2227 | default: | |||
2228 | prefix = "/* unknown visibility */ "; | |||
2229 | break; | |||
2230 | } | |||
2231 | ||||
2232 | if (! prepend_type (info, prefix)) | |||
2233 | return FALSE0; | |||
2234 | ||||
2235 | t = pop_type (info); | |||
2236 | if (t == NULL((void*)0)) | |||
2237 | return FALSE0; | |||
2238 | ||||
2239 | if (info->stack->num_parents && ! append_parent (info, ", ")) | |||
2240 | return FALSE0; | |||
2241 | ||||
2242 | if (! append_parent (info, t)) | |||
2243 | return FALSE0; | |||
2244 | info->stack->num_parents++; | |||
2245 | ||||
2246 | free (t); | |||
2247 | ||||
2248 | return TRUE1; | |||
2249 | } | |||
2250 | ||||
2251 | /* Add a variant to a method. */ | |||
2252 | ||||
2253 | static bfd_boolean | |||
2254 | tg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2255 | enum debug_visibility visibility, | |||
2256 | bfd_boolean constp, bfd_boolean volatilep, | |||
2257 | bfd_vma voffset ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2258 | bfd_boolean context) | |||
2259 | { | |||
2260 | struct pr_handle *info = (struct pr_handle *) p; | |||
2261 | char *method_type; | |||
2262 | char *context_type; | |||
2263 | char *method_name; | |||
2264 | ||||
2265 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2265, __func__, "info->stack != NULL")); | |||
2266 | assert (info->stack->next != NULL)((info->stack->next != ((void*)0)) ? (void)0 : __assert2 ("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c", 2266, __func__, "info->stack->next != NULL")); | |||
2267 | ||||
2268 | /* Put the const and volatile qualifiers on the type. */ | |||
2269 | if (volatilep) | |||
2270 | { | |||
2271 | if (! append_type (info, " volatile")) | |||
2272 | return FALSE0; | |||
2273 | } | |||
2274 | if (constp) | |||
2275 | { | |||
2276 | if (! append_type (info, " const")) | |||
2277 | return FALSE0; | |||
2278 | } | |||
2279 | ||||
2280 | method_name = strdup (context ? info->stack->next->next->method | |||
2281 | : info->stack->next->method); | |||
2282 | ||||
2283 | /* Stick the name of the method into its type. */ | |||
2284 | if (! substitute_type (info, method_name)) | |||
2285 | return FALSE0; | |||
2286 | ||||
2287 | /* Get the type. */ | |||
2288 | method_type = pop_type (info); | |||
2289 | if (method_type == NULL((void*)0)) | |||
2290 | return FALSE0; | |||
2291 | ||||
2292 | /* Pull off the context type if there is one. */ | |||
2293 | if (! context) | |||
2294 | context_type = NULL((void*)0); | |||
2295 | else | |||
2296 | { | |||
2297 | context_type = pop_type (info); | |||
2298 | if (context_type == NULL((void*)0)) | |||
2299 | return FALSE0; | |||
2300 | } | |||
2301 | ||||
2302 | /* Now the top of the stack is the class. */ | |||
2303 | if (! tg_fix_visibility (info, visibility)) | |||
2304 | return FALSE0; | |||
2305 | ||||
2306 | fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n", | |||
2307 | method_name, info->filename, method_type, info->stack->type); | |||
2308 | free (method_type); | |||
2309 | free (method_name); | |||
2310 | free (context_type); | |||
2311 | ||||
2312 | return TRUE1; | |||
2313 | } | |||
2314 | ||||
2315 | /* Add a static variant to a method. */ | |||
2316 | ||||
2317 | static bfd_boolean | |||
2318 | tg_class_static_method_variant (void *p, | |||
2319 | const char *physname ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2320 | enum debug_visibility visibility, | |||
2321 | bfd_boolean constp, bfd_boolean volatilep) | |||
2322 | { | |||
2323 | struct pr_handle *info = (struct pr_handle *) p; | |||
2324 | char *method_type; | |||
2325 | char *method_name; | |||
2326 | ||||
2327 | assert (info->stack != NULL)((info->stack != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2327, __func__, "info->stack != NULL")); | |||
| ||||
2328 | assert (info->stack->next != NULL)((info->stack->next != ((void*)0)) ? (void)0 : __assert2 ("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c", 2328, __func__, "info->stack->next != NULL")); | |||
2329 | assert (info->stack->next->method != NULL)((info->stack->next->method != ((void*)0)) ? (void)0 : __assert2("/usr/src/gnu/usr.bin/binutils-2.17/binutils/prdbg.c" , 2329, __func__, "info->stack->next->method != NULL" )); | |||
2330 | ||||
2331 | /* Put the const and volatile qualifiers on the type. */ | |||
2332 | if (volatilep) | |||
2333 | { | |||
2334 | if (! append_type (info, " volatile")) | |||
2335 | return FALSE0; | |||
2336 | } | |||
2337 | if (constp) | |||
2338 | { | |||
2339 | if (! append_type (info, " const")) | |||
2340 | return FALSE0; | |||
2341 | } | |||
2342 | ||||
2343 | /* Mark it as static. */ | |||
2344 | if (! prepend_type (info, "static ")) | |||
2345 | return FALSE0; | |||
2346 | ||||
2347 | method_name = strdup (info->stack->next->method); | |||
2348 | /* Stick the name of the method into its type. */ | |||
2349 | if (! substitute_type (info, info->stack->next->method)) | |||
2350 | return FALSE0; | |||
2351 | ||||
2352 | /* Get the type. */ | |||
2353 | method_type = pop_type (info); | |||
2354 | if (method_type == NULL((void*)0)) | |||
2355 | return FALSE0; | |||
| ||||
2356 | ||||
2357 | /* Now the top of the stack is the class. */ | |||
2358 | if (! tg_fix_visibility (info, visibility)) | |||
2359 | return FALSE0; | |||
2360 | ||||
2361 | fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n", | |||
2362 | method_name, info->filename, method_type, info->stack->type, | |||
2363 | visibility_name (visibility)); | |||
2364 | free (method_type); | |||
2365 | free (method_name); | |||
2366 | ||||
2367 | return TRUE1; | |||
2368 | } | |||
2369 | ||||
2370 | /* Finish up a class. */ | |||
2371 | ||||
2372 | static bfd_boolean | |||
2373 | tg_end_class_type (void *p) | |||
2374 | { | |||
2375 | struct pr_handle *info = (struct pr_handle *) p; | |||
2376 | ||||
2377 | fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type, | |||
2378 | info->filename, info->stack->flavor); | |||
2379 | if (info->stack->num_parents) | |||
2380 | { | |||
2381 | fprintf (info->f, "\tinherits:%s", info->stack->parents); | |||
2382 | free (info->stack->parents); | |||
2383 | } | |||
2384 | fputc ('\n', info->f); | |||
2385 | ||||
2386 | return tg_end_struct_type (p); | |||
2387 | } | |||
2388 | ||||
2389 | /* Push a type on the stack using a tag name. */ | |||
2390 | ||||
2391 | static bfd_boolean | |||
2392 | tg_tag_type (void *p, const char *name, unsigned int id, | |||
2393 | enum debug_type_kind kind) | |||
2394 | { | |||
2395 | struct pr_handle *info = (struct pr_handle *) p; | |||
2396 | const char *t, *tag; | |||
2397 | char idbuf[20]; | |||
2398 | ||||
2399 | switch (kind) | |||
2400 | { | |||
2401 | case DEBUG_KIND_STRUCT: | |||
2402 | t = "struct "; | |||
2403 | break; | |||
2404 | case DEBUG_KIND_UNION: | |||
2405 | t = "union "; | |||
2406 | break; | |||
2407 | case DEBUG_KIND_ENUM: | |||
2408 | t = "enum "; | |||
2409 | break; | |||
2410 | case DEBUG_KIND_CLASS: | |||
2411 | t = "class "; | |||
2412 | break; | |||
2413 | case DEBUG_KIND_UNION_CLASS: | |||
2414 | t = "union class "; | |||
2415 | break; | |||
2416 | default: | |||
2417 | abort (); | |||
2418 | return FALSE0; | |||
2419 | } | |||
2420 | ||||
2421 | if (! push_type (info, t)) | |||
2422 | return FALSE0; | |||
2423 | if (name != NULL((void*)0)) | |||
2424 | tag = name; | |||
2425 | else | |||
2426 | { | |||
2427 | sprintf (idbuf, "%%anon%u", id); | |||
2428 | tag = idbuf; | |||
2429 | } | |||
2430 | ||||
2431 | if (! append_type (info, tag)) | |||
2432 | return FALSE0; | |||
2433 | ||||
2434 | return TRUE1; | |||
2435 | } | |||
2436 | ||||
2437 | /* Output a typedef. */ | |||
2438 | ||||
2439 | static bfd_boolean | |||
2440 | tg_typdef (void *p, const char *name) | |||
2441 | { | |||
2442 | struct pr_handle *info = (struct pr_handle *) p; | |||
2443 | char *s; | |||
2444 | ||||
2445 | s = pop_type (info); | |||
2446 | if (s == NULL((void*)0)) | |||
2447 | return FALSE0; | |||
2448 | ||||
2449 | fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name, | |||
2450 | info->filename, s); | |||
2451 | ||||
2452 | free (s); | |||
2453 | ||||
2454 | return TRUE1; | |||
2455 | } | |||
2456 | ||||
2457 | /* Output a tag. The tag should already be in the string on the | |||
2458 | stack, so all we have to do here is print it out. */ | |||
2459 | ||||
2460 | static bfd_boolean | |||
2461 | tg_tag (void *p ATTRIBUTE_UNUSED__attribute__ ((__unused__)), const char *name ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2462 | { | |||
2463 | struct pr_handle *info = (struct pr_handle *) p; | |||
2464 | char *t; | |||
2465 | ||||
2466 | t = pop_type (info); | |||
2467 | if (t == NULL((void*)0)) | |||
2468 | return FALSE0; | |||
2469 | free (t); | |||
2470 | ||||
2471 | return TRUE1; | |||
2472 | } | |||
2473 | ||||
2474 | /* Output an integer constant. */ | |||
2475 | ||||
2476 | static bfd_boolean | |||
2477 | tg_int_constant (void *p, const char *name, bfd_vma val) | |||
2478 | { | |||
2479 | struct pr_handle *info = (struct pr_handle *) p; | |||
2480 | char ab[20]; | |||
2481 | ||||
2482 | indent (info); | |||
2483 | print_vma (val, ab, FALSE0, FALSE0); | |||
2484 | fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n", | |||
2485 | name, info->filename, ab); | |||
2486 | return TRUE1; | |||
2487 | } | |||
2488 | ||||
2489 | /* Output a floating point constant. */ | |||
2490 | ||||
2491 | static bfd_boolean | |||
2492 | tg_float_constant (void *p, const char *name, double val) | |||
2493 | { | |||
2494 | struct pr_handle *info = (struct pr_handle *) p; | |||
2495 | ||||
2496 | indent (info); | |||
2497 | fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n", | |||
2498 | name, info->filename, val); | |||
2499 | return TRUE1; | |||
2500 | } | |||
2501 | ||||
2502 | /* Output a typed constant. */ | |||
2503 | ||||
2504 | static bfd_boolean | |||
2505 | tg_typed_constant (void *p, const char *name, bfd_vma val) | |||
2506 | { | |||
2507 | struct pr_handle *info = (struct pr_handle *) p; | |||
2508 | char *t; | |||
2509 | char ab[20]; | |||
2510 | ||||
2511 | t = pop_type (info); | |||
2512 | if (t == NULL((void*)0)) | |||
2513 | return FALSE0; | |||
2514 | ||||
2515 | indent (info); | |||
2516 | print_vma (val, ab, FALSE0, FALSE0); | |||
2517 | fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n", | |||
2518 | name, info->filename, t, ab); | |||
2519 | ||||
2520 | free (t); | |||
2521 | ||||
2522 | return TRUE1; | |||
2523 | } | |||
2524 | ||||
2525 | /* Output a variable. */ | |||
2526 | ||||
2527 | static bfd_boolean | |||
2528 | tg_variable (void *p, const char *name, enum debug_var_kind kind, | |||
2529 | bfd_vma val ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2530 | { | |||
2531 | struct pr_handle *info = (struct pr_handle *) p; | |||
2532 | char *t; | |||
2533 | const char *dname, *from_class; | |||
2534 | ||||
2535 | t = pop_type (info); | |||
2536 | if (t == NULL((void*)0)) | |||
2537 | return FALSE0; | |||
2538 | ||||
2539 | dname = name; | |||
2540 | if (info->demangler) | |||
2541 | { | |||
2542 | dname = info->demangler (info->abfd, name); | |||
2543 | if (strcmp (name, dname) == 0) | |||
2544 | { | |||
2545 | free ((char *) dname); | |||
2546 | dname = name; | |||
2547 | } | |||
2548 | } | |||
2549 | ||||
2550 | if (dname != name) | |||
2551 | { | |||
2552 | char *sep; | |||
2553 | sep = strstr (dname, "::"); | |||
2554 | if (sep) | |||
2555 | { | |||
2556 | *sep = 0; | |||
2557 | name = sep + 2; | |||
2558 | from_class = dname; | |||
2559 | } | |||
2560 | else | |||
2561 | { | |||
2562 | /* Obscure types as vts and type_info nodes. */ | |||
2563 | name = dname; | |||
2564 | from_class = NULL((void*)0); | |||
2565 | } | |||
2566 | } | |||
2567 | else | |||
2568 | from_class = NULL((void*)0); | |||
2569 | ||||
2570 | fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t); | |||
2571 | ||||
2572 | switch (kind) | |||
2573 | { | |||
2574 | case DEBUG_STATIC: | |||
2575 | case DEBUG_LOCAL_STATIC: | |||
2576 | fprintf (info->f, "\tfile:"); | |||
2577 | break; | |||
2578 | case DEBUG_REGISTER: | |||
2579 | fprintf (info->f, "\tregister:"); | |||
2580 | break; | |||
2581 | default: | |||
2582 | break; | |||
2583 | } | |||
2584 | ||||
2585 | if (from_class) | |||
2586 | { | |||
2587 | fprintf (info->f, "\tclass:%s",from_class); | |||
2588 | free ((char *) dname); | |||
2589 | } | |||
2590 | ||||
2591 | fprintf (info->f, "\n"); | |||
2592 | ||||
2593 | free (t); | |||
2594 | ||||
2595 | return TRUE1; | |||
2596 | } | |||
2597 | ||||
2598 | /* Start outputting a function. */ | |||
2599 | ||||
2600 | static bfd_boolean | |||
2601 | tg_start_function (void *p, const char *name, bfd_boolean global) | |||
2602 | { | |||
2603 | struct pr_handle *info = (struct pr_handle *) p; | |||
2604 | const char *dname; | |||
2605 | ||||
2606 | if (! global) | |||
2607 | info->stack->flavor = "static"; | |||
2608 | else | |||
2609 | info->stack->flavor = NULL((void*)0); | |||
2610 | ||||
2611 | dname = name; | |||
2612 | if (info->demangler) | |||
2613 | { | |||
2614 | dname = info->demangler (info->abfd, name); | |||
2615 | if (strcmp (name, dname) == 0) | |||
2616 | { | |||
2617 | free ((char *) dname); | |||
2618 | dname = name; | |||
2619 | } | |||
2620 | } | |||
2621 | ||||
2622 | if (! substitute_type (info, dname)) | |||
2623 | return FALSE0; | |||
2624 | ||||
2625 | if (dname != name) | |||
2626 | { | |||
2627 | char *sep; | |||
2628 | sep = strstr (dname, "::"); | |||
2629 | if (sep) | |||
2630 | { | |||
2631 | info->stack->method = dname; | |||
2632 | *sep = 0; | |||
2633 | name = sep + 2; | |||
2634 | } | |||
2635 | else | |||
2636 | { | |||
2637 | info->stack->method = ""; | |||
2638 | name = dname; | |||
2639 | } | |||
2640 | sep = strchr (name, '('); | |||
2641 | if (sep) | |||
2642 | *sep = 0; | |||
2643 | /* Obscure functions as type_info function. */ | |||
2644 | } | |||
2645 | else | |||
2646 | info->stack->method = NULL((void*)0); | |||
2647 | ||||
2648 | info->stack->parents = strdup (name); | |||
2649 | ||||
2650 | if (! info->stack->method && ! append_type (info, "(")) | |||
2651 | return FALSE0; | |||
2652 | ||||
2653 | info->parameter = 1; | |||
2654 | ||||
2655 | return TRUE1; | |||
2656 | } | |||
2657 | ||||
2658 | /* Output a function parameter. */ | |||
2659 | ||||
2660 | static bfd_boolean | |||
2661 | tg_function_parameter (void *p, const char *name, enum debug_parm_kind kind, | |||
2662 | bfd_vma val ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2663 | { | |||
2664 | struct pr_handle *info = (struct pr_handle *) p; | |||
2665 | char *t; | |||
2666 | ||||
2667 | if (kind == DEBUG_PARM_REFERENCE | |||
2668 | || kind == DEBUG_PARM_REF_REG) | |||
2669 | { | |||
2670 | if (! pr_reference_type (p)) | |||
2671 | return FALSE0; | |||
2672 | } | |||
2673 | ||||
2674 | if (! substitute_type (info, name)) | |||
2675 | return FALSE0; | |||
2676 | ||||
2677 | t = pop_type (info); | |||
2678 | if (t == NULL((void*)0)) | |||
2679 | return FALSE0; | |||
2680 | ||||
2681 | if (! info->stack->method) | |||
2682 | { | |||
2683 | if (info->parameter != 1 && ! append_type (info, ", ")) | |||
2684 | return FALSE0; | |||
2685 | ||||
2686 | if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) | |||
2687 | if (! append_type (info, "register ")) | |||
2688 | return FALSE0; | |||
2689 | ||||
2690 | if (! append_type (info, t)) | |||
2691 | return FALSE0; | |||
2692 | } | |||
2693 | ||||
2694 | free (t); | |||
2695 | ||||
2696 | ++info->parameter; | |||
2697 | ||||
2698 | return TRUE1; | |||
2699 | } | |||
2700 | ||||
2701 | /* Start writing out a block. */ | |||
2702 | ||||
2703 | static bfd_boolean | |||
2704 | tg_start_block (void *p, bfd_vma addr) | |||
2705 | { | |||
2706 | struct pr_handle *info = (struct pr_handle *) p; | |||
2707 | char ab[20], kind, *partof; | |||
2708 | char *t; | |||
2709 | bfd_boolean local; | |||
2710 | ||||
2711 | if (info->parameter > 0) | |||
2712 | { | |||
2713 | info->parameter = 0; | |||
2714 | ||||
2715 | /* Delayed name. */ | |||
2716 | fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename); | |||
2717 | free (info->stack->parents); | |||
2718 | ||||
2719 | print_vma (addr, ab, TRUE1, TRUE1); | |||
2720 | translate_addresses (info->abfd, ab, info->f, info->syms); | |||
2721 | local = info->stack->flavor != NULL((void*)0); | |||
2722 | if (info->stack->method && *info->stack->method) | |||
2723 | { | |||
2724 | kind = 'm'; | |||
2725 | partof = (char *) info->stack->method; | |||
2726 | } | |||
2727 | else | |||
2728 | { | |||
2729 | kind = 'f'; | |||
2730 | partof = NULL((void*)0); | |||
2731 | if (! info->stack->method && ! append_type (info, ")")) | |||
2732 | return FALSE0; | |||
2733 | } | |||
2734 | t = pop_type (info); | |||
2735 | if (t == NULL((void*)0)) | |||
2736 | return FALSE0; | |||
2737 | fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t); | |||
2738 | if (local) | |||
2739 | fputs ("\tfile:", info->f); | |||
2740 | if (partof) | |||
2741 | { | |||
2742 | fprintf (info->f, "\tclass:%s", partof); | |||
2743 | free (partof); | |||
2744 | } | |||
2745 | fputc ('\n', info->f); | |||
2746 | } | |||
2747 | ||||
2748 | return TRUE1; | |||
2749 | } | |||
2750 | ||||
2751 | /* Write out line number information. */ | |||
2752 | ||||
2753 | static bfd_boolean | |||
2754 | tg_lineno (void *p ATTRIBUTE_UNUSED__attribute__ ((__unused__)), const char *filename ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2755 | unsigned long lineno ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
2756 | bfd_vma addr ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2757 | { | |||
2758 | return TRUE1; | |||
2759 | } | |||
2760 | ||||
2761 | /* Finish writing out a block. */ | |||
2762 | ||||
2763 | static bfd_boolean | |||
2764 | tg_end_block (void *p ATTRIBUTE_UNUSED__attribute__ ((__unused__)), bfd_vma addr ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
2765 | { | |||
2766 | return TRUE1; | |||
2767 | } | |||
2768 | ||||
2769 | /* Convert the visibility value into a human readable name. */ | |||
2770 | ||||
2771 | static const char * | |||
2772 | visibility_name (enum debug_visibility visibility) | |||
2773 | { | |||
2774 | const char *s; | |||
2775 | ||||
2776 | switch (visibility) | |||
2777 | { | |||
2778 | case DEBUG_VISIBILITY_PUBLIC: | |||
2779 | s = "public"; | |||
2780 | break; | |||
2781 | case DEBUG_VISIBILITY_PRIVATE: | |||
2782 | s = "private"; | |||
2783 | break; | |||
2784 | case DEBUG_VISIBILITY_PROTECTED: | |||
2785 | s = "protected"; | |||
2786 | break; | |||
2787 | case DEBUG_VISIBILITY_IGNORE: | |||
2788 | s = "/* ignore */"; | |||
2789 | break; | |||
2790 | default: | |||
2791 | abort (); | |||
2792 | return FALSE0; | |||
2793 | } | |||
2794 | return s; | |||
2795 | } |