133965Sjdp/* prdbg.c -- Print out generic debugging information. 2218822Sdim Copyright 1995, 1996, 1999, 2002, 2003, 2004, 2006, 2007 3218822Sdim Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor <ian@cygnus.com>. 5130561Sobrien Tags style generation written by Salvador E. Tropea <set@computer.org>. 633965Sjdp 733965Sjdp This file is part of GNU Binutils. 833965Sjdp 933965Sjdp This program is free software; you can redistribute it and/or modify 1033965Sjdp it under the terms of the GNU General Public License as published by 1133965Sjdp the Free Software Foundation; either version 2 of the License, or 1233965Sjdp (at your option) any later version. 1333965Sjdp 1433965Sjdp This program is distributed in the hope that it will be useful, 1533965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1633965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1733965Sjdp GNU General Public License for more details. 1833965Sjdp 1933965Sjdp You should have received a copy of the GNU General Public License 2033965Sjdp along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22218822Sdim 02110-1301, USA. */ 2333965Sjdp 2433965Sjdp/* This file prints out the generic debugging information, by 2533965Sjdp supplying a set of routines to debug_write. */ 2633965Sjdp 27218822Sdim#include "sysdep.h" 2833965Sjdp#include <assert.h> 2933965Sjdp#include "bfd.h" 3033965Sjdp#include "libiberty.h" 31218822Sdim#include "demangle.h" 3233965Sjdp#include "debug.h" 3333965Sjdp#include "budbg.h" 3433965Sjdp 3533965Sjdp/* This is the structure we use as a handle for these routines. */ 3633965Sjdp 3733965Sjdpstruct pr_handle 3833965Sjdp{ 3933965Sjdp /* File to print information to. */ 4033965Sjdp FILE *f; 4133965Sjdp /* Current indentation level. */ 4233965Sjdp unsigned int indent; 4333965Sjdp /* Type stack. */ 4433965Sjdp struct pr_stack *stack; 4533965Sjdp /* Parameter number we are about to output. */ 4633965Sjdp int parameter; 47130561Sobrien /* The following are used only by the tags code (tg_). */ 48130561Sobrien /* Name of the file we are using. */ 49130561Sobrien char *filename; 50130561Sobrien /* The BFD. */ 51130561Sobrien bfd *abfd; 52130561Sobrien /* The symbols table for this BFD. */ 53130561Sobrien asymbol **syms; 54130561Sobrien /* Pointer to a function to demangle symbols. */ 55218822Sdim char *(*demangler) (bfd *, const char *, int); 5633965Sjdp}; 5733965Sjdp 5833965Sjdp/* The type stack. */ 5933965Sjdp 6033965Sjdpstruct pr_stack 6133965Sjdp{ 6233965Sjdp /* Next element on the stack. */ 6333965Sjdp struct pr_stack *next; 6433965Sjdp /* This element. */ 6533965Sjdp char *type; 6633965Sjdp /* Current visibility of fields if this is a class. */ 6733965Sjdp enum debug_visibility visibility; 6833965Sjdp /* Name of the current method we are handling. */ 6933965Sjdp const char *method; 70130561Sobrien /* The following are used only by the tags code (tg_). */ 71130561Sobrien /* Type for the container (struct, union, class, union class). */ 72130561Sobrien const char *flavor; 73130561Sobrien /* A comma separated list of parent classes. */ 74130561Sobrien char *parents; 75130561Sobrien /* How many parents contains parents. */ 76130561Sobrien int num_parents; 7733965Sjdp}; 7833965Sjdp 79130561Sobrienstatic void indent (struct pr_handle *); 80130561Sobrienstatic bfd_boolean push_type (struct pr_handle *, const char *); 81130561Sobrienstatic bfd_boolean prepend_type (struct pr_handle *, const char *); 82130561Sobrienstatic bfd_boolean append_type (struct pr_handle *, const char *); 83130561Sobrienstatic bfd_boolean substitute_type (struct pr_handle *, const char *); 84130561Sobrienstatic bfd_boolean indent_type (struct pr_handle *); 85130561Sobrienstatic char *pop_type (struct pr_handle *); 86130561Sobrienstatic void print_vma (bfd_vma, char *, bfd_boolean, bfd_boolean); 87130561Sobrienstatic bfd_boolean pr_fix_visibility 88130561Sobrien (struct pr_handle *, enum debug_visibility); 89130561Sobrienstatic bfd_boolean pr_start_compilation_unit (void *, const char *); 90130561Sobrienstatic bfd_boolean pr_start_source (void *, const char *); 91130561Sobrienstatic bfd_boolean pr_empty_type (void *); 92130561Sobrienstatic bfd_boolean pr_void_type (void *); 93130561Sobrienstatic bfd_boolean pr_int_type (void *, unsigned int, bfd_boolean); 94130561Sobrienstatic bfd_boolean pr_float_type (void *, unsigned int); 95130561Sobrienstatic bfd_boolean pr_complex_type (void *, unsigned int); 96130561Sobrienstatic bfd_boolean pr_bool_type (void *, unsigned int); 97130561Sobrienstatic bfd_boolean pr_enum_type 98130561Sobrien (void *, const char *, const char **, bfd_signed_vma *); 99130561Sobrienstatic bfd_boolean pr_pointer_type (void *); 100130561Sobrienstatic bfd_boolean pr_function_type (void *, int, bfd_boolean); 101130561Sobrienstatic bfd_boolean pr_reference_type (void *); 102130561Sobrienstatic bfd_boolean pr_range_type (void *, bfd_signed_vma, bfd_signed_vma); 103130561Sobrienstatic bfd_boolean pr_array_type 104130561Sobrien (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean); 105130561Sobrienstatic bfd_boolean pr_set_type (void *, bfd_boolean); 106130561Sobrienstatic bfd_boolean pr_offset_type (void *); 107130561Sobrienstatic bfd_boolean pr_method_type (void *, bfd_boolean, int, bfd_boolean); 108130561Sobrienstatic bfd_boolean pr_const_type (void *); 109130561Sobrienstatic bfd_boolean pr_volatile_type (void *); 110130561Sobrienstatic bfd_boolean pr_start_struct_type 111130561Sobrien (void *, const char *, unsigned int, bfd_boolean, unsigned int); 112130561Sobrienstatic bfd_boolean pr_struct_field 113130561Sobrien (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); 114130561Sobrienstatic bfd_boolean pr_end_struct_type (void *); 115130561Sobrienstatic bfd_boolean pr_start_class_type 116130561Sobrien (void *, const char *, unsigned int, bfd_boolean, unsigned int, 117130561Sobrien bfd_boolean, bfd_boolean); 118130561Sobrienstatic bfd_boolean pr_class_static_member 119130561Sobrien (void *, const char *, const char *, enum debug_visibility); 120130561Sobrienstatic bfd_boolean pr_class_baseclass 121130561Sobrien (void *, bfd_vma, bfd_boolean, enum debug_visibility); 122130561Sobrienstatic bfd_boolean pr_class_start_method (void *, const char *); 123130561Sobrienstatic bfd_boolean pr_class_method_variant 124130561Sobrien (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, 125130561Sobrien bfd_vma, bfd_boolean); 126130561Sobrienstatic bfd_boolean pr_class_static_method_variant 127130561Sobrien (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean); 128130561Sobrienstatic bfd_boolean pr_class_end_method (void *); 129130561Sobrienstatic bfd_boolean pr_end_class_type (void *); 130130561Sobrienstatic bfd_boolean pr_typedef_type (void *, const char *); 131130561Sobrienstatic bfd_boolean pr_tag_type 132130561Sobrien (void *, const char *, unsigned int, enum debug_type_kind); 133130561Sobrienstatic bfd_boolean pr_typdef (void *, const char *); 134130561Sobrienstatic bfd_boolean pr_tag (void *, const char *); 135130561Sobrienstatic bfd_boolean pr_int_constant (void *, const char *, bfd_vma); 136130561Sobrienstatic bfd_boolean pr_float_constant (void *, const char *, double); 137130561Sobrienstatic bfd_boolean pr_typed_constant (void *, const char *, bfd_vma); 138130561Sobrienstatic bfd_boolean pr_variable 139130561Sobrien (void *, const char *, enum debug_var_kind, bfd_vma); 140130561Sobrienstatic bfd_boolean pr_start_function (void *, const char *, bfd_boolean); 141130561Sobrienstatic bfd_boolean pr_function_parameter 142130561Sobrien (void *, const char *, enum debug_parm_kind, bfd_vma); 143130561Sobrienstatic bfd_boolean pr_start_block (void *, bfd_vma); 144130561Sobrienstatic bfd_boolean pr_end_block (void *, bfd_vma); 145130561Sobrienstatic bfd_boolean pr_end_function (void *); 146130561Sobrienstatic bfd_boolean pr_lineno (void *, const char *, unsigned long, bfd_vma); 147130561Sobrienstatic bfd_boolean append_parent (struct pr_handle *, const char *); 148130561Sobrien/* Only used by tg_ code. */ 149130561Sobrienstatic bfd_boolean tg_fix_visibility 150130561Sobrien (struct pr_handle *, enum debug_visibility); 151130561Sobrienstatic void find_address_in_section (bfd *, asection *, void *); 152130561Sobrienstatic void translate_addresses (bfd *, char *, FILE *, asymbol **); 153130561Sobrienstatic const char *visibility_name (enum debug_visibility); 154130561Sobrien/* Tags style replacements. */ 155130561Sobrienstatic bfd_boolean tg_start_compilation_unit (void *, const char *); 156130561Sobrienstatic bfd_boolean tg_start_source (void *, const char *); 157130561Sobrienstatic bfd_boolean tg_enum_type 158130561Sobrien (void *, const char *, const char **, bfd_signed_vma *); 159130561Sobrienstatic bfd_boolean tg_start_struct_type 160130561Sobrien (void *, const char *, unsigned int, bfd_boolean, unsigned int); 161130561Sobrienstatic bfd_boolean pr_struct_field 162130561Sobrien (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); 163130561Sobrienstatic bfd_boolean tg_struct_field 164130561Sobrien (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); 165130561Sobrienstatic bfd_boolean tg_struct_field 166130561Sobrien (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility); 167130561Sobrienstatic bfd_boolean tg_end_struct_type (void *); 168130561Sobrienstatic bfd_boolean tg_start_class_type 169130561Sobrien (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, bfd_boolean); 170130561Sobrienstatic bfd_boolean tg_class_static_member 171130561Sobrien (void *, const char *, const char *, enum debug_visibility); 172130561Sobrienstatic bfd_boolean tg_class_baseclass 173130561Sobrien (void *, bfd_vma, bfd_boolean, enum debug_visibility); 174130561Sobrienstatic bfd_boolean tg_class_method_variant 175130561Sobrien (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean); 176130561Sobrienstatic bfd_boolean tg_class_static_method_variant 177130561Sobrien (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean); 178130561Sobrienstatic bfd_boolean tg_end_class_type (void *); 179130561Sobrienstatic bfd_boolean tg_tag_type 180130561Sobrien (void *, const char *, unsigned int, enum debug_type_kind); 181130561Sobrienstatic bfd_boolean tg_typdef (void *, const char *); 182130561Sobrienstatic bfd_boolean tg_tag (void *, const char *); 183130561Sobrienstatic bfd_boolean tg_int_constant (void *, const char *, bfd_vma); 184130561Sobrienstatic bfd_boolean tg_float_constant (void *, const char *, double); 185130561Sobrienstatic bfd_boolean tg_typed_constant (void *, const char *, bfd_vma); 186130561Sobrienstatic bfd_boolean tg_variable 187130561Sobrien (void *, const char *, enum debug_var_kind, bfd_vma); 188130561Sobrienstatic bfd_boolean tg_start_function (void *, const char *, bfd_boolean); 189130561Sobrienstatic bfd_boolean tg_function_parameter 190130561Sobrien (void *, const char *, enum debug_parm_kind, bfd_vma); 191130561Sobrienstatic bfd_boolean tg_start_block (void *, bfd_vma); 192130561Sobrienstatic bfd_boolean tg_end_block (void *, bfd_vma); 193130561Sobrienstatic bfd_boolean tg_lineno (void *, const char *, unsigned long, bfd_vma); 194130561Sobrien 19533965Sjdpstatic const struct debug_write_fns pr_fns = 19633965Sjdp{ 19733965Sjdp pr_start_compilation_unit, 19833965Sjdp pr_start_source, 19933965Sjdp pr_empty_type, 20033965Sjdp pr_void_type, 20133965Sjdp pr_int_type, 20233965Sjdp pr_float_type, 20333965Sjdp pr_complex_type, 20433965Sjdp pr_bool_type, 20533965Sjdp pr_enum_type, 20633965Sjdp pr_pointer_type, 20733965Sjdp pr_function_type, 20833965Sjdp pr_reference_type, 20933965Sjdp pr_range_type, 21033965Sjdp pr_array_type, 21133965Sjdp pr_set_type, 21233965Sjdp pr_offset_type, 21333965Sjdp pr_method_type, 21433965Sjdp pr_const_type, 21533965Sjdp pr_volatile_type, 21633965Sjdp pr_start_struct_type, 21733965Sjdp pr_struct_field, 21833965Sjdp pr_end_struct_type, 21933965Sjdp pr_start_class_type, 22033965Sjdp pr_class_static_member, 22133965Sjdp pr_class_baseclass, 22233965Sjdp pr_class_start_method, 22333965Sjdp pr_class_method_variant, 22433965Sjdp pr_class_static_method_variant, 22533965Sjdp pr_class_end_method, 22633965Sjdp pr_end_class_type, 22733965Sjdp pr_typedef_type, 22833965Sjdp pr_tag_type, 22933965Sjdp pr_typdef, 23033965Sjdp pr_tag, 23133965Sjdp pr_int_constant, 23233965Sjdp pr_float_constant, 23333965Sjdp pr_typed_constant, 23433965Sjdp pr_variable, 23533965Sjdp pr_start_function, 23633965Sjdp pr_function_parameter, 23733965Sjdp pr_start_block, 23833965Sjdp pr_end_block, 23933965Sjdp pr_end_function, 24033965Sjdp pr_lineno 24133965Sjdp}; 24233965Sjdp 243130561Sobrienstatic const struct debug_write_fns tg_fns = 244130561Sobrien{ 245130561Sobrien tg_start_compilation_unit, 246130561Sobrien tg_start_source, 247130561Sobrien pr_empty_type, /* Same, push_type. */ 248130561Sobrien pr_void_type, /* Same, push_type. */ 249130561Sobrien pr_int_type, /* Same, push_type. */ 250130561Sobrien pr_float_type, /* Same, push_type. */ 251130561Sobrien pr_complex_type, /* Same, push_type. */ 252130561Sobrien pr_bool_type, /* Same, push_type. */ 253130561Sobrien tg_enum_type, 254130561Sobrien pr_pointer_type, /* Same, changes to pointer. */ 255130561Sobrien pr_function_type, /* Same, push_type. */ 256130561Sobrien pr_reference_type, /* Same, changes to reference. */ 257130561Sobrien pr_range_type, /* FIXME: What's that?. */ 258130561Sobrien pr_array_type, /* Same, push_type. */ 259130561Sobrien pr_set_type, /* FIXME: What's that?. */ 260130561Sobrien pr_offset_type, /* FIXME: What's that?. */ 261130561Sobrien pr_method_type, /* Same. */ 262130561Sobrien pr_const_type, /* Same, changes to const. */ 263130561Sobrien pr_volatile_type, /* Same, changes to volatile. */ 264130561Sobrien tg_start_struct_type, 265130561Sobrien tg_struct_field, 266130561Sobrien tg_end_struct_type, 267130561Sobrien tg_start_class_type, 268130561Sobrien tg_class_static_member, 269130561Sobrien tg_class_baseclass, 270130561Sobrien pr_class_start_method, /* Same, remembers that's a method. */ 271130561Sobrien tg_class_method_variant, 272130561Sobrien tg_class_static_method_variant, 273130561Sobrien pr_class_end_method, /* Same, forgets that's a method. */ 274130561Sobrien tg_end_class_type, 275130561Sobrien pr_typedef_type, /* Same, just push type. */ 276130561Sobrien tg_tag_type, 277130561Sobrien tg_typdef, 278130561Sobrien tg_tag, 279130561Sobrien tg_int_constant, /* Untested. */ 280130561Sobrien tg_float_constant, /* Untested. */ 281130561Sobrien tg_typed_constant, /* Untested. */ 282130561Sobrien tg_variable, 283130561Sobrien tg_start_function, 284130561Sobrien tg_function_parameter, 285130561Sobrien tg_start_block, 286130561Sobrien tg_end_block, 287130561Sobrien pr_end_function, /* Same, does nothing. */ 288130561Sobrien tg_lineno 289130561Sobrien}; 290130561Sobrien 29133965Sjdp/* Print out the generic debugging information recorded in dhandle. */ 29233965Sjdp 293130561Sobrienbfd_boolean 294130561Sobrienprint_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms, 295130561Sobrien void *demangler, bfd_boolean as_tags) 29633965Sjdp{ 29733965Sjdp struct pr_handle info; 29833965Sjdp 29933965Sjdp info.f = f; 30033965Sjdp info.indent = 0; 30133965Sjdp info.stack = NULL; 30233965Sjdp info.parameter = 0; 303130561Sobrien info.filename = NULL; 304130561Sobrien info.abfd = abfd; 305130561Sobrien info.syms = syms; 306130561Sobrien info.demangler = demangler; 30733965Sjdp 308130561Sobrien if (as_tags) 309130561Sobrien { 310130561Sobrien fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f); 311130561Sobrien fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f); 312130561Sobrien fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f); 313130561Sobrien fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f); 314130561Sobrien } 315130561Sobrien 316130561Sobrien return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info) 317130561Sobrien : debug_write (dhandle, &pr_fns, (void *) & info); 31833965Sjdp} 31933965Sjdp 32033965Sjdp/* Indent to the current indentation level. */ 32133965Sjdp 32233965Sjdpstatic void 323130561Sobrienindent (struct pr_handle *info) 32433965Sjdp{ 32533965Sjdp unsigned int i; 32633965Sjdp 32733965Sjdp for (i = 0; i < info->indent; i++) 32833965Sjdp putc (' ', info->f); 32933965Sjdp} 33033965Sjdp 33133965Sjdp/* Push a type on the type stack. */ 33233965Sjdp 333130561Sobrienstatic bfd_boolean 334130561Sobrienpush_type (struct pr_handle *info, const char *type) 33533965Sjdp{ 33633965Sjdp struct pr_stack *n; 33733965Sjdp 33833965Sjdp if (type == NULL) 339130561Sobrien return FALSE; 34033965Sjdp 34133965Sjdp n = (struct pr_stack *) xmalloc (sizeof *n); 34233965Sjdp memset (n, 0, sizeof *n); 34333965Sjdp 34433965Sjdp n->type = xstrdup (type); 34533965Sjdp n->visibility = DEBUG_VISIBILITY_IGNORE; 34633965Sjdp n->method = NULL; 34733965Sjdp n->next = info->stack; 34833965Sjdp info->stack = n; 34933965Sjdp 350130561Sobrien return TRUE; 35133965Sjdp} 35233965Sjdp 35333965Sjdp/* Prepend a string onto the type on the top of the type stack. */ 35433965Sjdp 355130561Sobrienstatic bfd_boolean 356130561Sobrienprepend_type (struct pr_handle *info, const char *s) 35733965Sjdp{ 35833965Sjdp char *n; 35933965Sjdp 36033965Sjdp assert (info->stack != NULL); 36133965Sjdp 36233965Sjdp n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1); 36333965Sjdp sprintf (n, "%s%s", s, info->stack->type); 36433965Sjdp free (info->stack->type); 36533965Sjdp info->stack->type = n; 36633965Sjdp 367130561Sobrien return TRUE; 36833965Sjdp} 36933965Sjdp 37033965Sjdp/* Append a string to the type on the top of the type stack. */ 37133965Sjdp 372130561Sobrienstatic bfd_boolean 373130561Sobrienappend_type (struct pr_handle *info, const char *s) 37433965Sjdp{ 37533965Sjdp unsigned int len; 37633965Sjdp 37733965Sjdp if (s == NULL) 378130561Sobrien return FALSE; 37933965Sjdp 38033965Sjdp assert (info->stack != NULL); 38133965Sjdp 38233965Sjdp len = strlen (info->stack->type); 38333965Sjdp info->stack->type = (char *) xrealloc (info->stack->type, 38433965Sjdp len + strlen (s) + 1); 38533965Sjdp strcpy (info->stack->type + len, s); 38633965Sjdp 387130561Sobrien return TRUE; 38833965Sjdp} 38933965Sjdp 390130561Sobrien/* Append a string to the parents on the top of the type stack. */ 391130561Sobrien 392130561Sobrienstatic bfd_boolean 393130561Sobrienappend_parent (struct pr_handle *info, const char *s) 394130561Sobrien{ 395130561Sobrien unsigned int len; 396130561Sobrien 397130561Sobrien if (s == NULL) 398130561Sobrien return FALSE; 399130561Sobrien 400130561Sobrien assert (info->stack != NULL); 401130561Sobrien 402130561Sobrien len = info->stack->parents ? strlen (info->stack->parents) : 0; 403130561Sobrien info->stack->parents = (char *) xrealloc (info->stack->parents, 404130561Sobrien len + strlen (s) + 1); 405130561Sobrien strcpy (info->stack->parents + len, s); 406130561Sobrien 407130561Sobrien return TRUE; 408130561Sobrien} 409130561Sobrien 41033965Sjdp/* We use an underscore to indicate where the name should go in a type 41133965Sjdp string. This function substitutes a string for the underscore. If 41233965Sjdp there is no underscore, the name follows the type. */ 41333965Sjdp 414130561Sobrienstatic bfd_boolean 415130561Sobriensubstitute_type (struct pr_handle *info, const char *s) 41633965Sjdp{ 41733965Sjdp char *u; 41833965Sjdp 41933965Sjdp assert (info->stack != NULL); 42033965Sjdp 42133965Sjdp u = strchr (info->stack->type, '|'); 42233965Sjdp if (u != NULL) 42333965Sjdp { 42433965Sjdp char *n; 42533965Sjdp 42633965Sjdp n = (char *) xmalloc (strlen (info->stack->type) + strlen (s)); 42733965Sjdp 42833965Sjdp memcpy (n, info->stack->type, u - info->stack->type); 42933965Sjdp strcpy (n + (u - info->stack->type), s); 43033965Sjdp strcat (n, u + 1); 43133965Sjdp 43233965Sjdp free (info->stack->type); 43333965Sjdp info->stack->type = n; 43433965Sjdp 435130561Sobrien return TRUE; 43633965Sjdp } 43733965Sjdp 43833965Sjdp if (strchr (s, '|') != NULL 43933965Sjdp && (strchr (info->stack->type, '{') != NULL 44033965Sjdp || strchr (info->stack->type, '(') != NULL)) 44133965Sjdp { 44233965Sjdp if (! prepend_type (info, "(") 44333965Sjdp || ! append_type (info, ")")) 444130561Sobrien return FALSE; 44533965Sjdp } 44633965Sjdp 44733965Sjdp if (*s == '\0') 448130561Sobrien return TRUE; 44933965Sjdp 45033965Sjdp return (append_type (info, " ") 45133965Sjdp && append_type (info, s)); 45233965Sjdp} 45333965Sjdp 45433965Sjdp/* Indent the type at the top of the stack by appending spaces. */ 45533965Sjdp 456130561Sobrienstatic bfd_boolean 457130561Sobrienindent_type (struct pr_handle *info) 45833965Sjdp{ 45933965Sjdp unsigned int i; 46033965Sjdp 46133965Sjdp for (i = 0; i < info->indent; i++) 46233965Sjdp { 46333965Sjdp if (! append_type (info, " ")) 464130561Sobrien return FALSE; 46533965Sjdp } 46633965Sjdp 467130561Sobrien return TRUE; 46833965Sjdp} 46933965Sjdp 47033965Sjdp/* Pop a type from the type stack. */ 47133965Sjdp 47233965Sjdpstatic char * 473130561Sobrienpop_type (struct pr_handle *info) 47433965Sjdp{ 47533965Sjdp struct pr_stack *o; 47633965Sjdp char *ret; 47733965Sjdp 47833965Sjdp assert (info->stack != NULL); 47933965Sjdp 48033965Sjdp o = info->stack; 48133965Sjdp info->stack = o->next; 48233965Sjdp ret = o->type; 48333965Sjdp free (o); 48433965Sjdp 48533965Sjdp return ret; 48633965Sjdp} 48733965Sjdp 48833965Sjdp/* Print a VMA value into a string. */ 48933965Sjdp 49033965Sjdpstatic void 491130561Sobrienprint_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp) 49233965Sjdp{ 49333965Sjdp if (sizeof (vma) <= sizeof (unsigned long)) 49433965Sjdp { 49533965Sjdp if (hexp) 49633965Sjdp sprintf (buf, "0x%lx", (unsigned long) vma); 49733965Sjdp else if (unsignedp) 49833965Sjdp sprintf (buf, "%lu", (unsigned long) vma); 49933965Sjdp else 50033965Sjdp sprintf (buf, "%ld", (long) vma); 50133965Sjdp } 50233965Sjdp else 50333965Sjdp { 50433965Sjdp buf[0] = '0'; 50533965Sjdp buf[1] = 'x'; 50633965Sjdp sprintf_vma (buf + 2, vma); 50733965Sjdp } 50833965Sjdp} 50933965Sjdp 51033965Sjdp/* Start a new compilation unit. */ 51133965Sjdp 512130561Sobrienstatic bfd_boolean 513130561Sobrienpr_start_compilation_unit (void *p, const char *filename) 51433965Sjdp{ 51533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 51633965Sjdp 51733965Sjdp assert (info->indent == 0); 51833965Sjdp 51933965Sjdp fprintf (info->f, "%s:\n", filename); 52033965Sjdp 521130561Sobrien return TRUE; 52233965Sjdp} 52333965Sjdp 52433965Sjdp/* Start a source file within a compilation unit. */ 52533965Sjdp 526130561Sobrienstatic bfd_boolean 527130561Sobrienpr_start_source (void *p, const char *filename) 52833965Sjdp{ 52933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 53033965Sjdp 53133965Sjdp assert (info->indent == 0); 53233965Sjdp 53333965Sjdp fprintf (info->f, " %s:\n", filename); 53433965Sjdp 535130561Sobrien return TRUE; 53633965Sjdp} 53733965Sjdp 53833965Sjdp/* Push an empty type onto the type stack. */ 53933965Sjdp 540130561Sobrienstatic bfd_boolean 541130561Sobrienpr_empty_type (void *p) 54233965Sjdp{ 54333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 54433965Sjdp 54533965Sjdp return push_type (info, "<undefined>"); 54633965Sjdp} 54733965Sjdp 54833965Sjdp/* Push a void type onto the type stack. */ 54933965Sjdp 550130561Sobrienstatic bfd_boolean 551130561Sobrienpr_void_type (void *p) 55233965Sjdp{ 55333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 55433965Sjdp 55533965Sjdp return push_type (info, "void"); 55633965Sjdp} 55733965Sjdp 55833965Sjdp/* Push an integer type onto the type stack. */ 55933965Sjdp 560130561Sobrienstatic bfd_boolean 561130561Sobrienpr_int_type (void *p, unsigned int size, bfd_boolean unsignedp) 56233965Sjdp{ 56333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 56433965Sjdp char ab[10]; 56533965Sjdp 56633965Sjdp sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8); 56733965Sjdp return push_type (info, ab); 56833965Sjdp} 56933965Sjdp 57033965Sjdp/* Push a floating type onto the type stack. */ 57133965Sjdp 572130561Sobrienstatic bfd_boolean 573130561Sobrienpr_float_type (void *p, unsigned int size) 57433965Sjdp{ 57533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 57633965Sjdp char ab[10]; 57733965Sjdp 57833965Sjdp if (size == 4) 57933965Sjdp return push_type (info, "float"); 58033965Sjdp else if (size == 8) 58133965Sjdp return push_type (info, "double"); 58233965Sjdp 58333965Sjdp sprintf (ab, "float%d", size * 8); 58433965Sjdp return push_type (info, ab); 58533965Sjdp} 58633965Sjdp 58733965Sjdp/* Push a complex type onto the type stack. */ 58833965Sjdp 589130561Sobrienstatic bfd_boolean 590130561Sobrienpr_complex_type (void *p, unsigned int size) 59133965Sjdp{ 59233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 59333965Sjdp 59433965Sjdp if (! pr_float_type (p, size)) 595130561Sobrien return FALSE; 59633965Sjdp 59733965Sjdp return prepend_type (info, "complex "); 59833965Sjdp} 59933965Sjdp 600130561Sobrien/* Push a bfd_boolean type onto the type stack. */ 60133965Sjdp 602130561Sobrienstatic bfd_boolean 603130561Sobrienpr_bool_type (void *p, unsigned int size) 60433965Sjdp{ 60533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 60633965Sjdp char ab[10]; 60733965Sjdp 60833965Sjdp sprintf (ab, "bool%d", size * 8); 60933965Sjdp 61033965Sjdp return push_type (info, ab); 61133965Sjdp} 61233965Sjdp 61333965Sjdp/* Push an enum type onto the type stack. */ 61433965Sjdp 615130561Sobrienstatic bfd_boolean 616130561Sobrienpr_enum_type (void *p, const char *tag, const char **names, 617130561Sobrien bfd_signed_vma *values) 61833965Sjdp{ 61933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 62033965Sjdp unsigned int i; 62133965Sjdp bfd_signed_vma val; 62233965Sjdp 62333965Sjdp if (! push_type (info, "enum ")) 624130561Sobrien return FALSE; 62533965Sjdp if (tag != NULL) 62633965Sjdp { 62733965Sjdp if (! append_type (info, tag) 62833965Sjdp || ! append_type (info, " ")) 629130561Sobrien return FALSE; 63033965Sjdp } 63133965Sjdp if (! append_type (info, "{ ")) 632130561Sobrien return FALSE; 63333965Sjdp 63433965Sjdp if (names == NULL) 63533965Sjdp { 63633965Sjdp if (! append_type (info, "/* undefined */")) 637130561Sobrien return FALSE; 63833965Sjdp } 63933965Sjdp else 64033965Sjdp { 64133965Sjdp val = 0; 64233965Sjdp for (i = 0; names[i] != NULL; i++) 64333965Sjdp { 64433965Sjdp if (i > 0) 64533965Sjdp { 64633965Sjdp if (! append_type (info, ", ")) 647130561Sobrien return FALSE; 64833965Sjdp } 64933965Sjdp 65033965Sjdp if (! append_type (info, names[i])) 651130561Sobrien return FALSE; 65233965Sjdp 65333965Sjdp if (values[i] != val) 65433965Sjdp { 65533965Sjdp char ab[20]; 65633965Sjdp 657130561Sobrien print_vma (values[i], ab, FALSE, FALSE); 65833965Sjdp if (! append_type (info, " = ") 65933965Sjdp || ! append_type (info, ab)) 660130561Sobrien return FALSE; 66133965Sjdp val = values[i]; 66233965Sjdp } 66333965Sjdp 66433965Sjdp ++val; 66533965Sjdp } 66633965Sjdp } 66733965Sjdp 66833965Sjdp return append_type (info, " }"); 66933965Sjdp} 67033965Sjdp 67133965Sjdp/* Turn the top type on the stack into a pointer. */ 67233965Sjdp 673130561Sobrienstatic bfd_boolean 674130561Sobrienpr_pointer_type (void *p) 67533965Sjdp{ 67633965Sjdp struct pr_handle *info = (struct pr_handle *) p; 67733965Sjdp char *s; 67833965Sjdp 67933965Sjdp assert (info->stack != NULL); 68033965Sjdp 68133965Sjdp s = strchr (info->stack->type, '|'); 68233965Sjdp if (s != NULL && s[1] == '[') 68333965Sjdp return substitute_type (info, "(*|)"); 68433965Sjdp return substitute_type (info, "*|"); 68533965Sjdp} 68633965Sjdp 68733965Sjdp/* Turn the top type on the stack into a function returning that type. */ 68833965Sjdp 689130561Sobrienstatic bfd_boolean 690130561Sobrienpr_function_type (void *p, int argcount, bfd_boolean varargs) 69133965Sjdp{ 69233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 69333965Sjdp char **arg_types; 69433965Sjdp unsigned int len; 69533965Sjdp char *s; 69633965Sjdp 69733965Sjdp assert (info->stack != NULL); 69833965Sjdp 69933965Sjdp len = 10; 70033965Sjdp 70133965Sjdp if (argcount <= 0) 70233965Sjdp { 70333965Sjdp arg_types = NULL; 70433965Sjdp len += 15; 70533965Sjdp } 70633965Sjdp else 70733965Sjdp { 70833965Sjdp int i; 70933965Sjdp 71033965Sjdp arg_types = (char **) xmalloc (argcount * sizeof *arg_types); 71133965Sjdp for (i = argcount - 1; i >= 0; i--) 71233965Sjdp { 71333965Sjdp if (! substitute_type (info, "")) 714130561Sobrien return FALSE; 71533965Sjdp arg_types[i] = pop_type (info); 71633965Sjdp if (arg_types[i] == NULL) 717130561Sobrien return FALSE; 71833965Sjdp len += strlen (arg_types[i]) + 2; 71933965Sjdp } 72033965Sjdp if (varargs) 72133965Sjdp len += 5; 72233965Sjdp } 72333965Sjdp 72433965Sjdp /* Now the return type is on the top of the stack. */ 72533965Sjdp 726218822Sdim s = xmalloc (len); 727218822Sdim LITSTRCPY (s, "(|) ("); 72833965Sjdp 72933965Sjdp if (argcount < 0) 73033965Sjdp strcat (s, "/* unknown */"); 73133965Sjdp else 73233965Sjdp { 73333965Sjdp int i; 73433965Sjdp 73533965Sjdp for (i = 0; i < argcount; i++) 73633965Sjdp { 73733965Sjdp if (i > 0) 73833965Sjdp strcat (s, ", "); 73933965Sjdp strcat (s, arg_types[i]); 74033965Sjdp } 74133965Sjdp if (varargs) 74233965Sjdp { 74333965Sjdp if (i > 0) 74433965Sjdp strcat (s, ", "); 74533965Sjdp strcat (s, "..."); 74633965Sjdp } 74733965Sjdp if (argcount > 0) 74833965Sjdp free (arg_types); 74933965Sjdp } 75033965Sjdp 75133965Sjdp strcat (s, ")"); 75233965Sjdp 75333965Sjdp if (! substitute_type (info, s)) 754130561Sobrien return FALSE; 75533965Sjdp 75633965Sjdp free (s); 75733965Sjdp 758130561Sobrien return TRUE; 75933965Sjdp} 76033965Sjdp 76133965Sjdp/* Turn the top type on the stack into a reference to that type. */ 76233965Sjdp 763130561Sobrienstatic bfd_boolean 764130561Sobrienpr_reference_type (void *p) 76533965Sjdp{ 76633965Sjdp struct pr_handle *info = (struct pr_handle *) p; 76733965Sjdp 76833965Sjdp assert (info->stack != NULL); 76933965Sjdp 77033965Sjdp return substitute_type (info, "&|"); 77133965Sjdp} 77233965Sjdp 77333965Sjdp/* Make a range type. */ 77433965Sjdp 775130561Sobrienstatic bfd_boolean 776130561Sobrienpr_range_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper) 77733965Sjdp{ 77833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 77933965Sjdp char abl[20], abu[20]; 78033965Sjdp 78133965Sjdp assert (info->stack != NULL); 78233965Sjdp 78333965Sjdp if (! substitute_type (info, "")) 784130561Sobrien return FALSE; 78533965Sjdp 786130561Sobrien print_vma (lower, abl, FALSE, FALSE); 787130561Sobrien print_vma (upper, abu, FALSE, FALSE); 78833965Sjdp 78933965Sjdp return (prepend_type (info, "range (") 79033965Sjdp && append_type (info, "):") 79133965Sjdp && append_type (info, abl) 79233965Sjdp && append_type (info, ":") 79333965Sjdp && append_type (info, abu)); 79433965Sjdp} 79533965Sjdp 79633965Sjdp/* Make an array type. */ 79733965Sjdp 798130561Sobrienstatic bfd_boolean 799130561Sobrienpr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper, 800130561Sobrien bfd_boolean stringp) 80133965Sjdp{ 80233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 80333965Sjdp char *range_type; 80433965Sjdp char abl[20], abu[20], ab[50]; 80533965Sjdp 80633965Sjdp range_type = pop_type (info); 80733965Sjdp if (range_type == NULL) 808130561Sobrien return FALSE; 80933965Sjdp 81033965Sjdp if (lower == 0) 81133965Sjdp { 81233965Sjdp if (upper == -1) 81333965Sjdp sprintf (ab, "|[]"); 81433965Sjdp else 81533965Sjdp { 816130561Sobrien print_vma (upper + 1, abu, FALSE, FALSE); 81733965Sjdp sprintf (ab, "|[%s]", abu); 81833965Sjdp } 81933965Sjdp } 82033965Sjdp else 82133965Sjdp { 822130561Sobrien print_vma (lower, abl, FALSE, FALSE); 823130561Sobrien print_vma (upper, abu, FALSE, FALSE); 82433965Sjdp sprintf (ab, "|[%s:%s]", abl, abu); 82533965Sjdp } 82633965Sjdp 82733965Sjdp if (! substitute_type (info, ab)) 828130561Sobrien return FALSE; 82933965Sjdp 83033965Sjdp if (strcmp (range_type, "int") != 0) 83133965Sjdp { 83233965Sjdp if (! append_type (info, ":") 83333965Sjdp || ! append_type (info, range_type)) 834130561Sobrien return FALSE; 83533965Sjdp } 83633965Sjdp 83733965Sjdp if (stringp) 83833965Sjdp { 83933965Sjdp if (! append_type (info, " /* string */")) 840130561Sobrien return FALSE; 84133965Sjdp } 84233965Sjdp 843130561Sobrien return TRUE; 84433965Sjdp} 84533965Sjdp 84633965Sjdp/* Make a set type. */ 84733965Sjdp 848130561Sobrienstatic bfd_boolean 849130561Sobrienpr_set_type (void *p, bfd_boolean bitstringp) 85033965Sjdp{ 85133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 85233965Sjdp 85333965Sjdp if (! substitute_type (info, "")) 854130561Sobrien return FALSE; 85533965Sjdp 85633965Sjdp if (! prepend_type (info, "set { ") 85733965Sjdp || ! append_type (info, " }")) 858130561Sobrien return FALSE; 85933965Sjdp 86033965Sjdp if (bitstringp) 86133965Sjdp { 86233965Sjdp if (! append_type (info, "/* bitstring */")) 863130561Sobrien return FALSE; 86433965Sjdp } 86533965Sjdp 866130561Sobrien return TRUE; 86733965Sjdp} 86833965Sjdp 86933965Sjdp/* Make an offset type. */ 87033965Sjdp 871130561Sobrienstatic bfd_boolean 872130561Sobrienpr_offset_type (void *p) 87333965Sjdp{ 87433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 87533965Sjdp char *t; 87633965Sjdp 87733965Sjdp if (! substitute_type (info, "")) 878130561Sobrien return FALSE; 87933965Sjdp 88033965Sjdp t = pop_type (info); 88133965Sjdp if (t == NULL) 882130561Sobrien return FALSE; 88333965Sjdp 88433965Sjdp return (substitute_type (info, "") 88533965Sjdp && prepend_type (info, " ") 88633965Sjdp && prepend_type (info, t) 88733965Sjdp && append_type (info, "::|")); 88833965Sjdp} 88933965Sjdp 89033965Sjdp/* Make a method type. */ 89133965Sjdp 892130561Sobrienstatic bfd_boolean 893130561Sobrienpr_method_type (void *p, bfd_boolean domain, int argcount, bfd_boolean varargs) 89433965Sjdp{ 89533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 89633965Sjdp unsigned int len; 89733965Sjdp char *domain_type; 89833965Sjdp char **arg_types; 89933965Sjdp char *s; 90033965Sjdp 90133965Sjdp len = 10; 90233965Sjdp 90333965Sjdp if (! domain) 90433965Sjdp domain_type = NULL; 90533965Sjdp else 90633965Sjdp { 90733965Sjdp if (! substitute_type (info, "")) 908130561Sobrien return FALSE; 90933965Sjdp domain_type = pop_type (info); 91033965Sjdp if (domain_type == NULL) 911130561Sobrien return FALSE; 912218822Sdim if (CONST_STRNEQ (domain_type, "class ") 91333965Sjdp && strchr (domain_type + sizeof "class " - 1, ' ') == NULL) 91433965Sjdp domain_type += sizeof "class " - 1; 915218822Sdim else if (CONST_STRNEQ (domain_type, "union class ") 91633965Sjdp && (strchr (domain_type + sizeof "union class " - 1, ' ') 91733965Sjdp == NULL)) 91833965Sjdp domain_type += sizeof "union class " - 1; 91933965Sjdp len += strlen (domain_type); 92033965Sjdp } 92133965Sjdp 92233965Sjdp if (argcount <= 0) 92333965Sjdp { 92433965Sjdp arg_types = NULL; 92533965Sjdp len += 15; 92633965Sjdp } 92733965Sjdp else 92833965Sjdp { 92933965Sjdp int i; 93033965Sjdp 93133965Sjdp arg_types = (char **) xmalloc (argcount * sizeof *arg_types); 93233965Sjdp for (i = argcount - 1; i >= 0; i--) 93333965Sjdp { 93433965Sjdp if (! substitute_type (info, "")) 935130561Sobrien return FALSE; 93633965Sjdp arg_types[i] = pop_type (info); 93733965Sjdp if (arg_types[i] == NULL) 938130561Sobrien return FALSE; 93933965Sjdp len += strlen (arg_types[i]) + 2; 94033965Sjdp } 94133965Sjdp if (varargs) 94233965Sjdp len += 5; 94333965Sjdp } 94433965Sjdp 94533965Sjdp /* Now the return type is on the top of the stack. */ 94633965Sjdp 94733965Sjdp s = (char *) xmalloc (len); 94833965Sjdp if (! domain) 94933965Sjdp *s = '\0'; 95033965Sjdp else 95133965Sjdp strcpy (s, domain_type); 95233965Sjdp strcat (s, "::| ("); 95333965Sjdp 95433965Sjdp if (argcount < 0) 95533965Sjdp strcat (s, "/* unknown */"); 95633965Sjdp else 95733965Sjdp { 95833965Sjdp int i; 95933965Sjdp 96033965Sjdp for (i = 0; i < argcount; i++) 96133965Sjdp { 96233965Sjdp if (i > 0) 96333965Sjdp strcat (s, ", "); 96433965Sjdp strcat (s, arg_types[i]); 96533965Sjdp } 96633965Sjdp if (varargs) 96733965Sjdp { 96833965Sjdp if (i > 0) 96933965Sjdp strcat (s, ", "); 97033965Sjdp strcat (s, "..."); 97133965Sjdp } 97233965Sjdp if (argcount > 0) 97333965Sjdp free (arg_types); 97433965Sjdp } 97533965Sjdp 97633965Sjdp strcat (s, ")"); 97733965Sjdp 97833965Sjdp if (! substitute_type (info, s)) 979130561Sobrien return FALSE; 98033965Sjdp 98133965Sjdp free (s); 98233965Sjdp 983130561Sobrien return TRUE; 98433965Sjdp} 98533965Sjdp 98633965Sjdp/* Make a const qualified type. */ 98733965Sjdp 988130561Sobrienstatic bfd_boolean 989130561Sobrienpr_const_type (void *p) 99033965Sjdp{ 99133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 99233965Sjdp 99333965Sjdp return substitute_type (info, "const |"); 99433965Sjdp} 99533965Sjdp 99633965Sjdp/* Make a volatile qualified type. */ 99733965Sjdp 998130561Sobrienstatic bfd_boolean 999130561Sobrienpr_volatile_type (void *p) 100033965Sjdp{ 100133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 100233965Sjdp 100333965Sjdp return substitute_type (info, "volatile |"); 100433965Sjdp} 100533965Sjdp 100633965Sjdp/* Start accumulating a struct type. */ 100733965Sjdp 1008130561Sobrienstatic bfd_boolean 1009130561Sobrienpr_start_struct_type (void *p, const char *tag, unsigned int id, 1010130561Sobrien bfd_boolean structp, unsigned int size) 101133965Sjdp{ 101233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 101333965Sjdp 101433965Sjdp info->indent += 2; 101533965Sjdp 101633965Sjdp if (! push_type (info, structp ? "struct " : "union ")) 1017130561Sobrien return FALSE; 101833965Sjdp if (tag != NULL) 101933965Sjdp { 102033965Sjdp if (! append_type (info, tag)) 1021130561Sobrien return FALSE; 102233965Sjdp } 102333965Sjdp else 102433965Sjdp { 102533965Sjdp char idbuf[20]; 102633965Sjdp 102733965Sjdp sprintf (idbuf, "%%anon%u", id); 102833965Sjdp if (! append_type (info, idbuf)) 1029130561Sobrien return FALSE; 103033965Sjdp } 103133965Sjdp 103233965Sjdp if (! append_type (info, " {")) 1033130561Sobrien return FALSE; 103433965Sjdp if (size != 0 || tag != NULL) 103533965Sjdp { 103633965Sjdp char ab[30]; 103733965Sjdp 103833965Sjdp if (! append_type (info, " /*")) 1039130561Sobrien return FALSE; 104033965Sjdp 104133965Sjdp if (size != 0) 104233965Sjdp { 104333965Sjdp sprintf (ab, " size %u", size); 104433965Sjdp if (! append_type (info, ab)) 1045130561Sobrien return FALSE; 104633965Sjdp } 104733965Sjdp if (tag != NULL) 104833965Sjdp { 104933965Sjdp sprintf (ab, " id %u", id); 105033965Sjdp if (! append_type (info, ab)) 1051130561Sobrien return FALSE; 105233965Sjdp } 105333965Sjdp if (! append_type (info, " */")) 1054130561Sobrien return FALSE; 105533965Sjdp } 105633965Sjdp if (! append_type (info, "\n")) 1057130561Sobrien return FALSE; 105833965Sjdp 105933965Sjdp info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; 106033965Sjdp 106133965Sjdp return indent_type (info); 106233965Sjdp} 106333965Sjdp 106433965Sjdp/* Output the visibility of a field in a struct. */ 106533965Sjdp 1066130561Sobrienstatic bfd_boolean 1067130561Sobrienpr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) 106833965Sjdp{ 106960484Sobrien const char *s = NULL; 107033965Sjdp char *t; 107133965Sjdp unsigned int len; 107233965Sjdp 107333965Sjdp assert (info->stack != NULL); 107433965Sjdp 107533965Sjdp if (info->stack->visibility == visibility) 1076130561Sobrien return TRUE; 107733965Sjdp 107833965Sjdp switch (visibility) 107933965Sjdp { 108033965Sjdp case DEBUG_VISIBILITY_PUBLIC: 108133965Sjdp s = "public"; 108233965Sjdp break; 108333965Sjdp case DEBUG_VISIBILITY_PRIVATE: 108433965Sjdp s = "private"; 108533965Sjdp break; 108633965Sjdp case DEBUG_VISIBILITY_PROTECTED: 108733965Sjdp s = "protected"; 108833965Sjdp break; 108933965Sjdp case DEBUG_VISIBILITY_IGNORE: 109033965Sjdp s = "/* ignore */"; 109133965Sjdp break; 109233965Sjdp default: 109333965Sjdp abort (); 1094130561Sobrien return FALSE; 109533965Sjdp } 109633965Sjdp 109733965Sjdp /* Trim off a trailing space in the struct string, to make the 109833965Sjdp output look a bit better, then stick on the visibility string. */ 109933965Sjdp 110033965Sjdp t = info->stack->type; 110133965Sjdp len = strlen (t); 110233965Sjdp assert (t[len - 1] == ' '); 110333965Sjdp t[len - 1] = '\0'; 110433965Sjdp 110533965Sjdp if (! append_type (info, s) 110633965Sjdp || ! append_type (info, ":\n") 110733965Sjdp || ! indent_type (info)) 1108130561Sobrien return FALSE; 110933965Sjdp 111033965Sjdp info->stack->visibility = visibility; 111133965Sjdp 1112130561Sobrien return TRUE; 111333965Sjdp} 111433965Sjdp 111533965Sjdp/* Add a field to a struct type. */ 111633965Sjdp 1117130561Sobrienstatic bfd_boolean 1118130561Sobrienpr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize, 1119130561Sobrien enum debug_visibility visibility) 112033965Sjdp{ 112133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 112233965Sjdp char ab[20]; 112333965Sjdp char *t; 112433965Sjdp 112533965Sjdp if (! substitute_type (info, name)) 1126130561Sobrien return FALSE; 112733965Sjdp 112833965Sjdp if (! append_type (info, "; /* ")) 1129130561Sobrien return FALSE; 113033965Sjdp 113133965Sjdp if (bitsize != 0) 113233965Sjdp { 1133130561Sobrien print_vma (bitsize, ab, TRUE, FALSE); 113433965Sjdp if (! append_type (info, "bitsize ") 113533965Sjdp || ! append_type (info, ab) 113633965Sjdp || ! append_type (info, ", ")) 1137130561Sobrien return FALSE; 113833965Sjdp } 113933965Sjdp 1140130561Sobrien print_vma (bitpos, ab, TRUE, FALSE); 114133965Sjdp if (! append_type (info, "bitpos ") 114233965Sjdp || ! append_type (info, ab) 114333965Sjdp || ! append_type (info, " */\n") 114433965Sjdp || ! indent_type (info)) 1145130561Sobrien return FALSE; 114633965Sjdp 114733965Sjdp t = pop_type (info); 114833965Sjdp if (t == NULL) 1149130561Sobrien return FALSE; 115033965Sjdp 115133965Sjdp if (! pr_fix_visibility (info, visibility)) 1152130561Sobrien return FALSE; 115333965Sjdp 115433965Sjdp return append_type (info, t); 115533965Sjdp} 115633965Sjdp 115733965Sjdp/* Finish a struct type. */ 115833965Sjdp 1159130561Sobrienstatic bfd_boolean 1160130561Sobrienpr_end_struct_type (void *p) 116133965Sjdp{ 116233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 116333965Sjdp char *s; 116433965Sjdp 116533965Sjdp assert (info->stack != NULL); 116633965Sjdp assert (info->indent >= 2); 116733965Sjdp 116833965Sjdp info->indent -= 2; 116933965Sjdp 117033965Sjdp /* Change the trailing indentation to have a close brace. */ 117133965Sjdp s = info->stack->type + strlen (info->stack->type) - 2; 117233965Sjdp assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0'); 117333965Sjdp 117433965Sjdp *s++ = '}'; 117533965Sjdp *s = '\0'; 117633965Sjdp 1177130561Sobrien return TRUE; 117833965Sjdp} 117933965Sjdp 118033965Sjdp/* Start a class type. */ 118133965Sjdp 1182130561Sobrienstatic bfd_boolean 1183130561Sobrienpr_start_class_type (void *p, const char *tag, unsigned int id, 1184130561Sobrien bfd_boolean structp, unsigned int size, 1185130561Sobrien bfd_boolean vptr, bfd_boolean ownvptr) 118633965Sjdp{ 118733965Sjdp struct pr_handle *info = (struct pr_handle *) p; 118833965Sjdp char *tv = NULL; 118933965Sjdp 119033965Sjdp info->indent += 2; 119133965Sjdp 119233965Sjdp if (vptr && ! ownvptr) 119333965Sjdp { 119433965Sjdp tv = pop_type (info); 119533965Sjdp if (tv == NULL) 1196130561Sobrien return FALSE; 119733965Sjdp } 119833965Sjdp 119933965Sjdp if (! push_type (info, structp ? "class " : "union class ")) 1200130561Sobrien return FALSE; 120133965Sjdp if (tag != NULL) 120233965Sjdp { 120333965Sjdp if (! append_type (info, tag)) 1204130561Sobrien return FALSE; 120533965Sjdp } 120633965Sjdp else 120733965Sjdp { 120833965Sjdp char idbuf[20]; 120933965Sjdp 121033965Sjdp sprintf (idbuf, "%%anon%u", id); 121133965Sjdp if (! append_type (info, idbuf)) 1212130561Sobrien return FALSE; 121333965Sjdp } 121433965Sjdp 121533965Sjdp if (! append_type (info, " {")) 1216130561Sobrien return FALSE; 121733965Sjdp if (size != 0 || vptr || ownvptr || tag != NULL) 121833965Sjdp { 121933965Sjdp if (! append_type (info, " /*")) 1220130561Sobrien return FALSE; 122133965Sjdp 122233965Sjdp if (size != 0) 122333965Sjdp { 122433965Sjdp char ab[20]; 122533965Sjdp 122633965Sjdp sprintf (ab, "%u", size); 122733965Sjdp if (! append_type (info, " size ") 122833965Sjdp || ! append_type (info, ab)) 1229130561Sobrien return FALSE; 123033965Sjdp } 123133965Sjdp 123233965Sjdp if (vptr) 123333965Sjdp { 123433965Sjdp if (! append_type (info, " vtable ")) 1235130561Sobrien return FALSE; 123633965Sjdp if (ownvptr) 123733965Sjdp { 123833965Sjdp if (! append_type (info, "self ")) 1239130561Sobrien return FALSE; 124033965Sjdp } 124133965Sjdp else 124233965Sjdp { 124333965Sjdp if (! append_type (info, tv) 124433965Sjdp || ! append_type (info, " ")) 1245130561Sobrien return FALSE; 124633965Sjdp } 124733965Sjdp } 124833965Sjdp 124933965Sjdp if (tag != NULL) 125033965Sjdp { 125133965Sjdp char ab[30]; 125233965Sjdp 125333965Sjdp sprintf (ab, " id %u", id); 125433965Sjdp if (! append_type (info, ab)) 1255130561Sobrien return FALSE; 125633965Sjdp } 125733965Sjdp 125833965Sjdp if (! append_type (info, " */")) 1259130561Sobrien return FALSE; 126033965Sjdp } 126133965Sjdp 126233965Sjdp info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; 126333965Sjdp 126433965Sjdp return (append_type (info, "\n") 126533965Sjdp && indent_type (info)); 126633965Sjdp} 126733965Sjdp 126833965Sjdp/* Add a static member to a class. */ 126933965Sjdp 1270130561Sobrienstatic bfd_boolean 1271130561Sobrienpr_class_static_member (void *p, const char *name, const char *physname, 1272130561Sobrien enum debug_visibility visibility) 127333965Sjdp{ 127433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 127533965Sjdp char *t; 127633965Sjdp 127733965Sjdp if (! substitute_type (info, name)) 1278130561Sobrien return FALSE; 127933965Sjdp 128033965Sjdp if (! prepend_type (info, "static ") 128133965Sjdp || ! append_type (info, "; /* ") 128233965Sjdp || ! append_type (info, physname) 128333965Sjdp || ! append_type (info, " */\n") 128433965Sjdp || ! indent_type (info)) 1285130561Sobrien return FALSE; 128633965Sjdp 128733965Sjdp t = pop_type (info); 128833965Sjdp if (t == NULL) 1289130561Sobrien return FALSE; 129033965Sjdp 129133965Sjdp if (! pr_fix_visibility (info, visibility)) 1292130561Sobrien return FALSE; 129333965Sjdp 129433965Sjdp return append_type (info, t); 129533965Sjdp} 129633965Sjdp 129733965Sjdp/* Add a base class to a class. */ 129833965Sjdp 1299130561Sobrienstatic bfd_boolean 1300130561Sobrienpr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual, 1301130561Sobrien enum debug_visibility visibility) 130233965Sjdp{ 130333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 130433965Sjdp char *t; 130533965Sjdp const char *prefix; 130633965Sjdp char ab[20]; 130733965Sjdp char *s, *l, *n; 130833965Sjdp 130933965Sjdp assert (info->stack != NULL && info->stack->next != NULL); 131033965Sjdp 131133965Sjdp if (! substitute_type (info, "")) 1312130561Sobrien return FALSE; 131333965Sjdp 131433965Sjdp t = pop_type (info); 131533965Sjdp if (t == NULL) 1316130561Sobrien return FALSE; 131733965Sjdp 1318218822Sdim if (CONST_STRNEQ (t, "class ")) 131933965Sjdp t += sizeof "class " - 1; 132033965Sjdp 132133965Sjdp /* Push it back on to take advantage of the prepend_type and 132233965Sjdp append_type routines. */ 132333965Sjdp if (! push_type (info, t)) 1324130561Sobrien return FALSE; 132533965Sjdp 132633965Sjdp if (virtual) 132733965Sjdp { 132833965Sjdp if (! prepend_type (info, "virtual ")) 1329130561Sobrien return FALSE; 133033965Sjdp } 133133965Sjdp 133233965Sjdp switch (visibility) 133333965Sjdp { 133433965Sjdp case DEBUG_VISIBILITY_PUBLIC: 133533965Sjdp prefix = "public "; 133633965Sjdp break; 133733965Sjdp case DEBUG_VISIBILITY_PROTECTED: 133833965Sjdp prefix = "protected "; 133933965Sjdp break; 134033965Sjdp case DEBUG_VISIBILITY_PRIVATE: 134133965Sjdp prefix = "private "; 134233965Sjdp break; 134333965Sjdp default: 134433965Sjdp prefix = "/* unknown visibility */ "; 134533965Sjdp break; 134633965Sjdp } 134733965Sjdp 134833965Sjdp if (! prepend_type (info, prefix)) 1349130561Sobrien return FALSE; 135033965Sjdp 135133965Sjdp if (bitpos != 0) 135233965Sjdp { 1353130561Sobrien print_vma (bitpos, ab, TRUE, FALSE); 135433965Sjdp if (! append_type (info, " /* bitpos ") 135533965Sjdp || ! append_type (info, ab) 135633965Sjdp || ! append_type (info, " */")) 1357130561Sobrien return FALSE; 135833965Sjdp } 135933965Sjdp 136033965Sjdp /* Now the top of the stack is something like "public A / * bitpos 136133965Sjdp 10 * /". The next element on the stack is something like "class 136233965Sjdp xx { / * size 8 * /\n...". We want to substitute the top of the 136333965Sjdp stack in before the {. */ 136433965Sjdp s = strchr (info->stack->next->type, '{'); 136533965Sjdp assert (s != NULL); 136633965Sjdp --s; 136733965Sjdp 136833965Sjdp /* If there is already a ':', then we already have a baseclass, and 136933965Sjdp we must append this one after a comma. */ 137033965Sjdp for (l = info->stack->next->type; l != s; l++) 137133965Sjdp if (*l == ':') 137233965Sjdp break; 137333965Sjdp if (! prepend_type (info, l == s ? " : " : ", ")) 1374130561Sobrien return FALSE; 137533965Sjdp 137633965Sjdp t = pop_type (info); 137733965Sjdp if (t == NULL) 1378130561Sobrien return FALSE; 137933965Sjdp 138033965Sjdp n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); 138133965Sjdp memcpy (n, info->stack->type, s - info->stack->type); 138233965Sjdp strcpy (n + (s - info->stack->type), t); 138333965Sjdp strcat (n, s); 138433965Sjdp 138533965Sjdp free (info->stack->type); 138633965Sjdp info->stack->type = n; 138733965Sjdp 138833965Sjdp free (t); 138933965Sjdp 1390130561Sobrien return TRUE; 139133965Sjdp} 139233965Sjdp 139333965Sjdp/* Start adding a method to a class. */ 139433965Sjdp 1395130561Sobrienstatic bfd_boolean 1396130561Sobrienpr_class_start_method (void *p, const char *name) 139733965Sjdp{ 139833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 139933965Sjdp 140033965Sjdp assert (info->stack != NULL); 140133965Sjdp info->stack->method = name; 1402130561Sobrien return TRUE; 140333965Sjdp} 140433965Sjdp 140533965Sjdp/* Add a variant to a method. */ 140633965Sjdp 1407130561Sobrienstatic bfd_boolean 1408130561Sobrienpr_class_method_variant (void *p, const char *physname, 1409130561Sobrien enum debug_visibility visibility, 1410130561Sobrien bfd_boolean constp, bfd_boolean volatilep, 1411130561Sobrien bfd_vma voffset, bfd_boolean context) 141233965Sjdp{ 141333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 141433965Sjdp char *method_type; 141533965Sjdp char *context_type; 141633965Sjdp 141733965Sjdp assert (info->stack != NULL); 141833965Sjdp assert (info->stack->next != NULL); 141933965Sjdp 142033965Sjdp /* Put the const and volatile qualifiers on the type. */ 142133965Sjdp if (volatilep) 142233965Sjdp { 142333965Sjdp if (! append_type (info, " volatile")) 1424130561Sobrien return FALSE; 142533965Sjdp } 142633965Sjdp if (constp) 142733965Sjdp { 142833965Sjdp if (! append_type (info, " const")) 1429130561Sobrien return FALSE; 143033965Sjdp } 143133965Sjdp 143233965Sjdp /* Stick the name of the method into its type. */ 143333965Sjdp if (! substitute_type (info, 143433965Sjdp (context 143533965Sjdp ? info->stack->next->next->method 143633965Sjdp : info->stack->next->method))) 1437130561Sobrien return FALSE; 143833965Sjdp 143933965Sjdp /* Get the type. */ 144033965Sjdp method_type = pop_type (info); 144133965Sjdp if (method_type == NULL) 1442130561Sobrien return FALSE; 144333965Sjdp 144433965Sjdp /* Pull off the context type if there is one. */ 144533965Sjdp if (! context) 144633965Sjdp context_type = NULL; 144733965Sjdp else 144833965Sjdp { 144933965Sjdp context_type = pop_type (info); 145033965Sjdp if (context_type == NULL) 1451130561Sobrien return FALSE; 145233965Sjdp } 145333965Sjdp 145433965Sjdp /* Now the top of the stack is the class. */ 145533965Sjdp 145633965Sjdp if (! pr_fix_visibility (info, visibility)) 1457130561Sobrien return FALSE; 145833965Sjdp 145933965Sjdp if (! append_type (info, method_type) 146033965Sjdp || ! append_type (info, " /* ") 146133965Sjdp || ! append_type (info, physname) 146233965Sjdp || ! append_type (info, " ")) 1463130561Sobrien return FALSE; 146433965Sjdp if (context || voffset != 0) 146533965Sjdp { 146633965Sjdp char ab[20]; 146733965Sjdp 146833965Sjdp if (context) 146933965Sjdp { 147033965Sjdp if (! append_type (info, "context ") 147133965Sjdp || ! append_type (info, context_type) 147233965Sjdp || ! append_type (info, " ")) 1473130561Sobrien return FALSE; 147433965Sjdp } 1475130561Sobrien print_vma (voffset, ab, TRUE, FALSE); 147633965Sjdp if (! append_type (info, "voffset ") 147733965Sjdp || ! append_type (info, ab)) 1478130561Sobrien return FALSE; 147933965Sjdp } 148033965Sjdp 148133965Sjdp return (append_type (info, " */;\n") 148233965Sjdp && indent_type (info)); 148333965Sjdp} 148433965Sjdp 148533965Sjdp/* Add a static variant to a method. */ 148633965Sjdp 1487130561Sobrienstatic bfd_boolean 1488130561Sobrienpr_class_static_method_variant (void *p, const char *physname, 1489130561Sobrien enum debug_visibility visibility, 1490130561Sobrien bfd_boolean constp, bfd_boolean volatilep) 149133965Sjdp{ 149233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 149333965Sjdp char *method_type; 149433965Sjdp 149533965Sjdp assert (info->stack != NULL); 149633965Sjdp assert (info->stack->next != NULL); 149733965Sjdp assert (info->stack->next->method != NULL); 149833965Sjdp 149933965Sjdp /* Put the const and volatile qualifiers on the type. */ 150033965Sjdp if (volatilep) 150133965Sjdp { 150233965Sjdp if (! append_type (info, " volatile")) 1503130561Sobrien return FALSE; 150433965Sjdp } 150533965Sjdp if (constp) 150633965Sjdp { 150733965Sjdp if (! append_type (info, " const")) 1508130561Sobrien return FALSE; 150933965Sjdp } 151033965Sjdp 151133965Sjdp /* Mark it as static. */ 151233965Sjdp if (! prepend_type (info, "static ")) 1513130561Sobrien return FALSE; 151433965Sjdp 151533965Sjdp /* Stick the name of the method into its type. */ 151633965Sjdp if (! substitute_type (info, info->stack->next->method)) 1517130561Sobrien return FALSE; 151833965Sjdp 151933965Sjdp /* Get the type. */ 152033965Sjdp method_type = pop_type (info); 152133965Sjdp if (method_type == NULL) 1522130561Sobrien return FALSE; 152333965Sjdp 152433965Sjdp /* Now the top of the stack is the class. */ 152533965Sjdp 152633965Sjdp if (! pr_fix_visibility (info, visibility)) 1527130561Sobrien return FALSE; 152833965Sjdp 152933965Sjdp return (append_type (info, method_type) 153033965Sjdp && append_type (info, " /* ") 153133965Sjdp && append_type (info, physname) 153233965Sjdp && append_type (info, " */;\n") 153333965Sjdp && indent_type (info)); 153433965Sjdp} 153533965Sjdp 153633965Sjdp/* Finish up a method. */ 153733965Sjdp 1538130561Sobrienstatic bfd_boolean 1539130561Sobrienpr_class_end_method (void *p) 154033965Sjdp{ 154133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 154233965Sjdp 154333965Sjdp info->stack->method = NULL; 1544130561Sobrien return TRUE; 154533965Sjdp} 154633965Sjdp 154733965Sjdp/* Finish up a class. */ 154833965Sjdp 1549130561Sobrienstatic bfd_boolean 1550130561Sobrienpr_end_class_type (void *p) 155133965Sjdp{ 155233965Sjdp return pr_end_struct_type (p); 155333965Sjdp} 155433965Sjdp 155533965Sjdp/* Push a type on the stack using a typedef name. */ 155633965Sjdp 1557130561Sobrienstatic bfd_boolean 1558130561Sobrienpr_typedef_type (void *p, const char *name) 155933965Sjdp{ 156033965Sjdp struct pr_handle *info = (struct pr_handle *) p; 156133965Sjdp 156233965Sjdp return push_type (info, name); 156333965Sjdp} 156433965Sjdp 156533965Sjdp/* Push a type on the stack using a tag name. */ 156633965Sjdp 1567130561Sobrienstatic bfd_boolean 1568130561Sobrienpr_tag_type (void *p, const char *name, unsigned int id, 1569130561Sobrien enum debug_type_kind kind) 157033965Sjdp{ 157133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 157233965Sjdp const char *t, *tag; 157333965Sjdp char idbuf[20]; 157433965Sjdp 157533965Sjdp switch (kind) 157633965Sjdp { 157733965Sjdp case DEBUG_KIND_STRUCT: 157833965Sjdp t = "struct "; 157933965Sjdp break; 158033965Sjdp case DEBUG_KIND_UNION: 158133965Sjdp t = "union "; 158233965Sjdp break; 158333965Sjdp case DEBUG_KIND_ENUM: 158433965Sjdp t = "enum "; 158533965Sjdp break; 158633965Sjdp case DEBUG_KIND_CLASS: 158733965Sjdp t = "class "; 158833965Sjdp break; 158933965Sjdp case DEBUG_KIND_UNION_CLASS: 159033965Sjdp t = "union class "; 159133965Sjdp break; 159233965Sjdp default: 159333965Sjdp abort (); 1594130561Sobrien return FALSE; 159533965Sjdp } 159633965Sjdp 159733965Sjdp if (! push_type (info, t)) 1598130561Sobrien return FALSE; 159933965Sjdp if (name != NULL) 160033965Sjdp tag = name; 160133965Sjdp else 160233965Sjdp { 160333965Sjdp sprintf (idbuf, "%%anon%u", id); 160433965Sjdp tag = idbuf; 160533965Sjdp } 160633965Sjdp 160733965Sjdp if (! append_type (info, tag)) 1608130561Sobrien return FALSE; 160933965Sjdp if (name != NULL && kind != DEBUG_KIND_ENUM) 161033965Sjdp { 161133965Sjdp sprintf (idbuf, " /* id %u */", id); 161233965Sjdp if (! append_type (info, idbuf)) 1613130561Sobrien return FALSE; 161433965Sjdp } 161533965Sjdp 1616130561Sobrien return TRUE; 161733965Sjdp} 161833965Sjdp 161933965Sjdp/* Output a typedef. */ 162033965Sjdp 1621130561Sobrienstatic bfd_boolean 1622130561Sobrienpr_typdef (void *p, const char *name) 162333965Sjdp{ 162433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 162533965Sjdp char *s; 162633965Sjdp 162733965Sjdp if (! substitute_type (info, name)) 1628130561Sobrien return FALSE; 162933965Sjdp 163033965Sjdp s = pop_type (info); 163133965Sjdp if (s == NULL) 1632130561Sobrien return FALSE; 163333965Sjdp 163433965Sjdp indent (info); 163533965Sjdp fprintf (info->f, "typedef %s;\n", s); 163633965Sjdp 163733965Sjdp free (s); 163833965Sjdp 1639130561Sobrien return TRUE; 164033965Sjdp} 164133965Sjdp 164233965Sjdp/* Output a tag. The tag should already be in the string on the 164333965Sjdp stack, so all we have to do here is print it out. */ 164433965Sjdp 1645130561Sobrienstatic bfd_boolean 1646130561Sobrienpr_tag (void *p, const char *name ATTRIBUTE_UNUSED) 164733965Sjdp{ 164833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 164933965Sjdp char *t; 165033965Sjdp 165133965Sjdp t = pop_type (info); 165233965Sjdp if (t == NULL) 1653130561Sobrien return FALSE; 165433965Sjdp 165533965Sjdp indent (info); 165633965Sjdp fprintf (info->f, "%s;\n", t); 165733965Sjdp 165833965Sjdp free (t); 165933965Sjdp 1660130561Sobrien return TRUE; 166133965Sjdp} 166233965Sjdp 166333965Sjdp/* Output an integer constant. */ 166433965Sjdp 1665130561Sobrienstatic bfd_boolean 1666130561Sobrienpr_int_constant (void *p, const char *name, bfd_vma val) 166733965Sjdp{ 166833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 166933965Sjdp char ab[20]; 167033965Sjdp 167133965Sjdp indent (info); 1672130561Sobrien print_vma (val, ab, FALSE, FALSE); 167333965Sjdp fprintf (info->f, "const int %s = %s;\n", name, ab); 1674130561Sobrien return TRUE; 167533965Sjdp} 167633965Sjdp 167733965Sjdp/* Output a floating point constant. */ 167833965Sjdp 1679130561Sobrienstatic bfd_boolean 1680130561Sobrienpr_float_constant (void *p, const char *name, double val) 168133965Sjdp{ 168233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 168333965Sjdp 168433965Sjdp indent (info); 168533965Sjdp fprintf (info->f, "const double %s = %g;\n", name, val); 1686130561Sobrien return TRUE; 168733965Sjdp} 168833965Sjdp 168933965Sjdp/* Output a typed constant. */ 169033965Sjdp 1691130561Sobrienstatic bfd_boolean 1692130561Sobrienpr_typed_constant (void *p, const char *name, bfd_vma val) 169333965Sjdp{ 169433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 169533965Sjdp char *t; 169633965Sjdp char ab[20]; 169733965Sjdp 169833965Sjdp t = pop_type (info); 169933965Sjdp if (t == NULL) 1700130561Sobrien return FALSE; 170133965Sjdp 170233965Sjdp indent (info); 1703130561Sobrien print_vma (val, ab, FALSE, FALSE); 170433965Sjdp fprintf (info->f, "const %s %s = %s;\n", t, name, ab); 170533965Sjdp 170633965Sjdp free (t); 170733965Sjdp 1708130561Sobrien return TRUE; 170933965Sjdp} 171033965Sjdp 171133965Sjdp/* Output a variable. */ 171233965Sjdp 1713130561Sobrienstatic bfd_boolean 1714130561Sobrienpr_variable (void *p, const char *name, enum debug_var_kind kind, 1715130561Sobrien bfd_vma val) 171633965Sjdp{ 171733965Sjdp struct pr_handle *info = (struct pr_handle *) p; 171833965Sjdp char *t; 171933965Sjdp char ab[20]; 172033965Sjdp 172133965Sjdp if (! substitute_type (info, name)) 1722130561Sobrien return FALSE; 172333965Sjdp 172433965Sjdp t = pop_type (info); 172533965Sjdp if (t == NULL) 1726130561Sobrien return FALSE; 172733965Sjdp 172833965Sjdp indent (info); 172933965Sjdp switch (kind) 173033965Sjdp { 173133965Sjdp case DEBUG_STATIC: 173233965Sjdp case DEBUG_LOCAL_STATIC: 173333965Sjdp fprintf (info->f, "static "); 173433965Sjdp break; 173533965Sjdp case DEBUG_REGISTER: 173633965Sjdp fprintf (info->f, "register "); 173733965Sjdp break; 173833965Sjdp default: 173933965Sjdp break; 174033965Sjdp } 1741130561Sobrien print_vma (val, ab, TRUE, TRUE); 174233965Sjdp fprintf (info->f, "%s /* %s */;\n", t, ab); 174333965Sjdp 174433965Sjdp free (t); 174533965Sjdp 1746130561Sobrien return TRUE; 174733965Sjdp} 174833965Sjdp 174933965Sjdp/* Start outputting a function. */ 175033965Sjdp 1751130561Sobrienstatic bfd_boolean 1752130561Sobrienpr_start_function (void *p, const char *name, bfd_boolean global) 175333965Sjdp{ 175433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 175533965Sjdp char *t; 175633965Sjdp 175733965Sjdp if (! substitute_type (info, name)) 1758130561Sobrien return FALSE; 175933965Sjdp 176033965Sjdp t = pop_type (info); 176133965Sjdp if (t == NULL) 1762130561Sobrien return FALSE; 176333965Sjdp 176433965Sjdp indent (info); 176533965Sjdp if (! global) 176633965Sjdp fprintf (info->f, "static "); 176733965Sjdp fprintf (info->f, "%s (", t); 176833965Sjdp 176933965Sjdp info->parameter = 1; 177033965Sjdp 1771130561Sobrien return TRUE; 177233965Sjdp} 177333965Sjdp 177433965Sjdp/* Output a function parameter. */ 177533965Sjdp 1776130561Sobrienstatic bfd_boolean 1777130561Sobrienpr_function_parameter (void *p, const char *name, 1778130561Sobrien enum debug_parm_kind kind, bfd_vma val) 177933965Sjdp{ 178033965Sjdp struct pr_handle *info = (struct pr_handle *) p; 178133965Sjdp char *t; 178233965Sjdp char ab[20]; 178333965Sjdp 178433965Sjdp if (kind == DEBUG_PARM_REFERENCE 178533965Sjdp || kind == DEBUG_PARM_REF_REG) 178633965Sjdp { 178733965Sjdp if (! pr_reference_type (p)) 1788130561Sobrien return FALSE; 178933965Sjdp } 179033965Sjdp 179133965Sjdp if (! substitute_type (info, name)) 1792130561Sobrien return FALSE; 179333965Sjdp 179433965Sjdp t = pop_type (info); 179533965Sjdp if (t == NULL) 1796130561Sobrien return FALSE; 179733965Sjdp 179833965Sjdp if (info->parameter != 1) 179933965Sjdp fprintf (info->f, ", "); 180033965Sjdp 180133965Sjdp if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) 180233965Sjdp fprintf (info->f, "register "); 180333965Sjdp 1804130561Sobrien print_vma (val, ab, TRUE, TRUE); 180533965Sjdp fprintf (info->f, "%s /* %s */", t, ab); 180633965Sjdp 180733965Sjdp free (t); 180833965Sjdp 180933965Sjdp ++info->parameter; 181033965Sjdp 1811130561Sobrien return TRUE; 181233965Sjdp} 181333965Sjdp 181433965Sjdp/* Start writing out a block. */ 181533965Sjdp 1816130561Sobrienstatic bfd_boolean 1817130561Sobrienpr_start_block (void *p, bfd_vma addr) 181833965Sjdp{ 181933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 182033965Sjdp char ab[20]; 182133965Sjdp 182233965Sjdp if (info->parameter > 0) 182333965Sjdp { 182433965Sjdp fprintf (info->f, ")\n"); 182533965Sjdp info->parameter = 0; 182633965Sjdp } 182733965Sjdp 182833965Sjdp indent (info); 1829130561Sobrien print_vma (addr, ab, TRUE, TRUE); 183033965Sjdp fprintf (info->f, "{ /* %s */\n", ab); 183133965Sjdp 183233965Sjdp info->indent += 2; 183333965Sjdp 1834130561Sobrien return TRUE; 183533965Sjdp} 183633965Sjdp 183733965Sjdp/* Write out line number information. */ 183833965Sjdp 1839130561Sobrienstatic bfd_boolean 1840130561Sobrienpr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr) 184133965Sjdp{ 184233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 184333965Sjdp char ab[20]; 184433965Sjdp 184533965Sjdp indent (info); 1846130561Sobrien print_vma (addr, ab, TRUE, TRUE); 184733965Sjdp fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab); 184833965Sjdp 1849130561Sobrien return TRUE; 185033965Sjdp} 185133965Sjdp 185233965Sjdp/* Finish writing out a block. */ 185333965Sjdp 1854130561Sobrienstatic bfd_boolean 1855130561Sobrienpr_end_block (void *p, bfd_vma addr) 185633965Sjdp{ 185733965Sjdp struct pr_handle *info = (struct pr_handle *) p; 185833965Sjdp char ab[20]; 185933965Sjdp 186033965Sjdp info->indent -= 2; 186133965Sjdp 186233965Sjdp indent (info); 1863130561Sobrien print_vma (addr, ab, TRUE, TRUE); 186433965Sjdp fprintf (info->f, "} /* %s */\n", ab); 186533965Sjdp 1866130561Sobrien return TRUE; 186733965Sjdp} 186833965Sjdp 186933965Sjdp/* Finish writing out a function. */ 187033965Sjdp 1871130561Sobrienstatic bfd_boolean 1872130561Sobrienpr_end_function (void *p ATTRIBUTE_UNUSED) 187333965Sjdp{ 1874130561Sobrien return TRUE; 187533965Sjdp} 1876130561Sobrien 1877130561Sobrien/* Tags style generation functions start here. */ 1878130561Sobrien 1879130561Sobrien/* Variables for address to line translation. */ 1880130561Sobrienstatic bfd_vma pc; 1881130561Sobrienstatic const char *filename; 1882130561Sobrienstatic const char *functionname; 1883130561Sobrienstatic unsigned int line; 1884130561Sobrienstatic bfd_boolean found; 1885130561Sobrien 1886130561Sobrien/* Look for an address in a section. This is called via 1887130561Sobrien bfd_map_over_sections. */ 1888130561Sobrien 1889130561Sobrienstatic void 1890130561Sobrienfind_address_in_section (bfd *abfd, asection *section, void *data) 1891130561Sobrien{ 1892130561Sobrien bfd_vma vma; 1893130561Sobrien bfd_size_type size; 1894130561Sobrien asymbol **syms = (asymbol **) data; 1895130561Sobrien 1896130561Sobrien if (found) 1897130561Sobrien return; 1898130561Sobrien 1899130561Sobrien if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) 1900130561Sobrien return; 1901130561Sobrien 1902130561Sobrien vma = bfd_get_section_vma (abfd, section); 1903130561Sobrien if (pc < vma) 1904130561Sobrien return; 1905130561Sobrien 1906218822Sdim size = bfd_get_section_size (section); 1907130561Sobrien if (pc >= vma + size) 1908130561Sobrien return; 1909130561Sobrien 1910130561Sobrien found = bfd_find_nearest_line (abfd, section, syms, pc - vma, 1911130561Sobrien &filename, &functionname, &line); 1912130561Sobrien} 1913130561Sobrien 1914130561Sobrienstatic void 1915130561Sobrientranslate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms) 1916130561Sobrien{ 1917130561Sobrien pc = bfd_scan_vma (addr_hex, NULL, 16); 1918130561Sobrien found = FALSE; 1919130561Sobrien bfd_map_over_sections (abfd, find_address_in_section, syms); 1920130561Sobrien 1921130561Sobrien if (! found) 1922130561Sobrien fprintf (f, "??"); 1923130561Sobrien else 1924130561Sobrien fprintf (f, "%u", line); 1925130561Sobrien} 1926130561Sobrien 1927130561Sobrien/* Start a new compilation unit. */ 1928130561Sobrien 1929130561Sobrienstatic bfd_boolean 1930130561Sobrientg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED) 1931130561Sobrien{ 1932130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1933130561Sobrien 1934130561Sobrien fprintf (stderr, "New compilation unit: %s\n", filename); 1935130561Sobrien 1936130561Sobrien free (info->filename); 1937130561Sobrien /* Should it be relative? best way to do it here?. */ 1938130561Sobrien info->filename = strdup (filename); 1939130561Sobrien 1940130561Sobrien return TRUE; 1941130561Sobrien} 1942130561Sobrien 1943130561Sobrien/* Start a source file within a compilation unit. */ 1944130561Sobrien 1945130561Sobrienstatic bfd_boolean 1946130561Sobrientg_start_source (void *p, const char *filename) 1947130561Sobrien{ 1948130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1949130561Sobrien 1950130561Sobrien free (info->filename); 1951130561Sobrien /* Should it be relative? best way to do it here?. */ 1952130561Sobrien info->filename = strdup (filename); 1953130561Sobrien 1954130561Sobrien return TRUE; 1955130561Sobrien} 1956130561Sobrien 1957130561Sobrien/* Push an enum type onto the type stack. */ 1958130561Sobrien 1959130561Sobrienstatic bfd_boolean 1960130561Sobrientg_enum_type (void *p, const char *tag, const char **names, 1961130561Sobrien bfd_signed_vma *values) 1962130561Sobrien{ 1963130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1964130561Sobrien unsigned int i; 1965130561Sobrien const char *name; 1966130561Sobrien char ab[20]; 1967130561Sobrien 1968130561Sobrien if (! pr_enum_type (p, tag, names, values)) 1969130561Sobrien return FALSE; 1970130561Sobrien 1971130561Sobrien name = tag ? tag : "unknown"; 1972130561Sobrien /* Generate an entry for the enum. */ 1973130561Sobrien if (tag) 1974130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag, 1975130561Sobrien info->filename, info->stack->type); 1976130561Sobrien 1977130561Sobrien /* Generate entries for the values. */ 1978130561Sobrien if (names != NULL) 1979130561Sobrien { 1980130561Sobrien for (i = 0; names[i] != NULL; i++) 1981130561Sobrien { 1982130561Sobrien print_vma (values[i], ab, FALSE, FALSE); 1983130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n", 1984130561Sobrien names[i], info->filename, name, ab); 1985130561Sobrien } 1986130561Sobrien } 1987130561Sobrien 1988130561Sobrien return TRUE; 1989130561Sobrien} 1990130561Sobrien 1991130561Sobrien/* Start accumulating a struct type. */ 1992130561Sobrien 1993130561Sobrienstatic bfd_boolean 1994130561Sobrientg_start_struct_type (void *p, const char *tag, unsigned int id, 1995130561Sobrien bfd_boolean structp, 1996130561Sobrien unsigned int size ATTRIBUTE_UNUSED) 1997130561Sobrien{ 1998130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1999130561Sobrien const char *name; 2000130561Sobrien char idbuf[20]; 2001130561Sobrien 2002130561Sobrien if (tag != NULL) 2003130561Sobrien name = tag; 2004130561Sobrien else 2005130561Sobrien { 2006130561Sobrien name = idbuf; 2007130561Sobrien sprintf (idbuf, "%%anon%u", id); 2008130561Sobrien } 2009130561Sobrien 2010130561Sobrien if (! push_type (info, name)) 2011130561Sobrien return FALSE; 2012130561Sobrien 2013130561Sobrien info->stack->flavor = structp ? "struct" : "union"; 2014130561Sobrien 2015130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename, 2016130561Sobrien info->stack->flavor[0]); 2017130561Sobrien 2018130561Sobrien info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; 2019130561Sobrien 2020130561Sobrien return indent_type (info); 2021130561Sobrien} 2022130561Sobrien 2023130561Sobrien/* Output the visibility of a field in a struct. */ 2024130561Sobrien 2025130561Sobrienstatic bfd_boolean 2026130561Sobrientg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) 2027130561Sobrien{ 2028130561Sobrien assert (info->stack != NULL); 2029130561Sobrien 2030130561Sobrien if (info->stack->visibility == visibility) 2031130561Sobrien return TRUE; 2032130561Sobrien 2033130561Sobrien assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); 2034130561Sobrien 2035130561Sobrien info->stack->visibility = visibility; 2036130561Sobrien 2037130561Sobrien return TRUE; 2038130561Sobrien} 2039130561Sobrien 2040130561Sobrien/* Add a field to a struct type. */ 2041130561Sobrien 2042130561Sobrienstatic bfd_boolean 2043130561Sobrientg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED, 2044130561Sobrien bfd_vma bitsize ATTRIBUTE_UNUSED, 2045130561Sobrien enum debug_visibility visibility) 2046130561Sobrien{ 2047130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2048130561Sobrien char *t; 2049130561Sobrien 2050130561Sobrien t = pop_type (info); 2051130561Sobrien if (t == NULL) 2052130561Sobrien return FALSE; 2053130561Sobrien 2054130561Sobrien if (! tg_fix_visibility (info, visibility)) 2055130561Sobrien return FALSE; 2056130561Sobrien 2057130561Sobrien /* It happens, a bug? */ 2058130561Sobrien if (! name[0]) 2059130561Sobrien return TRUE; 2060130561Sobrien 2061130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n", 2062130561Sobrien name, info->filename, t, info->stack->flavor, info->stack->type, 2063130561Sobrien visibility_name (visibility)); 2064130561Sobrien 2065130561Sobrien return TRUE; 2066130561Sobrien} 2067130561Sobrien 2068130561Sobrien/* Finish a struct type. */ 2069130561Sobrien 2070130561Sobrienstatic bfd_boolean 2071130561Sobrientg_end_struct_type (void *p ATTRIBUTE_UNUSED) 2072130561Sobrien{ 2073130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2074130561Sobrien assert (info->stack != NULL); 2075130561Sobrien 2076130561Sobrien return TRUE; 2077130561Sobrien} 2078130561Sobrien 2079130561Sobrien/* Start a class type. */ 2080130561Sobrien 2081130561Sobrienstatic bfd_boolean 2082130561Sobrientg_start_class_type (void *p, const char *tag, unsigned int id, 2083130561Sobrien bfd_boolean structp, unsigned int size, 2084130561Sobrien bfd_boolean vptr, bfd_boolean ownvptr) 2085130561Sobrien{ 2086130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2087130561Sobrien char *tv = NULL; 2088130561Sobrien const char *name; 2089130561Sobrien 2090130561Sobrien info->indent += 2; 2091130561Sobrien 2092130561Sobrien if (vptr && ! ownvptr) 2093130561Sobrien { 2094130561Sobrien tv = pop_type (info); 2095130561Sobrien if (tv == NULL) 2096130561Sobrien return FALSE; 2097130561Sobrien } 2098130561Sobrien 2099130561Sobrien if (tag != NULL) 2100130561Sobrien name = tag; 2101130561Sobrien else 2102130561Sobrien { 2103130561Sobrien char idbuf[20]; 2104130561Sobrien 2105130561Sobrien sprintf (idbuf, "%%anon%u", id); 2106130561Sobrien name = idbuf; 2107130561Sobrien } 2108130561Sobrien 2109130561Sobrien if (! push_type (info, name)) 2110130561Sobrien return FALSE; 2111130561Sobrien 2112130561Sobrien info->stack->flavor = structp ? "class" : "union class"; 2113130561Sobrien info->stack->parents = NULL; 2114130561Sobrien info->stack->num_parents = 0; 2115130561Sobrien 2116130561Sobrien if (size != 0 || vptr || ownvptr || tag != NULL) 2117130561Sobrien { 2118130561Sobrien if (vptr) 2119130561Sobrien { 2120130561Sobrien if (! append_type (info, " vtable ")) 2121130561Sobrien return FALSE; 2122130561Sobrien if (ownvptr) 2123130561Sobrien { 2124130561Sobrien if (! append_type (info, "self ")) 2125130561Sobrien return FALSE; 2126130561Sobrien } 2127130561Sobrien else 2128130561Sobrien { 2129130561Sobrien if (! append_type (info, tv) 2130130561Sobrien || ! append_type (info, " ")) 2131130561Sobrien return FALSE; 2132130561Sobrien } 2133130561Sobrien } 2134130561Sobrien } 2135130561Sobrien 2136130561Sobrien info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; 2137130561Sobrien 2138130561Sobrien return TRUE; 2139130561Sobrien} 2140130561Sobrien 2141130561Sobrien/* Add a static member to a class. */ 2142130561Sobrien 2143130561Sobrienstatic bfd_boolean 2144130561Sobrientg_class_static_member (void *p, const char *name, 2145130561Sobrien const char *physname ATTRIBUTE_UNUSED, 2146130561Sobrien enum debug_visibility visibility) 2147130561Sobrien{ 2148130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2149130561Sobrien char *t; 2150130561Sobrien int len_var, len_class; 2151130561Sobrien char *full_name; 2152130561Sobrien 2153130561Sobrien len_var = strlen (name); 2154130561Sobrien len_class = strlen (info->stack->next->type); 2155218822Sdim full_name = xmalloc (len_var + len_class + 3); 2156130561Sobrien if (! full_name) 2157130561Sobrien return FALSE; 2158218822Sdim sprintf (full_name, "%s::%s", info->stack->next->type, name); 2159130561Sobrien 2160130561Sobrien if (! substitute_type (info, full_name)) 2161130561Sobrien return FALSE; 2162130561Sobrien 2163130561Sobrien if (! prepend_type (info, "static ")) 2164130561Sobrien return FALSE; 2165130561Sobrien 2166130561Sobrien t = pop_type (info); 2167130561Sobrien if (t == NULL) 2168130561Sobrien return FALSE; 2169130561Sobrien 2170130561Sobrien if (! tg_fix_visibility (info, visibility)) 2171130561Sobrien return FALSE; 2172130561Sobrien 2173130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n", 2174130561Sobrien name, info->filename, t, info->stack->type, 2175130561Sobrien visibility_name (visibility)); 2176130561Sobrien free (t); 2177130561Sobrien free (full_name); 2178130561Sobrien 2179130561Sobrien return TRUE; 2180130561Sobrien} 2181130561Sobrien 2182130561Sobrien/* Add a base class to a class. */ 2183130561Sobrien 2184130561Sobrienstatic bfd_boolean 2185130561Sobrientg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED, 2186130561Sobrien bfd_boolean virtual, enum debug_visibility visibility) 2187130561Sobrien{ 2188130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2189130561Sobrien char *t; 2190130561Sobrien const char *prefix; 2191130561Sobrien 2192130561Sobrien assert (info->stack != NULL && info->stack->next != NULL); 2193130561Sobrien 2194130561Sobrien t = pop_type (info); 2195130561Sobrien if (t == NULL) 2196130561Sobrien return FALSE; 2197130561Sobrien 2198218822Sdim if (CONST_STRNEQ (t, "class ")) 2199130561Sobrien t += sizeof "class " - 1; 2200130561Sobrien 2201130561Sobrien /* Push it back on to take advantage of the prepend_type and 2202130561Sobrien append_type routines. */ 2203130561Sobrien if (! push_type (info, t)) 2204130561Sobrien return FALSE; 2205130561Sobrien 2206130561Sobrien if (virtual) 2207130561Sobrien { 2208130561Sobrien if (! prepend_type (info, "virtual ")) 2209130561Sobrien return FALSE; 2210130561Sobrien } 2211130561Sobrien 2212130561Sobrien switch (visibility) 2213130561Sobrien { 2214130561Sobrien case DEBUG_VISIBILITY_PUBLIC: 2215130561Sobrien prefix = "public "; 2216130561Sobrien break; 2217130561Sobrien case DEBUG_VISIBILITY_PROTECTED: 2218130561Sobrien prefix = "protected "; 2219130561Sobrien break; 2220130561Sobrien case DEBUG_VISIBILITY_PRIVATE: 2221130561Sobrien prefix = "private "; 2222130561Sobrien break; 2223130561Sobrien default: 2224130561Sobrien prefix = "/* unknown visibility */ "; 2225130561Sobrien break; 2226130561Sobrien } 2227130561Sobrien 2228130561Sobrien if (! prepend_type (info, prefix)) 2229130561Sobrien return FALSE; 2230130561Sobrien 2231130561Sobrien t = pop_type (info); 2232130561Sobrien if (t == NULL) 2233130561Sobrien return FALSE; 2234130561Sobrien 2235130561Sobrien if (info->stack->num_parents && ! append_parent (info, ", ")) 2236130561Sobrien return FALSE; 2237130561Sobrien 2238130561Sobrien if (! append_parent (info, t)) 2239130561Sobrien return FALSE; 2240130561Sobrien info->stack->num_parents++; 2241130561Sobrien 2242130561Sobrien free (t); 2243130561Sobrien 2244130561Sobrien return TRUE; 2245130561Sobrien} 2246130561Sobrien 2247130561Sobrien/* Add a variant to a method. */ 2248130561Sobrien 2249130561Sobrienstatic bfd_boolean 2250130561Sobrientg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED, 2251130561Sobrien enum debug_visibility visibility, 2252130561Sobrien bfd_boolean constp, bfd_boolean volatilep, 2253130561Sobrien bfd_vma voffset ATTRIBUTE_UNUSED, 2254130561Sobrien bfd_boolean context) 2255130561Sobrien{ 2256130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2257130561Sobrien char *method_type; 2258130561Sobrien char *context_type; 2259130561Sobrien char *method_name; 2260130561Sobrien 2261130561Sobrien assert (info->stack != NULL); 2262130561Sobrien assert (info->stack->next != NULL); 2263130561Sobrien 2264130561Sobrien /* Put the const and volatile qualifiers on the type. */ 2265130561Sobrien if (volatilep) 2266130561Sobrien { 2267130561Sobrien if (! append_type (info, " volatile")) 2268130561Sobrien return FALSE; 2269130561Sobrien } 2270130561Sobrien if (constp) 2271130561Sobrien { 2272130561Sobrien if (! append_type (info, " const")) 2273130561Sobrien return FALSE; 2274130561Sobrien } 2275130561Sobrien 2276130561Sobrien method_name = strdup (context ? info->stack->next->next->method 2277130561Sobrien : info->stack->next->method); 2278130561Sobrien 2279130561Sobrien /* Stick the name of the method into its type. */ 2280130561Sobrien if (! substitute_type (info, method_name)) 2281130561Sobrien return FALSE; 2282130561Sobrien 2283130561Sobrien /* Get the type. */ 2284130561Sobrien method_type = pop_type (info); 2285130561Sobrien if (method_type == NULL) 2286130561Sobrien return FALSE; 2287130561Sobrien 2288130561Sobrien /* Pull off the context type if there is one. */ 2289130561Sobrien if (! context) 2290130561Sobrien context_type = NULL; 2291130561Sobrien else 2292130561Sobrien { 2293130561Sobrien context_type = pop_type (info); 2294130561Sobrien if (context_type == NULL) 2295130561Sobrien return FALSE; 2296130561Sobrien } 2297130561Sobrien 2298130561Sobrien /* Now the top of the stack is the class. */ 2299130561Sobrien if (! tg_fix_visibility (info, visibility)) 2300130561Sobrien return FALSE; 2301130561Sobrien 2302130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n", 2303130561Sobrien method_name, info->filename, method_type, info->stack->type); 2304130561Sobrien free (method_type); 2305130561Sobrien free (method_name); 2306130561Sobrien free (context_type); 2307130561Sobrien 2308130561Sobrien return TRUE; 2309130561Sobrien} 2310130561Sobrien 2311130561Sobrien/* Add a static variant to a method. */ 2312130561Sobrien 2313130561Sobrienstatic bfd_boolean 2314130561Sobrientg_class_static_method_variant (void *p, 2315130561Sobrien const char *physname ATTRIBUTE_UNUSED, 2316130561Sobrien enum debug_visibility visibility, 2317130561Sobrien bfd_boolean constp, bfd_boolean volatilep) 2318130561Sobrien{ 2319130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2320130561Sobrien char *method_type; 2321130561Sobrien char *method_name; 2322130561Sobrien 2323130561Sobrien assert (info->stack != NULL); 2324130561Sobrien assert (info->stack->next != NULL); 2325130561Sobrien assert (info->stack->next->method != NULL); 2326130561Sobrien 2327130561Sobrien /* Put the const and volatile qualifiers on the type. */ 2328130561Sobrien if (volatilep) 2329130561Sobrien { 2330130561Sobrien if (! append_type (info, " volatile")) 2331130561Sobrien return FALSE; 2332130561Sobrien } 2333130561Sobrien if (constp) 2334130561Sobrien { 2335130561Sobrien if (! append_type (info, " const")) 2336130561Sobrien return FALSE; 2337130561Sobrien } 2338130561Sobrien 2339130561Sobrien /* Mark it as static. */ 2340130561Sobrien if (! prepend_type (info, "static ")) 2341130561Sobrien return FALSE; 2342130561Sobrien 2343130561Sobrien method_name = strdup (info->stack->next->method); 2344130561Sobrien /* Stick the name of the method into its type. */ 2345130561Sobrien if (! substitute_type (info, info->stack->next->method)) 2346130561Sobrien return FALSE; 2347130561Sobrien 2348130561Sobrien /* Get the type. */ 2349130561Sobrien method_type = pop_type (info); 2350130561Sobrien if (method_type == NULL) 2351130561Sobrien return FALSE; 2352130561Sobrien 2353130561Sobrien /* Now the top of the stack is the class. */ 2354130561Sobrien if (! tg_fix_visibility (info, visibility)) 2355130561Sobrien return FALSE; 2356130561Sobrien 2357130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n", 2358130561Sobrien method_name, info->filename, method_type, info->stack->type, 2359130561Sobrien visibility_name (visibility)); 2360130561Sobrien free (method_type); 2361130561Sobrien free (method_name); 2362130561Sobrien 2363130561Sobrien return TRUE; 2364130561Sobrien} 2365130561Sobrien 2366130561Sobrien/* Finish up a class. */ 2367130561Sobrien 2368130561Sobrienstatic bfd_boolean 2369130561Sobrientg_end_class_type (void *p) 2370130561Sobrien{ 2371130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2372130561Sobrien 2373130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type, 2374130561Sobrien info->filename, info->stack->flavor); 2375130561Sobrien if (info->stack->num_parents) 2376130561Sobrien { 2377130561Sobrien fprintf (info->f, "\tinherits:%s", info->stack->parents); 2378130561Sobrien free (info->stack->parents); 2379130561Sobrien } 2380130561Sobrien fputc ('\n', info->f); 2381130561Sobrien 2382130561Sobrien return tg_end_struct_type (p); 2383130561Sobrien} 2384130561Sobrien 2385130561Sobrien/* Push a type on the stack using a tag name. */ 2386130561Sobrien 2387130561Sobrienstatic bfd_boolean 2388130561Sobrientg_tag_type (void *p, const char *name, unsigned int id, 2389130561Sobrien enum debug_type_kind kind) 2390130561Sobrien{ 2391130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2392130561Sobrien const char *t, *tag; 2393130561Sobrien char idbuf[20]; 2394130561Sobrien 2395130561Sobrien switch (kind) 2396130561Sobrien { 2397130561Sobrien case DEBUG_KIND_STRUCT: 2398130561Sobrien t = "struct "; 2399130561Sobrien break; 2400130561Sobrien case DEBUG_KIND_UNION: 2401130561Sobrien t = "union "; 2402130561Sobrien break; 2403130561Sobrien case DEBUG_KIND_ENUM: 2404130561Sobrien t = "enum "; 2405130561Sobrien break; 2406130561Sobrien case DEBUG_KIND_CLASS: 2407130561Sobrien t = "class "; 2408130561Sobrien break; 2409130561Sobrien case DEBUG_KIND_UNION_CLASS: 2410130561Sobrien t = "union class "; 2411130561Sobrien break; 2412130561Sobrien default: 2413130561Sobrien abort (); 2414130561Sobrien return FALSE; 2415130561Sobrien } 2416130561Sobrien 2417130561Sobrien if (! push_type (info, t)) 2418130561Sobrien return FALSE; 2419130561Sobrien if (name != NULL) 2420130561Sobrien tag = name; 2421130561Sobrien else 2422130561Sobrien { 2423130561Sobrien sprintf (idbuf, "%%anon%u", id); 2424130561Sobrien tag = idbuf; 2425130561Sobrien } 2426130561Sobrien 2427130561Sobrien if (! append_type (info, tag)) 2428130561Sobrien return FALSE; 2429130561Sobrien 2430130561Sobrien return TRUE; 2431130561Sobrien} 2432130561Sobrien 2433130561Sobrien/* Output a typedef. */ 2434130561Sobrien 2435130561Sobrienstatic bfd_boolean 2436130561Sobrientg_typdef (void *p, const char *name) 2437130561Sobrien{ 2438130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2439130561Sobrien char *s; 2440130561Sobrien 2441130561Sobrien s = pop_type (info); 2442130561Sobrien if (s == NULL) 2443130561Sobrien return FALSE; 2444130561Sobrien 2445130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name, 2446130561Sobrien info->filename, s); 2447130561Sobrien 2448130561Sobrien free (s); 2449130561Sobrien 2450130561Sobrien return TRUE; 2451130561Sobrien} 2452130561Sobrien 2453130561Sobrien/* Output a tag. The tag should already be in the string on the 2454130561Sobrien stack, so all we have to do here is print it out. */ 2455130561Sobrien 2456130561Sobrienstatic bfd_boolean 2457130561Sobrientg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED) 2458130561Sobrien{ 2459130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2460130561Sobrien char *t; 2461130561Sobrien 2462130561Sobrien t = pop_type (info); 2463130561Sobrien if (t == NULL) 2464130561Sobrien return FALSE; 2465130561Sobrien free (t); 2466130561Sobrien 2467130561Sobrien return TRUE; 2468130561Sobrien} 2469130561Sobrien 2470130561Sobrien/* Output an integer constant. */ 2471130561Sobrien 2472130561Sobrienstatic bfd_boolean 2473130561Sobrientg_int_constant (void *p, const char *name, bfd_vma val) 2474130561Sobrien{ 2475130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2476130561Sobrien char ab[20]; 2477130561Sobrien 2478130561Sobrien indent (info); 2479130561Sobrien print_vma (val, ab, FALSE, FALSE); 2480130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n", 2481130561Sobrien name, info->filename, ab); 2482130561Sobrien return TRUE; 2483130561Sobrien} 2484130561Sobrien 2485130561Sobrien/* Output a floating point constant. */ 2486130561Sobrien 2487130561Sobrienstatic bfd_boolean 2488130561Sobrientg_float_constant (void *p, const char *name, double val) 2489130561Sobrien{ 2490130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2491130561Sobrien 2492130561Sobrien indent (info); 2493130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n", 2494130561Sobrien name, info->filename, val); 2495130561Sobrien return TRUE; 2496130561Sobrien} 2497130561Sobrien 2498130561Sobrien/* Output a typed constant. */ 2499130561Sobrien 2500130561Sobrienstatic bfd_boolean 2501130561Sobrientg_typed_constant (void *p, const char *name, bfd_vma val) 2502130561Sobrien{ 2503130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2504130561Sobrien char *t; 2505130561Sobrien char ab[20]; 2506130561Sobrien 2507130561Sobrien t = pop_type (info); 2508130561Sobrien if (t == NULL) 2509130561Sobrien return FALSE; 2510130561Sobrien 2511130561Sobrien indent (info); 2512130561Sobrien print_vma (val, ab, FALSE, FALSE); 2513130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n", 2514130561Sobrien name, info->filename, t, ab); 2515130561Sobrien 2516130561Sobrien free (t); 2517130561Sobrien 2518130561Sobrien return TRUE; 2519130561Sobrien} 2520130561Sobrien 2521130561Sobrien/* Output a variable. */ 2522130561Sobrien 2523130561Sobrienstatic bfd_boolean 2524130561Sobrientg_variable (void *p, const char *name, enum debug_var_kind kind, 2525130561Sobrien bfd_vma val ATTRIBUTE_UNUSED) 2526130561Sobrien{ 2527130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2528218822Sdim char *t, *dname, *from_class; 2529130561Sobrien 2530130561Sobrien t = pop_type (info); 2531130561Sobrien if (t == NULL) 2532130561Sobrien return FALSE; 2533130561Sobrien 2534218822Sdim dname = NULL; 2535130561Sobrien if (info->demangler) 2536218822Sdim dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS); 2537130561Sobrien 2538218822Sdim from_class = NULL; 2539218822Sdim if (dname != NULL) 2540130561Sobrien { 2541130561Sobrien char *sep; 2542130561Sobrien sep = strstr (dname, "::"); 2543130561Sobrien if (sep) 2544130561Sobrien { 2545130561Sobrien *sep = 0; 2546130561Sobrien name = sep + 2; 2547130561Sobrien from_class = dname; 2548130561Sobrien } 2549130561Sobrien else 2550218822Sdim /* Obscure types as vts and type_info nodes. */ 2551218822Sdim name = dname; 2552130561Sobrien } 2553130561Sobrien 2554130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t); 2555130561Sobrien 2556130561Sobrien switch (kind) 2557130561Sobrien { 2558130561Sobrien case DEBUG_STATIC: 2559130561Sobrien case DEBUG_LOCAL_STATIC: 2560130561Sobrien fprintf (info->f, "\tfile:"); 2561130561Sobrien break; 2562130561Sobrien case DEBUG_REGISTER: 2563130561Sobrien fprintf (info->f, "\tregister:"); 2564130561Sobrien break; 2565130561Sobrien default: 2566130561Sobrien break; 2567130561Sobrien } 2568130561Sobrien 2569130561Sobrien if (from_class) 2570218822Sdim fprintf (info->f, "\tclass:%s", from_class); 2571130561Sobrien 2572218822Sdim if (dname) 2573218822Sdim free (dname); 2574218822Sdim 2575130561Sobrien fprintf (info->f, "\n"); 2576130561Sobrien 2577130561Sobrien free (t); 2578130561Sobrien 2579130561Sobrien return TRUE; 2580130561Sobrien} 2581130561Sobrien 2582130561Sobrien/* Start outputting a function. */ 2583130561Sobrien 2584130561Sobrienstatic bfd_boolean 2585130561Sobrientg_start_function (void *p, const char *name, bfd_boolean global) 2586130561Sobrien{ 2587130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2588218822Sdim char *dname; 2589130561Sobrien 2590130561Sobrien if (! global) 2591130561Sobrien info->stack->flavor = "static"; 2592130561Sobrien else 2593130561Sobrien info->stack->flavor = NULL; 2594130561Sobrien 2595218822Sdim dname = NULL; 2596130561Sobrien if (info->demangler) 2597218822Sdim dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS); 2598130561Sobrien 2599218822Sdim if (! substitute_type (info, dname ? dname : name)) 2600130561Sobrien return FALSE; 2601130561Sobrien 2602218822Sdim info->stack->method = NULL; 2603218822Sdim if (dname != NULL) 2604130561Sobrien { 2605130561Sobrien char *sep; 2606130561Sobrien sep = strstr (dname, "::"); 2607130561Sobrien if (sep) 2608130561Sobrien { 2609130561Sobrien info->stack->method = dname; 2610130561Sobrien *sep = 0; 2611130561Sobrien name = sep + 2; 2612130561Sobrien } 2613130561Sobrien else 2614130561Sobrien { 2615130561Sobrien info->stack->method = ""; 2616130561Sobrien name = dname; 2617130561Sobrien } 2618130561Sobrien sep = strchr (name, '('); 2619130561Sobrien if (sep) 2620130561Sobrien *sep = 0; 2621130561Sobrien /* Obscure functions as type_info function. */ 2622130561Sobrien } 2623130561Sobrien 2624130561Sobrien info->stack->parents = strdup (name); 2625130561Sobrien 2626130561Sobrien if (! info->stack->method && ! append_type (info, "(")) 2627130561Sobrien return FALSE; 2628130561Sobrien 2629130561Sobrien info->parameter = 1; 2630130561Sobrien 2631130561Sobrien return TRUE; 2632130561Sobrien} 2633130561Sobrien 2634130561Sobrien/* Output a function parameter. */ 2635130561Sobrien 2636130561Sobrienstatic bfd_boolean 2637130561Sobrientg_function_parameter (void *p, const char *name, enum debug_parm_kind kind, 2638130561Sobrien bfd_vma val ATTRIBUTE_UNUSED) 2639130561Sobrien{ 2640130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2641130561Sobrien char *t; 2642130561Sobrien 2643130561Sobrien if (kind == DEBUG_PARM_REFERENCE 2644130561Sobrien || kind == DEBUG_PARM_REF_REG) 2645130561Sobrien { 2646130561Sobrien if (! pr_reference_type (p)) 2647130561Sobrien return FALSE; 2648130561Sobrien } 2649130561Sobrien 2650130561Sobrien if (! substitute_type (info, name)) 2651130561Sobrien return FALSE; 2652130561Sobrien 2653130561Sobrien t = pop_type (info); 2654130561Sobrien if (t == NULL) 2655130561Sobrien return FALSE; 2656130561Sobrien 2657130561Sobrien if (! info->stack->method) 2658130561Sobrien { 2659130561Sobrien if (info->parameter != 1 && ! append_type (info, ", ")) 2660130561Sobrien return FALSE; 2661130561Sobrien 2662130561Sobrien if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) 2663130561Sobrien if (! append_type (info, "register ")) 2664130561Sobrien return FALSE; 2665130561Sobrien 2666130561Sobrien if (! append_type (info, t)) 2667130561Sobrien return FALSE; 2668130561Sobrien } 2669130561Sobrien 2670130561Sobrien free (t); 2671130561Sobrien 2672130561Sobrien ++info->parameter; 2673130561Sobrien 2674130561Sobrien return TRUE; 2675130561Sobrien} 2676130561Sobrien 2677130561Sobrien/* Start writing out a block. */ 2678130561Sobrien 2679130561Sobrienstatic bfd_boolean 2680130561Sobrientg_start_block (void *p, bfd_vma addr) 2681130561Sobrien{ 2682130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2683130561Sobrien char ab[20], kind, *partof; 2684130561Sobrien char *t; 2685130561Sobrien bfd_boolean local; 2686130561Sobrien 2687130561Sobrien if (info->parameter > 0) 2688130561Sobrien { 2689130561Sobrien info->parameter = 0; 2690130561Sobrien 2691130561Sobrien /* Delayed name. */ 2692130561Sobrien fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename); 2693130561Sobrien free (info->stack->parents); 2694130561Sobrien 2695130561Sobrien print_vma (addr, ab, TRUE, TRUE); 2696130561Sobrien translate_addresses (info->abfd, ab, info->f, info->syms); 2697130561Sobrien local = info->stack->flavor != NULL; 2698130561Sobrien if (info->stack->method && *info->stack->method) 2699130561Sobrien { 2700130561Sobrien kind = 'm'; 2701130561Sobrien partof = (char *) info->stack->method; 2702130561Sobrien } 2703130561Sobrien else 2704130561Sobrien { 2705130561Sobrien kind = 'f'; 2706130561Sobrien partof = NULL; 2707130561Sobrien if (! info->stack->method && ! append_type (info, ")")) 2708130561Sobrien return FALSE; 2709130561Sobrien } 2710130561Sobrien t = pop_type (info); 2711130561Sobrien if (t == NULL) 2712130561Sobrien return FALSE; 2713130561Sobrien fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t); 2714130561Sobrien if (local) 2715130561Sobrien fputs ("\tfile:", info->f); 2716130561Sobrien if (partof) 2717130561Sobrien { 2718130561Sobrien fprintf (info->f, "\tclass:%s", partof); 2719130561Sobrien free (partof); 2720130561Sobrien } 2721130561Sobrien fputc ('\n', info->f); 2722130561Sobrien } 2723130561Sobrien 2724130561Sobrien return TRUE; 2725130561Sobrien} 2726130561Sobrien 2727130561Sobrien/* Write out line number information. */ 2728130561Sobrien 2729130561Sobrienstatic bfd_boolean 2730130561Sobrientg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED, 2731130561Sobrien unsigned long lineno ATTRIBUTE_UNUSED, 2732130561Sobrien bfd_vma addr ATTRIBUTE_UNUSED) 2733130561Sobrien{ 2734130561Sobrien return TRUE; 2735130561Sobrien} 2736130561Sobrien 2737130561Sobrien/* Finish writing out a block. */ 2738130561Sobrien 2739130561Sobrienstatic bfd_boolean 2740130561Sobrientg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED) 2741130561Sobrien{ 2742130561Sobrien return TRUE; 2743130561Sobrien} 2744130561Sobrien 2745130561Sobrien/* Convert the visibility value into a human readable name. */ 2746130561Sobrien 2747130561Sobrienstatic const char * 2748130561Sobrienvisibility_name (enum debug_visibility visibility) 2749130561Sobrien{ 2750130561Sobrien const char *s; 2751130561Sobrien 2752130561Sobrien switch (visibility) 2753130561Sobrien { 2754130561Sobrien case DEBUG_VISIBILITY_PUBLIC: 2755130561Sobrien s = "public"; 2756130561Sobrien break; 2757130561Sobrien case DEBUG_VISIBILITY_PRIVATE: 2758130561Sobrien s = "private"; 2759130561Sobrien break; 2760130561Sobrien case DEBUG_VISIBILITY_PROTECTED: 2761130561Sobrien s = "protected"; 2762130561Sobrien break; 2763130561Sobrien case DEBUG_VISIBILITY_IGNORE: 2764130561Sobrien s = "/* ignore */"; 2765130561Sobrien break; 2766130561Sobrien default: 2767130561Sobrien abort (); 2768130561Sobrien return FALSE; 2769130561Sobrien } 2770130561Sobrien return s; 2771130561Sobrien} 2772