133965Sjdp/* wrstabs.c -- Output stabs debugging information
2218822Sdim   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007
3130561Sobrien   Free Software Foundation, Inc.
433965Sjdp   Written by Ian Lance Taylor <ian@cygnus.com>.
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
20218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim   02110-1301, USA.  */
2233965Sjdp
2333965Sjdp/* This file contains code which writes out stabs debugging
2433965Sjdp   information.  */
2533965Sjdp
26218822Sdim#include "sysdep.h"
2733965Sjdp#include <assert.h>
2833965Sjdp#include "bfd.h"
2933965Sjdp#include "libiberty.h"
3089857Sobrien#include "safe-ctype.h"
31218822Sdim#include "bucomm.h"
3233965Sjdp#include "debug.h"
3333965Sjdp#include "budbg.h"
3433965Sjdp#include "aout/aout64.h"
3533965Sjdp#include "aout/stab_gnu.h"
3633965Sjdp
3733965Sjdp/* The size of a stabs symbol.  This presumes 32 bit values.  */
3833965Sjdp
3933965Sjdp#define STAB_SYMBOL_SIZE (12)
4033965Sjdp
4133965Sjdp/* An entry in a string hash table.  */
4233965Sjdp
4333965Sjdpstruct string_hash_entry
4433965Sjdp{
4533965Sjdp  struct bfd_hash_entry root;
4633965Sjdp  /* Next string in this table.  */
4733965Sjdp  struct string_hash_entry *next;
4833965Sjdp  /* Index in string table.  */
4933965Sjdp  long index;
5033965Sjdp  /* Size of type if this is a typedef.  */
5133965Sjdp  unsigned int size;
5233965Sjdp};
5333965Sjdp
5433965Sjdp/* A string hash table.  */
5533965Sjdp
5633965Sjdpstruct string_hash_table
5733965Sjdp{
5833965Sjdp  struct bfd_hash_table table;
5933965Sjdp};
6033965Sjdp
6133965Sjdp/* The type stack.  Each element on the stack is a string.  */
6233965Sjdp
6333965Sjdpstruct stab_type_stack
6433965Sjdp{
6533965Sjdp  /* The next element on the stack.  */
6633965Sjdp  struct stab_type_stack *next;
6733965Sjdp  /* This element as a string.  */
6833965Sjdp  char *string;
6933965Sjdp  /* The type index of this element.  */
7033965Sjdp  long index;
7133965Sjdp  /* The size of the type.  */
7233965Sjdp  unsigned int size;
7333965Sjdp  /* Whether type string defines a new type.  */
74130561Sobrien  bfd_boolean definition;
7533965Sjdp  /* String defining struct fields.  */
7633965Sjdp  char *fields;
7733965Sjdp  /* NULL terminated array of strings defining base classes for a
7833965Sjdp     class.  */
7933965Sjdp  char **baseclasses;
8033965Sjdp  /* String defining class methods.  */
8133965Sjdp  char *methods;
8233965Sjdp  /* String defining vtable pointer for a class.  */
8333965Sjdp  char *vtable;
8433965Sjdp};
8533965Sjdp
8633965Sjdp/* This structure is used to keep track of type indices for tagged
8733965Sjdp   types.  */
8833965Sjdp
8933965Sjdpstruct stab_tag
9033965Sjdp{
9133965Sjdp  /* The type index.  */
9233965Sjdp  long index;
9333965Sjdp  /* The tag name.  */
9433965Sjdp  const char *tag;
9533965Sjdp  /* The kind of type.  This is set to DEBUG_KIND_ILLEGAL when the
9633965Sjdp     type is defined.  */
9733965Sjdp  enum debug_type_kind kind;
9833965Sjdp  /* The size of the struct.  */
9933965Sjdp  unsigned int size;
10033965Sjdp};
10133965Sjdp
10233965Sjdp/* We remember various sorts of type indices.  They are not related,
10333965Sjdp   but, for convenience, we keep all the information in this
10433965Sjdp   structure.  */
10533965Sjdp
10633965Sjdpstruct stab_type_cache
10733965Sjdp{
10833965Sjdp  /* The void type index.  */
10933965Sjdp  long void_type;
11033965Sjdp  /* Signed integer type indices, indexed by size - 1.  */
11133965Sjdp  long signed_integer_types[8];
11233965Sjdp  /* Unsigned integer type indices, indexed by size - 1.  */
11333965Sjdp  long unsigned_integer_types[8];
11433965Sjdp  /* Floating point types, indexed by size - 1.  */
11533965Sjdp  long float_types[16];
11633965Sjdp  /* Pointers to types, indexed by the type index.  */
11733965Sjdp  long *pointer_types;
11833965Sjdp  size_t pointer_types_alloc;
11933965Sjdp  /* Functions returning types, indexed by the type index.  */
12033965Sjdp  long *function_types;
12133965Sjdp  size_t function_types_alloc;
12233965Sjdp  /* References to types, indexed by the type index.  */
12333965Sjdp  long *reference_types;
12433965Sjdp  size_t reference_types_alloc;
12533965Sjdp  /* Struct/union/class type indices, indexed by the struct id.  */
12633965Sjdp  struct stab_tag *struct_types;
12733965Sjdp  size_t struct_types_alloc;
12833965Sjdp};
12933965Sjdp
13033965Sjdp/* This is the handle passed through debug_write.  */
13133965Sjdp
13233965Sjdpstruct stab_write_handle
13333965Sjdp{
13433965Sjdp  /* The BFD.  */
13533965Sjdp  bfd *abfd;
13633965Sjdp  /* This buffer holds the symbols.  */
13733965Sjdp  bfd_byte *symbols;
13833965Sjdp  size_t symbols_size;
13933965Sjdp  size_t symbols_alloc;
14033965Sjdp  /* This is a list of hash table entries for the strings.  */
14133965Sjdp  struct string_hash_entry *strings;
14233965Sjdp  /* The last string hash table entry.  */
14333965Sjdp  struct string_hash_entry *last_string;
14433965Sjdp  /* The size of the strings.  */
14533965Sjdp  size_t strings_size;
14633965Sjdp  /* This hash table eliminates duplicate strings.  */
14733965Sjdp  struct string_hash_table strhash;
14833965Sjdp  /* The type stack.  */
14933965Sjdp  struct stab_type_stack *type_stack;
15033965Sjdp  /* The next type index.  */
15133965Sjdp  long type_index;
15233965Sjdp  /* The type cache.  */
15333965Sjdp  struct stab_type_cache type_cache;
15433965Sjdp  /* A mapping from typedef names to type indices.  */
15533965Sjdp  struct string_hash_table typedef_hash;
15633965Sjdp  /* If this is not -1, it is the offset to the most recent N_SO
15733965Sjdp     symbol, and the value of that symbol needs to be set.  */
15833965Sjdp  long so_offset;
15933965Sjdp  /* If this is not -1, it is the offset to the most recent N_FUN
16033965Sjdp     symbol, and the value of that symbol needs to be set.  */
16133965Sjdp  long fun_offset;
16233965Sjdp  /* The last text section address seen.  */
16333965Sjdp  bfd_vma last_text_address;
16433965Sjdp  /* The block nesting depth.  */
16533965Sjdp  unsigned int nesting;
16633965Sjdp  /* The function address.  */
16733965Sjdp  bfd_vma fnaddr;
16833965Sjdp  /* A pending LBRAC symbol.  */
16933965Sjdp  bfd_vma pending_lbrac;
17033965Sjdp  /* The current line number file name.  */
17133965Sjdp  const char *lineno_filename;
17233965Sjdp};
17333965Sjdp
17433965Sjdpstatic struct bfd_hash_entry *string_hash_newfunc
175130561Sobrien  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
176130561Sobrienstatic bfd_boolean stab_write_symbol
177130561Sobrien  (struct stab_write_handle *, int, int, bfd_vma, const char *);
178130561Sobrienstatic bfd_boolean stab_push_string
179130561Sobrien  (struct stab_write_handle *, const char *, long, bfd_boolean, unsigned int);
180130561Sobrienstatic bfd_boolean stab_push_defined_type
181130561Sobrien  (struct stab_write_handle *, long, unsigned int);
182130561Sobrienstatic char *stab_pop_type (struct stab_write_handle *);
183130561Sobrienstatic bfd_boolean stab_modify_type
184130561Sobrien  (struct stab_write_handle *, int, unsigned int, long **, size_t *);
18533965Sjdpstatic long stab_get_struct_index
186130561Sobrien  (struct stab_write_handle *, const char *, unsigned int,
187130561Sobrien   enum debug_type_kind, unsigned int *);
188130561Sobrienstatic bfd_boolean stab_class_method_var
189130561Sobrien  (struct stab_write_handle *, const char *, enum debug_visibility,
190130561Sobrien   bfd_boolean, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
191130561Sobrienstatic bfd_boolean stab_start_compilation_unit (void *, const char *);
192130561Sobrienstatic bfd_boolean stab_start_source (void *, const char *);
193130561Sobrienstatic bfd_boolean stab_empty_type (void *);
194130561Sobrienstatic bfd_boolean stab_void_type (void *);
195130561Sobrienstatic bfd_boolean stab_int_type (void *, unsigned int, bfd_boolean);
196130561Sobrienstatic bfd_boolean stab_float_type (void *, unsigned int);
197130561Sobrienstatic bfd_boolean stab_complex_type (void *, unsigned int);
198130561Sobrienstatic bfd_boolean stab_bool_type (void *, unsigned int);
199130561Sobrienstatic bfd_boolean stab_enum_type
200130561Sobrien  (void *, const char *, const char **, bfd_signed_vma *);
201130561Sobrienstatic bfd_boolean stab_pointer_type (void *);
202130561Sobrienstatic bfd_boolean stab_function_type (void *, int, bfd_boolean);
203130561Sobrienstatic bfd_boolean stab_reference_type (void *);
204130561Sobrienstatic bfd_boolean stab_range_type (void *, bfd_signed_vma, bfd_signed_vma);
205130561Sobrienstatic bfd_boolean stab_array_type
206130561Sobrien  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
207130561Sobrienstatic bfd_boolean stab_set_type (void *, bfd_boolean);
208130561Sobrienstatic bfd_boolean stab_offset_type (void *);
209130561Sobrienstatic bfd_boolean stab_method_type (void *, bfd_boolean, int, bfd_boolean);
210130561Sobrienstatic bfd_boolean stab_const_type (void *);
211130561Sobrienstatic bfd_boolean stab_volatile_type (void *);
212130561Sobrienstatic bfd_boolean stab_start_struct_type
213130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
214130561Sobrienstatic bfd_boolean stab_struct_field
215130561Sobrien  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
216130561Sobrienstatic bfd_boolean stab_end_struct_type (void *);
217130561Sobrienstatic bfd_boolean stab_start_class_type
218130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int,
219130561Sobrien   bfd_boolean, bfd_boolean);
220130561Sobrienstatic bfd_boolean stab_class_static_member
221130561Sobrien  (void *, const char *, const char *, enum debug_visibility);
222130561Sobrienstatic bfd_boolean stab_class_baseclass
223130561Sobrien  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
224130561Sobrienstatic bfd_boolean stab_class_start_method (void *, const char *);
225130561Sobrienstatic bfd_boolean stab_class_method_variant
226130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
227130561Sobrien   bfd_vma, bfd_boolean);
228130561Sobrienstatic bfd_boolean stab_class_static_method_variant
229130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
230130561Sobrienstatic bfd_boolean stab_class_end_method (void *);
231130561Sobrienstatic bfd_boolean stab_end_class_type (void *);
232130561Sobrienstatic bfd_boolean stab_typedef_type (void *, const char *);
233130561Sobrienstatic bfd_boolean stab_tag_type
234130561Sobrien  (void *, const char *, unsigned int, enum debug_type_kind);
235130561Sobrienstatic bfd_boolean stab_typdef (void *, const char *);
236130561Sobrienstatic bfd_boolean stab_tag (void *, const char *);
237130561Sobrienstatic bfd_boolean stab_int_constant (void *, const char *, bfd_vma);
238130561Sobrienstatic bfd_boolean stab_float_constant (void *, const char *, double);
239130561Sobrienstatic bfd_boolean stab_typed_constant (void *, const char *, bfd_vma);
240130561Sobrienstatic bfd_boolean stab_variable
241130561Sobrien  (void *, const char *, enum debug_var_kind, bfd_vma);
242130561Sobrienstatic bfd_boolean stab_start_function (void *, const char *, bfd_boolean);
243130561Sobrienstatic bfd_boolean stab_function_parameter
244130561Sobrien  (void *, const char *, enum debug_parm_kind, bfd_vma);
245130561Sobrienstatic bfd_boolean stab_start_block (void *, bfd_vma);
246130561Sobrienstatic bfd_boolean stab_end_block (void *, bfd_vma);
247130561Sobrienstatic bfd_boolean stab_end_function (void *);
248130561Sobrienstatic bfd_boolean stab_lineno (void *, const char *, unsigned long, bfd_vma);
24933965Sjdp
25033965Sjdpstatic const struct debug_write_fns stab_fns =
25133965Sjdp{
25233965Sjdp  stab_start_compilation_unit,
25333965Sjdp  stab_start_source,
25433965Sjdp  stab_empty_type,
25533965Sjdp  stab_void_type,
25633965Sjdp  stab_int_type,
25733965Sjdp  stab_float_type,
25833965Sjdp  stab_complex_type,
25933965Sjdp  stab_bool_type,
26033965Sjdp  stab_enum_type,
26133965Sjdp  stab_pointer_type,
26233965Sjdp  stab_function_type,
26333965Sjdp  stab_reference_type,
26433965Sjdp  stab_range_type,
26533965Sjdp  stab_array_type,
26633965Sjdp  stab_set_type,
26733965Sjdp  stab_offset_type,
26833965Sjdp  stab_method_type,
26933965Sjdp  stab_const_type,
27033965Sjdp  stab_volatile_type,
27133965Sjdp  stab_start_struct_type,
27233965Sjdp  stab_struct_field,
27333965Sjdp  stab_end_struct_type,
27433965Sjdp  stab_start_class_type,
27533965Sjdp  stab_class_static_member,
27633965Sjdp  stab_class_baseclass,
27733965Sjdp  stab_class_start_method,
27833965Sjdp  stab_class_method_variant,
27933965Sjdp  stab_class_static_method_variant,
28033965Sjdp  stab_class_end_method,
28133965Sjdp  stab_end_class_type,
28233965Sjdp  stab_typedef_type,
28333965Sjdp  stab_tag_type,
28433965Sjdp  stab_typdef,
28533965Sjdp  stab_tag,
28633965Sjdp  stab_int_constant,
28733965Sjdp  stab_float_constant,
28833965Sjdp  stab_typed_constant,
28933965Sjdp  stab_variable,
29033965Sjdp  stab_start_function,
29133965Sjdp  stab_function_parameter,
29233965Sjdp  stab_start_block,
29333965Sjdp  stab_end_block,
29433965Sjdp  stab_end_function,
29533965Sjdp  stab_lineno
29633965Sjdp};
29733965Sjdp
29833965Sjdp/* Routine to create an entry in a string hash table.  */
29933965Sjdp
30033965Sjdpstatic struct bfd_hash_entry *
301130561Sobrienstring_hash_newfunc (struct bfd_hash_entry *entry,
302130561Sobrien		     struct bfd_hash_table *table, const char *string)
30333965Sjdp{
30433965Sjdp  struct string_hash_entry *ret = (struct string_hash_entry *) entry;
30533965Sjdp
30633965Sjdp  /* Allocate the structure if it has not already been allocated by a
30733965Sjdp     subclass.  */
30833965Sjdp  if (ret == (struct string_hash_entry *) NULL)
30933965Sjdp    ret = ((struct string_hash_entry *)
31033965Sjdp	   bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
31133965Sjdp  if (ret == (struct string_hash_entry *) NULL)
31233965Sjdp    return NULL;
31333965Sjdp
31433965Sjdp  /* Call the allocation method of the superclass.  */
31533965Sjdp  ret = ((struct string_hash_entry *)
31633965Sjdp	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
31733965Sjdp
31833965Sjdp  if (ret)
31933965Sjdp    {
32033965Sjdp      /* Initialize the local fields.  */
32133965Sjdp      ret->next = NULL;
32233965Sjdp      ret->index = -1;
32333965Sjdp      ret->size = 0;
32433965Sjdp    }
32533965Sjdp
32633965Sjdp  return (struct bfd_hash_entry *) ret;
32733965Sjdp}
32833965Sjdp
32933965Sjdp/* Look up an entry in a string hash table.  */
33033965Sjdp
33133965Sjdp#define string_hash_lookup(t, string, create, copy) \
33233965Sjdp  ((struct string_hash_entry *) \
33333965Sjdp   bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
33433965Sjdp
33533965Sjdp/* Add a symbol to the stabs debugging information we are building.  */
33633965Sjdp
337130561Sobrienstatic bfd_boolean
338130561Sobrienstab_write_symbol (struct stab_write_handle *info, int type, int desc,
339130561Sobrien		   bfd_vma value, const char *string)
34033965Sjdp{
34133965Sjdp  bfd_size_type strx;
34233965Sjdp  bfd_byte sym[STAB_SYMBOL_SIZE];
34333965Sjdp
34433965Sjdp  if (string == NULL)
34533965Sjdp    strx = 0;
34633965Sjdp  else
34733965Sjdp    {
34833965Sjdp      struct string_hash_entry *h;
34933965Sjdp
350130561Sobrien      h = string_hash_lookup (&info->strhash, string, TRUE, TRUE);
35133965Sjdp      if (h == NULL)
35233965Sjdp	{
35360484Sobrien	  non_fatal (_("string_hash_lookup failed: %s"),
35460484Sobrien		     bfd_errmsg (bfd_get_error ()));
355130561Sobrien	  return FALSE;
35633965Sjdp	}
35733965Sjdp      if (h->index != -1)
35833965Sjdp	strx = h->index;
35933965Sjdp      else
36033965Sjdp	{
36133965Sjdp	  strx = info->strings_size;
36233965Sjdp	  h->index = strx;
36333965Sjdp	  if (info->last_string == NULL)
36433965Sjdp	    info->strings = h;
36533965Sjdp	  else
36633965Sjdp	    info->last_string->next = h;
36733965Sjdp	  info->last_string = h;
36833965Sjdp	  info->strings_size += strlen (string) + 1;
36933965Sjdp	}
37033965Sjdp    }
37133965Sjdp
37233965Sjdp  /* This presumes 32 bit values.  */
37333965Sjdp  bfd_put_32 (info->abfd, strx, sym);
37433965Sjdp  bfd_put_8 (info->abfd, type, sym + 4);
37533965Sjdp  bfd_put_8 (info->abfd, 0, sym + 5);
37633965Sjdp  bfd_put_16 (info->abfd, desc, sym + 6);
37733965Sjdp  bfd_put_32 (info->abfd, value, sym + 8);
37833965Sjdp
37933965Sjdp  if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc)
38033965Sjdp    {
38133965Sjdp      info->symbols_alloc *= 2;
38233965Sjdp      info->symbols = (bfd_byte *) xrealloc (info->symbols,
38333965Sjdp					     info->symbols_alloc);
38433965Sjdp    }
38533965Sjdp
38633965Sjdp  memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE);
38733965Sjdp
38833965Sjdp  info->symbols_size += STAB_SYMBOL_SIZE;
38933965Sjdp
390130561Sobrien  return TRUE;
39133965Sjdp}
39233965Sjdp
39333965Sjdp/* Push a string on to the type stack.  */
39433965Sjdp
395130561Sobrienstatic bfd_boolean
396130561Sobrienstab_push_string (struct stab_write_handle *info, const char *string,
397130561Sobrien		  long index, bfd_boolean definition, unsigned int size)
39833965Sjdp{
39933965Sjdp  struct stab_type_stack *s;
40033965Sjdp
40133965Sjdp  s = (struct stab_type_stack *) xmalloc (sizeof *s);
40233965Sjdp  s->string = xstrdup (string);
40333965Sjdp  s->index = index;
40433965Sjdp  s->definition = definition;
40533965Sjdp  s->size = size;
40633965Sjdp
40733965Sjdp  s->fields = NULL;
40833965Sjdp  s->baseclasses = NULL;
40933965Sjdp  s->methods = NULL;
41033965Sjdp  s->vtable = NULL;
41133965Sjdp
41233965Sjdp  s->next = info->type_stack;
41333965Sjdp  info->type_stack = s;
41433965Sjdp
415130561Sobrien  return TRUE;
41633965Sjdp}
41733965Sjdp
41833965Sjdp/* Push a type index which has already been defined.  */
41933965Sjdp
420130561Sobrienstatic bfd_boolean
421130561Sobrienstab_push_defined_type (struct stab_write_handle *info, long index,
422130561Sobrien			unsigned int size)
42333965Sjdp{
42433965Sjdp  char buf[20];
42533965Sjdp
42633965Sjdp  sprintf (buf, "%ld", index);
427130561Sobrien  return stab_push_string (info, buf, index, FALSE, size);
42833965Sjdp}
42933965Sjdp
43033965Sjdp/* Pop a type off the type stack.  The caller is responsible for
43133965Sjdp   freeing the string.  */
43233965Sjdp
43333965Sjdpstatic char *
434130561Sobrienstab_pop_type (struct stab_write_handle *info)
43533965Sjdp{
43633965Sjdp  struct stab_type_stack *s;
43733965Sjdp  char *ret;
43833965Sjdp
43933965Sjdp  s = info->type_stack;
44033965Sjdp  assert (s != NULL);
44133965Sjdp
44233965Sjdp  info->type_stack = s->next;
44333965Sjdp
44433965Sjdp  ret = s->string;
44533965Sjdp
44633965Sjdp  free (s);
44733965Sjdp
44833965Sjdp  return ret;
44933965Sjdp}
45033965Sjdp
45133965Sjdp/* The general routine to write out stabs in sections debugging
45233965Sjdp   information.  This accumulates the stabs symbols and the strings in
45333965Sjdp   two obstacks.  We can't easily write out the information as we go
45433965Sjdp   along, because we need to know the section sizes before we can
45533965Sjdp   write out the section contents.  ABFD is the BFD and DHANDLE is the
45633965Sjdp   handle for the debugging information.  This sets *PSYMS to point to
45733965Sjdp   the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the
45833965Sjdp   strings, and *PSTRINGSIZE to the size of the strings.  */
45933965Sjdp
460130561Sobrienbfd_boolean
461130561Sobrienwrite_stabs_in_sections_debugging_info (bfd *abfd, void *dhandle,
462130561Sobrien					bfd_byte **psyms,
463130561Sobrien					bfd_size_type *psymsize,
464130561Sobrien					bfd_byte **pstrings,
465130561Sobrien					bfd_size_type *pstringsize)
46633965Sjdp{
46733965Sjdp  struct stab_write_handle info;
46833965Sjdp  struct string_hash_entry *h;
46933965Sjdp  bfd_byte *p;
47033965Sjdp
47133965Sjdp  info.abfd = abfd;
47233965Sjdp
47333965Sjdp  info.symbols_size = 0;
47433965Sjdp  info.symbols_alloc = 500;
47533965Sjdp  info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);
47633965Sjdp
47733965Sjdp  info.strings = NULL;
47833965Sjdp  info.last_string = NULL;
47933965Sjdp  /* Reserve 1 byte for a null byte.  */
48033965Sjdp  info.strings_size = 1;
48133965Sjdp
482218822Sdim  if (!bfd_hash_table_init (&info.strhash.table, string_hash_newfunc,
483218822Sdim			    sizeof (struct string_hash_entry))
484218822Sdim      || !bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc,
485218822Sdim			       sizeof (struct string_hash_entry)))
48633965Sjdp    {
48760484Sobrien      non_fatal ("bfd_hash_table_init_failed: %s",
48860484Sobrien		 bfd_errmsg (bfd_get_error ()));
489130561Sobrien      return FALSE;
49033965Sjdp    }
49133965Sjdp
49233965Sjdp  info.type_stack = NULL;
49333965Sjdp  info.type_index = 1;
49433965Sjdp  memset (&info.type_cache, 0, sizeof info.type_cache);
49533965Sjdp  info.so_offset = -1;
49633965Sjdp  info.fun_offset = -1;
49733965Sjdp  info.last_text_address = 0;
49833965Sjdp  info.nesting = 0;
49933965Sjdp  info.fnaddr = 0;
50033965Sjdp  info.pending_lbrac = (bfd_vma) -1;
50133965Sjdp
50233965Sjdp  /* The initial symbol holds the string size.  */
50333965Sjdp  if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL))
504130561Sobrien    return FALSE;
50533965Sjdp
50633965Sjdp  /* Output an initial N_SO symbol.  */
50733965Sjdp  info.so_offset = info.symbols_size;
50833965Sjdp  if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd)))
509130561Sobrien    return FALSE;
51033965Sjdp
511130561Sobrien  if (! debug_write (dhandle, &stab_fns, (void *) &info))
512130561Sobrien    return FALSE;
51333965Sjdp
51433965Sjdp  assert (info.pending_lbrac == (bfd_vma) -1);
51533965Sjdp
51633965Sjdp  /* Output a trailing N_SO.  */
51733965Sjdp  if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address,
51833965Sjdp			   (const char *) NULL))
519130561Sobrien    return FALSE;
52033965Sjdp
52133965Sjdp  /* Put the string size in the initial symbol.  */
52233965Sjdp  bfd_put_32 (abfd, info.strings_size, info.symbols + 8);
52333965Sjdp
52433965Sjdp  *psyms = info.symbols;
52533965Sjdp  *psymsize = info.symbols_size;
52633965Sjdp
52733965Sjdp  *pstringsize = info.strings_size;
52833965Sjdp  *pstrings = (bfd_byte *) xmalloc (info.strings_size);
52933965Sjdp
53033965Sjdp  p = *pstrings;
53133965Sjdp  *p++ = '\0';
53233965Sjdp  for (h = info.strings; h != NULL; h = h->next)
53333965Sjdp    {
53438889Sjdp      strcpy ((char *) p, h->root.string);
53538889Sjdp      p += strlen ((char *) p) + 1;
53633965Sjdp    }
53733965Sjdp
538130561Sobrien  return TRUE;
53933965Sjdp}
54033965Sjdp
54133965Sjdp/* Start writing out information for a compilation unit.  */
54233965Sjdp
543130561Sobrienstatic bfd_boolean
544130561Sobrienstab_start_compilation_unit (void *p, const char *filename)
54533965Sjdp{
54633965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
54733965Sjdp
54833965Sjdp  /* We would normally output an N_SO symbol here.  However, that
54933965Sjdp     would force us to reset all of our type information.  I think we
55033965Sjdp     will be better off just outputting an N_SOL symbol, and not
55133965Sjdp     worrying about splitting information between files.  */
55233965Sjdp
55333965Sjdp  info->lineno_filename = filename;
55433965Sjdp
55533965Sjdp  return stab_write_symbol (info, N_SOL, 0, 0, filename);
55633965Sjdp}
55733965Sjdp
55833965Sjdp/* Start writing out information for a particular source file.  */
55933965Sjdp
560130561Sobrienstatic bfd_boolean
561130561Sobrienstab_start_source (void *p, const char *filename)
56233965Sjdp{
56333965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
56433965Sjdp
56533965Sjdp  /* FIXME: The symbol's value is supposed to be the text section
56633965Sjdp     address.  However, we would have to fill it in later, and gdb
56733965Sjdp     doesn't care, so we don't bother with it.  */
56833965Sjdp
56933965Sjdp  info->lineno_filename = filename;
57033965Sjdp
57133965Sjdp  return stab_write_symbol (info, N_SOL, 0, 0, filename);
57233965Sjdp}
57333965Sjdp
57433965Sjdp/* Push an empty type.  This shouldn't normally happen.  We just use a
57533965Sjdp   void type.  */
57633965Sjdp
577130561Sobrienstatic bfd_boolean
578130561Sobrienstab_empty_type (void *p)
57933965Sjdp{
58033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
58133965Sjdp
58233965Sjdp  /* We don't call stab_void_type if the type is not yet defined,
58333965Sjdp     because that might screw up the typedef.  */
58433965Sjdp
58533965Sjdp  if (info->type_cache.void_type != 0)
58633965Sjdp    return stab_push_defined_type (info, info->type_cache.void_type, 0);
58733965Sjdp  else
58833965Sjdp    {
58933965Sjdp      long index;
59033965Sjdp      char buf[40];
59133965Sjdp
59233965Sjdp      index = info->type_index;
59333965Sjdp      ++info->type_index;
59433965Sjdp
59533965Sjdp      sprintf (buf, "%ld=%ld", index, index);
59633965Sjdp
597130561Sobrien      return stab_push_string (info, buf, index, FALSE, 0);
59833965Sjdp    }
59933965Sjdp}
60033965Sjdp
60133965Sjdp/* Push a void type.  */
60233965Sjdp
603130561Sobrienstatic bfd_boolean
604130561Sobrienstab_void_type (void *p)
60533965Sjdp{
60633965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
60733965Sjdp
60833965Sjdp  if (info->type_cache.void_type != 0)
60933965Sjdp    return stab_push_defined_type (info, info->type_cache.void_type, 0);
61033965Sjdp  else
61133965Sjdp    {
61233965Sjdp      long index;
61333965Sjdp      char buf[40];
61433965Sjdp
61533965Sjdp      index = info->type_index;
61633965Sjdp      ++info->type_index;
61733965Sjdp
61833965Sjdp      info->type_cache.void_type = index;
61933965Sjdp
62033965Sjdp      sprintf (buf, "%ld=%ld", index, index);
62133965Sjdp
622130561Sobrien      return stab_push_string (info, buf, index, TRUE, 0);
62333965Sjdp    }
62433965Sjdp}
62533965Sjdp
62633965Sjdp/* Push an integer type.  */
62733965Sjdp
628130561Sobrienstatic bfd_boolean
629130561Sobrienstab_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
63033965Sjdp{
63133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
63233965Sjdp  long *cache;
63333965Sjdp
63433965Sjdp  if (size <= 0 || (size > sizeof (long) && size != 8))
63533965Sjdp    {
63660484Sobrien      non_fatal (_("stab_int_type: bad size %u"), size);
637130561Sobrien      return FALSE;
63833965Sjdp    }
63933965Sjdp
64033965Sjdp  if (unsignedp)
64133965Sjdp    cache = info->type_cache.signed_integer_types;
64233965Sjdp  else
64333965Sjdp    cache = info->type_cache.unsigned_integer_types;
64433965Sjdp
64533965Sjdp  if (cache[size - 1] != 0)
64633965Sjdp    return stab_push_defined_type (info, cache[size - 1], size);
64733965Sjdp  else
64833965Sjdp    {
64933965Sjdp      long index;
65033965Sjdp      char buf[100];
65133965Sjdp
65233965Sjdp      index = info->type_index;
65333965Sjdp      ++info->type_index;
65433965Sjdp
65533965Sjdp      cache[size - 1] = index;
65633965Sjdp
65733965Sjdp      sprintf (buf, "%ld=r%ld;", index, index);
65833965Sjdp      if (unsignedp)
65933965Sjdp	{
66033965Sjdp	  strcat (buf, "0;");
66133965Sjdp	  if (size < sizeof (long))
66233965Sjdp	    sprintf (buf + strlen (buf), "%ld;", ((long) 1 << (size * 8)) - 1);
66333965Sjdp	  else if (size == sizeof (long))
66433965Sjdp	    strcat (buf, "-1;");
66533965Sjdp	  else if (size == 8)
66633965Sjdp	    strcat (buf, "01777777777777777777777;");
66733965Sjdp	  else
66833965Sjdp	    abort ();
66933965Sjdp	}
67033965Sjdp      else
67133965Sjdp	{
67233965Sjdp	  if (size <= sizeof (long))
67333965Sjdp	    sprintf (buf + strlen (buf), "%ld;%ld;",
67433965Sjdp		     (long) - ((unsigned long) 1 << (size * 8 - 1)),
67533965Sjdp		     (long) (((unsigned long) 1 << (size * 8 - 1)) - 1));
67633965Sjdp	  else if (size == 8)
67733965Sjdp	    strcat (buf, "01000000000000000000000;0777777777777777777777;");
67833965Sjdp	  else
67933965Sjdp	    abort ();
68033965Sjdp	}
68133965Sjdp
682130561Sobrien      return stab_push_string (info, buf, index, TRUE, size);
68333965Sjdp    }
68433965Sjdp}
68533965Sjdp
68633965Sjdp/* Push a floating point type.  */
68733965Sjdp
688130561Sobrienstatic bfd_boolean
689130561Sobrienstab_float_type (void *p, unsigned int size)
69033965Sjdp{
69133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
69233965Sjdp
69333965Sjdp  if (size > 0
69433965Sjdp      && size - 1 < (sizeof info->type_cache.float_types
69533965Sjdp		     / sizeof info->type_cache.float_types[0])
69633965Sjdp      && info->type_cache.float_types[size - 1] != 0)
69733965Sjdp    return stab_push_defined_type (info,
69833965Sjdp				   info->type_cache.float_types[size - 1],
69933965Sjdp				   size);
70033965Sjdp  else
70133965Sjdp    {
70233965Sjdp      long index;
70333965Sjdp      char *int_type;
70433965Sjdp      char buf[50];
70533965Sjdp
70633965Sjdp      /* Floats are defined as a subrange of int.  */
707130561Sobrien      if (! stab_int_type (info, 4, FALSE))
708130561Sobrien	return FALSE;
70933965Sjdp      int_type = stab_pop_type (info);
71033965Sjdp
71133965Sjdp      index = info->type_index;
71233965Sjdp      ++info->type_index;
71333965Sjdp
71433965Sjdp      if (size > 0
71533965Sjdp	  && size - 1 < (sizeof info->type_cache.float_types
71633965Sjdp			 / sizeof info->type_cache.float_types[0]))
71733965Sjdp	info->type_cache.float_types[size - 1] = index;
71833965Sjdp
71933965Sjdp      sprintf (buf, "%ld=r%s;%u;0;", index, int_type, size);
72033965Sjdp
72133965Sjdp      free (int_type);
72233965Sjdp
723130561Sobrien      return stab_push_string (info, buf, index, TRUE, size);
72433965Sjdp    }
72533965Sjdp}
72633965Sjdp
72733965Sjdp/* Push a complex type.  */
72833965Sjdp
729130561Sobrienstatic bfd_boolean
730130561Sobrienstab_complex_type (void *p, unsigned int size)
73133965Sjdp{
73233965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
73333965Sjdp  char buf[50];
73433965Sjdp  long index;
73533965Sjdp
73633965Sjdp  index = info->type_index;
73733965Sjdp  ++info->type_index;
73833965Sjdp
73933965Sjdp  sprintf (buf, "%ld=r%ld;%u;0;", index, index, size);
74033965Sjdp
741130561Sobrien  return stab_push_string (info, buf, index, TRUE, size * 2);
74233965Sjdp}
74333965Sjdp
744130561Sobrien/* Push a bfd_boolean type.  We use an XCOFF predefined type, since gdb
74533965Sjdp   always recognizes them.  */
74633965Sjdp
747130561Sobrienstatic bfd_boolean
748130561Sobrienstab_bool_type (void *p, unsigned int size)
74933965Sjdp{
75033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
75133965Sjdp  long index;
75233965Sjdp
75333965Sjdp  switch (size)
75433965Sjdp    {
75533965Sjdp    case 1:
75633965Sjdp      index = -21;
75733965Sjdp      break;
75833965Sjdp
75933965Sjdp    case 2:
76033965Sjdp      index = -22;
76133965Sjdp      break;
762104834Sobrien
76333965Sjdp    default:
76433965Sjdp    case 4:
76533965Sjdp      index = -16;
76633965Sjdp      break;
76733965Sjdp
76833965Sjdp    case 8:
76933965Sjdp      index = -33;
77033965Sjdp      break;
77133965Sjdp    }
77233965Sjdp
77333965Sjdp  return stab_push_defined_type (info, index, size);
77433965Sjdp}
77533965Sjdp
77633965Sjdp/* Push an enum type.  */
77733965Sjdp
778130561Sobrienstatic bfd_boolean
779130561Sobrienstab_enum_type (void *p, const char *tag, const char **names,
780130561Sobrien		bfd_signed_vma *vals)
78133965Sjdp{
78233965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
78333965Sjdp  size_t len;
78433965Sjdp  const char **pn;
78533965Sjdp  char *buf;
78633965Sjdp  long index = 0;
78733965Sjdp  bfd_signed_vma *pv;
78833965Sjdp
78933965Sjdp  if (names == NULL)
79033965Sjdp    {
79133965Sjdp      assert (tag != NULL);
79233965Sjdp
79333965Sjdp      buf = (char *) xmalloc (10 + strlen (tag));
79433965Sjdp      sprintf (buf, "xe%s:", tag);
79533965Sjdp      /* FIXME: The size is just a guess.  */
796130561Sobrien      if (! stab_push_string (info, buf, 0, FALSE, 4))
797130561Sobrien	return FALSE;
79833965Sjdp      free (buf);
799130561Sobrien      return TRUE;
80033965Sjdp    }
80133965Sjdp
80233965Sjdp  len = 10;
80333965Sjdp  if (tag != NULL)
80433965Sjdp    len += strlen (tag);
80533965Sjdp  for (pn = names; *pn != NULL; pn++)
80633965Sjdp    len += strlen (*pn) + 20;
80733965Sjdp
80833965Sjdp  buf = (char *) xmalloc (len);
80933965Sjdp
81033965Sjdp  if (tag == NULL)
81133965Sjdp    strcpy (buf, "e");
81233965Sjdp  else
81333965Sjdp    {
81433965Sjdp      index = info->type_index;
81533965Sjdp      ++info->type_index;
81633965Sjdp      sprintf (buf, "%s:T%ld=e", tag, index);
81733965Sjdp    }
81833965Sjdp
81933965Sjdp  for (pn = names, pv = vals; *pn != NULL; pn++, pv++)
82033965Sjdp    sprintf (buf + strlen (buf), "%s:%ld,", *pn, (long) *pv);
82133965Sjdp  strcat (buf, ";");
82233965Sjdp
82333965Sjdp  if (tag == NULL)
82433965Sjdp    {
82533965Sjdp      /* FIXME: The size is just a guess.  */
826130561Sobrien      if (! stab_push_string (info, buf, 0, FALSE, 4))
827130561Sobrien	return FALSE;
82833965Sjdp    }
82933965Sjdp  else
83033965Sjdp    {
83133965Sjdp      /* FIXME: The size is just a guess.  */
83233965Sjdp      if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)
83333965Sjdp	  || ! stab_push_defined_type (info, index, 4))
834130561Sobrien	return FALSE;
83533965Sjdp    }
83633965Sjdp
83733965Sjdp  free (buf);
83833965Sjdp
839130561Sobrien  return TRUE;
84033965Sjdp}
84133965Sjdp
84233965Sjdp/* Push a modification of the top type on the stack.  Cache the
84333965Sjdp   results in CACHE and CACHE_ALLOC.  */
84433965Sjdp
845130561Sobrienstatic bfd_boolean
846130561Sobrienstab_modify_type (struct stab_write_handle *info, int mod,
847130561Sobrien		  unsigned int size, long **cache, size_t *cache_alloc)
84833965Sjdp{
84933965Sjdp  long targindex;
85033965Sjdp  long index;
85133965Sjdp  char *s, *buf;
85233965Sjdp
85333965Sjdp  assert (info->type_stack != NULL);
85433965Sjdp  targindex = info->type_stack->index;
85533965Sjdp
85633965Sjdp  if (targindex <= 0
85733965Sjdp      || cache == NULL)
85833965Sjdp    {
859130561Sobrien      bfd_boolean definition;
86033965Sjdp
86133965Sjdp      /* Either the target type has no index, or we aren't caching
86233965Sjdp         this modifier.  Either way we have no way of recording the
86333965Sjdp         new type, so we don't bother to define one.  */
86433965Sjdp      definition = info->type_stack->definition;
86533965Sjdp      s = stab_pop_type (info);
86633965Sjdp      buf = (char *) xmalloc (strlen (s) + 2);
86733965Sjdp      sprintf (buf, "%c%s", mod, s);
86833965Sjdp      free (s);
86933965Sjdp      if (! stab_push_string (info, buf, 0, definition, size))
870130561Sobrien	return FALSE;
87133965Sjdp      free (buf);
87233965Sjdp    }
87333965Sjdp  else
87433965Sjdp    {
87538889Sjdp      if ((size_t) targindex >= *cache_alloc)
87633965Sjdp	{
87733965Sjdp	  size_t alloc;
87833965Sjdp
87933965Sjdp	  alloc = *cache_alloc;
88033965Sjdp	  if (alloc == 0)
88133965Sjdp	    alloc = 10;
88238889Sjdp	  while ((size_t) targindex >= alloc)
88333965Sjdp	    alloc *= 2;
88433965Sjdp	  *cache = (long *) xrealloc (*cache, alloc * sizeof (long));
88533965Sjdp	  memset (*cache + *cache_alloc, 0,
88633965Sjdp		  (alloc - *cache_alloc) * sizeof (long));
88733965Sjdp	  *cache_alloc = alloc;
88833965Sjdp	}
88933965Sjdp
89033965Sjdp      index = (*cache)[targindex];
89133965Sjdp      if (index != 0 && ! info->type_stack->definition)
89233965Sjdp	{
89333965Sjdp	  /* We have already defined a modification of this type, and
89433965Sjdp             the entry on the type stack is not a definition, so we
89533965Sjdp             can safely discard it (we may have a definition on the
89633965Sjdp             stack, even if we already defined a modification, if it
89733965Sjdp             is a struct which we did not define at the time it was
89833965Sjdp             referenced).  */
89933965Sjdp	  free (stab_pop_type (info));
90033965Sjdp	  if (! stab_push_defined_type (info, index, size))
901130561Sobrien	    return FALSE;
90233965Sjdp	}
90333965Sjdp      else
90433965Sjdp	{
90533965Sjdp	  index = info->type_index;
90633965Sjdp	  ++info->type_index;
90733965Sjdp
90833965Sjdp	  s = stab_pop_type (info);
90933965Sjdp	  buf = (char *) xmalloc (strlen (s) + 20);
91033965Sjdp	  sprintf (buf, "%ld=%c%s", index, mod, s);
91133965Sjdp	  free (s);
91233965Sjdp
91333965Sjdp	  (*cache)[targindex] = index;
91433965Sjdp
915130561Sobrien	  if (! stab_push_string (info, buf, index, TRUE, size))
916130561Sobrien	    return FALSE;
91733965Sjdp
91833965Sjdp	  free (buf);
91933965Sjdp	}
92033965Sjdp    }
92133965Sjdp
922130561Sobrien  return TRUE;
923104834Sobrien}
92433965Sjdp
92533965Sjdp/* Push a pointer type.  */
92633965Sjdp
927130561Sobrienstatic bfd_boolean
928130561Sobrienstab_pointer_type (void *p)
92933965Sjdp{
93033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
93133965Sjdp
93233965Sjdp  /* FIXME: The size should depend upon the architecture.  */
93333965Sjdp  return stab_modify_type (info, '*', 4, &info->type_cache.pointer_types,
93433965Sjdp			   &info->type_cache.pointer_types_alloc);
93533965Sjdp}
93633965Sjdp
93733965Sjdp/* Push a function type.  */
93833965Sjdp
939130561Sobrienstatic bfd_boolean
940130561Sobrienstab_function_type (void *p, int argcount,
941130561Sobrien		    bfd_boolean varargs ATTRIBUTE_UNUSED)
94233965Sjdp{
94333965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
94433965Sjdp  int i;
94533965Sjdp
94633965Sjdp  /* We have no way to represent the argument types, so we just
94733965Sjdp     discard them.  However, if they define new types, we must output
94833965Sjdp     them.  We do this by producing empty typedefs.  */
94933965Sjdp  for (i = 0; i < argcount; i++)
95033965Sjdp    {
95133965Sjdp      if (! info->type_stack->definition)
95233965Sjdp	free (stab_pop_type (info));
95333965Sjdp      else
95433965Sjdp	{
95533965Sjdp	  char *s, *buf;
95633965Sjdp
95733965Sjdp	  s = stab_pop_type (info);
95833965Sjdp
95933965Sjdp	  buf = (char *) xmalloc (strlen (s) + 3);
96033965Sjdp	  sprintf (buf, ":t%s", s);
96133965Sjdp	  free (s);
96233965Sjdp
96333965Sjdp	  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
964130561Sobrien	    return FALSE;
96533965Sjdp
96633965Sjdp	  free (buf);
96733965Sjdp	}
96833965Sjdp    }
96933965Sjdp
97033965Sjdp  return stab_modify_type (info, 'f', 0, &info->type_cache.function_types,
97133965Sjdp			   &info->type_cache.function_types_alloc);
97233965Sjdp}
97333965Sjdp
97433965Sjdp/* Push a reference type.  */
97533965Sjdp
976130561Sobrienstatic bfd_boolean
977130561Sobrienstab_reference_type (void *p)
97833965Sjdp{
97933965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
98033965Sjdp
98133965Sjdp  /* FIXME: The size should depend upon the architecture.  */
98233965Sjdp  return stab_modify_type (info, '&', 4, &info->type_cache.reference_types,
98333965Sjdp			   &info->type_cache.reference_types_alloc);
98433965Sjdp}
98533965Sjdp
98633965Sjdp/* Push a range type.  */
98733965Sjdp
988130561Sobrienstatic bfd_boolean
989130561Sobrienstab_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
99033965Sjdp{
99133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
992130561Sobrien  bfd_boolean definition;
99333965Sjdp  unsigned int size;
99433965Sjdp  char *s, *buf;
99533965Sjdp
99633965Sjdp  definition = info->type_stack->definition;
99733965Sjdp  size = info->type_stack->size;
99833965Sjdp
99933965Sjdp  s = stab_pop_type (info);
100033965Sjdp  buf = (char *) xmalloc (strlen (s) + 100);
100133965Sjdp  sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high);
100233965Sjdp  free (s);
100333965Sjdp
100433965Sjdp  if (! stab_push_string (info, buf, 0, definition, size))
1005130561Sobrien    return FALSE;
100633965Sjdp
100733965Sjdp  free (buf);
100833965Sjdp
1009130561Sobrien  return TRUE;
101033965Sjdp}
101133965Sjdp
101233965Sjdp/* Push an array type.  */
101333965Sjdp
1014130561Sobrienstatic bfd_boolean
1015130561Sobrienstab_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
1016130561Sobrien		 bfd_boolean stringp)
101733965Sjdp{
101833965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1019130561Sobrien  bfd_boolean definition;
102033965Sjdp  unsigned int element_size;
102133965Sjdp  char *range, *element, *buf;
102233965Sjdp  long index;
102333965Sjdp  unsigned int size;
102433965Sjdp
102533965Sjdp  definition = info->type_stack->definition;
102633965Sjdp  range = stab_pop_type (info);
102733965Sjdp
102833965Sjdp  definition = definition || info->type_stack->definition;
102933965Sjdp  element_size = info->type_stack->size;
103033965Sjdp  element = stab_pop_type (info);
103133965Sjdp
103233965Sjdp  buf = (char *) xmalloc (strlen (range) + strlen (element) + 100);
103333965Sjdp
103433965Sjdp  if (! stringp)
103533965Sjdp    {
103633965Sjdp      index = 0;
103733965Sjdp      *buf = '\0';
103833965Sjdp    }
103933965Sjdp  else
104033965Sjdp    {
104133965Sjdp      /* We need to define a type in order to include the string
104233965Sjdp         attribute.  */
104333965Sjdp      index = info->type_index;
104433965Sjdp      ++info->type_index;
1045130561Sobrien      definition = TRUE;
104633965Sjdp      sprintf (buf, "%ld=@S;", index);
104733965Sjdp    }
104833965Sjdp
104933965Sjdp  sprintf (buf + strlen (buf), "ar%s;%ld;%ld;%s",
105033965Sjdp	   range, (long) low, (long) high, element);
105133965Sjdp  free (range);
105233965Sjdp  free (element);
105333965Sjdp
105433965Sjdp  if (high < low)
105533965Sjdp    size = 0;
105633965Sjdp  else
105733965Sjdp    size = element_size * ((high - low) + 1);
105833965Sjdp  if (! stab_push_string (info, buf, index, definition, size))
1059130561Sobrien    return FALSE;
106033965Sjdp
106133965Sjdp  free (buf);
106233965Sjdp
1063130561Sobrien  return TRUE;
106433965Sjdp}
106533965Sjdp
106633965Sjdp/* Push a set type.  */
106733965Sjdp
1068130561Sobrienstatic bfd_boolean
1069130561Sobrienstab_set_type (void *p, bfd_boolean bitstringp)
107033965Sjdp{
107133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1072130561Sobrien  bfd_boolean definition;
107333965Sjdp  char *s, *buf;
107433965Sjdp  long index;
107533965Sjdp
107633965Sjdp  definition = info->type_stack->definition;
107733965Sjdp
107833965Sjdp  s = stab_pop_type (info);
107933965Sjdp  buf = (char *) xmalloc (strlen (s) + 30);
108033965Sjdp
108133965Sjdp  if (! bitstringp)
108233965Sjdp    {
108333965Sjdp      *buf = '\0';
108433965Sjdp      index = 0;
108533965Sjdp    }
108633965Sjdp  else
108733965Sjdp    {
108833965Sjdp      /* We need to define a type in order to include the string
108933965Sjdp         attribute.  */
109033965Sjdp      index = info->type_index;
109133965Sjdp      ++info->type_index;
1092130561Sobrien      definition = TRUE;
109333965Sjdp      sprintf (buf, "%ld=@S;", index);
109433965Sjdp    }
109533965Sjdp
109633965Sjdp  sprintf (buf + strlen (buf), "S%s", s);
109733965Sjdp  free (s);
109833965Sjdp
109933965Sjdp  if (! stab_push_string (info, buf, index, definition, 0))
1100130561Sobrien    return FALSE;
110133965Sjdp
110233965Sjdp  free (buf);
110333965Sjdp
1104130561Sobrien  return TRUE;
110533965Sjdp}
110633965Sjdp
110733965Sjdp/* Push an offset type.  */
110833965Sjdp
1109130561Sobrienstatic bfd_boolean
1110130561Sobrienstab_offset_type (void *p)
111133965Sjdp{
111233965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1113130561Sobrien  bfd_boolean definition;
111433965Sjdp  char *target, *base, *buf;
111533965Sjdp
111633965Sjdp  definition = info->type_stack->definition;
111733965Sjdp  target = stab_pop_type (info);
111833965Sjdp
111933965Sjdp  definition = definition || info->type_stack->definition;
112033965Sjdp  base = stab_pop_type (info);
112133965Sjdp
112233965Sjdp  buf = (char *) xmalloc (strlen (target) + strlen (base) + 3);
112333965Sjdp  sprintf (buf, "@%s,%s", base, target);
112433965Sjdp  free (base);
112533965Sjdp  free (target);
112633965Sjdp
112733965Sjdp  if (! stab_push_string (info, buf, 0, definition, 0))
1128130561Sobrien    return FALSE;
112933965Sjdp
113033965Sjdp  free (buf);
113133965Sjdp
1132130561Sobrien  return TRUE;
113333965Sjdp}
113433965Sjdp
113533965Sjdp/* Push a method type.  */
113633965Sjdp
1137130561Sobrienstatic bfd_boolean
1138130561Sobrienstab_method_type (void *p, bfd_boolean domainp, int argcount,
1139130561Sobrien		  bfd_boolean varargs)
114033965Sjdp{
114133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1142130561Sobrien  bfd_boolean definition;
114333965Sjdp  char *domain, *return_type, *buf;
114433965Sjdp  char **args;
114533965Sjdp  int i;
114633965Sjdp  size_t len;
114733965Sjdp
114833965Sjdp  /* We don't bother with stub method types, because that would
114933965Sjdp     require a mangler for C++ argument types.  This will waste space
115033965Sjdp     in the debugging output.  */
115133965Sjdp
115233965Sjdp  /* We need a domain.  I'm not sure DOMAINP can ever be false,
115333965Sjdp     anyhow.  */
115433965Sjdp  if (! domainp)
115533965Sjdp    {
115633965Sjdp      if (! stab_empty_type (p))
1157130561Sobrien	return FALSE;
115833965Sjdp    }
115933965Sjdp
116033965Sjdp  definition = info->type_stack->definition;
116133965Sjdp  domain = stab_pop_type (info);
116233965Sjdp
116333965Sjdp  /* A non-varargs function is indicated by making the last parameter
116433965Sjdp     type be void.  */
116533965Sjdp
116633965Sjdp  if (argcount < 0)
116733965Sjdp    {
116833965Sjdp      args = NULL;
116933965Sjdp      argcount = 0;
117033965Sjdp    }
117133965Sjdp  else if (argcount == 0)
117233965Sjdp    {
117333965Sjdp      if (varargs)
117433965Sjdp	args = NULL;
117533965Sjdp      else
117633965Sjdp	{
117733965Sjdp	  args = (char **) xmalloc (1 * sizeof (*args));
117833965Sjdp	  if (! stab_empty_type (p))
1179130561Sobrien	    return FALSE;
118033965Sjdp	  definition = definition || info->type_stack->definition;
118133965Sjdp	  args[0] = stab_pop_type (info);
118233965Sjdp	  argcount = 1;
118333965Sjdp	}
118433965Sjdp    }
118533965Sjdp  else
118633965Sjdp    {
118733965Sjdp      args = (char **) xmalloc ((argcount + 1) * sizeof (*args));
118833965Sjdp      for (i = argcount - 1; i >= 0; i--)
118933965Sjdp	{
119033965Sjdp	  definition = definition || info->type_stack->definition;
119133965Sjdp	  args[i] = stab_pop_type (info);
119233965Sjdp	}
119333965Sjdp      if (! varargs)
119433965Sjdp	{
119533965Sjdp	  if (! stab_empty_type (p))
1196130561Sobrien	    return FALSE;
119733965Sjdp	  definition = definition || info->type_stack->definition;
119833965Sjdp	  args[argcount] = stab_pop_type (info);
119933965Sjdp	  ++argcount;
120033965Sjdp	}
120133965Sjdp    }
120233965Sjdp
120333965Sjdp  definition = definition || info->type_stack->definition;
120433965Sjdp  return_type = stab_pop_type (info);
120533965Sjdp
120633965Sjdp  len = strlen (domain) + strlen (return_type) + 10;
120733965Sjdp  for (i = 0; i < argcount; i++)
120833965Sjdp    len += strlen (args[i]);
120933965Sjdp
121033965Sjdp  buf = (char *) xmalloc (len);
121133965Sjdp
121233965Sjdp  sprintf (buf, "#%s,%s", domain, return_type);
121333965Sjdp  free (domain);
121433965Sjdp  free (return_type);
121533965Sjdp  for (i = 0; i < argcount; i++)
121633965Sjdp    {
121733965Sjdp      strcat (buf, ",");
121833965Sjdp      strcat (buf, args[i]);
121933965Sjdp      free (args[i]);
122033965Sjdp    }
122133965Sjdp  strcat (buf, ";");
122233965Sjdp
122333965Sjdp  if (args != NULL)
122433965Sjdp    free (args);
122533965Sjdp
122633965Sjdp  if (! stab_push_string (info, buf, 0, definition, 0))
1227130561Sobrien    return FALSE;
122833965Sjdp
122933965Sjdp  free (buf);
123033965Sjdp
1231130561Sobrien  return TRUE;
123233965Sjdp}
123333965Sjdp
123433965Sjdp/* Push a const version of a type.  */
123533965Sjdp
1236130561Sobrienstatic bfd_boolean
1237130561Sobrienstab_const_type (void *p)
123833965Sjdp{
123933965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
124033965Sjdp
124133965Sjdp  return stab_modify_type (info, 'k', info->type_stack->size,
124233965Sjdp			   (long **) NULL, (size_t *) NULL);
124333965Sjdp}
124433965Sjdp
124533965Sjdp/* Push a volatile version of a type.  */
124633965Sjdp
1247130561Sobrienstatic bfd_boolean
1248130561Sobrienstab_volatile_type (void *p)
124933965Sjdp{
125033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
125133965Sjdp
125233965Sjdp  return stab_modify_type (info, 'B', info->type_stack->size,
125333965Sjdp			   (long **) NULL, (size_t *) NULL);
125433965Sjdp}
125533965Sjdp
125633965Sjdp/* Get the type index to use for a struct/union/class ID.  This should
125733965Sjdp   return -1 if it fails.  */
125833965Sjdp
125933965Sjdpstatic long
1260130561Sobrienstab_get_struct_index (struct stab_write_handle *info, const char *tag,
1261130561Sobrien		       unsigned int id, enum debug_type_kind kind,
1262130561Sobrien		       unsigned int *psize)
126333965Sjdp{
126433965Sjdp  if (id >= info->type_cache.struct_types_alloc)
126533965Sjdp    {
126633965Sjdp      size_t alloc;
126733965Sjdp
126833965Sjdp      alloc = info->type_cache.struct_types_alloc;
126933965Sjdp      if (alloc == 0)
127033965Sjdp	alloc = 10;
127133965Sjdp      while (id >= alloc)
127233965Sjdp	alloc *= 2;
127333965Sjdp      info->type_cache.struct_types =
127433965Sjdp	(struct stab_tag *) xrealloc (info->type_cache.struct_types,
127533965Sjdp				      alloc * sizeof (struct stab_tag));
127633965Sjdp      memset ((info->type_cache.struct_types
127733965Sjdp	       + info->type_cache.struct_types_alloc),
127833965Sjdp	      0,
127933965Sjdp	      ((alloc - info->type_cache.struct_types_alloc)
128033965Sjdp	       * sizeof (struct stab_tag)));
128133965Sjdp      info->type_cache.struct_types_alloc = alloc;
128233965Sjdp    }
128333965Sjdp
128433965Sjdp  if (info->type_cache.struct_types[id].index == 0)
128533965Sjdp    {
128633965Sjdp      info->type_cache.struct_types[id].index = info->type_index;
128733965Sjdp      ++info->type_index;
128833965Sjdp      info->type_cache.struct_types[id].tag = tag;
128933965Sjdp      info->type_cache.struct_types[id].kind = kind;
129033965Sjdp    }
129133965Sjdp
129233965Sjdp  if (kind == DEBUG_KIND_ILLEGAL)
129333965Sjdp    {
129433965Sjdp      /* This is a definition of the struct.  */
129533965Sjdp      info->type_cache.struct_types[id].kind = kind;
129633965Sjdp      info->type_cache.struct_types[id].size = *psize;
129733965Sjdp    }
129833965Sjdp  else
129933965Sjdp    *psize = info->type_cache.struct_types[id].size;
130033965Sjdp
130133965Sjdp  return info->type_cache.struct_types[id].index;
130233965Sjdp}
130333965Sjdp
130433965Sjdp/* Start outputting a struct.  We ignore the tag, and handle it in
130533965Sjdp   stab_tag.  */
130633965Sjdp
1307130561Sobrienstatic bfd_boolean
1308130561Sobrienstab_start_struct_type (void *p, const char *tag, unsigned int id,
1309130561Sobrien			bfd_boolean structp, unsigned int size)
131033965Sjdp{
131133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
131233965Sjdp  long index;
1313130561Sobrien  bfd_boolean definition;
131433965Sjdp  char *buf;
131533965Sjdp
131633965Sjdp  buf = (char *) xmalloc (40);
131733965Sjdp
131833965Sjdp  if (id == 0)
131933965Sjdp    {
132033965Sjdp      index = 0;
132133965Sjdp      *buf = '\0';
1322130561Sobrien      definition = FALSE;
132333965Sjdp    }
132433965Sjdp  else
132533965Sjdp    {
132633965Sjdp      index = stab_get_struct_index (info, tag, id, DEBUG_KIND_ILLEGAL,
132733965Sjdp				     &size);
132833965Sjdp      if (index < 0)
1329130561Sobrien	return FALSE;
133033965Sjdp      sprintf (buf, "%ld=", index);
1331130561Sobrien      definition = TRUE;
133233965Sjdp    }
133333965Sjdp
133433965Sjdp  sprintf (buf + strlen (buf), "%c%u",
133533965Sjdp	   structp ? 's' : 'u',
133633965Sjdp	   size);
133733965Sjdp
133833965Sjdp  if (! stab_push_string (info, buf, index, definition, size))
1339130561Sobrien    return FALSE;
134033965Sjdp
134133965Sjdp  info->type_stack->fields = (char *) xmalloc (1);
134233965Sjdp  info->type_stack->fields[0] = '\0';
134333965Sjdp
1344130561Sobrien  return TRUE;
134533965Sjdp}
134633965Sjdp
134733965Sjdp/* Add a field to a struct.  */
134833965Sjdp
1349130561Sobrienstatic bfd_boolean
1350130561Sobrienstab_struct_field (void *p, const char *name, bfd_vma bitpos,
1351130561Sobrien		   bfd_vma bitsize, enum debug_visibility visibility)
135233965Sjdp{
135333965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1354130561Sobrien  bfd_boolean definition;
135533965Sjdp  unsigned int size;
135633965Sjdp  char *s, *n;
135733965Sjdp  const char *vis;
135833965Sjdp
135933965Sjdp  definition = info->type_stack->definition;
136033965Sjdp  size = info->type_stack->size;
136133965Sjdp  s = stab_pop_type (info);
136233965Sjdp
136333965Sjdp  /* Add this field to the end of the current struct fields, which is
136433965Sjdp     currently on the top of the stack.  */
136533965Sjdp
136633965Sjdp  assert (info->type_stack->fields != NULL);
136733965Sjdp  n = (char *) xmalloc (strlen (info->type_stack->fields)
136833965Sjdp			+ strlen (name)
136933965Sjdp			+ strlen (s)
137033965Sjdp			+ 50);
137133965Sjdp
137233965Sjdp  switch (visibility)
137333965Sjdp    {
137433965Sjdp    default:
137533965Sjdp      abort ();
137633965Sjdp
137733965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
137833965Sjdp      vis = "";
137933965Sjdp      break;
138033965Sjdp
138133965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
138233965Sjdp      vis = "/0";
138333965Sjdp      break;
138433965Sjdp
138533965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
138633965Sjdp      vis = "/1";
138733965Sjdp      break;
138833965Sjdp    }
138933965Sjdp
139033965Sjdp  if (bitsize == 0)
139133965Sjdp    {
139233965Sjdp      bitsize = size * 8;
139333965Sjdp      if (bitsize == 0)
139460484Sobrien	non_fatal (_("%s: warning: unknown size for field `%s' in struct"),
139560484Sobrien		   bfd_get_filename (info->abfd), name);
139633965Sjdp    }
139733965Sjdp
139833965Sjdp  sprintf (n, "%s%s:%s%s,%ld,%ld;", info->type_stack->fields, name, vis, s,
139933965Sjdp	   (long) bitpos, (long) bitsize);
140033965Sjdp
140133965Sjdp  free (info->type_stack->fields);
140233965Sjdp  info->type_stack->fields = n;
140333965Sjdp
140433965Sjdp  if (definition)
1405130561Sobrien    info->type_stack->definition = TRUE;
140633965Sjdp
1407130561Sobrien  return TRUE;
140833965Sjdp}
140933965Sjdp
141033965Sjdp/* Finish up a struct.  */
141133965Sjdp
1412130561Sobrienstatic bfd_boolean
1413130561Sobrienstab_end_struct_type (void *p)
141433965Sjdp{
141533965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1416130561Sobrien  bfd_boolean definition;
141733965Sjdp  long index;
141833965Sjdp  unsigned int size;
141933965Sjdp  char *fields, *first, *buf;
142033965Sjdp
142133965Sjdp  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
142233965Sjdp
142333965Sjdp  definition = info->type_stack->definition;
142433965Sjdp  index = info->type_stack->index;
142533965Sjdp  size = info->type_stack->size;
142633965Sjdp  fields = info->type_stack->fields;
142733965Sjdp  first = stab_pop_type (info);
142833965Sjdp
142933965Sjdp  buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2);
143033965Sjdp  sprintf (buf, "%s%s;", first, fields);
143133965Sjdp  free (first);
143233965Sjdp  free (fields);
143333965Sjdp
143433965Sjdp  if (! stab_push_string (info, buf, index, definition, size))
1435130561Sobrien    return FALSE;
143633965Sjdp
143733965Sjdp  free (buf);
143833965Sjdp
1439130561Sobrien  return TRUE;
144033965Sjdp}
144133965Sjdp
144233965Sjdp/* Start outputting a class.  */
144333965Sjdp
1444130561Sobrienstatic bfd_boolean
1445130561Sobrienstab_start_class_type (void *p, const char *tag, unsigned int id, bfd_boolean structp, unsigned int size, bfd_boolean vptr, bfd_boolean ownvptr)
144633965Sjdp{
144733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1448130561Sobrien  bfd_boolean definition;
144933965Sjdp  char *vstring;
145033965Sjdp
145133965Sjdp  if (! vptr || ownvptr)
145233965Sjdp    {
1453130561Sobrien      definition = FALSE;
145433965Sjdp      vstring = NULL;
145533965Sjdp    }
145633965Sjdp  else
145733965Sjdp    {
145833965Sjdp      definition = info->type_stack->definition;
145933965Sjdp      vstring = stab_pop_type (info);
146033965Sjdp    }
146133965Sjdp
146233965Sjdp  if (! stab_start_struct_type (p, tag, id, structp, size))
1463130561Sobrien    return FALSE;
146433965Sjdp
146533965Sjdp  if (vptr)
146633965Sjdp    {
146733965Sjdp      char *vtable;
146833965Sjdp
146933965Sjdp      if (ownvptr)
147033965Sjdp	{
147133965Sjdp	  assert (info->type_stack->index > 0);
147233965Sjdp	  vtable = (char *) xmalloc (20);
147333965Sjdp	  sprintf (vtable, "~%%%ld", info->type_stack->index);
147433965Sjdp	}
147533965Sjdp      else
147633965Sjdp	{
147733965Sjdp	  vtable = (char *) xmalloc (strlen (vstring) + 3);
147833965Sjdp	  sprintf (vtable, "~%%%s", vstring);
147933965Sjdp	  free (vstring);
148033965Sjdp	}
148133965Sjdp
148233965Sjdp      info->type_stack->vtable = vtable;
148333965Sjdp    }
148433965Sjdp
148533965Sjdp  if (definition)
1486130561Sobrien    info->type_stack->definition = TRUE;
148733965Sjdp
1488130561Sobrien  return TRUE;
148933965Sjdp}
149033965Sjdp
149133965Sjdp/* Add a static member to the class on the type stack.  */
149233965Sjdp
1493130561Sobrienstatic bfd_boolean
1494130561Sobrienstab_class_static_member (void *p, const char *name, const char *physname,
1495130561Sobrien			  enum debug_visibility visibility)
149633965Sjdp{
149733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1498130561Sobrien  bfd_boolean definition;
149933965Sjdp  char *s, *n;
150033965Sjdp  const char *vis;
150133965Sjdp
150233965Sjdp  definition = info->type_stack->definition;
150333965Sjdp  s = stab_pop_type (info);
150433965Sjdp
150533965Sjdp  /* Add this field to the end of the current struct fields, which is
150633965Sjdp     currently on the top of the stack.  */
150733965Sjdp
150833965Sjdp  assert (info->type_stack->fields != NULL);
150933965Sjdp  n = (char *) xmalloc (strlen (info->type_stack->fields)
151033965Sjdp			+ strlen (name)
151133965Sjdp			+ strlen (s)
151233965Sjdp			+ strlen (physname)
151333965Sjdp			+ 10);
151433965Sjdp
151533965Sjdp  switch (visibility)
151633965Sjdp    {
151733965Sjdp    default:
151833965Sjdp      abort ();
151933965Sjdp
152033965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
152133965Sjdp      vis = "";
152233965Sjdp      break;
152333965Sjdp
152433965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
152533965Sjdp      vis = "/0";
152633965Sjdp      break;
152733965Sjdp
152833965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
152933965Sjdp      vis = "/1";
153033965Sjdp      break;
153133965Sjdp    }
153233965Sjdp
153333965Sjdp  sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s,
153433965Sjdp	   physname);
153533965Sjdp
153633965Sjdp  free (info->type_stack->fields);
153733965Sjdp  info->type_stack->fields = n;
153833965Sjdp
153933965Sjdp  if (definition)
1540130561Sobrien    info->type_stack->definition = TRUE;
154133965Sjdp
1542130561Sobrien  return TRUE;
154333965Sjdp}
154433965Sjdp
154533965Sjdp/* Add a base class to the class on the type stack.  */
154633965Sjdp
1547130561Sobrienstatic bfd_boolean
1548130561Sobrienstab_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
1549130561Sobrien		      enum debug_visibility visibility)
155033965Sjdp{
155133965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
1552130561Sobrien  bfd_boolean definition;
155333965Sjdp  char *s;
155433965Sjdp  char *buf;
155533965Sjdp  unsigned int c;
155633965Sjdp  char **baseclasses;
155733965Sjdp
155833965Sjdp  definition = info->type_stack->definition;
155933965Sjdp  s = stab_pop_type (info);
156033965Sjdp
156133965Sjdp  /* Build the base class specifier.  */
156233965Sjdp
156333965Sjdp  buf = (char *) xmalloc (strlen (s) + 25);
156433965Sjdp  buf[0] = virtual ? '1' : '0';
156533965Sjdp  switch (visibility)
156633965Sjdp    {
156733965Sjdp    default:
156833965Sjdp      abort ();
156933965Sjdp
157033965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
157133965Sjdp      buf[1] = '0';
157233965Sjdp      break;
157333965Sjdp
157433965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
157533965Sjdp      buf[1] = '1';
157633965Sjdp      break;
157733965Sjdp
157833965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
157933965Sjdp      buf[1] = '2';
158033965Sjdp      break;
158133965Sjdp    }
158233965Sjdp
158333965Sjdp  sprintf (buf + 2, "%ld,%s;", (long) bitpos, s);
158433965Sjdp  free (s);
158533965Sjdp
158633965Sjdp  /* Add the new baseclass to the existing ones.  */
158733965Sjdp
158833965Sjdp  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
158933965Sjdp
159033965Sjdp  if (info->type_stack->baseclasses == NULL)
159133965Sjdp    c = 0;
159233965Sjdp  else
159333965Sjdp    {
159433965Sjdp      c = 0;
159533965Sjdp      while (info->type_stack->baseclasses[c] != NULL)
159633965Sjdp	++c;
159733965Sjdp    }
159833965Sjdp
159933965Sjdp  baseclasses = (char **) xrealloc (info->type_stack->baseclasses,
160033965Sjdp				    (c + 2) * sizeof (*baseclasses));
160133965Sjdp  baseclasses[c] = buf;
160233965Sjdp  baseclasses[c + 1] = NULL;
160333965Sjdp
160433965Sjdp  info->type_stack->baseclasses = baseclasses;
160533965Sjdp
160633965Sjdp  if (definition)
1607130561Sobrien    info->type_stack->definition = TRUE;
160833965Sjdp
1609130561Sobrien  return TRUE;
161033965Sjdp}
161133965Sjdp
161233965Sjdp/* Start adding a method to the class on the type stack.  */
161333965Sjdp
1614130561Sobrienstatic bfd_boolean
1615130561Sobrienstab_class_start_method (void *p, const char *name)
161633965Sjdp{
161733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
161833965Sjdp  char *m;
161933965Sjdp
162033965Sjdp  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
162133965Sjdp
162233965Sjdp  if (info->type_stack->methods == NULL)
162333965Sjdp    {
162433965Sjdp      m = (char *) xmalloc (strlen (name) + 3);
162533965Sjdp      *m = '\0';
162633965Sjdp    }
162733965Sjdp  else
162833965Sjdp    {
162933965Sjdp      m = (char *) xrealloc (info->type_stack->methods,
163033965Sjdp			     (strlen (info->type_stack->methods)
163133965Sjdp			      + strlen (name)
163233965Sjdp			      + 4));
163333965Sjdp    }
163433965Sjdp
163533965Sjdp  sprintf (m + strlen (m), "%s::", name);
163633965Sjdp
163733965Sjdp  info->type_stack->methods = m;
163833965Sjdp
1639130561Sobrien  return TRUE;
164033965Sjdp}
164133965Sjdp
164233965Sjdp/* Add a variant, either static or not, to the current method.  */
164333965Sjdp
1644130561Sobrienstatic bfd_boolean
1645130561Sobrienstab_class_method_var (struct stab_write_handle *info, const char *physname,
1646130561Sobrien		       enum debug_visibility visibility,
1647130561Sobrien		       bfd_boolean staticp, bfd_boolean constp,
1648130561Sobrien		       bfd_boolean volatilep, bfd_vma voffset,
1649130561Sobrien		       bfd_boolean contextp)
165033965Sjdp{
1651130561Sobrien  bfd_boolean definition;
165233965Sjdp  char *type;
165333965Sjdp  char *context = NULL;
165433965Sjdp  char visc, qualc, typec;
165533965Sjdp
165633965Sjdp  definition = info->type_stack->definition;
165733965Sjdp  type = stab_pop_type (info);
165833965Sjdp
165933965Sjdp  if (contextp)
166033965Sjdp    {
166133965Sjdp      definition = definition || info->type_stack->definition;
166233965Sjdp      context = stab_pop_type (info);
166333965Sjdp    }
166433965Sjdp
166533965Sjdp  assert (info->type_stack != NULL && info->type_stack->methods != NULL);
166633965Sjdp
166733965Sjdp  switch (visibility)
166833965Sjdp    {
166933965Sjdp    default:
167033965Sjdp      abort ();
167133965Sjdp
167233965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
167333965Sjdp      visc = '0';
167433965Sjdp      break;
167533965Sjdp
167633965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
167733965Sjdp      visc = '1';
167833965Sjdp      break;
167933965Sjdp
168033965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
168133965Sjdp      visc = '2';
168233965Sjdp      break;
168333965Sjdp    }
168433965Sjdp
168533965Sjdp  if (constp)
168633965Sjdp    {
168733965Sjdp      if (volatilep)
168833965Sjdp	qualc = 'D';
168933965Sjdp      else
169033965Sjdp	qualc = 'B';
169133965Sjdp    }
169233965Sjdp  else
169333965Sjdp    {
169433965Sjdp      if (volatilep)
169533965Sjdp	qualc = 'C';
169633965Sjdp      else
169733965Sjdp	qualc = 'A';
169833965Sjdp    }
169933965Sjdp
170033965Sjdp  if (staticp)
170133965Sjdp    typec = '?';
170233965Sjdp  else if (! contextp)
170333965Sjdp    typec = '.';
170433965Sjdp  else
170533965Sjdp    typec = '*';
170633965Sjdp
170733965Sjdp  info->type_stack->methods =
170833965Sjdp    (char *) xrealloc (info->type_stack->methods,
170933965Sjdp		       (strlen (info->type_stack->methods)
171033965Sjdp			+ strlen (type)
171133965Sjdp			+ strlen (physname)
171233965Sjdp			+ (contextp ? strlen (context) : 0)
171333965Sjdp			+ 40));
171433965Sjdp
171533965Sjdp  sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
171633965Sjdp	   "%s:%s;%c%c%c", type, physname, visc, qualc, typec);
171733965Sjdp  free (type);
171833965Sjdp
171933965Sjdp  if (contextp)
172033965Sjdp    {
172133965Sjdp      sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
172233965Sjdp	       "%ld;%s;", (long) voffset, context);
172333965Sjdp      free (context);
172433965Sjdp    }
172533965Sjdp
172633965Sjdp  if (definition)
1727130561Sobrien    info->type_stack->definition = TRUE;
172833965Sjdp
1729130561Sobrien  return TRUE;
173033965Sjdp}
173133965Sjdp
173233965Sjdp/* Add a variant to the current method.  */
173333965Sjdp
1734130561Sobrienstatic bfd_boolean
1735130561Sobrienstab_class_method_variant (void *p, const char *physname,
1736130561Sobrien			   enum debug_visibility visibility,
1737130561Sobrien			   bfd_boolean constp, bfd_boolean volatilep,
1738130561Sobrien			   bfd_vma voffset, bfd_boolean contextp)
173933965Sjdp{
174033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
174133965Sjdp
1742130561Sobrien  return stab_class_method_var (info, physname, visibility, FALSE, constp,
174333965Sjdp				volatilep, voffset, contextp);
174433965Sjdp}
174533965Sjdp
174633965Sjdp/* Add a static variant to the current method.  */
174733965Sjdp
1748130561Sobrienstatic bfd_boolean
1749130561Sobrienstab_class_static_method_variant (void *p, const char *physname,
1750130561Sobrien				  enum debug_visibility visibility,
1751130561Sobrien				  bfd_boolean constp, bfd_boolean volatilep)
175233965Sjdp{
175333965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
175433965Sjdp
1755130561Sobrien  return stab_class_method_var (info, physname, visibility, TRUE, constp,
1756130561Sobrien				volatilep, 0, FALSE);
175733965Sjdp}
175833965Sjdp
175933965Sjdp/* Finish up a method.  */
176033965Sjdp
1761130561Sobrienstatic bfd_boolean
1762130561Sobrienstab_class_end_method (void *p)
176333965Sjdp{
176433965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
176533965Sjdp
176633965Sjdp  assert (info->type_stack != NULL && info->type_stack->methods != NULL);
176733965Sjdp
176833965Sjdp  /* We allocated enough room on info->type_stack->methods to add the
176933965Sjdp     trailing semicolon.  */
177033965Sjdp  strcat (info->type_stack->methods, ";");
177133965Sjdp
1772130561Sobrien  return TRUE;
177333965Sjdp}
177433965Sjdp
177533965Sjdp/* Finish up a class.  */
177633965Sjdp
1777130561Sobrienstatic bfd_boolean
1778130561Sobrienstab_end_class_type (void *p)
177933965Sjdp{
178033965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
178133965Sjdp  size_t len;
178238889Sjdp  unsigned int i = 0;
178333965Sjdp  char *buf;
178433965Sjdp
178533965Sjdp  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
178633965Sjdp
178733965Sjdp  /* Work out the size we need to allocate for the class definition.  */
178833965Sjdp
178933965Sjdp  len = (strlen (info->type_stack->string)
179033965Sjdp	 + strlen (info->type_stack->fields)
179133965Sjdp	 + 10);
179233965Sjdp  if (info->type_stack->baseclasses != NULL)
179333965Sjdp    {
179433965Sjdp      len += 20;
179533965Sjdp      for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
179633965Sjdp	len += strlen (info->type_stack->baseclasses[i]);
179733965Sjdp    }
179833965Sjdp  if (info->type_stack->methods != NULL)
179933965Sjdp    len += strlen (info->type_stack->methods);
180033965Sjdp  if (info->type_stack->vtable != NULL)
180133965Sjdp    len += strlen (info->type_stack->vtable);
180233965Sjdp
180333965Sjdp  /* Build the class definition.  */
180433965Sjdp
180533965Sjdp  buf = (char *) xmalloc (len);
180633965Sjdp
180733965Sjdp  strcpy (buf, info->type_stack->string);
180833965Sjdp
180933965Sjdp  if (info->type_stack->baseclasses != NULL)
181033965Sjdp    {
181133965Sjdp      sprintf (buf + strlen (buf), "!%u,", i);
181233965Sjdp      for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
181333965Sjdp	{
181433965Sjdp	  strcat (buf, info->type_stack->baseclasses[i]);
181533965Sjdp	  free (info->type_stack->baseclasses[i]);
181633965Sjdp	}
181733965Sjdp      free (info->type_stack->baseclasses);
181833965Sjdp      info->type_stack->baseclasses = NULL;
181933965Sjdp    }
182033965Sjdp
182133965Sjdp  strcat (buf, info->type_stack->fields);
182233965Sjdp  free (info->type_stack->fields);
182333965Sjdp  info->type_stack->fields = NULL;
182433965Sjdp
182533965Sjdp  if (info->type_stack->methods != NULL)
182633965Sjdp    {
182733965Sjdp      strcat (buf, info->type_stack->methods);
182833965Sjdp      free (info->type_stack->methods);
182933965Sjdp      info->type_stack->methods = NULL;
183033965Sjdp    }
183133965Sjdp
183233965Sjdp  strcat (buf, ";");
183333965Sjdp
183433965Sjdp  if (info->type_stack->vtable != NULL)
183533965Sjdp    {
183633965Sjdp      strcat (buf, info->type_stack->vtable);
183733965Sjdp      free (info->type_stack->vtable);
183833965Sjdp      info->type_stack->vtable = NULL;
183933965Sjdp    }
184033965Sjdp
184133965Sjdp  /* Replace the string on the top of the stack with the complete
184233965Sjdp     class definition.  */
184333965Sjdp  free (info->type_stack->string);
184433965Sjdp  info->type_stack->string = buf;
184533965Sjdp
1846130561Sobrien  return TRUE;
184733965Sjdp}
184833965Sjdp
184933965Sjdp/* Push a typedef which was previously defined.  */
185033965Sjdp
1851130561Sobrienstatic bfd_boolean
1852130561Sobrienstab_typedef_type (void *p, const char *name)
185333965Sjdp{
185433965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
185533965Sjdp  struct string_hash_entry *h;
185633965Sjdp
1857130561Sobrien  h = string_hash_lookup (&info->typedef_hash, name, FALSE, FALSE);
185833965Sjdp  assert (h != NULL && h->index > 0);
185933965Sjdp
186033965Sjdp  return stab_push_defined_type (info, h->index, h->size);
186133965Sjdp}
186233965Sjdp
186333965Sjdp/* Push a struct, union or class tag.  */
186433965Sjdp
1865130561Sobrienstatic bfd_boolean
1866130561Sobrienstab_tag_type (void *p, const char *name, unsigned int id,
1867130561Sobrien	       enum debug_type_kind kind)
186833965Sjdp{
186933965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
187033965Sjdp  long index;
1871218822Sdim  unsigned int size = 0;
187233965Sjdp
187333965Sjdp  index = stab_get_struct_index (info, name, id, kind, &size);
187433965Sjdp  if (index < 0)
1875130561Sobrien    return FALSE;
187633965Sjdp
187733965Sjdp  return stab_push_defined_type (info, index, size);
187833965Sjdp}
187933965Sjdp
188033965Sjdp/* Define a typedef.  */
188133965Sjdp
1882130561Sobrienstatic bfd_boolean
1883130561Sobrienstab_typdef (void *p, const char *name)
188433965Sjdp{
188533965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
188633965Sjdp  long index;
188733965Sjdp  unsigned int size;
188833965Sjdp  char *s, *buf;
188933965Sjdp  struct string_hash_entry *h;
189033965Sjdp
189133965Sjdp  index = info->type_stack->index;
189233965Sjdp  size = info->type_stack->size;
189333965Sjdp  s = stab_pop_type (info);
189433965Sjdp
189533965Sjdp  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
189633965Sjdp
189733965Sjdp  if (index > 0)
189833965Sjdp    sprintf (buf, "%s:t%s", name, s);
189933965Sjdp  else
190033965Sjdp    {
190133965Sjdp      index = info->type_index;
190233965Sjdp      ++info->type_index;
190333965Sjdp      sprintf (buf, "%s:t%ld=%s", name, index, s);
190433965Sjdp    }
190533965Sjdp
190633965Sjdp  free (s);
190733965Sjdp
190833965Sjdp  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1909130561Sobrien    return FALSE;
191033965Sjdp
191133965Sjdp  free (buf);
191233965Sjdp
1913130561Sobrien  h = string_hash_lookup (&info->typedef_hash, name, TRUE, FALSE);
191433965Sjdp  if (h == NULL)
191533965Sjdp    {
191660484Sobrien      non_fatal (_("string_hash_lookup failed: %s"),
191760484Sobrien		 bfd_errmsg (bfd_get_error ()));
1918130561Sobrien      return FALSE;
191933965Sjdp    }
192033965Sjdp
192133965Sjdp  /* I don't think we care about redefinitions.  */
192233965Sjdp
192333965Sjdp  h->index = index;
192433965Sjdp  h->size = size;
192533965Sjdp
1926130561Sobrien  return TRUE;
192733965Sjdp}
192833965Sjdp
192933965Sjdp/* Define a tag.  */
193033965Sjdp
1931130561Sobrienstatic bfd_boolean
1932130561Sobrienstab_tag (void *p, const char *tag)
193333965Sjdp{
193433965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
193533965Sjdp  char *s, *buf;
193633965Sjdp
193733965Sjdp  s = stab_pop_type (info);
193833965Sjdp
193933965Sjdp  buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3);
194033965Sjdp
194133965Sjdp  sprintf (buf, "%s:T%s", tag, s);
194233965Sjdp  free (s);
194333965Sjdp
194433965Sjdp  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1945130561Sobrien    return FALSE;
194633965Sjdp
194733965Sjdp  free (buf);
194833965Sjdp
1949130561Sobrien  return TRUE;
195033965Sjdp}
195133965Sjdp
195233965Sjdp/* Define an integer constant.  */
195333965Sjdp
1954130561Sobrienstatic bfd_boolean
1955130561Sobrienstab_int_constant (void *p, const char *name, bfd_vma val)
195633965Sjdp{
195733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
195833965Sjdp  char *buf;
195933965Sjdp
196033965Sjdp  buf = (char *) xmalloc (strlen (name) + 20);
196133965Sjdp  sprintf (buf, "%s:c=i%ld", name, (long) val);
196233965Sjdp
196333965Sjdp  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1964130561Sobrien    return FALSE;
196533965Sjdp
196633965Sjdp  free (buf);
196733965Sjdp
1968130561Sobrien  return TRUE;
196933965Sjdp}
197033965Sjdp
197133965Sjdp/* Define a floating point constant.  */
197233965Sjdp
1973130561Sobrienstatic bfd_boolean
1974130561Sobrienstab_float_constant (void *p, const char *name, double val)
197533965Sjdp{
197633965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
197733965Sjdp  char *buf;
197833965Sjdp
197933965Sjdp  buf = (char *) xmalloc (strlen (name) + 20);
198033965Sjdp  sprintf (buf, "%s:c=f%g", name, val);
198133965Sjdp
198233965Sjdp  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
1983130561Sobrien    return FALSE;
198433965Sjdp
198533965Sjdp  free (buf);
198633965Sjdp
1987130561Sobrien  return TRUE;
198833965Sjdp}
198933965Sjdp
199033965Sjdp/* Define a typed constant.  */
199133965Sjdp
1992130561Sobrienstatic bfd_boolean
1993130561Sobrienstab_typed_constant (void *p, const char *name, bfd_vma val)
199433965Sjdp{
199533965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
199633965Sjdp  char *s, *buf;
199733965Sjdp
199833965Sjdp  s = stab_pop_type (info);
199933965Sjdp
200033965Sjdp  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
200133965Sjdp  sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val);
200233965Sjdp  free (s);
200333965Sjdp
200433965Sjdp  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
2005130561Sobrien    return FALSE;
200633965Sjdp
200733965Sjdp  free (buf);
200833965Sjdp
2009130561Sobrien  return TRUE;
201033965Sjdp}
201133965Sjdp
201233965Sjdp/* Record a variable.  */
201333965Sjdp
2014130561Sobrienstatic bfd_boolean
2015130561Sobrienstab_variable (void *p, const char *name, enum debug_var_kind kind,
2016130561Sobrien	       bfd_vma val)
201733965Sjdp{
201833965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
201933965Sjdp  char *s, *buf;
202033965Sjdp  int stab_type;
202133965Sjdp  const char *kindstr;
202233965Sjdp
202333965Sjdp  s = stab_pop_type (info);
202433965Sjdp
202533965Sjdp  switch (kind)
202633965Sjdp    {
202733965Sjdp    default:
202833965Sjdp      abort ();
202933965Sjdp
203033965Sjdp    case DEBUG_GLOBAL:
203133965Sjdp      stab_type = N_GSYM;
203233965Sjdp      kindstr = "G";
203333965Sjdp      break;
203433965Sjdp
203533965Sjdp    case DEBUG_STATIC:
203633965Sjdp      stab_type = N_STSYM;
203733965Sjdp      kindstr = "S";
203833965Sjdp      break;
203933965Sjdp
204033965Sjdp    case DEBUG_LOCAL_STATIC:
204133965Sjdp      stab_type = N_STSYM;
204233965Sjdp      kindstr = "V";
204333965Sjdp      break;
204433965Sjdp
204533965Sjdp    case DEBUG_LOCAL:
204633965Sjdp      stab_type = N_LSYM;
204733965Sjdp      kindstr = "";
204833965Sjdp
204933965Sjdp      /* Make sure that this is a type reference or definition.  */
205089857Sobrien      if (! ISDIGIT (*s))
205133965Sjdp	{
205233965Sjdp	  char *n;
205333965Sjdp	  long index;
205433965Sjdp
205533965Sjdp	  index = info->type_index;
205633965Sjdp	  ++info->type_index;
205733965Sjdp	  n = (char *) xmalloc (strlen (s) + 20);
205833965Sjdp	  sprintf (n, "%ld=%s", index, s);
205933965Sjdp	  free (s);
206033965Sjdp	  s = n;
206133965Sjdp	}
206233965Sjdp      break;
206333965Sjdp
206433965Sjdp    case DEBUG_REGISTER:
206533965Sjdp      stab_type = N_RSYM;
206633965Sjdp      kindstr = "r";
206733965Sjdp      break;
206833965Sjdp    }
206933965Sjdp
207033965Sjdp  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
207133965Sjdp  sprintf (buf, "%s:%s%s", name, kindstr, s);
207233965Sjdp  free (s);
207333965Sjdp
207433965Sjdp  if (! stab_write_symbol (info, stab_type, 0, val, buf))
2075130561Sobrien    return FALSE;
207633965Sjdp
207733965Sjdp  free (buf);
207833965Sjdp
2079130561Sobrien  return TRUE;
208033965Sjdp}
208133965Sjdp
208233965Sjdp/* Start outputting a function.  */
208333965Sjdp
2084130561Sobrienstatic bfd_boolean
2085130561Sobrienstab_start_function (void *p, const char *name, bfd_boolean globalp)
208633965Sjdp{
208733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
208833965Sjdp  char *rettype, *buf;
208933965Sjdp
209033965Sjdp  assert (info->nesting == 0 && info->fun_offset == -1);
209133965Sjdp
209233965Sjdp  rettype = stab_pop_type (info);
209333965Sjdp
209433965Sjdp  buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3);
209533965Sjdp  sprintf (buf, "%s:%c%s", name,
209633965Sjdp	   globalp ? 'F' : 'f',
209733965Sjdp	   rettype);
209833965Sjdp
209933965Sjdp  /* We don't know the value now, so we set it in start_block.  */
210033965Sjdp  info->fun_offset = info->symbols_size;
210133965Sjdp
210233965Sjdp  if (! stab_write_symbol (info, N_FUN, 0, 0, buf))
2103130561Sobrien    return FALSE;
210433965Sjdp
210533965Sjdp  free (buf);
210633965Sjdp
2107130561Sobrien  return TRUE;
210833965Sjdp}
210933965Sjdp
211033965Sjdp/* Output a function parameter.  */
211133965Sjdp
2112130561Sobrienstatic bfd_boolean
2113130561Sobrienstab_function_parameter (void *p, const char *name, enum debug_parm_kind kind, bfd_vma val)
211433965Sjdp{
211533965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
211633965Sjdp  char *s, *buf;
211733965Sjdp  int stab_type;
211833965Sjdp  char kindc;
211933965Sjdp
212033965Sjdp  s = stab_pop_type (info);
212133965Sjdp
212233965Sjdp  switch (kind)
212333965Sjdp    {
212433965Sjdp    default:
212533965Sjdp      abort ();
212633965Sjdp
212733965Sjdp    case DEBUG_PARM_STACK:
212833965Sjdp      stab_type = N_PSYM;
212933965Sjdp      kindc = 'p';
213033965Sjdp      break;
213133965Sjdp
213233965Sjdp    case DEBUG_PARM_REG:
213333965Sjdp      stab_type = N_RSYM;
213433965Sjdp      kindc = 'P';
213533965Sjdp      break;
213633965Sjdp
213733965Sjdp    case DEBUG_PARM_REFERENCE:
213833965Sjdp      stab_type = N_PSYM;
213933965Sjdp      kindc = 'v';
214033965Sjdp      break;
214133965Sjdp
214233965Sjdp    case DEBUG_PARM_REF_REG:
214333965Sjdp      stab_type = N_RSYM;
214433965Sjdp      kindc = 'a';
214533965Sjdp      break;
214633965Sjdp    }
214733965Sjdp
214833965Sjdp  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
214933965Sjdp  sprintf (buf, "%s:%c%s", name, kindc, s);
215033965Sjdp  free (s);
215133965Sjdp
215233965Sjdp  if (! stab_write_symbol (info, stab_type, 0, val, buf))
2153130561Sobrien    return FALSE;
215433965Sjdp
215533965Sjdp  free (buf);
215633965Sjdp
2157130561Sobrien  return TRUE;
215833965Sjdp}
215933965Sjdp
216033965Sjdp/* Start a block.  */
216133965Sjdp
2162130561Sobrienstatic bfd_boolean
2163130561Sobrienstab_start_block (void *p, bfd_vma addr)
216433965Sjdp{
216533965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
216633965Sjdp
216733965Sjdp  /* Fill in any slots which have been waiting for the first known
216833965Sjdp     text address.  */
216933965Sjdp
217033965Sjdp  if (info->so_offset != -1)
217133965Sjdp    {
217233965Sjdp      bfd_put_32 (info->abfd, addr, info->symbols + info->so_offset + 8);
217333965Sjdp      info->so_offset = -1;
217433965Sjdp    }
217533965Sjdp
217633965Sjdp  if (info->fun_offset != -1)
217733965Sjdp    {
217833965Sjdp      bfd_put_32 (info->abfd, addr, info->symbols + info->fun_offset + 8);
217933965Sjdp      info->fun_offset = -1;
218033965Sjdp    }
218133965Sjdp
218233965Sjdp  ++info->nesting;
218333965Sjdp
218433965Sjdp  /* We will be called with a top level block surrounding the
218533965Sjdp     function, but stabs information does not output that block, so we
218633965Sjdp     ignore it.  */
218733965Sjdp
218833965Sjdp  if (info->nesting == 1)
218933965Sjdp    {
219033965Sjdp      info->fnaddr = addr;
2191130561Sobrien      return TRUE;
219233965Sjdp    }
219333965Sjdp
219433965Sjdp  /* We have to output the LBRAC symbol after any variables which are
219533965Sjdp     declared inside the block.  We postpone the LBRAC until the next
219633965Sjdp     start_block or end_block.  */
219733965Sjdp
219833965Sjdp  /* If we have postponed an LBRAC, output it now.  */
219933965Sjdp  if (info->pending_lbrac != (bfd_vma) -1)
220033965Sjdp    {
220133965Sjdp      if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
220233965Sjdp			       (const char *) NULL))
2203130561Sobrien	return FALSE;
220433965Sjdp    }
220533965Sjdp
220633965Sjdp  /* Remember the address and output it later.  */
220733965Sjdp
220833965Sjdp  info->pending_lbrac = addr - info->fnaddr;
220933965Sjdp
2210130561Sobrien  return TRUE;
221133965Sjdp}
221233965Sjdp
221333965Sjdp/* End a block.  */
221433965Sjdp
2215130561Sobrienstatic bfd_boolean
2216130561Sobrienstab_end_block (void *p, bfd_vma addr)
221733965Sjdp{
221833965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
221933965Sjdp
222033965Sjdp  if (addr > info->last_text_address)
222133965Sjdp    info->last_text_address = addr;
222233965Sjdp
222333965Sjdp  /* If we have postponed an LBRAC, output it now.  */
222433965Sjdp  if (info->pending_lbrac != (bfd_vma) -1)
222533965Sjdp    {
222633965Sjdp      if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
222733965Sjdp			       (const char *) NULL))
2228130561Sobrien	return FALSE;
222933965Sjdp      info->pending_lbrac = (bfd_vma) -1;
223033965Sjdp    }
223133965Sjdp
223233965Sjdp  assert (info->nesting > 0);
223333965Sjdp
223433965Sjdp  --info->nesting;
223533965Sjdp
223633965Sjdp  /* We ignore the outermost block.  */
223733965Sjdp  if (info->nesting == 0)
2238130561Sobrien    return TRUE;
223933965Sjdp
224033965Sjdp  return stab_write_symbol (info, N_RBRAC, 0, addr - info->fnaddr,
224133965Sjdp			    (const char *) NULL);
224233965Sjdp}
224333965Sjdp
224433965Sjdp/* End a function.  */
224533965Sjdp
2246130561Sobrienstatic bfd_boolean
2247130561Sobrienstab_end_function (void *p ATTRIBUTE_UNUSED)
224833965Sjdp{
2249130561Sobrien  return TRUE;
225033965Sjdp}
225133965Sjdp
225233965Sjdp/* Output a line number.  */
225333965Sjdp
2254130561Sobrienstatic bfd_boolean
2255130561Sobrienstab_lineno (void *p, const char *file, unsigned long lineno, bfd_vma addr)
225633965Sjdp{
225733965Sjdp  struct stab_write_handle *info = (struct stab_write_handle *) p;
225833965Sjdp
225933965Sjdp  assert (info->lineno_filename != NULL);
226033965Sjdp
226133965Sjdp  if (addr > info->last_text_address)
226233965Sjdp    info->last_text_address = addr;
226333965Sjdp
226433965Sjdp  if (strcmp (file, info->lineno_filename) != 0)
226533965Sjdp    {
226633965Sjdp      if (! stab_write_symbol (info, N_SOL, 0, addr, file))
2267130561Sobrien	return FALSE;
226833965Sjdp      info->lineno_filename = file;
226933965Sjdp    }
227033965Sjdp
227133965Sjdp  return stab_write_symbol (info, N_SLINE, lineno, addr - info->fnaddr,
227233965Sjdp			    (const char *) NULL);
227333965Sjdp}
2274