prdbg.c revision 130561
133965Sjdp/* prdbg.c -- Print out generic debugging information. 2130561Sobrien Copyright 1995, 1996, 2002, 2003 Free Software Foundation, Inc. 333965Sjdp Written by Ian Lance Taylor <ian@cygnus.com>. 4130561Sobrien Tags style generation written by Salvador E. Tropea <set@computer.org>. 533965Sjdp 633965Sjdp This file is part of GNU Binutils. 733965Sjdp 833965Sjdp This program is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2 of the License, or 1133965Sjdp (at your option) any later version. 1233965Sjdp 1333965Sjdp This program is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with this program; if not, write to the Free Software 2033965Sjdp Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 2133965Sjdp 02111-1307, USA. */ 2233965Sjdp 2333965Sjdp/* This file prints out the generic debugging information, by 2433965Sjdp supplying a set of routines to debug_write. */ 2533965Sjdp 2633965Sjdp#include <stdio.h> 2733965Sjdp#include <assert.h> 2833965Sjdp 2933965Sjdp#include "bfd.h" 3033965Sjdp#include "bucomm.h" 3133965Sjdp#include "libiberty.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. */ 55130561Sobrien char *(*demangler) (bfd *, const char *); 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 72633965Sjdp s = (char *) xmalloc (len); 72733965Sjdp strcpy (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; 91233965Sjdp if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0 91333965Sjdp && strchr (domain_type + sizeof "class " - 1, ' ') == NULL) 91433965Sjdp domain_type += sizeof "class " - 1; 91533965Sjdp else if (strncmp (domain_type, "union class ", 91633965Sjdp sizeof "union class ") == 0 91733965Sjdp && (strchr (domain_type + sizeof "union class " - 1, ' ') 91833965Sjdp == NULL)) 91933965Sjdp domain_type += sizeof "union class " - 1; 92033965Sjdp len += strlen (domain_type); 92133965Sjdp } 92233965Sjdp 92333965Sjdp if (argcount <= 0) 92433965Sjdp { 92533965Sjdp arg_types = NULL; 92633965Sjdp len += 15; 92733965Sjdp } 92833965Sjdp else 92933965Sjdp { 93033965Sjdp int i; 93133965Sjdp 93233965Sjdp arg_types = (char **) xmalloc (argcount * sizeof *arg_types); 93333965Sjdp for (i = argcount - 1; i >= 0; i--) 93433965Sjdp { 93533965Sjdp if (! substitute_type (info, "")) 936130561Sobrien return FALSE; 93733965Sjdp arg_types[i] = pop_type (info); 93833965Sjdp if (arg_types[i] == NULL) 939130561Sobrien return FALSE; 94033965Sjdp len += strlen (arg_types[i]) + 2; 94133965Sjdp } 94233965Sjdp if (varargs) 94333965Sjdp len += 5; 94433965Sjdp } 94533965Sjdp 94633965Sjdp /* Now the return type is on the top of the stack. */ 94733965Sjdp 94833965Sjdp s = (char *) xmalloc (len); 94933965Sjdp if (! domain) 95033965Sjdp *s = '\0'; 95133965Sjdp else 95233965Sjdp strcpy (s, domain_type); 95333965Sjdp strcat (s, "::| ("); 95433965Sjdp 95533965Sjdp if (argcount < 0) 95633965Sjdp strcat (s, "/* unknown */"); 95733965Sjdp else 95833965Sjdp { 95933965Sjdp int i; 96033965Sjdp 96133965Sjdp for (i = 0; i < argcount; i++) 96233965Sjdp { 96333965Sjdp if (i > 0) 96433965Sjdp strcat (s, ", "); 96533965Sjdp strcat (s, arg_types[i]); 96633965Sjdp } 96733965Sjdp if (varargs) 96833965Sjdp { 96933965Sjdp if (i > 0) 97033965Sjdp strcat (s, ", "); 97133965Sjdp strcat (s, "..."); 97233965Sjdp } 97333965Sjdp if (argcount > 0) 97433965Sjdp free (arg_types); 97533965Sjdp } 97633965Sjdp 97733965Sjdp strcat (s, ")"); 97833965Sjdp 97933965Sjdp if (! substitute_type (info, s)) 980130561Sobrien return FALSE; 98133965Sjdp 98233965Sjdp free (s); 98333965Sjdp 984130561Sobrien return TRUE; 98533965Sjdp} 98633965Sjdp 98733965Sjdp/* Make a const qualified type. */ 98833965Sjdp 989130561Sobrienstatic bfd_boolean 990130561Sobrienpr_const_type (void *p) 99133965Sjdp{ 99233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 99333965Sjdp 99433965Sjdp return substitute_type (info, "const |"); 99533965Sjdp} 99633965Sjdp 99733965Sjdp/* Make a volatile qualified type. */ 99833965Sjdp 999130561Sobrienstatic bfd_boolean 1000130561Sobrienpr_volatile_type (void *p) 100133965Sjdp{ 100233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 100333965Sjdp 100433965Sjdp return substitute_type (info, "volatile |"); 100533965Sjdp} 100633965Sjdp 100733965Sjdp/* Start accumulating a struct type. */ 100833965Sjdp 1009130561Sobrienstatic bfd_boolean 1010130561Sobrienpr_start_struct_type (void *p, const char *tag, unsigned int id, 1011130561Sobrien bfd_boolean structp, unsigned int size) 101233965Sjdp{ 101333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 101433965Sjdp 101533965Sjdp info->indent += 2; 101633965Sjdp 101733965Sjdp if (! push_type (info, structp ? "struct " : "union ")) 1018130561Sobrien return FALSE; 101933965Sjdp if (tag != NULL) 102033965Sjdp { 102133965Sjdp if (! append_type (info, tag)) 1022130561Sobrien return FALSE; 102333965Sjdp } 102433965Sjdp else 102533965Sjdp { 102633965Sjdp char idbuf[20]; 102733965Sjdp 102833965Sjdp sprintf (idbuf, "%%anon%u", id); 102933965Sjdp if (! append_type (info, idbuf)) 1030130561Sobrien return FALSE; 103133965Sjdp } 103233965Sjdp 103333965Sjdp if (! append_type (info, " {")) 1034130561Sobrien return FALSE; 103533965Sjdp if (size != 0 || tag != NULL) 103633965Sjdp { 103733965Sjdp char ab[30]; 103833965Sjdp 103933965Sjdp if (! append_type (info, " /*")) 1040130561Sobrien return FALSE; 104133965Sjdp 104233965Sjdp if (size != 0) 104333965Sjdp { 104433965Sjdp sprintf (ab, " size %u", size); 104533965Sjdp if (! append_type (info, ab)) 1046130561Sobrien return FALSE; 104733965Sjdp } 104833965Sjdp if (tag != NULL) 104933965Sjdp { 105033965Sjdp sprintf (ab, " id %u", id); 105133965Sjdp if (! append_type (info, ab)) 1052130561Sobrien return FALSE; 105333965Sjdp } 105433965Sjdp if (! append_type (info, " */")) 1055130561Sobrien return FALSE; 105633965Sjdp } 105733965Sjdp if (! append_type (info, "\n")) 1058130561Sobrien return FALSE; 105933965Sjdp 106033965Sjdp info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; 106133965Sjdp 106233965Sjdp return indent_type (info); 106333965Sjdp} 106433965Sjdp 106533965Sjdp/* Output the visibility of a field in a struct. */ 106633965Sjdp 1067130561Sobrienstatic bfd_boolean 1068130561Sobrienpr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) 106933965Sjdp{ 107060484Sobrien const char *s = NULL; 107133965Sjdp char *t; 107233965Sjdp unsigned int len; 107333965Sjdp 107433965Sjdp assert (info->stack != NULL); 107533965Sjdp 107633965Sjdp if (info->stack->visibility == visibility) 1077130561Sobrien return TRUE; 107833965Sjdp 107933965Sjdp switch (visibility) 108033965Sjdp { 108133965Sjdp case DEBUG_VISIBILITY_PUBLIC: 108233965Sjdp s = "public"; 108333965Sjdp break; 108433965Sjdp case DEBUG_VISIBILITY_PRIVATE: 108533965Sjdp s = "private"; 108633965Sjdp break; 108733965Sjdp case DEBUG_VISIBILITY_PROTECTED: 108833965Sjdp s = "protected"; 108933965Sjdp break; 109033965Sjdp case DEBUG_VISIBILITY_IGNORE: 109133965Sjdp s = "/* ignore */"; 109233965Sjdp break; 109333965Sjdp default: 109433965Sjdp abort (); 1095130561Sobrien return FALSE; 109633965Sjdp } 109733965Sjdp 109833965Sjdp /* Trim off a trailing space in the struct string, to make the 109933965Sjdp output look a bit better, then stick on the visibility string. */ 110033965Sjdp 110133965Sjdp t = info->stack->type; 110233965Sjdp len = strlen (t); 110333965Sjdp assert (t[len - 1] == ' '); 110433965Sjdp t[len - 1] = '\0'; 110533965Sjdp 110633965Sjdp if (! append_type (info, s) 110733965Sjdp || ! append_type (info, ":\n") 110833965Sjdp || ! indent_type (info)) 1109130561Sobrien return FALSE; 111033965Sjdp 111133965Sjdp info->stack->visibility = visibility; 111233965Sjdp 1113130561Sobrien return TRUE; 111433965Sjdp} 111533965Sjdp 111633965Sjdp/* Add a field to a struct type. */ 111733965Sjdp 1118130561Sobrienstatic bfd_boolean 1119130561Sobrienpr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize, 1120130561Sobrien enum debug_visibility visibility) 112133965Sjdp{ 112233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 112333965Sjdp char ab[20]; 112433965Sjdp char *t; 112533965Sjdp 112633965Sjdp if (! substitute_type (info, name)) 1127130561Sobrien return FALSE; 112833965Sjdp 112933965Sjdp if (! append_type (info, "; /* ")) 1130130561Sobrien return FALSE; 113133965Sjdp 113233965Sjdp if (bitsize != 0) 113333965Sjdp { 1134130561Sobrien print_vma (bitsize, ab, TRUE, FALSE); 113533965Sjdp if (! append_type (info, "bitsize ") 113633965Sjdp || ! append_type (info, ab) 113733965Sjdp || ! append_type (info, ", ")) 1138130561Sobrien return FALSE; 113933965Sjdp } 114033965Sjdp 1141130561Sobrien print_vma (bitpos, ab, TRUE, FALSE); 114233965Sjdp if (! append_type (info, "bitpos ") 114333965Sjdp || ! append_type (info, ab) 114433965Sjdp || ! append_type (info, " */\n") 114533965Sjdp || ! indent_type (info)) 1146130561Sobrien return FALSE; 114733965Sjdp 114833965Sjdp t = pop_type (info); 114933965Sjdp if (t == NULL) 1150130561Sobrien return FALSE; 115133965Sjdp 115233965Sjdp if (! pr_fix_visibility (info, visibility)) 1153130561Sobrien return FALSE; 115433965Sjdp 115533965Sjdp return append_type (info, t); 115633965Sjdp} 115733965Sjdp 115833965Sjdp/* Finish a struct type. */ 115933965Sjdp 1160130561Sobrienstatic bfd_boolean 1161130561Sobrienpr_end_struct_type (void *p) 116233965Sjdp{ 116333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 116433965Sjdp char *s; 116533965Sjdp 116633965Sjdp assert (info->stack != NULL); 116733965Sjdp assert (info->indent >= 2); 116833965Sjdp 116933965Sjdp info->indent -= 2; 117033965Sjdp 117133965Sjdp /* Change the trailing indentation to have a close brace. */ 117233965Sjdp s = info->stack->type + strlen (info->stack->type) - 2; 117333965Sjdp assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0'); 117433965Sjdp 117533965Sjdp *s++ = '}'; 117633965Sjdp *s = '\0'; 117733965Sjdp 1178130561Sobrien return TRUE; 117933965Sjdp} 118033965Sjdp 118133965Sjdp/* Start a class type. */ 118233965Sjdp 1183130561Sobrienstatic bfd_boolean 1184130561Sobrienpr_start_class_type (void *p, const char *tag, unsigned int id, 1185130561Sobrien bfd_boolean structp, unsigned int size, 1186130561Sobrien bfd_boolean vptr, bfd_boolean ownvptr) 118733965Sjdp{ 118833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 118933965Sjdp char *tv = NULL; 119033965Sjdp 119133965Sjdp info->indent += 2; 119233965Sjdp 119333965Sjdp if (vptr && ! ownvptr) 119433965Sjdp { 119533965Sjdp tv = pop_type (info); 119633965Sjdp if (tv == NULL) 1197130561Sobrien return FALSE; 119833965Sjdp } 119933965Sjdp 120033965Sjdp if (! push_type (info, structp ? "class " : "union class ")) 1201130561Sobrien return FALSE; 120233965Sjdp if (tag != NULL) 120333965Sjdp { 120433965Sjdp if (! append_type (info, tag)) 1205130561Sobrien return FALSE; 120633965Sjdp } 120733965Sjdp else 120833965Sjdp { 120933965Sjdp char idbuf[20]; 121033965Sjdp 121133965Sjdp sprintf (idbuf, "%%anon%u", id); 121233965Sjdp if (! append_type (info, idbuf)) 1213130561Sobrien return FALSE; 121433965Sjdp } 121533965Sjdp 121633965Sjdp if (! append_type (info, " {")) 1217130561Sobrien return FALSE; 121833965Sjdp if (size != 0 || vptr || ownvptr || tag != NULL) 121933965Sjdp { 122033965Sjdp if (! append_type (info, " /*")) 1221130561Sobrien return FALSE; 122233965Sjdp 122333965Sjdp if (size != 0) 122433965Sjdp { 122533965Sjdp char ab[20]; 122633965Sjdp 122733965Sjdp sprintf (ab, "%u", size); 122833965Sjdp if (! append_type (info, " size ") 122933965Sjdp || ! append_type (info, ab)) 1230130561Sobrien return FALSE; 123133965Sjdp } 123233965Sjdp 123333965Sjdp if (vptr) 123433965Sjdp { 123533965Sjdp if (! append_type (info, " vtable ")) 1236130561Sobrien return FALSE; 123733965Sjdp if (ownvptr) 123833965Sjdp { 123933965Sjdp if (! append_type (info, "self ")) 1240130561Sobrien return FALSE; 124133965Sjdp } 124233965Sjdp else 124333965Sjdp { 124433965Sjdp if (! append_type (info, tv) 124533965Sjdp || ! append_type (info, " ")) 1246130561Sobrien return FALSE; 124733965Sjdp } 124833965Sjdp } 124933965Sjdp 125033965Sjdp if (tag != NULL) 125133965Sjdp { 125233965Sjdp char ab[30]; 125333965Sjdp 125433965Sjdp sprintf (ab, " id %u", id); 125533965Sjdp if (! append_type (info, ab)) 1256130561Sobrien return FALSE; 125733965Sjdp } 125833965Sjdp 125933965Sjdp if (! append_type (info, " */")) 1260130561Sobrien return FALSE; 126133965Sjdp } 126233965Sjdp 126333965Sjdp info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; 126433965Sjdp 126533965Sjdp return (append_type (info, "\n") 126633965Sjdp && indent_type (info)); 126733965Sjdp} 126833965Sjdp 126933965Sjdp/* Add a static member to a class. */ 127033965Sjdp 1271130561Sobrienstatic bfd_boolean 1272130561Sobrienpr_class_static_member (void *p, const char *name, const char *physname, 1273130561Sobrien enum debug_visibility visibility) 127433965Sjdp{ 127533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 127633965Sjdp char *t; 127733965Sjdp 127833965Sjdp if (! substitute_type (info, name)) 1279130561Sobrien return FALSE; 128033965Sjdp 128133965Sjdp if (! prepend_type (info, "static ") 128233965Sjdp || ! append_type (info, "; /* ") 128333965Sjdp || ! append_type (info, physname) 128433965Sjdp || ! append_type (info, " */\n") 128533965Sjdp || ! indent_type (info)) 1286130561Sobrien return FALSE; 128733965Sjdp 128833965Sjdp t = pop_type (info); 128933965Sjdp if (t == NULL) 1290130561Sobrien return FALSE; 129133965Sjdp 129233965Sjdp if (! pr_fix_visibility (info, visibility)) 1293130561Sobrien return FALSE; 129433965Sjdp 129533965Sjdp return append_type (info, t); 129633965Sjdp} 129733965Sjdp 129833965Sjdp/* Add a base class to a class. */ 129933965Sjdp 1300130561Sobrienstatic bfd_boolean 1301130561Sobrienpr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual, 1302130561Sobrien enum debug_visibility visibility) 130333965Sjdp{ 130433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 130533965Sjdp char *t; 130633965Sjdp const char *prefix; 130733965Sjdp char ab[20]; 130833965Sjdp char *s, *l, *n; 130933965Sjdp 131033965Sjdp assert (info->stack != NULL && info->stack->next != NULL); 131133965Sjdp 131233965Sjdp if (! substitute_type (info, "")) 1313130561Sobrien return FALSE; 131433965Sjdp 131533965Sjdp t = pop_type (info); 131633965Sjdp if (t == NULL) 1317130561Sobrien return FALSE; 131833965Sjdp 131933965Sjdp if (strncmp (t, "class ", sizeof "class " - 1) == 0) 132033965Sjdp t += sizeof "class " - 1; 132133965Sjdp 132233965Sjdp /* Push it back on to take advantage of the prepend_type and 132333965Sjdp append_type routines. */ 132433965Sjdp if (! push_type (info, t)) 1325130561Sobrien return FALSE; 132633965Sjdp 132733965Sjdp if (virtual) 132833965Sjdp { 132933965Sjdp if (! prepend_type (info, "virtual ")) 1330130561Sobrien return FALSE; 133133965Sjdp } 133233965Sjdp 133333965Sjdp switch (visibility) 133433965Sjdp { 133533965Sjdp case DEBUG_VISIBILITY_PUBLIC: 133633965Sjdp prefix = "public "; 133733965Sjdp break; 133833965Sjdp case DEBUG_VISIBILITY_PROTECTED: 133933965Sjdp prefix = "protected "; 134033965Sjdp break; 134133965Sjdp case DEBUG_VISIBILITY_PRIVATE: 134233965Sjdp prefix = "private "; 134333965Sjdp break; 134433965Sjdp default: 134533965Sjdp prefix = "/* unknown visibility */ "; 134633965Sjdp break; 134733965Sjdp } 134833965Sjdp 134933965Sjdp if (! prepend_type (info, prefix)) 1350130561Sobrien return FALSE; 135133965Sjdp 135233965Sjdp if (bitpos != 0) 135333965Sjdp { 1354130561Sobrien print_vma (bitpos, ab, TRUE, FALSE); 135533965Sjdp if (! append_type (info, " /* bitpos ") 135633965Sjdp || ! append_type (info, ab) 135733965Sjdp || ! append_type (info, " */")) 1358130561Sobrien return FALSE; 135933965Sjdp } 136033965Sjdp 136133965Sjdp /* Now the top of the stack is something like "public A / * bitpos 136233965Sjdp 10 * /". The next element on the stack is something like "class 136333965Sjdp xx { / * size 8 * /\n...". We want to substitute the top of the 136433965Sjdp stack in before the {. */ 136533965Sjdp s = strchr (info->stack->next->type, '{'); 136633965Sjdp assert (s != NULL); 136733965Sjdp --s; 136833965Sjdp 136933965Sjdp /* If there is already a ':', then we already have a baseclass, and 137033965Sjdp we must append this one after a comma. */ 137133965Sjdp for (l = info->stack->next->type; l != s; l++) 137233965Sjdp if (*l == ':') 137333965Sjdp break; 137433965Sjdp if (! prepend_type (info, l == s ? " : " : ", ")) 1375130561Sobrien return FALSE; 137633965Sjdp 137733965Sjdp t = pop_type (info); 137833965Sjdp if (t == NULL) 1379130561Sobrien return FALSE; 138033965Sjdp 138133965Sjdp n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); 138233965Sjdp memcpy (n, info->stack->type, s - info->stack->type); 138333965Sjdp strcpy (n + (s - info->stack->type), t); 138433965Sjdp strcat (n, s); 138533965Sjdp 138633965Sjdp free (info->stack->type); 138733965Sjdp info->stack->type = n; 138833965Sjdp 138933965Sjdp free (t); 139033965Sjdp 1391130561Sobrien return TRUE; 139233965Sjdp} 139333965Sjdp 139433965Sjdp/* Start adding a method to a class. */ 139533965Sjdp 1396130561Sobrienstatic bfd_boolean 1397130561Sobrienpr_class_start_method (void *p, const char *name) 139833965Sjdp{ 139933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 140033965Sjdp 140133965Sjdp assert (info->stack != NULL); 140233965Sjdp info->stack->method = name; 1403130561Sobrien return TRUE; 140433965Sjdp} 140533965Sjdp 140633965Sjdp/* Add a variant to a method. */ 140733965Sjdp 1408130561Sobrienstatic bfd_boolean 1409130561Sobrienpr_class_method_variant (void *p, const char *physname, 1410130561Sobrien enum debug_visibility visibility, 1411130561Sobrien bfd_boolean constp, bfd_boolean volatilep, 1412130561Sobrien bfd_vma voffset, bfd_boolean context) 141333965Sjdp{ 141433965Sjdp struct pr_handle *info = (struct pr_handle *) p; 141533965Sjdp char *method_type; 141633965Sjdp char *context_type; 141733965Sjdp 141833965Sjdp assert (info->stack != NULL); 141933965Sjdp assert (info->stack->next != NULL); 142033965Sjdp 142133965Sjdp /* Put the const and volatile qualifiers on the type. */ 142233965Sjdp if (volatilep) 142333965Sjdp { 142433965Sjdp if (! append_type (info, " volatile")) 1425130561Sobrien return FALSE; 142633965Sjdp } 142733965Sjdp if (constp) 142833965Sjdp { 142933965Sjdp if (! append_type (info, " const")) 1430130561Sobrien return FALSE; 143133965Sjdp } 143233965Sjdp 143333965Sjdp /* Stick the name of the method into its type. */ 143433965Sjdp if (! substitute_type (info, 143533965Sjdp (context 143633965Sjdp ? info->stack->next->next->method 143733965Sjdp : info->stack->next->method))) 1438130561Sobrien return FALSE; 143933965Sjdp 144033965Sjdp /* Get the type. */ 144133965Sjdp method_type = pop_type (info); 144233965Sjdp if (method_type == NULL) 1443130561Sobrien return FALSE; 144433965Sjdp 144533965Sjdp /* Pull off the context type if there is one. */ 144633965Sjdp if (! context) 144733965Sjdp context_type = NULL; 144833965Sjdp else 144933965Sjdp { 145033965Sjdp context_type = pop_type (info); 145133965Sjdp if (context_type == NULL) 1452130561Sobrien return FALSE; 145333965Sjdp } 145433965Sjdp 145533965Sjdp /* Now the top of the stack is the class. */ 145633965Sjdp 145733965Sjdp if (! pr_fix_visibility (info, visibility)) 1458130561Sobrien return FALSE; 145933965Sjdp 146033965Sjdp if (! append_type (info, method_type) 146133965Sjdp || ! append_type (info, " /* ") 146233965Sjdp || ! append_type (info, physname) 146333965Sjdp || ! append_type (info, " ")) 1464130561Sobrien return FALSE; 146533965Sjdp if (context || voffset != 0) 146633965Sjdp { 146733965Sjdp char ab[20]; 146833965Sjdp 146933965Sjdp if (context) 147033965Sjdp { 147133965Sjdp if (! append_type (info, "context ") 147233965Sjdp || ! append_type (info, context_type) 147333965Sjdp || ! append_type (info, " ")) 1474130561Sobrien return FALSE; 147533965Sjdp } 1476130561Sobrien print_vma (voffset, ab, TRUE, FALSE); 147733965Sjdp if (! append_type (info, "voffset ") 147833965Sjdp || ! append_type (info, ab)) 1479130561Sobrien return FALSE; 148033965Sjdp } 148133965Sjdp 148233965Sjdp return (append_type (info, " */;\n") 148333965Sjdp && indent_type (info)); 148433965Sjdp} 148533965Sjdp 148633965Sjdp/* Add a static variant to a method. */ 148733965Sjdp 1488130561Sobrienstatic bfd_boolean 1489130561Sobrienpr_class_static_method_variant (void *p, const char *physname, 1490130561Sobrien enum debug_visibility visibility, 1491130561Sobrien bfd_boolean constp, bfd_boolean volatilep) 149233965Sjdp{ 149333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 149433965Sjdp char *method_type; 149533965Sjdp 149633965Sjdp assert (info->stack != NULL); 149733965Sjdp assert (info->stack->next != NULL); 149833965Sjdp assert (info->stack->next->method != NULL); 149933965Sjdp 150033965Sjdp /* Put the const and volatile qualifiers on the type. */ 150133965Sjdp if (volatilep) 150233965Sjdp { 150333965Sjdp if (! append_type (info, " volatile")) 1504130561Sobrien return FALSE; 150533965Sjdp } 150633965Sjdp if (constp) 150733965Sjdp { 150833965Sjdp if (! append_type (info, " const")) 1509130561Sobrien return FALSE; 151033965Sjdp } 151133965Sjdp 151233965Sjdp /* Mark it as static. */ 151333965Sjdp if (! prepend_type (info, "static ")) 1514130561Sobrien return FALSE; 151533965Sjdp 151633965Sjdp /* Stick the name of the method into its type. */ 151733965Sjdp if (! substitute_type (info, info->stack->next->method)) 1518130561Sobrien return FALSE; 151933965Sjdp 152033965Sjdp /* Get the type. */ 152133965Sjdp method_type = pop_type (info); 152233965Sjdp if (method_type == NULL) 1523130561Sobrien return FALSE; 152433965Sjdp 152533965Sjdp /* Now the top of the stack is the class. */ 152633965Sjdp 152733965Sjdp if (! pr_fix_visibility (info, visibility)) 1528130561Sobrien return FALSE; 152933965Sjdp 153033965Sjdp return (append_type (info, method_type) 153133965Sjdp && append_type (info, " /* ") 153233965Sjdp && append_type (info, physname) 153333965Sjdp && append_type (info, " */;\n") 153433965Sjdp && indent_type (info)); 153533965Sjdp} 153633965Sjdp 153733965Sjdp/* Finish up a method. */ 153833965Sjdp 1539130561Sobrienstatic bfd_boolean 1540130561Sobrienpr_class_end_method (void *p) 154133965Sjdp{ 154233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 154333965Sjdp 154433965Sjdp info->stack->method = NULL; 1545130561Sobrien return TRUE; 154633965Sjdp} 154733965Sjdp 154833965Sjdp/* Finish up a class. */ 154933965Sjdp 1550130561Sobrienstatic bfd_boolean 1551130561Sobrienpr_end_class_type (void *p) 155233965Sjdp{ 155333965Sjdp return pr_end_struct_type (p); 155433965Sjdp} 155533965Sjdp 155633965Sjdp/* Push a type on the stack using a typedef name. */ 155733965Sjdp 1558130561Sobrienstatic bfd_boolean 1559130561Sobrienpr_typedef_type (void *p, const char *name) 156033965Sjdp{ 156133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 156233965Sjdp 156333965Sjdp return push_type (info, name); 156433965Sjdp} 156533965Sjdp 156633965Sjdp/* Push a type on the stack using a tag name. */ 156733965Sjdp 1568130561Sobrienstatic bfd_boolean 1569130561Sobrienpr_tag_type (void *p, const char *name, unsigned int id, 1570130561Sobrien enum debug_type_kind kind) 157133965Sjdp{ 157233965Sjdp struct pr_handle *info = (struct pr_handle *) p; 157333965Sjdp const char *t, *tag; 157433965Sjdp char idbuf[20]; 157533965Sjdp 157633965Sjdp switch (kind) 157733965Sjdp { 157833965Sjdp case DEBUG_KIND_STRUCT: 157933965Sjdp t = "struct "; 158033965Sjdp break; 158133965Sjdp case DEBUG_KIND_UNION: 158233965Sjdp t = "union "; 158333965Sjdp break; 158433965Sjdp case DEBUG_KIND_ENUM: 158533965Sjdp t = "enum "; 158633965Sjdp break; 158733965Sjdp case DEBUG_KIND_CLASS: 158833965Sjdp t = "class "; 158933965Sjdp break; 159033965Sjdp case DEBUG_KIND_UNION_CLASS: 159133965Sjdp t = "union class "; 159233965Sjdp break; 159333965Sjdp default: 159433965Sjdp abort (); 1595130561Sobrien return FALSE; 159633965Sjdp } 159733965Sjdp 159833965Sjdp if (! push_type (info, t)) 1599130561Sobrien return FALSE; 160033965Sjdp if (name != NULL) 160133965Sjdp tag = name; 160233965Sjdp else 160333965Sjdp { 160433965Sjdp sprintf (idbuf, "%%anon%u", id); 160533965Sjdp tag = idbuf; 160633965Sjdp } 160733965Sjdp 160833965Sjdp if (! append_type (info, tag)) 1609130561Sobrien return FALSE; 161033965Sjdp if (name != NULL && kind != DEBUG_KIND_ENUM) 161133965Sjdp { 161233965Sjdp sprintf (idbuf, " /* id %u */", id); 161333965Sjdp if (! append_type (info, idbuf)) 1614130561Sobrien return FALSE; 161533965Sjdp } 161633965Sjdp 1617130561Sobrien return TRUE; 161833965Sjdp} 161933965Sjdp 162033965Sjdp/* Output a typedef. */ 162133965Sjdp 1622130561Sobrienstatic bfd_boolean 1623130561Sobrienpr_typdef (void *p, const char *name) 162433965Sjdp{ 162533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 162633965Sjdp char *s; 162733965Sjdp 162833965Sjdp if (! substitute_type (info, name)) 1629130561Sobrien return FALSE; 163033965Sjdp 163133965Sjdp s = pop_type (info); 163233965Sjdp if (s == NULL) 1633130561Sobrien return FALSE; 163433965Sjdp 163533965Sjdp indent (info); 163633965Sjdp fprintf (info->f, "typedef %s;\n", s); 163733965Sjdp 163833965Sjdp free (s); 163933965Sjdp 1640130561Sobrien return TRUE; 164133965Sjdp} 164233965Sjdp 164333965Sjdp/* Output a tag. The tag should already be in the string on the 164433965Sjdp stack, so all we have to do here is print it out. */ 164533965Sjdp 1646130561Sobrienstatic bfd_boolean 1647130561Sobrienpr_tag (void *p, const char *name ATTRIBUTE_UNUSED) 164833965Sjdp{ 164933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 165033965Sjdp char *t; 165133965Sjdp 165233965Sjdp t = pop_type (info); 165333965Sjdp if (t == NULL) 1654130561Sobrien return FALSE; 165533965Sjdp 165633965Sjdp indent (info); 165733965Sjdp fprintf (info->f, "%s;\n", t); 165833965Sjdp 165933965Sjdp free (t); 166033965Sjdp 1661130561Sobrien return TRUE; 166233965Sjdp} 166333965Sjdp 166433965Sjdp/* Output an integer constant. */ 166533965Sjdp 1666130561Sobrienstatic bfd_boolean 1667130561Sobrienpr_int_constant (void *p, const char *name, bfd_vma val) 166833965Sjdp{ 166933965Sjdp struct pr_handle *info = (struct pr_handle *) p; 167033965Sjdp char ab[20]; 167133965Sjdp 167233965Sjdp indent (info); 1673130561Sobrien print_vma (val, ab, FALSE, FALSE); 167433965Sjdp fprintf (info->f, "const int %s = %s;\n", name, ab); 1675130561Sobrien return TRUE; 167633965Sjdp} 167733965Sjdp 167833965Sjdp/* Output a floating point constant. */ 167933965Sjdp 1680130561Sobrienstatic bfd_boolean 1681130561Sobrienpr_float_constant (void *p, const char *name, double val) 168233965Sjdp{ 168333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 168433965Sjdp 168533965Sjdp indent (info); 168633965Sjdp fprintf (info->f, "const double %s = %g;\n", name, val); 1687130561Sobrien return TRUE; 168833965Sjdp} 168933965Sjdp 169033965Sjdp/* Output a typed constant. */ 169133965Sjdp 1692130561Sobrienstatic bfd_boolean 1693130561Sobrienpr_typed_constant (void *p, const char *name, bfd_vma val) 169433965Sjdp{ 169533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 169633965Sjdp char *t; 169733965Sjdp char ab[20]; 169833965Sjdp 169933965Sjdp t = pop_type (info); 170033965Sjdp if (t == NULL) 1701130561Sobrien return FALSE; 170233965Sjdp 170333965Sjdp indent (info); 1704130561Sobrien print_vma (val, ab, FALSE, FALSE); 170533965Sjdp fprintf (info->f, "const %s %s = %s;\n", t, name, ab); 170633965Sjdp 170733965Sjdp free (t); 170833965Sjdp 1709130561Sobrien return TRUE; 171033965Sjdp} 171133965Sjdp 171233965Sjdp/* Output a variable. */ 171333965Sjdp 1714130561Sobrienstatic bfd_boolean 1715130561Sobrienpr_variable (void *p, const char *name, enum debug_var_kind kind, 1716130561Sobrien bfd_vma val) 171733965Sjdp{ 171833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 171933965Sjdp char *t; 172033965Sjdp char ab[20]; 172133965Sjdp 172233965Sjdp if (! substitute_type (info, name)) 1723130561Sobrien return FALSE; 172433965Sjdp 172533965Sjdp t = pop_type (info); 172633965Sjdp if (t == NULL) 1727130561Sobrien return FALSE; 172833965Sjdp 172933965Sjdp indent (info); 173033965Sjdp switch (kind) 173133965Sjdp { 173233965Sjdp case DEBUG_STATIC: 173333965Sjdp case DEBUG_LOCAL_STATIC: 173433965Sjdp fprintf (info->f, "static "); 173533965Sjdp break; 173633965Sjdp case DEBUG_REGISTER: 173733965Sjdp fprintf (info->f, "register "); 173833965Sjdp break; 173933965Sjdp default: 174033965Sjdp break; 174133965Sjdp } 1742130561Sobrien print_vma (val, ab, TRUE, TRUE); 174333965Sjdp fprintf (info->f, "%s /* %s */;\n", t, ab); 174433965Sjdp 174533965Sjdp free (t); 174633965Sjdp 1747130561Sobrien return TRUE; 174833965Sjdp} 174933965Sjdp 175033965Sjdp/* Start outputting a function. */ 175133965Sjdp 1752130561Sobrienstatic bfd_boolean 1753130561Sobrienpr_start_function (void *p, const char *name, bfd_boolean global) 175433965Sjdp{ 175533965Sjdp struct pr_handle *info = (struct pr_handle *) p; 175633965Sjdp char *t; 175733965Sjdp 175833965Sjdp if (! substitute_type (info, name)) 1759130561Sobrien return FALSE; 176033965Sjdp 176133965Sjdp t = pop_type (info); 176233965Sjdp if (t == NULL) 1763130561Sobrien return FALSE; 176433965Sjdp 176533965Sjdp indent (info); 176633965Sjdp if (! global) 176733965Sjdp fprintf (info->f, "static "); 176833965Sjdp fprintf (info->f, "%s (", t); 176933965Sjdp 177033965Sjdp info->parameter = 1; 177133965Sjdp 1772130561Sobrien return TRUE; 177333965Sjdp} 177433965Sjdp 177533965Sjdp/* Output a function parameter. */ 177633965Sjdp 1777130561Sobrienstatic bfd_boolean 1778130561Sobrienpr_function_parameter (void *p, const char *name, 1779130561Sobrien enum debug_parm_kind kind, bfd_vma val) 178033965Sjdp{ 178133965Sjdp struct pr_handle *info = (struct pr_handle *) p; 178233965Sjdp char *t; 178333965Sjdp char ab[20]; 178433965Sjdp 178533965Sjdp if (kind == DEBUG_PARM_REFERENCE 178633965Sjdp || kind == DEBUG_PARM_REF_REG) 178733965Sjdp { 178833965Sjdp if (! pr_reference_type (p)) 1789130561Sobrien return FALSE; 179033965Sjdp } 179133965Sjdp 179233965Sjdp if (! substitute_type (info, name)) 1793130561Sobrien return FALSE; 179433965Sjdp 179533965Sjdp t = pop_type (info); 179633965Sjdp if (t == NULL) 1797130561Sobrien return FALSE; 179833965Sjdp 179933965Sjdp if (info->parameter != 1) 180033965Sjdp fprintf (info->f, ", "); 180133965Sjdp 180233965Sjdp if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) 180333965Sjdp fprintf (info->f, "register "); 180433965Sjdp 1805130561Sobrien print_vma (val, ab, TRUE, TRUE); 180633965Sjdp fprintf (info->f, "%s /* %s */", t, ab); 180733965Sjdp 180833965Sjdp free (t); 180933965Sjdp 181033965Sjdp ++info->parameter; 181133965Sjdp 1812130561Sobrien return TRUE; 181333965Sjdp} 181433965Sjdp 181533965Sjdp/* Start writing out a block. */ 181633965Sjdp 1817130561Sobrienstatic bfd_boolean 1818130561Sobrienpr_start_block (void *p, bfd_vma addr) 181933965Sjdp{ 182033965Sjdp struct pr_handle *info = (struct pr_handle *) p; 182133965Sjdp char ab[20]; 182233965Sjdp 182333965Sjdp if (info->parameter > 0) 182433965Sjdp { 182533965Sjdp fprintf (info->f, ")\n"); 182633965Sjdp info->parameter = 0; 182733965Sjdp } 182833965Sjdp 182933965Sjdp indent (info); 1830130561Sobrien print_vma (addr, ab, TRUE, TRUE); 183133965Sjdp fprintf (info->f, "{ /* %s */\n", ab); 183233965Sjdp 183333965Sjdp info->indent += 2; 183433965Sjdp 1835130561Sobrien return TRUE; 183633965Sjdp} 183733965Sjdp 183833965Sjdp/* Write out line number information. */ 183933965Sjdp 1840130561Sobrienstatic bfd_boolean 1841130561Sobrienpr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr) 184233965Sjdp{ 184333965Sjdp struct pr_handle *info = (struct pr_handle *) p; 184433965Sjdp char ab[20]; 184533965Sjdp 184633965Sjdp indent (info); 1847130561Sobrien print_vma (addr, ab, TRUE, TRUE); 184833965Sjdp fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab); 184933965Sjdp 1850130561Sobrien return TRUE; 185133965Sjdp} 185233965Sjdp 185333965Sjdp/* Finish writing out a block. */ 185433965Sjdp 1855130561Sobrienstatic bfd_boolean 1856130561Sobrienpr_end_block (void *p, bfd_vma addr) 185733965Sjdp{ 185833965Sjdp struct pr_handle *info = (struct pr_handle *) p; 185933965Sjdp char ab[20]; 186033965Sjdp 186133965Sjdp info->indent -= 2; 186233965Sjdp 186333965Sjdp indent (info); 1864130561Sobrien print_vma (addr, ab, TRUE, TRUE); 186533965Sjdp fprintf (info->f, "} /* %s */\n", ab); 186633965Sjdp 1867130561Sobrien return TRUE; 186833965Sjdp} 186933965Sjdp 187033965Sjdp/* Finish writing out a function. */ 187133965Sjdp 1872130561Sobrienstatic bfd_boolean 1873130561Sobrienpr_end_function (void *p ATTRIBUTE_UNUSED) 187433965Sjdp{ 1875130561Sobrien return TRUE; 187633965Sjdp} 1877130561Sobrien 1878130561Sobrien/* Tags style generation functions start here. */ 1879130561Sobrien 1880130561Sobrien/* Variables for address to line translation. */ 1881130561Sobrienstatic bfd_vma pc; 1882130561Sobrienstatic const char *filename; 1883130561Sobrienstatic const char *functionname; 1884130561Sobrienstatic unsigned int line; 1885130561Sobrienstatic bfd_boolean found; 1886130561Sobrien 1887130561Sobrien/* Look for an address in a section. This is called via 1888130561Sobrien bfd_map_over_sections. */ 1889130561Sobrien 1890130561Sobrienstatic void 1891130561Sobrienfind_address_in_section (bfd *abfd, asection *section, void *data) 1892130561Sobrien{ 1893130561Sobrien bfd_vma vma; 1894130561Sobrien bfd_size_type size; 1895130561Sobrien asymbol **syms = (asymbol **) data; 1896130561Sobrien 1897130561Sobrien if (found) 1898130561Sobrien return; 1899130561Sobrien 1900130561Sobrien if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) 1901130561Sobrien return; 1902130561Sobrien 1903130561Sobrien vma = bfd_get_section_vma (abfd, section); 1904130561Sobrien if (pc < vma) 1905130561Sobrien return; 1906130561Sobrien 1907130561Sobrien size = bfd_get_section_size_before_reloc (section); 1908130561Sobrien if (pc >= vma + size) 1909130561Sobrien return; 1910130561Sobrien 1911130561Sobrien found = bfd_find_nearest_line (abfd, section, syms, pc - vma, 1912130561Sobrien &filename, &functionname, &line); 1913130561Sobrien} 1914130561Sobrien 1915130561Sobrienstatic void 1916130561Sobrientranslate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms) 1917130561Sobrien{ 1918130561Sobrien pc = bfd_scan_vma (addr_hex, NULL, 16); 1919130561Sobrien found = FALSE; 1920130561Sobrien bfd_map_over_sections (abfd, find_address_in_section, syms); 1921130561Sobrien 1922130561Sobrien if (! found) 1923130561Sobrien fprintf (f, "??"); 1924130561Sobrien else 1925130561Sobrien fprintf (f, "%u", line); 1926130561Sobrien} 1927130561Sobrien 1928130561Sobrien/* Start a new compilation unit. */ 1929130561Sobrien 1930130561Sobrienstatic bfd_boolean 1931130561Sobrientg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED) 1932130561Sobrien{ 1933130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1934130561Sobrien 1935130561Sobrien fprintf (stderr, "New compilation unit: %s\n", filename); 1936130561Sobrien 1937130561Sobrien free (info->filename); 1938130561Sobrien /* Should it be relative? best way to do it here?. */ 1939130561Sobrien info->filename = strdup (filename); 1940130561Sobrien 1941130561Sobrien return TRUE; 1942130561Sobrien} 1943130561Sobrien 1944130561Sobrien/* Start a source file within a compilation unit. */ 1945130561Sobrien 1946130561Sobrienstatic bfd_boolean 1947130561Sobrientg_start_source (void *p, const char *filename) 1948130561Sobrien{ 1949130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1950130561Sobrien 1951130561Sobrien free (info->filename); 1952130561Sobrien /* Should it be relative? best way to do it here?. */ 1953130561Sobrien info->filename = strdup (filename); 1954130561Sobrien 1955130561Sobrien return TRUE; 1956130561Sobrien} 1957130561Sobrien 1958130561Sobrien/* Push an enum type onto the type stack. */ 1959130561Sobrien 1960130561Sobrienstatic bfd_boolean 1961130561Sobrientg_enum_type (void *p, const char *tag, const char **names, 1962130561Sobrien bfd_signed_vma *values) 1963130561Sobrien{ 1964130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 1965130561Sobrien unsigned int i; 1966130561Sobrien const char *name; 1967130561Sobrien char ab[20]; 1968130561Sobrien 1969130561Sobrien if (! pr_enum_type (p, tag, names, values)) 1970130561Sobrien return FALSE; 1971130561Sobrien 1972130561Sobrien name = tag ? tag : "unknown"; 1973130561Sobrien /* Generate an entry for the enum. */ 1974130561Sobrien if (tag) 1975130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag, 1976130561Sobrien info->filename, info->stack->type); 1977130561Sobrien 1978130561Sobrien /* Generate entries for the values. */ 1979130561Sobrien if (names != NULL) 1980130561Sobrien { 1981130561Sobrien for (i = 0; names[i] != NULL; i++) 1982130561Sobrien { 1983130561Sobrien print_vma (values[i], ab, FALSE, FALSE); 1984130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n", 1985130561Sobrien names[i], info->filename, name, ab); 1986130561Sobrien } 1987130561Sobrien } 1988130561Sobrien 1989130561Sobrien return TRUE; 1990130561Sobrien} 1991130561Sobrien 1992130561Sobrien/* Start accumulating a struct type. */ 1993130561Sobrien 1994130561Sobrienstatic bfd_boolean 1995130561Sobrientg_start_struct_type (void *p, const char *tag, unsigned int id, 1996130561Sobrien bfd_boolean structp, 1997130561Sobrien unsigned int size ATTRIBUTE_UNUSED) 1998130561Sobrien{ 1999130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2000130561Sobrien const char *name; 2001130561Sobrien char idbuf[20]; 2002130561Sobrien 2003130561Sobrien if (tag != NULL) 2004130561Sobrien name = tag; 2005130561Sobrien else 2006130561Sobrien { 2007130561Sobrien name = idbuf; 2008130561Sobrien sprintf (idbuf, "%%anon%u", id); 2009130561Sobrien } 2010130561Sobrien 2011130561Sobrien if (! push_type (info, name)) 2012130561Sobrien return FALSE; 2013130561Sobrien 2014130561Sobrien info->stack->flavor = structp ? "struct" : "union"; 2015130561Sobrien 2016130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename, 2017130561Sobrien info->stack->flavor[0]); 2018130561Sobrien 2019130561Sobrien info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; 2020130561Sobrien 2021130561Sobrien return indent_type (info); 2022130561Sobrien} 2023130561Sobrien 2024130561Sobrien/* Output the visibility of a field in a struct. */ 2025130561Sobrien 2026130561Sobrienstatic bfd_boolean 2027130561Sobrientg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility) 2028130561Sobrien{ 2029130561Sobrien assert (info->stack != NULL); 2030130561Sobrien 2031130561Sobrien if (info->stack->visibility == visibility) 2032130561Sobrien return TRUE; 2033130561Sobrien 2034130561Sobrien assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); 2035130561Sobrien 2036130561Sobrien info->stack->visibility = visibility; 2037130561Sobrien 2038130561Sobrien return TRUE; 2039130561Sobrien} 2040130561Sobrien 2041130561Sobrien/* Add a field to a struct type. */ 2042130561Sobrien 2043130561Sobrienstatic bfd_boolean 2044130561Sobrientg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED, 2045130561Sobrien bfd_vma bitsize ATTRIBUTE_UNUSED, 2046130561Sobrien enum debug_visibility visibility) 2047130561Sobrien{ 2048130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2049130561Sobrien char *t; 2050130561Sobrien 2051130561Sobrien t = pop_type (info); 2052130561Sobrien if (t == NULL) 2053130561Sobrien return FALSE; 2054130561Sobrien 2055130561Sobrien if (! tg_fix_visibility (info, visibility)) 2056130561Sobrien return FALSE; 2057130561Sobrien 2058130561Sobrien /* It happens, a bug? */ 2059130561Sobrien if (! name[0]) 2060130561Sobrien return TRUE; 2061130561Sobrien 2062130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n", 2063130561Sobrien name, info->filename, t, info->stack->flavor, info->stack->type, 2064130561Sobrien visibility_name (visibility)); 2065130561Sobrien 2066130561Sobrien return TRUE; 2067130561Sobrien} 2068130561Sobrien 2069130561Sobrien/* Finish a struct type. */ 2070130561Sobrien 2071130561Sobrienstatic bfd_boolean 2072130561Sobrientg_end_struct_type (void *p ATTRIBUTE_UNUSED) 2073130561Sobrien{ 2074130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2075130561Sobrien assert (info->stack != NULL); 2076130561Sobrien 2077130561Sobrien return TRUE; 2078130561Sobrien} 2079130561Sobrien 2080130561Sobrien/* Start a class type. */ 2081130561Sobrien 2082130561Sobrienstatic bfd_boolean 2083130561Sobrientg_start_class_type (void *p, const char *tag, unsigned int id, 2084130561Sobrien bfd_boolean structp, unsigned int size, 2085130561Sobrien bfd_boolean vptr, bfd_boolean ownvptr) 2086130561Sobrien{ 2087130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2088130561Sobrien char *tv = NULL; 2089130561Sobrien const char *name; 2090130561Sobrien 2091130561Sobrien info->indent += 2; 2092130561Sobrien 2093130561Sobrien if (vptr && ! ownvptr) 2094130561Sobrien { 2095130561Sobrien tv = pop_type (info); 2096130561Sobrien if (tv == NULL) 2097130561Sobrien return FALSE; 2098130561Sobrien } 2099130561Sobrien 2100130561Sobrien if (tag != NULL) 2101130561Sobrien name = tag; 2102130561Sobrien else 2103130561Sobrien { 2104130561Sobrien char idbuf[20]; 2105130561Sobrien 2106130561Sobrien sprintf (idbuf, "%%anon%u", id); 2107130561Sobrien name = idbuf; 2108130561Sobrien } 2109130561Sobrien 2110130561Sobrien if (! push_type (info, name)) 2111130561Sobrien return FALSE; 2112130561Sobrien 2113130561Sobrien info->stack->flavor = structp ? "class" : "union class"; 2114130561Sobrien info->stack->parents = NULL; 2115130561Sobrien info->stack->num_parents = 0; 2116130561Sobrien 2117130561Sobrien if (size != 0 || vptr || ownvptr || tag != NULL) 2118130561Sobrien { 2119130561Sobrien if (vptr) 2120130561Sobrien { 2121130561Sobrien if (! append_type (info, " vtable ")) 2122130561Sobrien return FALSE; 2123130561Sobrien if (ownvptr) 2124130561Sobrien { 2125130561Sobrien if (! append_type (info, "self ")) 2126130561Sobrien return FALSE; 2127130561Sobrien } 2128130561Sobrien else 2129130561Sobrien { 2130130561Sobrien if (! append_type (info, tv) 2131130561Sobrien || ! append_type (info, " ")) 2132130561Sobrien return FALSE; 2133130561Sobrien } 2134130561Sobrien } 2135130561Sobrien } 2136130561Sobrien 2137130561Sobrien info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; 2138130561Sobrien 2139130561Sobrien return TRUE; 2140130561Sobrien} 2141130561Sobrien 2142130561Sobrien/* Add a static member to a class. */ 2143130561Sobrien 2144130561Sobrienstatic bfd_boolean 2145130561Sobrientg_class_static_member (void *p, const char *name, 2146130561Sobrien const char *physname ATTRIBUTE_UNUSED, 2147130561Sobrien enum debug_visibility visibility) 2148130561Sobrien{ 2149130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2150130561Sobrien char *t; 2151130561Sobrien int len_var, len_class; 2152130561Sobrien char *full_name; 2153130561Sobrien 2154130561Sobrien len_var = strlen (name); 2155130561Sobrien len_class = strlen (info->stack->next->type); 2156130561Sobrien full_name = (char *) xmalloc (len_var + len_class + 3); 2157130561Sobrien if (! full_name) 2158130561Sobrien return FALSE; 2159130561Sobrien memcpy (full_name, info->stack->next->type, len_class); 2160130561Sobrien memcpy (full_name + len_class, "::", 2); 2161130561Sobrien memcpy (full_name + len_class + 2, name, len_var + 1); 2162130561Sobrien 2163130561Sobrien if (! substitute_type (info, full_name)) 2164130561Sobrien return FALSE; 2165130561Sobrien 2166130561Sobrien if (! prepend_type (info, "static ")) 2167130561Sobrien return FALSE; 2168130561Sobrien 2169130561Sobrien t = pop_type (info); 2170130561Sobrien if (t == NULL) 2171130561Sobrien return FALSE; 2172130561Sobrien 2173130561Sobrien if (! tg_fix_visibility (info, visibility)) 2174130561Sobrien return FALSE; 2175130561Sobrien 2176130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n", 2177130561Sobrien name, info->filename, t, info->stack->type, 2178130561Sobrien visibility_name (visibility)); 2179130561Sobrien free (t); 2180130561Sobrien free (full_name); 2181130561Sobrien 2182130561Sobrien return TRUE; 2183130561Sobrien} 2184130561Sobrien 2185130561Sobrien/* Add a base class to a class. */ 2186130561Sobrien 2187130561Sobrienstatic bfd_boolean 2188130561Sobrientg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED, 2189130561Sobrien bfd_boolean virtual, enum debug_visibility visibility) 2190130561Sobrien{ 2191130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2192130561Sobrien char *t; 2193130561Sobrien const char *prefix; 2194130561Sobrien 2195130561Sobrien assert (info->stack != NULL && info->stack->next != NULL); 2196130561Sobrien 2197130561Sobrien t = pop_type (info); 2198130561Sobrien if (t == NULL) 2199130561Sobrien return FALSE; 2200130561Sobrien 2201130561Sobrien if (strncmp (t, "class ", sizeof "class " - 1) == 0) 2202130561Sobrien t += sizeof "class " - 1; 2203130561Sobrien 2204130561Sobrien /* Push it back on to take advantage of the prepend_type and 2205130561Sobrien append_type routines. */ 2206130561Sobrien if (! push_type (info, t)) 2207130561Sobrien return FALSE; 2208130561Sobrien 2209130561Sobrien if (virtual) 2210130561Sobrien { 2211130561Sobrien if (! prepend_type (info, "virtual ")) 2212130561Sobrien return FALSE; 2213130561Sobrien } 2214130561Sobrien 2215130561Sobrien switch (visibility) 2216130561Sobrien { 2217130561Sobrien case DEBUG_VISIBILITY_PUBLIC: 2218130561Sobrien prefix = "public "; 2219130561Sobrien break; 2220130561Sobrien case DEBUG_VISIBILITY_PROTECTED: 2221130561Sobrien prefix = "protected "; 2222130561Sobrien break; 2223130561Sobrien case DEBUG_VISIBILITY_PRIVATE: 2224130561Sobrien prefix = "private "; 2225130561Sobrien break; 2226130561Sobrien default: 2227130561Sobrien prefix = "/* unknown visibility */ "; 2228130561Sobrien break; 2229130561Sobrien } 2230130561Sobrien 2231130561Sobrien if (! prepend_type (info, prefix)) 2232130561Sobrien return FALSE; 2233130561Sobrien 2234130561Sobrien t = pop_type (info); 2235130561Sobrien if (t == NULL) 2236130561Sobrien return FALSE; 2237130561Sobrien 2238130561Sobrien if (info->stack->num_parents && ! append_parent (info, ", ")) 2239130561Sobrien return FALSE; 2240130561Sobrien 2241130561Sobrien if (! append_parent (info, t)) 2242130561Sobrien return FALSE; 2243130561Sobrien info->stack->num_parents++; 2244130561Sobrien 2245130561Sobrien free (t); 2246130561Sobrien 2247130561Sobrien return TRUE; 2248130561Sobrien} 2249130561Sobrien 2250130561Sobrien/* Add a variant to a method. */ 2251130561Sobrien 2252130561Sobrienstatic bfd_boolean 2253130561Sobrientg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED, 2254130561Sobrien enum debug_visibility visibility, 2255130561Sobrien bfd_boolean constp, bfd_boolean volatilep, 2256130561Sobrien bfd_vma voffset ATTRIBUTE_UNUSED, 2257130561Sobrien bfd_boolean context) 2258130561Sobrien{ 2259130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2260130561Sobrien char *method_type; 2261130561Sobrien char *context_type; 2262130561Sobrien char *method_name; 2263130561Sobrien 2264130561Sobrien assert (info->stack != NULL); 2265130561Sobrien assert (info->stack->next != NULL); 2266130561Sobrien 2267130561Sobrien /* Put the const and volatile qualifiers on the type. */ 2268130561Sobrien if (volatilep) 2269130561Sobrien { 2270130561Sobrien if (! append_type (info, " volatile")) 2271130561Sobrien return FALSE; 2272130561Sobrien } 2273130561Sobrien if (constp) 2274130561Sobrien { 2275130561Sobrien if (! append_type (info, " const")) 2276130561Sobrien return FALSE; 2277130561Sobrien } 2278130561Sobrien 2279130561Sobrien method_name = strdup (context ? info->stack->next->next->method 2280130561Sobrien : info->stack->next->method); 2281130561Sobrien 2282130561Sobrien /* Stick the name of the method into its type. */ 2283130561Sobrien if (! substitute_type (info, method_name)) 2284130561Sobrien return FALSE; 2285130561Sobrien 2286130561Sobrien /* Get the type. */ 2287130561Sobrien method_type = pop_type (info); 2288130561Sobrien if (method_type == NULL) 2289130561Sobrien return FALSE; 2290130561Sobrien 2291130561Sobrien /* Pull off the context type if there is one. */ 2292130561Sobrien if (! context) 2293130561Sobrien context_type = NULL; 2294130561Sobrien else 2295130561Sobrien { 2296130561Sobrien context_type = pop_type (info); 2297130561Sobrien if (context_type == NULL) 2298130561Sobrien return FALSE; 2299130561Sobrien } 2300130561Sobrien 2301130561Sobrien /* Now the top of the stack is the class. */ 2302130561Sobrien if (! tg_fix_visibility (info, visibility)) 2303130561Sobrien return FALSE; 2304130561Sobrien 2305130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n", 2306130561Sobrien method_name, info->filename, method_type, info->stack->type); 2307130561Sobrien free (method_type); 2308130561Sobrien free (method_name); 2309130561Sobrien free (context_type); 2310130561Sobrien 2311130561Sobrien return TRUE; 2312130561Sobrien} 2313130561Sobrien 2314130561Sobrien/* Add a static variant to a method. */ 2315130561Sobrien 2316130561Sobrienstatic bfd_boolean 2317130561Sobrientg_class_static_method_variant (void *p, 2318130561Sobrien const char *physname ATTRIBUTE_UNUSED, 2319130561Sobrien enum debug_visibility visibility, 2320130561Sobrien bfd_boolean constp, bfd_boolean volatilep) 2321130561Sobrien{ 2322130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2323130561Sobrien char *method_type; 2324130561Sobrien char *method_name; 2325130561Sobrien 2326130561Sobrien assert (info->stack != NULL); 2327130561Sobrien assert (info->stack->next != NULL); 2328130561Sobrien assert (info->stack->next->method != NULL); 2329130561Sobrien 2330130561Sobrien /* Put the const and volatile qualifiers on the type. */ 2331130561Sobrien if (volatilep) 2332130561Sobrien { 2333130561Sobrien if (! append_type (info, " volatile")) 2334130561Sobrien return FALSE; 2335130561Sobrien } 2336130561Sobrien if (constp) 2337130561Sobrien { 2338130561Sobrien if (! append_type (info, " const")) 2339130561Sobrien return FALSE; 2340130561Sobrien } 2341130561Sobrien 2342130561Sobrien /* Mark it as static. */ 2343130561Sobrien if (! prepend_type (info, "static ")) 2344130561Sobrien return FALSE; 2345130561Sobrien 2346130561Sobrien method_name = strdup (info->stack->next->method); 2347130561Sobrien /* Stick the name of the method into its type. */ 2348130561Sobrien if (! substitute_type (info, info->stack->next->method)) 2349130561Sobrien return FALSE; 2350130561Sobrien 2351130561Sobrien /* Get the type. */ 2352130561Sobrien method_type = pop_type (info); 2353130561Sobrien if (method_type == NULL) 2354130561Sobrien return FALSE; 2355130561Sobrien 2356130561Sobrien /* Now the top of the stack is the class. */ 2357130561Sobrien if (! tg_fix_visibility (info, visibility)) 2358130561Sobrien return FALSE; 2359130561Sobrien 2360130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n", 2361130561Sobrien method_name, info->filename, method_type, info->stack->type, 2362130561Sobrien visibility_name (visibility)); 2363130561Sobrien free (method_type); 2364130561Sobrien free (method_name); 2365130561Sobrien 2366130561Sobrien return TRUE; 2367130561Sobrien} 2368130561Sobrien 2369130561Sobrien/* Finish up a class. */ 2370130561Sobrien 2371130561Sobrienstatic bfd_boolean 2372130561Sobrientg_end_class_type (void *p) 2373130561Sobrien{ 2374130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2375130561Sobrien 2376130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type, 2377130561Sobrien info->filename, info->stack->flavor); 2378130561Sobrien if (info->stack->num_parents) 2379130561Sobrien { 2380130561Sobrien fprintf (info->f, "\tinherits:%s", info->stack->parents); 2381130561Sobrien free (info->stack->parents); 2382130561Sobrien } 2383130561Sobrien fputc ('\n', info->f); 2384130561Sobrien 2385130561Sobrien return tg_end_struct_type (p); 2386130561Sobrien} 2387130561Sobrien 2388130561Sobrien/* Push a type on the stack using a tag name. */ 2389130561Sobrien 2390130561Sobrienstatic bfd_boolean 2391130561Sobrientg_tag_type (void *p, const char *name, unsigned int id, 2392130561Sobrien enum debug_type_kind kind) 2393130561Sobrien{ 2394130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2395130561Sobrien const char *t, *tag; 2396130561Sobrien char idbuf[20]; 2397130561Sobrien 2398130561Sobrien switch (kind) 2399130561Sobrien { 2400130561Sobrien case DEBUG_KIND_STRUCT: 2401130561Sobrien t = "struct "; 2402130561Sobrien break; 2403130561Sobrien case DEBUG_KIND_UNION: 2404130561Sobrien t = "union "; 2405130561Sobrien break; 2406130561Sobrien case DEBUG_KIND_ENUM: 2407130561Sobrien t = "enum "; 2408130561Sobrien break; 2409130561Sobrien case DEBUG_KIND_CLASS: 2410130561Sobrien t = "class "; 2411130561Sobrien break; 2412130561Sobrien case DEBUG_KIND_UNION_CLASS: 2413130561Sobrien t = "union class "; 2414130561Sobrien break; 2415130561Sobrien default: 2416130561Sobrien abort (); 2417130561Sobrien return FALSE; 2418130561Sobrien } 2419130561Sobrien 2420130561Sobrien if (! push_type (info, t)) 2421130561Sobrien return FALSE; 2422130561Sobrien if (name != NULL) 2423130561Sobrien tag = name; 2424130561Sobrien else 2425130561Sobrien { 2426130561Sobrien sprintf (idbuf, "%%anon%u", id); 2427130561Sobrien tag = idbuf; 2428130561Sobrien } 2429130561Sobrien 2430130561Sobrien if (! append_type (info, tag)) 2431130561Sobrien return FALSE; 2432130561Sobrien 2433130561Sobrien return TRUE; 2434130561Sobrien} 2435130561Sobrien 2436130561Sobrien/* Output a typedef. */ 2437130561Sobrien 2438130561Sobrienstatic bfd_boolean 2439130561Sobrientg_typdef (void *p, const char *name) 2440130561Sobrien{ 2441130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2442130561Sobrien char *s; 2443130561Sobrien 2444130561Sobrien s = pop_type (info); 2445130561Sobrien if (s == NULL) 2446130561Sobrien return FALSE; 2447130561Sobrien 2448130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name, 2449130561Sobrien info->filename, s); 2450130561Sobrien 2451130561Sobrien free (s); 2452130561Sobrien 2453130561Sobrien return TRUE; 2454130561Sobrien} 2455130561Sobrien 2456130561Sobrien/* Output a tag. The tag should already be in the string on the 2457130561Sobrien stack, so all we have to do here is print it out. */ 2458130561Sobrien 2459130561Sobrienstatic bfd_boolean 2460130561Sobrientg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED) 2461130561Sobrien{ 2462130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2463130561Sobrien char *t; 2464130561Sobrien 2465130561Sobrien t = pop_type (info); 2466130561Sobrien if (t == NULL) 2467130561Sobrien return FALSE; 2468130561Sobrien free (t); 2469130561Sobrien 2470130561Sobrien return TRUE; 2471130561Sobrien} 2472130561Sobrien 2473130561Sobrien/* Output an integer constant. */ 2474130561Sobrien 2475130561Sobrienstatic bfd_boolean 2476130561Sobrientg_int_constant (void *p, const char *name, bfd_vma val) 2477130561Sobrien{ 2478130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2479130561Sobrien char ab[20]; 2480130561Sobrien 2481130561Sobrien indent (info); 2482130561Sobrien print_vma (val, ab, FALSE, FALSE); 2483130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n", 2484130561Sobrien name, info->filename, ab); 2485130561Sobrien return TRUE; 2486130561Sobrien} 2487130561Sobrien 2488130561Sobrien/* Output a floating point constant. */ 2489130561Sobrien 2490130561Sobrienstatic bfd_boolean 2491130561Sobrientg_float_constant (void *p, const char *name, double val) 2492130561Sobrien{ 2493130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2494130561Sobrien 2495130561Sobrien indent (info); 2496130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n", 2497130561Sobrien name, info->filename, val); 2498130561Sobrien return TRUE; 2499130561Sobrien} 2500130561Sobrien 2501130561Sobrien/* Output a typed constant. */ 2502130561Sobrien 2503130561Sobrienstatic bfd_boolean 2504130561Sobrientg_typed_constant (void *p, const char *name, bfd_vma val) 2505130561Sobrien{ 2506130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2507130561Sobrien char *t; 2508130561Sobrien char ab[20]; 2509130561Sobrien 2510130561Sobrien t = pop_type (info); 2511130561Sobrien if (t == NULL) 2512130561Sobrien return FALSE; 2513130561Sobrien 2514130561Sobrien indent (info); 2515130561Sobrien print_vma (val, ab, FALSE, FALSE); 2516130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n", 2517130561Sobrien name, info->filename, t, ab); 2518130561Sobrien 2519130561Sobrien free (t); 2520130561Sobrien 2521130561Sobrien return TRUE; 2522130561Sobrien} 2523130561Sobrien 2524130561Sobrien/* Output a variable. */ 2525130561Sobrien 2526130561Sobrienstatic bfd_boolean 2527130561Sobrientg_variable (void *p, const char *name, enum debug_var_kind kind, 2528130561Sobrien bfd_vma val ATTRIBUTE_UNUSED) 2529130561Sobrien{ 2530130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2531130561Sobrien char *t; 2532130561Sobrien const char *dname, *from_class; 2533130561Sobrien 2534130561Sobrien t = pop_type (info); 2535130561Sobrien if (t == NULL) 2536130561Sobrien return FALSE; 2537130561Sobrien 2538130561Sobrien dname = name; 2539130561Sobrien if (info->demangler) 2540130561Sobrien { 2541130561Sobrien dname = info->demangler (info->abfd, name); 2542130561Sobrien if (strcmp (name, dname) == 0) 2543130561Sobrien { 2544130561Sobrien free ((char *) dname); 2545130561Sobrien dname = name; 2546130561Sobrien } 2547130561Sobrien } 2548130561Sobrien 2549130561Sobrien if (dname != name) 2550130561Sobrien { 2551130561Sobrien char *sep; 2552130561Sobrien sep = strstr (dname, "::"); 2553130561Sobrien if (sep) 2554130561Sobrien { 2555130561Sobrien *sep = 0; 2556130561Sobrien name = sep + 2; 2557130561Sobrien from_class = dname; 2558130561Sobrien } 2559130561Sobrien else 2560130561Sobrien { 2561130561Sobrien /* Obscure types as vts and type_info nodes. */ 2562130561Sobrien name = dname; 2563130561Sobrien from_class = NULL; 2564130561Sobrien } 2565130561Sobrien } 2566130561Sobrien else 2567130561Sobrien from_class = NULL; 2568130561Sobrien 2569130561Sobrien fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t); 2570130561Sobrien 2571130561Sobrien switch (kind) 2572130561Sobrien { 2573130561Sobrien case DEBUG_STATIC: 2574130561Sobrien case DEBUG_LOCAL_STATIC: 2575130561Sobrien fprintf (info->f, "\tfile:"); 2576130561Sobrien break; 2577130561Sobrien case DEBUG_REGISTER: 2578130561Sobrien fprintf (info->f, "\tregister:"); 2579130561Sobrien break; 2580130561Sobrien default: 2581130561Sobrien break; 2582130561Sobrien } 2583130561Sobrien 2584130561Sobrien if (from_class) 2585130561Sobrien { 2586130561Sobrien fprintf (info->f, "\tclass:%s",from_class); 2587130561Sobrien free ((char *) dname); 2588130561Sobrien } 2589130561Sobrien 2590130561Sobrien fprintf (info->f, "\n"); 2591130561Sobrien 2592130561Sobrien free (t); 2593130561Sobrien 2594130561Sobrien return TRUE; 2595130561Sobrien} 2596130561Sobrien 2597130561Sobrien/* Start outputting a function. */ 2598130561Sobrien 2599130561Sobrienstatic bfd_boolean 2600130561Sobrientg_start_function (void *p, const char *name, bfd_boolean global) 2601130561Sobrien{ 2602130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2603130561Sobrien const char *dname; 2604130561Sobrien 2605130561Sobrien if (! global) 2606130561Sobrien info->stack->flavor = "static"; 2607130561Sobrien else 2608130561Sobrien info->stack->flavor = NULL; 2609130561Sobrien 2610130561Sobrien dname = name; 2611130561Sobrien if (info->demangler) 2612130561Sobrien { 2613130561Sobrien dname = info->demangler (info->abfd, name); 2614130561Sobrien if (strcmp (name, dname) == 0) 2615130561Sobrien { 2616130561Sobrien free ((char *) dname); 2617130561Sobrien dname = name; 2618130561Sobrien } 2619130561Sobrien } 2620130561Sobrien 2621130561Sobrien if (! substitute_type (info, dname)) 2622130561Sobrien return FALSE; 2623130561Sobrien 2624130561Sobrien if (dname != name) 2625130561Sobrien { 2626130561Sobrien char *sep; 2627130561Sobrien sep = strstr (dname, "::"); 2628130561Sobrien if (sep) 2629130561Sobrien { 2630130561Sobrien info->stack->method = dname; 2631130561Sobrien *sep = 0; 2632130561Sobrien name = sep + 2; 2633130561Sobrien } 2634130561Sobrien else 2635130561Sobrien { 2636130561Sobrien info->stack->method = ""; 2637130561Sobrien name = dname; 2638130561Sobrien } 2639130561Sobrien sep = strchr (name, '('); 2640130561Sobrien if (sep) 2641130561Sobrien *sep = 0; 2642130561Sobrien /* Obscure functions as type_info function. */ 2643130561Sobrien } 2644130561Sobrien else 2645130561Sobrien info->stack->method = NULL; 2646130561Sobrien 2647130561Sobrien info->stack->parents = strdup (name); 2648130561Sobrien 2649130561Sobrien if (! info->stack->method && ! append_type (info, "(")) 2650130561Sobrien return FALSE; 2651130561Sobrien 2652130561Sobrien info->parameter = 1; 2653130561Sobrien 2654130561Sobrien return TRUE; 2655130561Sobrien} 2656130561Sobrien 2657130561Sobrien/* Output a function parameter. */ 2658130561Sobrien 2659130561Sobrienstatic bfd_boolean 2660130561Sobrientg_function_parameter (void *p, const char *name, enum debug_parm_kind kind, 2661130561Sobrien bfd_vma val ATTRIBUTE_UNUSED) 2662130561Sobrien{ 2663130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2664130561Sobrien char *t; 2665130561Sobrien 2666130561Sobrien if (kind == DEBUG_PARM_REFERENCE 2667130561Sobrien || kind == DEBUG_PARM_REF_REG) 2668130561Sobrien { 2669130561Sobrien if (! pr_reference_type (p)) 2670130561Sobrien return FALSE; 2671130561Sobrien } 2672130561Sobrien 2673130561Sobrien if (! substitute_type (info, name)) 2674130561Sobrien return FALSE; 2675130561Sobrien 2676130561Sobrien t = pop_type (info); 2677130561Sobrien if (t == NULL) 2678130561Sobrien return FALSE; 2679130561Sobrien 2680130561Sobrien if (! info->stack->method) 2681130561Sobrien { 2682130561Sobrien if (info->parameter != 1 && ! append_type (info, ", ")) 2683130561Sobrien return FALSE; 2684130561Sobrien 2685130561Sobrien if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) 2686130561Sobrien if (! append_type (info, "register ")) 2687130561Sobrien return FALSE; 2688130561Sobrien 2689130561Sobrien if (! append_type (info, t)) 2690130561Sobrien return FALSE; 2691130561Sobrien } 2692130561Sobrien 2693130561Sobrien free (t); 2694130561Sobrien 2695130561Sobrien ++info->parameter; 2696130561Sobrien 2697130561Sobrien return TRUE; 2698130561Sobrien} 2699130561Sobrien 2700130561Sobrien/* Start writing out a block. */ 2701130561Sobrien 2702130561Sobrienstatic bfd_boolean 2703130561Sobrientg_start_block (void *p, bfd_vma addr) 2704130561Sobrien{ 2705130561Sobrien struct pr_handle *info = (struct pr_handle *) p; 2706130561Sobrien char ab[20], kind, *partof; 2707130561Sobrien char *t; 2708130561Sobrien bfd_boolean local; 2709130561Sobrien 2710130561Sobrien if (info->parameter > 0) 2711130561Sobrien { 2712130561Sobrien info->parameter = 0; 2713130561Sobrien 2714130561Sobrien /* Delayed name. */ 2715130561Sobrien fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename); 2716130561Sobrien free (info->stack->parents); 2717130561Sobrien 2718130561Sobrien print_vma (addr, ab, TRUE, TRUE); 2719130561Sobrien translate_addresses (info->abfd, ab, info->f, info->syms); 2720130561Sobrien local = info->stack->flavor != NULL; 2721130561Sobrien if (info->stack->method && *info->stack->method) 2722130561Sobrien { 2723130561Sobrien kind = 'm'; 2724130561Sobrien partof = (char *) info->stack->method; 2725130561Sobrien } 2726130561Sobrien else 2727130561Sobrien { 2728130561Sobrien kind = 'f'; 2729130561Sobrien partof = NULL; 2730130561Sobrien if (! info->stack->method && ! append_type (info, ")")) 2731130561Sobrien return FALSE; 2732130561Sobrien } 2733130561Sobrien t = pop_type (info); 2734130561Sobrien if (t == NULL) 2735130561Sobrien return FALSE; 2736130561Sobrien fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t); 2737130561Sobrien if (local) 2738130561Sobrien fputs ("\tfile:", info->f); 2739130561Sobrien if (partof) 2740130561Sobrien { 2741130561Sobrien fprintf (info->f, "\tclass:%s", partof); 2742130561Sobrien free (partof); 2743130561Sobrien } 2744130561Sobrien fputc ('\n', info->f); 2745130561Sobrien } 2746130561Sobrien 2747130561Sobrien return TRUE; 2748130561Sobrien} 2749130561Sobrien 2750130561Sobrien/* Write out line number information. */ 2751130561Sobrien 2752130561Sobrienstatic bfd_boolean 2753130561Sobrientg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED, 2754130561Sobrien unsigned long lineno ATTRIBUTE_UNUSED, 2755130561Sobrien bfd_vma addr ATTRIBUTE_UNUSED) 2756130561Sobrien{ 2757130561Sobrien return TRUE; 2758130561Sobrien} 2759130561Sobrien 2760130561Sobrien/* Finish writing out a block. */ 2761130561Sobrien 2762130561Sobrienstatic bfd_boolean 2763130561Sobrientg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED) 2764130561Sobrien{ 2765130561Sobrien return TRUE; 2766130561Sobrien} 2767130561Sobrien 2768130561Sobrien/* Convert the visibility value into a human readable name. */ 2769130561Sobrien 2770130561Sobrienstatic const char * 2771130561Sobrienvisibility_name (enum debug_visibility visibility) 2772130561Sobrien{ 2773130561Sobrien const char *s; 2774130561Sobrien 2775130561Sobrien switch (visibility) 2776130561Sobrien { 2777130561Sobrien case DEBUG_VISIBILITY_PUBLIC: 2778130561Sobrien s = "public"; 2779130561Sobrien break; 2780130561Sobrien case DEBUG_VISIBILITY_PRIVATE: 2781130561Sobrien s = "private"; 2782130561Sobrien break; 2783130561Sobrien case DEBUG_VISIBILITY_PROTECTED: 2784130561Sobrien s = "protected"; 2785130561Sobrien break; 2786130561Sobrien case DEBUG_VISIBILITY_IGNORE: 2787130561Sobrien s = "/* ignore */"; 2788130561Sobrien break; 2789130561Sobrien default: 2790130561Sobrien abort (); 2791130561Sobrien return FALSE; 2792130561Sobrien } 2793130561Sobrien return s; 2794130561Sobrien} 2795