Home | History | Annotate | Line # | Download | only in binutils
      1 /* stabs.c -- Parse COFF debugging information
      2    Copyright (C) 1996-2025 Free Software Foundation, Inc.
      3    Written by Ian Lance Taylor <ian (at) cygnus.com>.
      4 
      5    This file is part of GNU Binutils.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
     20    02110-1301, USA.  */
     21 
     22 /* This file contains code which parses COFF debugging information.  */
     23 
     24 #include "sysdep.h"
     25 #include "bfd.h"
     26 #include "coff/internal.h"
     27 #include "libiberty.h"
     28 #include "bucomm.h"
     29 #include "debug.h"
     30 #include "budbg.h"
     31 
     32 /* FIXME: We should not need this BFD internal file.  We need it for
     33    the N_BTMASK, etc., values.  */
     34 #include "libcoff.h"
     35 
     36 /* These macros extract the right mask and shifts for this BFD.  They
     37    assume that there is a local variable named ABFD.  This is so that
     38    macros like ISFCN and DECREF, from coff/internal.h, will work
     39    without modification.  */
     40 #define N_BTMASK (coff_data (abfd)->local_n_btmask)
     41 #define	N_BTSHFT (coff_data (abfd)->local_n_btshft)
     42 #define	N_TMASK  (coff_data (abfd)->local_n_tmask)
     43 #define	N_TSHIFT (coff_data (abfd)->local_n_tshift)
     44 
     45 /* This structure is used to hold the symbols, as well as the current
     46    location within the symbols.  */
     47 
     48 struct coff_symbols
     49 {
     50   /* The symbols.  */
     51   asymbol **syms;
     52   /* The number of symbols.  */
     53   long symcount;
     54   /* The index of the current symbol.  */
     55   long symno;
     56   /* The index of the current symbol in the COFF symbol table (where
     57      each auxent counts as a symbol).  */
     58   long coff_symno;
     59 };
     60 
     61 /* This structure is used to map symbol indices to types.  */
     62 
     63 struct coff_types
     64 {
     65   /* Next set of slots.  */
     66   struct coff_types *next;
     67   /* Where the TYPES array starts.  */
     68   unsigned int base_index;
     69   /* Slots.  */
     70 #define COFF_SLOTS (16)
     71   debug_type types[COFF_SLOTS];
     72 };
     73 
     74 static debug_type parse_coff_base_type
     75   (bfd *, struct coff_symbols *, struct coff_types **, long, int,
     76    union internal_auxent *, void *);
     77 static debug_type parse_coff_struct_type
     78   (bfd *, struct coff_symbols *, struct coff_types **, int,
     79    union internal_auxent *, void *);
     80 static debug_type parse_coff_enum_type
     81   (bfd *, struct coff_symbols *, struct coff_types **,
     82    union internal_auxent *, void *);
     83 
     84 /* Return the slot for a type.  */
     86 
     87 static debug_type *
     88 coff_get_slot (void *dhandle, struct coff_types **types, long indx)
     89 {
     90   unsigned int base_index;
     91 
     92   base_index = indx / COFF_SLOTS * COFF_SLOTS;
     93   indx -= base_index;
     94 
     95   while (*types && (*types)->base_index < base_index)
     96     types = &(*types)->next;
     97 
     98   if (*types == NULL || (*types)->base_index != base_index)
     99     {
    100       struct coff_types *n = debug_xzalloc (dhandle, sizeof (*n));
    101       n->next = *types;
    102       n->base_index = base_index;
    103       *types = n;
    104     }
    105 
    106   return (*types)->types + indx;
    107 }
    108 
    109 /* Parse a COFF type code in NTYPE.  */
    110 
    111 static debug_type
    112 parse_coff_type (bfd *abfd, struct coff_symbols *symbols,
    113 		 struct coff_types **types, long coff_symno, int ntype,
    114 		 union internal_auxent *pauxent, bool useaux,
    115 		 void *dhandle)
    116 {
    117   debug_type type;
    118 
    119   if ((ntype & ~N_BTMASK) != 0)
    120     {
    121       int newtype;
    122 
    123       newtype = DECREF (ntype);
    124 
    125       if (ISPTR (ntype))
    126 	{
    127 	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
    128 				  pauxent, useaux, dhandle);
    129 	  type = debug_make_pointer_type (dhandle, type);
    130 	}
    131       else if (ISFCN (ntype))
    132 	{
    133 	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
    134 				  pauxent, useaux, dhandle);
    135 	  type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
    136 					   false);
    137 	}
    138       else if (ISARY (ntype))
    139 	{
    140 	  int n;
    141 
    142 	  if (pauxent == NULL)
    143 	    n = 0;
    144 	  else
    145 	    {
    146 	      unsigned short *dim;
    147 	      int i;
    148 
    149 	      /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
    150                  the c_naux field of the syment to 0.  */
    151 
    152 	      /* Move the dimensions down, so that the next array
    153                  picks up the next one.  */
    154 	      dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
    155 	      n = dim[0];
    156 	      for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
    157 		*dim = *(dim + 1);
    158 	      *dim = 0;
    159 	    }
    160 
    161 	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
    162 				  pauxent, false, dhandle);
    163 	  type = debug_make_array_type (dhandle, type,
    164 					parse_coff_base_type (abfd, symbols,
    165 							      types,
    166 							      coff_symno,
    167 							      T_INT,
    168 							      NULL, dhandle),
    169 					0, n - 1, false);
    170 	}
    171       else
    172 	{
    173 	  non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype);
    174 	  return DEBUG_TYPE_NULL;
    175 	}
    176 
    177       return type;
    178     }
    179 
    180   if (pauxent != NULL && (int32_t) pauxent->x_sym.x_tagndx.u32 > 0)
    181     {
    182       debug_type *slot;
    183 
    184       /* This is a reference to an existing type.  FIXME: gdb checks
    185 	 that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG.  */
    186       slot = coff_get_slot (dhandle, types, pauxent->x_sym.x_tagndx.u32);
    187       if (*slot != DEBUG_TYPE_NULL)
    188 	return *slot;
    189       else
    190 	return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
    191     }
    192 
    193   /* If the aux entry has already been used for something, useaux will
    194      have been set to false, indicating that parse_coff_base_type
    195      should not use it.  We need to do it this way, rather than simply
    196      passing pauxent as NULL, because we need to be able handle
    197      multiple array dimensions while still discarding pauxent after
    198      having handled all of them.  */
    199   if (! useaux)
    200     pauxent = NULL;
    201 
    202   return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
    203 			       pauxent, dhandle);
    204 }
    205 
    206 /* Parse a basic COFF type in NTYPE.  */
    207 
    208 static debug_type
    209 parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols,
    210 		      struct coff_types **types, long coff_symno, int ntype,
    211 		      union internal_auxent *pauxent, void *dhandle)
    212 {
    213   debug_type ret;
    214   const char *name = NULL;
    215 
    216   switch (ntype)
    217     {
    218     default:
    219       ret = debug_make_void_type (dhandle);
    220       break;
    221 
    222     case T_NULL:
    223     case T_VOID:
    224       ret = debug_make_void_type (dhandle);
    225       name = "void";
    226       break;
    227 
    228     case T_CHAR:
    229       ret = debug_make_int_type (dhandle, 1, false);
    230       name = "char";
    231       break;
    232 
    233     case T_SHORT:
    234       ret = debug_make_int_type (dhandle, 2, false);
    235       name = "short";
    236       break;
    237 
    238     case T_INT:
    239       /* FIXME: Perhaps the size should depend upon the architecture.  */
    240       ret = debug_make_int_type (dhandle, 4, false);
    241       name = "int";
    242       break;
    243 
    244     case T_LONG:
    245       ret = debug_make_int_type (dhandle, 4, false);
    246       name = "long";
    247       break;
    248 
    249     case T_FLOAT:
    250       ret = debug_make_float_type (dhandle, 4);
    251       name = "float";
    252       break;
    253 
    254     case T_DOUBLE:
    255       ret = debug_make_float_type (dhandle, 8);
    256       name = "double";
    257       break;
    258 
    259     case T_LNGDBL:
    260       ret = debug_make_float_type (dhandle, 12);
    261       name = "long double";
    262       break;
    263 
    264     case T_UCHAR:
    265       ret = debug_make_int_type (dhandle, 1, true);
    266       name = "unsigned char";
    267       break;
    268 
    269     case T_USHORT:
    270       ret = debug_make_int_type (dhandle, 2, true);
    271       name = "unsigned short";
    272       break;
    273 
    274     case T_UINT:
    275       ret = debug_make_int_type (dhandle, 4, true);
    276       name = "unsigned int";
    277       break;
    278 
    279     case T_ULONG:
    280       ret = debug_make_int_type (dhandle, 4, true);
    281       name = "unsigned long";
    282       break;
    283 
    284     case T_STRUCT:
    285       if (pauxent == NULL)
    286 	ret = debug_make_struct_type (dhandle, true, 0,
    287 				      (debug_field *) NULL);
    288       else
    289 	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
    290 				      dhandle);
    291       break;
    292 
    293     case T_UNION:
    294       if (pauxent == NULL)
    295 	ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL);
    296       else
    297 	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
    298 				      dhandle);
    299       break;
    300 
    301     case T_ENUM:
    302       if (pauxent == NULL)
    303 	ret = debug_make_enum_type (dhandle, (const char **) NULL,
    304 				    (bfd_signed_vma *) NULL);
    305       else
    306 	ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
    307       break;
    308     }
    309 
    310   if (name != NULL)
    311     ret = debug_name_type (dhandle, name, ret);
    312 
    313   debug_type *slot = coff_get_slot (dhandle, types, coff_symno);
    314   *slot = ret;
    315 
    316   return ret;
    317 }
    318 
    319 /* Parse a struct type.  */
    320 
    321 static debug_type
    322 parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols,
    323 			struct coff_types **types, int ntype,
    324 			union internal_auxent *pauxent, void *dhandle)
    325 {
    326   long symend;
    327   int alloc;
    328   debug_field *fields, *xfields;
    329   int count;
    330   bool done;
    331 
    332   symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.u32;
    333 
    334   alloc = 10;
    335   fields = (debug_field *) xmalloc (alloc * sizeof *fields);
    336   count = 0;
    337 
    338   done = false;
    339   while (! done
    340 	 && symbols->coff_symno < symend
    341 	 && symbols->symno < symbols->symcount)
    342     {
    343       asymbol *sym;
    344       long this_coff_symno;
    345       struct internal_syment syment;
    346       union internal_auxent auxent;
    347       union internal_auxent *psubaux;
    348       bfd_vma bitpos = 0, bitsize = 0;
    349 
    350       sym = symbols->syms[symbols->symno];
    351 
    352       if (! bfd_coff_get_syment (abfd, sym, &syment))
    353 	{
    354 	  non_fatal (_("bfd_coff_get_syment failed: %s"),
    355 		     bfd_errmsg (bfd_get_error ()));
    356 	  free (fields);
    357 	  return DEBUG_TYPE_NULL;
    358 	}
    359 
    360       this_coff_symno = symbols->coff_symno;
    361 
    362       ++symbols->symno;
    363       symbols->coff_symno += 1 + syment.n_numaux;
    364 
    365       if (syment.n_numaux == 0)
    366 	psubaux = NULL;
    367       else
    368 	{
    369 	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
    370 	    {
    371 	      non_fatal (_("bfd_coff_get_auxent failed: %s"),
    372 			 bfd_errmsg (bfd_get_error ()));
    373 	      free (fields);
    374 	      return DEBUG_TYPE_NULL;
    375 	    }
    376 	  psubaux = &auxent;
    377 	}
    378 
    379       switch (syment.n_sclass)
    380 	{
    381 	case C_MOS:
    382 	case C_MOU:
    383 	  bitpos = 8 * bfd_asymbol_value (sym);
    384 	  bitsize = 0;
    385 	  break;
    386 
    387 	case C_FIELD:
    388 	  bitpos = bfd_asymbol_value (sym);
    389 	  if (psubaux != NULL)
    390 	    bitsize = psubaux->x_sym.x_misc.x_lnsz.x_size;
    391 	  break;
    392 
    393 	case C_EOS:
    394 	  done = true;
    395 	  break;
    396 	}
    397 
    398       if (! done)
    399 	{
    400 	  debug_type ftype;
    401 	  debug_field f;
    402 
    403 	  ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
    404 				   syment.n_type, psubaux, true, dhandle);
    405 	  f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
    406 				bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
    407 	  if (f == DEBUG_FIELD_NULL)
    408 	    {
    409 	      free (fields);
    410 	      return DEBUG_TYPE_NULL;
    411 	    }
    412 
    413 	  if (count + 1 >= alloc)
    414 	    {
    415 	      alloc += 10;
    416 	      fields = ((debug_field *)
    417 			xrealloc (fields, alloc * sizeof *fields));
    418 	    }
    419 
    420 	  fields[count] = f;
    421 	  ++count;
    422 	}
    423     }
    424 
    425   fields[count] = DEBUG_FIELD_NULL;
    426   xfields = debug_xalloc (dhandle, (count + 1) * sizeof (*fields));
    427   memcpy (xfields, fields, (count + 1) * sizeof (*fields));
    428   free (fields);
    429 
    430   return debug_make_struct_type (dhandle, ntype == T_STRUCT,
    431 				 pauxent->x_sym.x_misc.x_lnsz.x_size,
    432 				 xfields);
    433 }
    434 
    435 /* Parse an enum type.  */
    436 
    437 static debug_type
    438 parse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols,
    439 		      struct coff_types **types ATTRIBUTE_UNUSED,
    440 		      union internal_auxent *pauxent, void *dhandle)
    441 {
    442   long symend;
    443   int alloc;
    444   const char **names, **xnames;
    445   bfd_signed_vma *vals, *xvals;
    446   int count;
    447   bool done;
    448 
    449   symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.u32;
    450 
    451   alloc = 10;
    452   names = (const char **) xmalloc (alloc * sizeof *names);
    453   vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
    454   count = 0;
    455 
    456   done = false;
    457   while (! done
    458 	 && symbols->coff_symno < symend
    459 	 && symbols->symno < symbols->symcount)
    460     {
    461       asymbol *sym;
    462       struct internal_syment syment;
    463 
    464       sym = symbols->syms[symbols->symno];
    465 
    466       if (! bfd_coff_get_syment (abfd, sym, &syment))
    467 	{
    468 	  non_fatal (_("bfd_coff_get_syment failed: %s"),
    469 		     bfd_errmsg (bfd_get_error ()));
    470 	  free (names);
    471 	  free (vals);
    472 	  return DEBUG_TYPE_NULL;
    473 	}
    474 
    475       ++symbols->symno;
    476       symbols->coff_symno += 1 + syment.n_numaux;
    477 
    478       switch (syment.n_sclass)
    479 	{
    480 	case C_MOE:
    481 	  if (count + 1 >= alloc)
    482 	    {
    483 	      alloc += 10;
    484 	      names = ((const char **)
    485 		       xrealloc (names, alloc * sizeof *names));
    486 	      vals = ((bfd_signed_vma *)
    487 		      xrealloc (vals, alloc * sizeof *vals));
    488 	    }
    489 
    490 	  names[count] = bfd_asymbol_name (sym);
    491 	  vals[count] = bfd_asymbol_value (sym);
    492 	  ++count;
    493 	  break;
    494 
    495 	case C_EOS:
    496 	  done = true;
    497 	  break;
    498 	}
    499     }
    500 
    501   names[count] = NULL;
    502   vals[count] = 0;
    503   xnames = debug_xalloc (dhandle, (count + 1) * sizeof (*names));
    504   memcpy (xnames, names, (count + 1) * sizeof (*names));
    505   free (names);
    506   xvals = debug_xalloc (dhandle, (count + 1) * sizeof (*vals));
    507   memcpy (xvals, vals, (count + 1) * sizeof (*vals));
    508   free (vals);
    509 
    510   return debug_make_enum_type (dhandle, xnames, xvals);
    511 }
    512 
    513 /* Handle a single COFF symbol.  */
    514 
    515 static bool
    516 parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types **types,
    517 		   asymbol *sym, long coff_symno,
    518 		   struct internal_syment *psyment, void *dhandle,
    519 		   debug_type type, bool within_function)
    520 {
    521   switch (psyment->n_sclass)
    522     {
    523     case C_NULL:
    524       break;
    525 
    526     case C_AUTO:
    527       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
    528 				   DEBUG_LOCAL, bfd_asymbol_value (sym)))
    529 	return false;
    530       break;
    531 
    532     case C_WEAKEXT:
    533     case C_EXT:
    534       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
    535 				   DEBUG_GLOBAL, bfd_asymbol_value (sym)))
    536 	return false;
    537       break;
    538 
    539     case C_STAT:
    540       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
    541 				   (within_function
    542 				    ? DEBUG_LOCAL_STATIC
    543 				    : DEBUG_STATIC),
    544 				   bfd_asymbol_value (sym)))
    545 	return false;
    546       break;
    547 
    548     case C_REG:
    549       /* FIXME: We may need to convert the register number.  */
    550       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
    551 				   DEBUG_REGISTER, bfd_asymbol_value (sym)))
    552 	return false;
    553       break;
    554 
    555     case C_LABEL:
    556       break;
    557 
    558     case C_ARG:
    559       if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
    560 				    DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
    561 	return false;
    562       break;
    563 
    564     case C_REGPARM:
    565       /* FIXME: We may need to convert the register number.  */
    566       if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
    567 				    DEBUG_PARM_REG, bfd_asymbol_value (sym)))
    568 	return false;
    569       break;
    570 
    571     case C_TPDEF:
    572       type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
    573       if (type == DEBUG_TYPE_NULL)
    574 	return false;
    575       break;
    576 
    577     case C_STRTAG:
    578     case C_UNTAG:
    579     case C_ENTAG:
    580       {
    581 	debug_type *slot;
    582 
    583 	type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
    584 	if (type == DEBUG_TYPE_NULL)
    585 	  return false;
    586 
    587 	/* Store the named type into the slot, so that references get
    588            the name.  */
    589 	slot = coff_get_slot (dhandle, types, coff_symno);
    590 	*slot = type;
    591       }
    592       break;
    593 
    594     default:
    595       break;
    596     }
    597 
    598   return true;
    599 }
    600 
    601 /* Determine if a symbol has external visibility.  */
    602 
    603 static bool
    604 external_coff_symbol_p (int sym_class)
    605 {
    606   switch (sym_class)
    607     {
    608     case C_EXT:
    609     case C_WEAKEXT:
    610       return true;
    611     default:
    612       break;
    613     }
    614   return false;
    615 }
    616 
    617 /* This is the main routine.  It looks through all the symbols and
    618    handles them.  */
    619 
    620 bool
    621 parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle)
    622 {
    623   struct coff_symbols symbols;
    624   struct coff_types *types;
    625   long next_c_file;
    626   const char *fnname;
    627   int fnclass;
    628   int fntype;
    629   bfd_vma fnend;
    630   alent *linenos;
    631   bool within_function;
    632   long this_coff_symno;
    633 
    634   symbols.syms = syms;
    635   symbols.symcount = symcount;
    636   symbols.symno = 0;
    637   symbols.coff_symno = 0;
    638 
    639   types= NULL;
    640 
    641   next_c_file = -1;
    642   fnname = NULL;
    643   fnclass = 0;
    644   fntype = 0;
    645   fnend = 0;
    646   linenos = NULL;
    647   within_function = false;
    648 
    649   while (symbols.symno < symcount)
    650     {
    651       asymbol *sym;
    652       const char *name;
    653       struct internal_syment syment;
    654       union internal_auxent auxent;
    655       union internal_auxent *paux;
    656       debug_type type;
    657 
    658       sym = syms[symbols.symno];
    659 
    660       if (! bfd_coff_get_syment (abfd, sym, &syment))
    661 	{
    662 	  non_fatal (_("bfd_coff_get_syment failed: %s"),
    663 		     bfd_errmsg (bfd_get_error ()));
    664 	  return false;
    665 	}
    666 
    667       name = bfd_asymbol_name (sym);
    668 
    669       this_coff_symno = symbols.coff_symno;
    670 
    671       ++symbols.symno;
    672       symbols.coff_symno += 1 + syment.n_numaux;
    673 
    674       /* We only worry about the first auxent, because that is the
    675 	 only one which is relevant for debugging information.  */
    676       if (syment.n_numaux == 0)
    677 	paux = NULL;
    678       else
    679 	{
    680 	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
    681 	    {
    682 	      non_fatal (_("bfd_coff_get_auxent failed: %s"),
    683 			 bfd_errmsg (bfd_get_error ()));
    684 	      return false;
    685 	    }
    686 	  paux = &auxent;
    687 	}
    688 
    689       if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
    690 	{
    691 	  /* The last C_FILE symbol points to the first external
    692              symbol.  */
    693 	  if (! debug_set_filename (dhandle, "*globals*"))
    694 	    return false;
    695 	}
    696 
    697       switch (syment.n_sclass)
    698 	{
    699 	case C_EFCN:
    700 	case C_EXTDEF:
    701 	case C_ULABEL:
    702 	case C_USTATIC:
    703 	case C_LINE:
    704 	case C_ALIAS:
    705 	case C_HIDDEN:
    706 	  /* Just ignore these classes.  */
    707 	  break;
    708 
    709 	case C_FILE:
    710 	  next_c_file = syment.n_value;
    711 	  if (! debug_set_filename (dhandle, name))
    712 	    return false;
    713 	  break;
    714 
    715 	case C_STAT:
    716 	  /* Ignore static symbols with a type of T_NULL.  These
    717              represent section entries.  */
    718 	  if (syment.n_type == T_NULL)
    719 	    break;
    720 	  /* Fall through.  */
    721 	case C_WEAKEXT:
    722 	case C_EXT:
    723 	  if (ISFCN (syment.n_type))
    724 	    {
    725 	      fnname = name;
    726 	      fnclass = syment.n_sclass;
    727 	      fntype = syment.n_type;
    728 	      if (syment.n_numaux > 0)
    729 		fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
    730 	      else
    731 		fnend = 0;
    732 	      linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
    733 	      break;
    734 	    }
    735 	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
    736 				  syment.n_type, paux, true, dhandle);
    737 	  if (type == DEBUG_TYPE_NULL)
    738 	    return false;
    739 	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
    740 				   dhandle, type, within_function))
    741 	    return false;
    742 	  break;
    743 
    744 	case C_FCN:
    745 	  if (strcmp (name, ".bf") == 0)
    746 	    {
    747 	      if (fnname == NULL)
    748 		{
    749 		  non_fatal (_("%ld: .bf without preceding function"),
    750 			     this_coff_symno);
    751 		  return false;
    752 		}
    753 
    754 	      type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
    755 				      DECREF (fntype), paux, false, dhandle);
    756 	      if (type == DEBUG_TYPE_NULL)
    757 		return false;
    758 
    759 	      if (! debug_record_function (dhandle, fnname, type,
    760 					   external_coff_symbol_p (fnclass),
    761 					   bfd_asymbol_value (sym)))
    762 		return false;
    763 
    764 	      if (linenos != NULL)
    765 		{
    766 		  int base;
    767 		  bfd_vma addr;
    768 
    769 		  if (syment.n_numaux == 0)
    770 		    base = 0;
    771 		  else
    772 		    base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
    773 
    774 		  addr = bfd_section_vma (bfd_asymbol_section (sym));
    775 
    776 		  ++linenos;
    777 
    778 		  while (linenos->line_number != 0)
    779 		    {
    780 		      if (! debug_record_line (dhandle,
    781 					       linenos->line_number + base,
    782 					       linenos->u.offset + addr))
    783 			return false;
    784 		      ++linenos;
    785 		    }
    786 		}
    787 
    788 	      fnname = NULL;
    789 	      linenos = NULL;
    790 	      fnclass = 0;
    791 	      fntype = 0;
    792 
    793 	      within_function = true;
    794 	    }
    795 	  else if (strcmp (name, ".ef") == 0)
    796 	    {
    797 	      if (! within_function)
    798 		{
    799 		  non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno);
    800 		  return false;
    801 		}
    802 
    803 	      if (bfd_asymbol_value (sym) > fnend)
    804 		fnend = bfd_asymbol_value (sym);
    805 	      if (! debug_end_function (dhandle, fnend))
    806 		return false;
    807 
    808 	      fnend = 0;
    809 	      within_function = false;
    810 	    }
    811 	  break;
    812 
    813 	case C_BLOCK:
    814 	  if (strcmp (name, ".bb") == 0)
    815 	    {
    816 	      if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
    817 		return false;
    818 	    }
    819 	  else if (strcmp (name, ".eb") == 0)
    820 	    {
    821 	      if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
    822 		return false;
    823 	    }
    824 	  break;
    825 
    826 	default:
    827 	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
    828 				  syment.n_type, paux, true, dhandle);
    829 	  if (type == DEBUG_TYPE_NULL)
    830 	    return false;
    831 	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
    832 				   dhandle, type, within_function))
    833 	    return false;
    834 	  break;
    835 	}
    836     }
    837 
    838   return true;
    839 }
    840