133965Sjdp/* stabs.c -- Parse COFF debugging information
2218822Sdim   Copyright 1996, 1999, 2000, 2002, 2003, 2007
3218822Sdim   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 parses COFF debugging information.  */
2433965Sjdp
25218822Sdim#include "sysdep.h"
2633965Sjdp#include "bfd.h"
2733965Sjdp#include "coff/internal.h"
28218822Sdim#include "libiberty.h"
2933965Sjdp#include "bucomm.h"
3033965Sjdp#include "debug.h"
3133965Sjdp#include "budbg.h"
3233965Sjdp
3333965Sjdp/* FIXME: We should not need this BFD internal file.  We need it for
3433965Sjdp   the N_BTMASK, etc., values.  */
3533965Sjdp#include "libcoff.h"
3633965Sjdp
3733965Sjdp/* These macros extract the right mask and shifts for this BFD.  They
3833965Sjdp   assume that there is a local variable named ABFD.  This is so that
3933965Sjdp   macros like ISFCN and DECREF, from coff/internal.h, will work
4033965Sjdp   without modification.  */
4133965Sjdp#define N_BTMASK (coff_data (abfd)->local_n_btmask)
4233965Sjdp#define	N_BTSHFT (coff_data (abfd)->local_n_btshft)
4333965Sjdp#define	N_TMASK  (coff_data (abfd)->local_n_tmask)
4433965Sjdp#define	N_TSHIFT (coff_data (abfd)->local_n_tshift)
4533965Sjdp
4633965Sjdp/* This structure is used to hold the symbols, as well as the current
4733965Sjdp   location within the symbols.  */
4833965Sjdp
4933965Sjdpstruct coff_symbols
5033965Sjdp{
5133965Sjdp  /* The symbols.  */
5233965Sjdp  asymbol **syms;
5333965Sjdp  /* The number of symbols.  */
5433965Sjdp  long symcount;
5533965Sjdp  /* The index of the current symbol.  */
5633965Sjdp  long symno;
5733965Sjdp  /* The index of the current symbol in the COFF symbol table (where
5833965Sjdp     each auxent counts as a symbol).  */
5933965Sjdp  long coff_symno;
6033965Sjdp};
6133965Sjdp
6233965Sjdp/* The largest basic type we are prepared to handle.  */
6333965Sjdp
6433965Sjdp#define T_MAX (T_LNGDBL)
6533965Sjdp
6633965Sjdp/* This structure is used to hold slots.  */
6733965Sjdp
6833965Sjdpstruct coff_slots
6933965Sjdp{
7033965Sjdp  /* Next set of slots.  */
7133965Sjdp  struct coff_slots *next;
7233965Sjdp  /* Slots.  */
7333965Sjdp#define COFF_SLOTS (16)
7433965Sjdp  debug_type slots[COFF_SLOTS];
7533965Sjdp};
7633965Sjdp
7733965Sjdp/* This structure is used to map symbol indices to types.  */
7833965Sjdp
7933965Sjdpstruct coff_types
8033965Sjdp{
8133965Sjdp  /* Slots.  */
8233965Sjdp  struct coff_slots *slots;
8333965Sjdp  /* Basic types.  */
8433965Sjdp  debug_type basic[T_MAX + 1];
8533965Sjdp};
8633965Sjdp
87130561Sobrienstatic debug_type *coff_get_slot (struct coff_types *, int);
8833965Sjdpstatic debug_type parse_coff_type
89130561Sobrien  (bfd *, struct coff_symbols *, struct coff_types *, long, int,
90130561Sobrien   union internal_auxent *, bfd_boolean, void *);
9133965Sjdpstatic debug_type parse_coff_base_type
92130561Sobrien  (bfd *, struct coff_symbols *, struct coff_types *, long, int,
93130561Sobrien   union internal_auxent *, void *);
9433965Sjdpstatic debug_type parse_coff_struct_type
95130561Sobrien  (bfd *, struct coff_symbols *, struct coff_types *, int,
96130561Sobrien   union internal_auxent *, void *);
9733965Sjdpstatic debug_type parse_coff_enum_type
98130561Sobrien  (bfd *, struct coff_symbols *, struct coff_types *,
99130561Sobrien   union internal_auxent *, void *);
100130561Sobrienstatic bfd_boolean parse_coff_symbol
101130561Sobrien  (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *,
102130561Sobrien   void *, debug_type, bfd_boolean);
103130561Sobrienstatic bfd_boolean external_coff_symbol_p (int sym_class);
10433965Sjdp
10533965Sjdp/* Return the slot for a type.  */
10633965Sjdp
10733965Sjdpstatic debug_type *
108130561Sobriencoff_get_slot (struct coff_types *types, int indx)
10933965Sjdp{
11033965Sjdp  struct coff_slots **pps;
11133965Sjdp
11233965Sjdp  pps = &types->slots;
11333965Sjdp
11433965Sjdp  while (indx >= COFF_SLOTS)
11533965Sjdp    {
11633965Sjdp      if (*pps == NULL)
11733965Sjdp	{
11833965Sjdp	  *pps = (struct coff_slots *) xmalloc (sizeof **pps);
11933965Sjdp	  memset (*pps, 0, sizeof **pps);
12033965Sjdp	}
12133965Sjdp      pps = &(*pps)->next;
12233965Sjdp      indx -= COFF_SLOTS;
12333965Sjdp    }
12433965Sjdp
12533965Sjdp  if (*pps == NULL)
12633965Sjdp    {
12733965Sjdp      *pps = (struct coff_slots *) xmalloc (sizeof **pps);
12833965Sjdp      memset (*pps, 0, sizeof **pps);
12933965Sjdp    }
13033965Sjdp
13133965Sjdp  return (*pps)->slots + indx;
13233965Sjdp}
13333965Sjdp
13433965Sjdp/* Parse a COFF type code in NTYPE.  */
13533965Sjdp
13633965Sjdpstatic debug_type
137130561Sobrienparse_coff_type (bfd *abfd, struct coff_symbols *symbols,
138130561Sobrien		 struct coff_types *types, long coff_symno, int ntype,
139130561Sobrien		 union internal_auxent *pauxent, bfd_boolean useaux,
140130561Sobrien		 void *dhandle)
14133965Sjdp{
14233965Sjdp  debug_type type;
14333965Sjdp
14433965Sjdp  if ((ntype & ~N_BTMASK) != 0)
14533965Sjdp    {
14633965Sjdp      int newtype;
14733965Sjdp
14833965Sjdp      newtype = DECREF (ntype);
14933965Sjdp
15033965Sjdp      if (ISPTR (ntype))
15133965Sjdp	{
15233965Sjdp	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
15333965Sjdp				  pauxent, useaux, dhandle);
15433965Sjdp	  type = debug_make_pointer_type (dhandle, type);
15533965Sjdp	}
15633965Sjdp      else if (ISFCN (ntype))
15733965Sjdp	{
15833965Sjdp	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
15933965Sjdp				  pauxent, useaux, dhandle);
16033965Sjdp	  type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
161130561Sobrien					   FALSE);
16233965Sjdp	}
16333965Sjdp      else if (ISARY (ntype))
16433965Sjdp	{
16533965Sjdp	  int n;
16633965Sjdp
16733965Sjdp	  if (pauxent == NULL)
16833965Sjdp	    n = 0;
16933965Sjdp	  else
17033965Sjdp	    {
17133965Sjdp	      unsigned short *dim;
17233965Sjdp	      int i;
17333965Sjdp
17433965Sjdp	      /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
17533965Sjdp                 the c_naux field of the syment to 0.  */
17633965Sjdp
17733965Sjdp	      /* Move the dimensions down, so that the next array
17833965Sjdp                 picks up the next one.  */
17933965Sjdp	      dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
18033965Sjdp	      n = dim[0];
18133965Sjdp	      for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
18233965Sjdp		*dim = *(dim + 1);
18333965Sjdp	      *dim = 0;
18433965Sjdp	    }
18533965Sjdp
18633965Sjdp	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
187130561Sobrien				  pauxent, FALSE, dhandle);
18833965Sjdp	  type = debug_make_array_type (dhandle, type,
18933965Sjdp					parse_coff_base_type (abfd, symbols,
19033965Sjdp							      types,
19133965Sjdp							      coff_symno,
19233965Sjdp							      T_INT,
19333965Sjdp							      NULL, dhandle),
194130561Sobrien					0, n - 1, FALSE);
19533965Sjdp	}
19633965Sjdp      else
19733965Sjdp	{
19860484Sobrien	  non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype);
19933965Sjdp	  return DEBUG_TYPE_NULL;
20033965Sjdp	}
20133965Sjdp
20233965Sjdp      return type;
20333965Sjdp    }
20433965Sjdp
20533965Sjdp  if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
20633965Sjdp    {
20733965Sjdp      debug_type *slot;
20833965Sjdp
20933965Sjdp      /* This is a reference to an existing type.  FIXME: gdb checks
21033965Sjdp	 that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG.  */
21133965Sjdp      slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
21233965Sjdp      if (*slot != DEBUG_TYPE_NULL)
21333965Sjdp	return *slot;
21433965Sjdp      else
21533965Sjdp	return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
21633965Sjdp    }
21733965Sjdp
21833965Sjdp  /* If the aux entry has already been used for something, useaux will
21933965Sjdp     have been set to false, indicating that parse_coff_base_type
22033965Sjdp     should not use it.  We need to do it this way, rather than simply
22133965Sjdp     passing pauxent as NULL, because we need to be able handle
22233965Sjdp     multiple array dimensions while still discarding pauxent after
22333965Sjdp     having handled all of them.  */
22433965Sjdp  if (! useaux)
22533965Sjdp    pauxent = NULL;
22633965Sjdp
22733965Sjdp  return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
22833965Sjdp			       pauxent, dhandle);
22933965Sjdp}
23033965Sjdp
23133965Sjdp/* Parse a basic COFF type in NTYPE.  */
23233965Sjdp
23333965Sjdpstatic debug_type
234130561Sobrienparse_coff_base_type (bfd *abfd, struct coff_symbols *symbols,
235130561Sobrien		      struct coff_types *types, long coff_symno, int ntype,
236130561Sobrien		      union internal_auxent *pauxent, void *dhandle)
23733965Sjdp{
23833965Sjdp  debug_type ret;
239130561Sobrien  bfd_boolean set_basic;
24033965Sjdp  const char *name;
24133965Sjdp  debug_type *slot;
24233965Sjdp
24333965Sjdp  if (ntype >= 0
24433965Sjdp      && ntype <= T_MAX
24533965Sjdp      && types->basic[ntype] != DEBUG_TYPE_NULL)
24633965Sjdp    return types->basic[ntype];
24733965Sjdp
248130561Sobrien  set_basic = TRUE;
24933965Sjdp  name = NULL;
25033965Sjdp
25133965Sjdp  switch (ntype)
25233965Sjdp    {
25333965Sjdp    default:
25433965Sjdp      ret = debug_make_void_type (dhandle);
25533965Sjdp      break;
25633965Sjdp
25733965Sjdp    case T_NULL:
25833965Sjdp    case T_VOID:
25933965Sjdp      ret = debug_make_void_type (dhandle);
26033965Sjdp      name = "void";
26133965Sjdp      break;
26233965Sjdp
26333965Sjdp    case T_CHAR:
264130561Sobrien      ret = debug_make_int_type (dhandle, 1, FALSE);
26533965Sjdp      name = "char";
26633965Sjdp      break;
26733965Sjdp
26833965Sjdp    case T_SHORT:
269130561Sobrien      ret = debug_make_int_type (dhandle, 2, FALSE);
27033965Sjdp      name = "short";
27133965Sjdp      break;
27233965Sjdp
27333965Sjdp    case T_INT:
27433965Sjdp      /* FIXME: Perhaps the size should depend upon the architecture.  */
275130561Sobrien      ret = debug_make_int_type (dhandle, 4, FALSE);
27633965Sjdp      name = "int";
27733965Sjdp      break;
27833965Sjdp
27933965Sjdp    case T_LONG:
280130561Sobrien      ret = debug_make_int_type (dhandle, 4, FALSE);
28133965Sjdp      name = "long";
28233965Sjdp      break;
28333965Sjdp
28433965Sjdp    case T_FLOAT:
28533965Sjdp      ret = debug_make_float_type (dhandle, 4);
28633965Sjdp      name = "float";
28733965Sjdp      break;
28833965Sjdp
28933965Sjdp    case T_DOUBLE:
29033965Sjdp      ret = debug_make_float_type (dhandle, 8);
29133965Sjdp      name = "double";
29233965Sjdp      break;
29333965Sjdp
29433965Sjdp    case T_LNGDBL:
29533965Sjdp      ret = debug_make_float_type (dhandle, 12);
29633965Sjdp      name = "long double";
29733965Sjdp      break;
29833965Sjdp
29933965Sjdp    case T_UCHAR:
300130561Sobrien      ret = debug_make_int_type (dhandle, 1, TRUE);
30133965Sjdp      name = "unsigned char";
30233965Sjdp      break;
30333965Sjdp
30433965Sjdp    case T_USHORT:
305130561Sobrien      ret = debug_make_int_type (dhandle, 2, TRUE);
30633965Sjdp      name = "unsigned short";
30733965Sjdp      break;
30833965Sjdp
30933965Sjdp    case T_UINT:
310130561Sobrien      ret = debug_make_int_type (dhandle, 4, TRUE);
31133965Sjdp      name = "unsigned int";
31233965Sjdp      break;
31333965Sjdp
31433965Sjdp    case T_ULONG:
315130561Sobrien      ret = debug_make_int_type (dhandle, 4, TRUE);
31633965Sjdp      name = "unsigned long";
31733965Sjdp      break;
31833965Sjdp
31933965Sjdp    case T_STRUCT:
32033965Sjdp      if (pauxent == NULL)
321130561Sobrien	ret = debug_make_struct_type (dhandle, TRUE, 0,
32233965Sjdp				      (debug_field *) NULL);
32333965Sjdp      else
32433965Sjdp	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
32533965Sjdp				      dhandle);
32633965Sjdp
32733965Sjdp      slot = coff_get_slot (types, coff_symno);
32833965Sjdp      *slot = ret;
32933965Sjdp
330130561Sobrien      set_basic = FALSE;
33133965Sjdp      break;
33233965Sjdp
33333965Sjdp    case T_UNION:
33433965Sjdp      if (pauxent == NULL)
335130561Sobrien	ret = debug_make_struct_type (dhandle, FALSE, 0, (debug_field *) NULL);
33633965Sjdp      else
33733965Sjdp	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
33833965Sjdp				      dhandle);
33933965Sjdp
34033965Sjdp      slot = coff_get_slot (types, coff_symno);
34133965Sjdp      *slot = ret;
34233965Sjdp
343130561Sobrien      set_basic = FALSE;
34433965Sjdp      break;
34533965Sjdp
34633965Sjdp    case T_ENUM:
34733965Sjdp      if (pauxent == NULL)
34833965Sjdp	ret = debug_make_enum_type (dhandle, (const char **) NULL,
34933965Sjdp				    (bfd_signed_vma *) NULL);
35033965Sjdp      else
35133965Sjdp	ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
35233965Sjdp
35333965Sjdp      slot = coff_get_slot (types, coff_symno);
35433965Sjdp      *slot = ret;
35533965Sjdp
356130561Sobrien      set_basic = FALSE;
35733965Sjdp      break;
35833965Sjdp    }
35933965Sjdp
36033965Sjdp  if (name != NULL)
36133965Sjdp    ret = debug_name_type (dhandle, name, ret);
36233965Sjdp
36333965Sjdp  if (set_basic
36433965Sjdp      && ntype >= 0
36533965Sjdp      && ntype <= T_MAX)
36633965Sjdp    types->basic[ntype] = ret;
36733965Sjdp
36833965Sjdp  return ret;
36933965Sjdp}
37033965Sjdp
37133965Sjdp/* Parse a struct type.  */
37233965Sjdp
37333965Sjdpstatic debug_type
374130561Sobrienparse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols,
375130561Sobrien			struct coff_types *types, int ntype,
376130561Sobrien			union internal_auxent *pauxent, void *dhandle)
37733965Sjdp{
37833965Sjdp  long symend;
37933965Sjdp  int alloc;
38033965Sjdp  debug_field *fields;
38133965Sjdp  int count;
382130561Sobrien  bfd_boolean done;
38333965Sjdp
38433965Sjdp  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
38533965Sjdp
38633965Sjdp  alloc = 10;
38733965Sjdp  fields = (debug_field *) xmalloc (alloc * sizeof *fields);
38833965Sjdp  count = 0;
38933965Sjdp
390130561Sobrien  done = FALSE;
39133965Sjdp  while (! done
39233965Sjdp	 && symbols->coff_symno < symend
39333965Sjdp	 && symbols->symno < symbols->symcount)
39433965Sjdp    {
39533965Sjdp      asymbol *sym;
39633965Sjdp      long this_coff_symno;
39733965Sjdp      struct internal_syment syment;
39833965Sjdp      union internal_auxent auxent;
39933965Sjdp      union internal_auxent *psubaux;
40033965Sjdp      bfd_vma bitpos = 0, bitsize = 0;
40133965Sjdp
40233965Sjdp      sym = symbols->syms[symbols->symno];
40333965Sjdp
40433965Sjdp      if (! bfd_coff_get_syment (abfd, sym, &syment))
40533965Sjdp	{
40660484Sobrien	  non_fatal (_("bfd_coff_get_syment failed: %s"),
40760484Sobrien		     bfd_errmsg (bfd_get_error ()));
40833965Sjdp	  return DEBUG_TYPE_NULL;
40933965Sjdp	}
41033965Sjdp
41133965Sjdp      this_coff_symno = symbols->coff_symno;
41233965Sjdp
41333965Sjdp      ++symbols->symno;
41433965Sjdp      symbols->coff_symno += 1 + syment.n_numaux;
41533965Sjdp
41633965Sjdp      if (syment.n_numaux == 0)
41733965Sjdp	psubaux = NULL;
41833965Sjdp      else
41933965Sjdp	{
42033965Sjdp	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
42133965Sjdp	    {
42260484Sobrien	      non_fatal (_("bfd_coff_get_auxent failed: %s"),
42360484Sobrien			 bfd_errmsg (bfd_get_error ()));
42433965Sjdp	      return DEBUG_TYPE_NULL;
42533965Sjdp	    }
42633965Sjdp	  psubaux = &auxent;
42733965Sjdp	}
42833965Sjdp
42933965Sjdp      switch (syment.n_sclass)
43033965Sjdp	{
43133965Sjdp	case C_MOS:
43233965Sjdp	case C_MOU:
43333965Sjdp	  bitpos = 8 * bfd_asymbol_value (sym);
43433965Sjdp	  bitsize = 0;
43533965Sjdp	  break;
43633965Sjdp
43733965Sjdp	case C_FIELD:
43833965Sjdp	  bitpos = bfd_asymbol_value (sym);
43933965Sjdp	  bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
44033965Sjdp	  break;
44133965Sjdp
44233965Sjdp	case C_EOS:
443130561Sobrien	  done = TRUE;
44433965Sjdp	  break;
44533965Sjdp	}
44633965Sjdp
44733965Sjdp      if (! done)
44833965Sjdp	{
44933965Sjdp	  debug_type ftype;
45033965Sjdp	  debug_field f;
45133965Sjdp
45233965Sjdp	  ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
453130561Sobrien				   syment.n_type, psubaux, TRUE, dhandle);
45433965Sjdp	  f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
45533965Sjdp				bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
45633965Sjdp	  if (f == DEBUG_FIELD_NULL)
45733965Sjdp	    return DEBUG_TYPE_NULL;
45833965Sjdp
45933965Sjdp	  if (count + 1 >= alloc)
46033965Sjdp	    {
46133965Sjdp	      alloc += 10;
46233965Sjdp	      fields = ((debug_field *)
46333965Sjdp			xrealloc (fields, alloc * sizeof *fields));
46433965Sjdp	    }
46533965Sjdp
46633965Sjdp	  fields[count] = f;
46733965Sjdp	  ++count;
46833965Sjdp	}
46933965Sjdp    }
47033965Sjdp
47133965Sjdp  fields[count] = DEBUG_FIELD_NULL;
47233965Sjdp
47333965Sjdp  return debug_make_struct_type (dhandle, ntype == T_STRUCT,
47433965Sjdp				 pauxent->x_sym.x_misc.x_lnsz.x_size,
47533965Sjdp				 fields);
47633965Sjdp}
47733965Sjdp
47833965Sjdp/* Parse an enum type.  */
47933965Sjdp
48033965Sjdpstatic debug_type
481130561Sobrienparse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols,
482130561Sobrien		      struct coff_types *types ATTRIBUTE_UNUSED,
483130561Sobrien		      union internal_auxent *pauxent, void *dhandle)
48433965Sjdp{
48533965Sjdp  long symend;
48633965Sjdp  int alloc;
48733965Sjdp  const char **names;
48833965Sjdp  bfd_signed_vma *vals;
48933965Sjdp  int count;
490130561Sobrien  bfd_boolean done;
49133965Sjdp
49233965Sjdp  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
49333965Sjdp
49433965Sjdp  alloc = 10;
49533965Sjdp  names = (const char **) xmalloc (alloc * sizeof *names);
49633965Sjdp  vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
49733965Sjdp  count = 0;
49833965Sjdp
499130561Sobrien  done = FALSE;
50033965Sjdp  while (! done
50133965Sjdp	 && symbols->coff_symno < symend
50233965Sjdp	 && symbols->symno < symbols->symcount)
50333965Sjdp    {
50433965Sjdp      asymbol *sym;
50533965Sjdp      struct internal_syment syment;
50633965Sjdp
50733965Sjdp      sym = symbols->syms[symbols->symno];
50833965Sjdp
50933965Sjdp      if (! bfd_coff_get_syment (abfd, sym, &syment))
51033965Sjdp	{
51160484Sobrien	  non_fatal (_("bfd_coff_get_syment failed: %s"),
51260484Sobrien		     bfd_errmsg (bfd_get_error ()));
51333965Sjdp	  return DEBUG_TYPE_NULL;
51433965Sjdp	}
51533965Sjdp
51633965Sjdp      ++symbols->symno;
51733965Sjdp      symbols->coff_symno += 1 + syment.n_numaux;
51833965Sjdp
51933965Sjdp      switch (syment.n_sclass)
52033965Sjdp	{
52133965Sjdp	case C_MOE:
52233965Sjdp	  if (count + 1 >= alloc)
52333965Sjdp	    {
52433965Sjdp	      alloc += 10;
52533965Sjdp	      names = ((const char **)
52633965Sjdp		       xrealloc (names, alloc * sizeof *names));
52733965Sjdp	      vals = ((bfd_signed_vma *)
52833965Sjdp		      xrealloc (vals, alloc * sizeof *vals));
52933965Sjdp	    }
53033965Sjdp
53133965Sjdp	  names[count] = bfd_asymbol_name (sym);
53233965Sjdp	  vals[count] = bfd_asymbol_value (sym);
53333965Sjdp	  ++count;
53433965Sjdp	  break;
53533965Sjdp
53633965Sjdp	case C_EOS:
537130561Sobrien	  done = TRUE;
53833965Sjdp	  break;
53933965Sjdp	}
54033965Sjdp    }
54133965Sjdp
54233965Sjdp  names[count] = NULL;
54333965Sjdp
54433965Sjdp  return debug_make_enum_type (dhandle, names, vals);
54533965Sjdp}
54633965Sjdp
54733965Sjdp/* Handle a single COFF symbol.  */
54833965Sjdp
549130561Sobrienstatic bfd_boolean
550130561Sobrienparse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types,
551130561Sobrien		   asymbol *sym, long coff_symno,
552130561Sobrien		   struct internal_syment *psyment, void *dhandle,
553130561Sobrien		   debug_type type, bfd_boolean within_function)
55433965Sjdp{
55533965Sjdp  switch (psyment->n_sclass)
55633965Sjdp    {
55733965Sjdp    case C_NULL:
55833965Sjdp      break;
55933965Sjdp
56033965Sjdp    case C_AUTO:
56133965Sjdp      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
56233965Sjdp				   DEBUG_LOCAL, bfd_asymbol_value (sym)))
563130561Sobrien	return FALSE;
56433965Sjdp      break;
56533965Sjdp
56677298Sobrien    case C_WEAKEXT:
56733965Sjdp    case C_EXT:
56833965Sjdp      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
56933965Sjdp				   DEBUG_GLOBAL, bfd_asymbol_value (sym)))
570130561Sobrien	return FALSE;
57133965Sjdp      break;
57233965Sjdp
57333965Sjdp    case C_STAT:
57433965Sjdp      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
57533965Sjdp				   (within_function
57633965Sjdp				    ? DEBUG_LOCAL_STATIC
57733965Sjdp				    : DEBUG_STATIC),
57833965Sjdp				   bfd_asymbol_value (sym)))
579130561Sobrien	return FALSE;
58033965Sjdp      break;
58133965Sjdp
58233965Sjdp    case C_REG:
58333965Sjdp      /* FIXME: We may need to convert the register number.  */
58433965Sjdp      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
58533965Sjdp				   DEBUG_REGISTER, bfd_asymbol_value (sym)))
586130561Sobrien	return FALSE;
58733965Sjdp      break;
58833965Sjdp
58933965Sjdp    case C_LABEL:
59033965Sjdp      break;
59133965Sjdp
59233965Sjdp    case C_ARG:
59333965Sjdp      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
59433965Sjdp				    DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
595130561Sobrien	return FALSE;
59633965Sjdp      break;
59733965Sjdp
59833965Sjdp    case C_REGPARM:
59933965Sjdp      /* FIXME: We may need to convert the register number.  */
60033965Sjdp      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
60133965Sjdp				    DEBUG_PARM_REG, bfd_asymbol_value (sym)))
602130561Sobrien	return FALSE;
60333965Sjdp      break;
60433965Sjdp
60533965Sjdp    case C_TPDEF:
60633965Sjdp      type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
60733965Sjdp      if (type == DEBUG_TYPE_NULL)
608130561Sobrien	return FALSE;
60933965Sjdp      break;
61033965Sjdp
61133965Sjdp    case C_STRTAG:
61233965Sjdp    case C_UNTAG:
61333965Sjdp    case C_ENTAG:
61433965Sjdp      {
61533965Sjdp	debug_type *slot;
61633965Sjdp
61733965Sjdp	type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
61833965Sjdp	if (type == DEBUG_TYPE_NULL)
619130561Sobrien	  return FALSE;
62033965Sjdp
62133965Sjdp	/* Store the named type into the slot, so that references get
62233965Sjdp           the name.  */
62333965Sjdp	slot = coff_get_slot (types, coff_symno);
62433965Sjdp	*slot = type;
62533965Sjdp      }
62633965Sjdp      break;
62733965Sjdp
62833965Sjdp    default:
62933965Sjdp      break;
63033965Sjdp    }
63133965Sjdp
632130561Sobrien  return TRUE;
63333965Sjdp}
63433965Sjdp
63577298Sobrien/* Determine if a symbol has external visibility.  */
63677298Sobrien
637130561Sobrienstatic bfd_boolean
638130561Sobrienexternal_coff_symbol_p (int sym_class)
63977298Sobrien{
64077298Sobrien  switch (sym_class)
64177298Sobrien    {
642104834Sobrien    case C_EXT:
643104834Sobrien    case C_WEAKEXT:
644130561Sobrien      return TRUE;
64577298Sobrien    default:
64677298Sobrien      break;
64777298Sobrien    }
648130561Sobrien  return FALSE;
64977298Sobrien}
65077298Sobrien
65133965Sjdp/* This is the main routine.  It looks through all the symbols and
65233965Sjdp   handles them.  */
65333965Sjdp
654130561Sobrienbfd_boolean
655130561Sobrienparse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle)
65633965Sjdp{
65733965Sjdp  struct coff_symbols symbols;
65833965Sjdp  struct coff_types types;
65933965Sjdp  int i;
66033965Sjdp  long next_c_file;
66133965Sjdp  const char *fnname;
66233965Sjdp  int fnclass;
66333965Sjdp  int fntype;
66433965Sjdp  bfd_vma fnend;
66533965Sjdp  alent *linenos;
666130561Sobrien  bfd_boolean within_function;
66733965Sjdp  long this_coff_symno;
66833965Sjdp
66933965Sjdp  symbols.syms = syms;
67033965Sjdp  symbols.symcount = symcount;
67133965Sjdp  symbols.symno = 0;
67233965Sjdp  symbols.coff_symno = 0;
67333965Sjdp
67433965Sjdp  types.slots = NULL;
67533965Sjdp  for (i = 0; i <= T_MAX; i++)
67633965Sjdp    types.basic[i] = DEBUG_TYPE_NULL;
67733965Sjdp
67833965Sjdp  next_c_file = -1;
67933965Sjdp  fnname = NULL;
68033965Sjdp  fnclass = 0;
68133965Sjdp  fntype = 0;
68233965Sjdp  fnend = 0;
68333965Sjdp  linenos = NULL;
684130561Sobrien  within_function = FALSE;
68533965Sjdp
68633965Sjdp  while (symbols.symno < symcount)
68733965Sjdp    {
68833965Sjdp      asymbol *sym;
68933965Sjdp      const char *name;
69033965Sjdp      struct internal_syment syment;
69133965Sjdp      union internal_auxent auxent;
69233965Sjdp      union internal_auxent *paux;
69333965Sjdp      debug_type type;
69433965Sjdp
69533965Sjdp      sym = syms[symbols.symno];
69633965Sjdp
69733965Sjdp      if (! bfd_coff_get_syment (abfd, sym, &syment))
69833965Sjdp	{
69960484Sobrien	  non_fatal (_("bfd_coff_get_syment failed: %s"),
70060484Sobrien		     bfd_errmsg (bfd_get_error ()));
701130561Sobrien	  return FALSE;
70233965Sjdp	}
70333965Sjdp
70433965Sjdp      name = bfd_asymbol_name (sym);
70533965Sjdp
70633965Sjdp      this_coff_symno = symbols.coff_symno;
70733965Sjdp
70833965Sjdp      ++symbols.symno;
70933965Sjdp      symbols.coff_symno += 1 + syment.n_numaux;
71033965Sjdp
71133965Sjdp      /* We only worry about the first auxent, because that is the
71233965Sjdp	 only one which is relevant for debugging information.  */
71333965Sjdp      if (syment.n_numaux == 0)
71433965Sjdp	paux = NULL;
71533965Sjdp      else
71633965Sjdp	{
71733965Sjdp	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
71833965Sjdp	    {
71960484Sobrien	      non_fatal (_("bfd_coff_get_auxent failed: %s"),
72060484Sobrien			 bfd_errmsg (bfd_get_error ()));
721130561Sobrien	      return FALSE;
72233965Sjdp	    }
72333965Sjdp	  paux = &auxent;
72433965Sjdp	}
72533965Sjdp
72633965Sjdp      if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
72733965Sjdp	{
72833965Sjdp	  /* The last C_FILE symbol points to the first external
72933965Sjdp             symbol.  */
73033965Sjdp	  if (! debug_set_filename (dhandle, "*globals*"))
731130561Sobrien	    return FALSE;
73233965Sjdp	}
73333965Sjdp
73433965Sjdp      switch (syment.n_sclass)
73533965Sjdp	{
73633965Sjdp	case C_EFCN:
73733965Sjdp	case C_EXTDEF:
73833965Sjdp	case C_ULABEL:
73933965Sjdp	case C_USTATIC:
74033965Sjdp	case C_LINE:
74133965Sjdp	case C_ALIAS:
74233965Sjdp	case C_HIDDEN:
74333965Sjdp	  /* Just ignore these classes.  */
74433965Sjdp	  break;
74533965Sjdp
74633965Sjdp	case C_FILE:
74733965Sjdp	  next_c_file = syment.n_value;
74833965Sjdp	  if (! debug_set_filename (dhandle, name))
749130561Sobrien	    return FALSE;
75033965Sjdp	  break;
75133965Sjdp
75233965Sjdp	case C_STAT:
75333965Sjdp	  /* Ignore static symbols with a type of T_NULL.  These
75433965Sjdp             represent section entries.  */
75533965Sjdp	  if (syment.n_type == T_NULL)
75633965Sjdp	    break;
75733965Sjdp	  /* Fall through.  */
758104834Sobrien	case C_WEAKEXT:
75933965Sjdp	case C_EXT:
76033965Sjdp	  if (ISFCN (syment.n_type))
76133965Sjdp	    {
76233965Sjdp	      fnname = name;
76333965Sjdp	      fnclass = syment.n_sclass;
76433965Sjdp	      fntype = syment.n_type;
76533965Sjdp	      if (syment.n_numaux > 0)
76633965Sjdp		fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
76733965Sjdp	      else
76833965Sjdp		fnend = 0;
76933965Sjdp	      linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
77033965Sjdp	      break;
77133965Sjdp	    }
77233965Sjdp	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
773130561Sobrien				  syment.n_type, paux, TRUE, dhandle);
77433965Sjdp	  if (type == DEBUG_TYPE_NULL)
775130561Sobrien	    return FALSE;
77633965Sjdp	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
77733965Sjdp				   dhandle, type, within_function))
778130561Sobrien	    return FALSE;
77933965Sjdp	  break;
78033965Sjdp
78133965Sjdp	case C_FCN:
78233965Sjdp	  if (strcmp (name, ".bf") == 0)
78333965Sjdp	    {
78433965Sjdp	      if (fnname == NULL)
78533965Sjdp		{
78660484Sobrien		  non_fatal (_("%ld: .bf without preceding function"),
78760484Sobrien			     this_coff_symno);
788130561Sobrien		  return FALSE;
78933965Sjdp		}
79033965Sjdp
79133965Sjdp	      type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
792130561Sobrien				      DECREF (fntype), paux, FALSE, dhandle);
79333965Sjdp	      if (type == DEBUG_TYPE_NULL)
794130561Sobrien		return FALSE;
79533965Sjdp
79633965Sjdp	      if (! debug_record_function (dhandle, fnname, type,
79777298Sobrien					   external_coff_symbol_p (fnclass),
79833965Sjdp					   bfd_asymbol_value (sym)))
799130561Sobrien		return FALSE;
80033965Sjdp
80133965Sjdp	      if (linenos != NULL)
80233965Sjdp		{
80333965Sjdp		  int base;
80433965Sjdp		  bfd_vma addr;
80533965Sjdp
80633965Sjdp		  if (syment.n_numaux == 0)
80733965Sjdp		    base = 0;
80833965Sjdp		  else
80933965Sjdp		    base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
81033965Sjdp
81133965Sjdp		  addr = bfd_get_section_vma (abfd, bfd_get_section (sym));
81233965Sjdp
81333965Sjdp		  ++linenos;
81433965Sjdp
81533965Sjdp		  while (linenos->line_number != 0)
81633965Sjdp		    {
81733965Sjdp		      if (! debug_record_line (dhandle,
81833965Sjdp					       linenos->line_number + base,
81933965Sjdp					       linenos->u.offset + addr))
820130561Sobrien			return FALSE;
82133965Sjdp		      ++linenos;
82233965Sjdp		    }
82333965Sjdp		}
82433965Sjdp
82533965Sjdp	      fnname = NULL;
82633965Sjdp	      linenos = NULL;
82733965Sjdp	      fnclass = 0;
82833965Sjdp	      fntype = 0;
82933965Sjdp
830130561Sobrien	      within_function = TRUE;
83133965Sjdp	    }
83233965Sjdp	  else if (strcmp (name, ".ef") == 0)
83333965Sjdp	    {
83433965Sjdp	      if (! within_function)
83533965Sjdp		{
83660484Sobrien		  non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno);
837130561Sobrien		  return FALSE;
83833965Sjdp		}
83933965Sjdp
84033965Sjdp	      if (bfd_asymbol_value (sym) > fnend)
84133965Sjdp		fnend = bfd_asymbol_value (sym);
84233965Sjdp	      if (! debug_end_function (dhandle, fnend))
843130561Sobrien		return FALSE;
84433965Sjdp
84533965Sjdp	      fnend = 0;
846130561Sobrien	      within_function = FALSE;
84733965Sjdp	    }
84833965Sjdp	  break;
84933965Sjdp
85033965Sjdp	case C_BLOCK:
85133965Sjdp	  if (strcmp (name, ".bb") == 0)
85233965Sjdp	    {
85333965Sjdp	      if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
854130561Sobrien		return FALSE;
85533965Sjdp	    }
85633965Sjdp	  else if (strcmp (name, ".eb") == 0)
85733965Sjdp	    {
85833965Sjdp	      if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
859130561Sobrien		return FALSE;
86033965Sjdp	    }
86133965Sjdp	  break;
86233965Sjdp
86333965Sjdp	default:
86433965Sjdp	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
865130561Sobrien				  syment.n_type, paux, TRUE, dhandle);
86633965Sjdp	  if (type == DEBUG_TYPE_NULL)
867130561Sobrien	    return FALSE;
86833965Sjdp	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
86933965Sjdp				   dhandle, type, within_function))
870130561Sobrien	    return FALSE;
87133965Sjdp	  break;
87233965Sjdp	}
87333965Sjdp    }
87433965Sjdp
875130561Sobrien  return TRUE;
87633965Sjdp}
877