/* stabs.c -- Parse COFF debugging information
   Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.
   Written by Ian Lance Taylor <ian@cygnus.com>.

   This file is part of GNU Binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  */

/* This file contains code which parses COFF debugging information.  */

#include "bfd.h"
#include "coff/internal.h"
#include "bucomm.h"
#include "libiberty.h"
#include "demangle.h"
#include "debug.h"
#include "budbg.h"

/* FIXME: We should not need this BFD internal file.  We need it for
   the N_BTMASK, etc., values.  */
#include "libcoff.h"

/* These macros extract the right mask and shifts for this BFD.  They
   assume that there is a local variable named ABFD.  This is so that
   macros like ISFCN and DECREF, from coff/internal.h, will work
   without modification.  */
#define N_BTMASK (coff_data (abfd)->local_n_btmask)
#define	N_BTSHFT (coff_data (abfd)->local_n_btshft)
#define	N_TMASK  (coff_data (abfd)->local_n_tmask)
#define	N_TSHIFT (coff_data (abfd)->local_n_tshift)

/* This structure is used to hold the symbols, as well as the current
   location within the symbols.  */

struct coff_symbols
{
  /* The symbols.  */
  asymbol **syms;
  /* The number of symbols.  */
  long symcount;
  /* The index of the current symbol.  */
  long symno;
  /* The index of the current symbol in the COFF symbol table (where
     each auxent counts as a symbol).  */
  long coff_symno;
};

/* The largest basic type we are prepared to handle.  */

#define T_MAX (T_LNGDBL)

/* This structure is used to hold slots.  */

struct coff_slots
{
  /* Next set of slots.  */
  struct coff_slots *next;
  /* Slots.  */
#define COFF_SLOTS (16)
  debug_type slots[COFF_SLOTS];
};

/* This structure is used to map symbol indices to types.  */

struct coff_types
{
  /* Slots.  */
  struct coff_slots *slots;
  /* Basic types.  */
  debug_type basic[T_MAX + 1];
};

static debug_type *coff_get_slot PARAMS ((struct coff_types *, int));
static debug_type parse_coff_type
  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
	   union internal_auxent *, boolean, PTR));
static debug_type parse_coff_base_type
  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
	   union internal_auxent *, PTR));
static debug_type parse_coff_struct_type
  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, int,
	   union internal_auxent *, PTR));
static debug_type parse_coff_enum_type
  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *,
	   union internal_auxent *, PTR));
static boolean parse_coff_symbol
  PARAMS ((bfd *, struct coff_types *, asymbol *, long,
	   struct internal_syment *, PTR, debug_type, boolean));

/* Return the slot for a type.  */

static debug_type *
coff_get_slot (types, indx)
     struct coff_types *types;
     int indx;
{
  struct coff_slots **pps;

  pps = &types->slots;

  while (indx >= COFF_SLOTS)
    {
      if (*pps == NULL)
	{
	  *pps = (struct coff_slots *) xmalloc (sizeof **pps);
	  memset (*pps, 0, sizeof **pps);
	}
      pps = &(*pps)->next;
      indx -= COFF_SLOTS;
    }

  if (*pps == NULL)
    {
      *pps = (struct coff_slots *) xmalloc (sizeof **pps);
      memset (*pps, 0, sizeof **pps);
    }

  return (*pps)->slots + indx;
}

/* Parse a COFF type code in NTYPE.  */

static debug_type
parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux,
		 dhandle)
     bfd *abfd;
     struct coff_symbols *symbols;
     struct coff_types *types;
     long coff_symno;
     int ntype;
     union internal_auxent *pauxent;
     boolean useaux;
     PTR dhandle;
{
  debug_type type;

  if ((ntype & ~N_BTMASK) != 0)
    {
      int newtype;

      newtype = DECREF (ntype);

      if (ISPTR (ntype))
	{
	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
				  pauxent, useaux, dhandle);
	  type = debug_make_pointer_type (dhandle, type);
	}
      else if (ISFCN (ntype))
	{
	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
				  pauxent, useaux, dhandle);
	  type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
					   false);
	}
      else if (ISARY (ntype))
	{
	  int n;

	  if (pauxent == NULL)
	    n = 0;
	  else
	    {
	      unsigned short *dim;
	      int i;

	      /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
                 the c_naux field of the syment to 0.  */

	      /* Move the dimensions down, so that the next array
                 picks up the next one.  */
	      dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
	      n = dim[0];
	      for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
		*dim = *(dim + 1);
	      *dim = 0;
	    }

	  type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
				  pauxent, false, dhandle);
	  type = debug_make_array_type (dhandle, type,
					parse_coff_base_type (abfd, symbols,
							      types,
							      coff_symno,
							      T_INT,
							      NULL, dhandle),
					0, n - 1, false);
	}
      else
	{
	  fprintf (stderr, _("%s: parse_coff_type: Bad type code 0x%x\n"),
		   program_name, ntype);
	  return DEBUG_TYPE_NULL;
	}

      return type;
    }

  if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
    {
      debug_type *slot;

      /* This is a reference to an existing type.  FIXME: gdb checks
	 that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG.  */
      slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
      if (*slot != DEBUG_TYPE_NULL)
	return *slot;
      else
	return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
    }

  /* If the aux entry has already been used for something, useaux will
     have been set to false, indicating that parse_coff_base_type
     should not use it.  We need to do it this way, rather than simply
     passing pauxent as NULL, because we need to be able handle
     multiple array dimensions while still discarding pauxent after
     having handled all of them.  */
  if (! useaux)
    pauxent = NULL;

  return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
			       pauxent, dhandle);
}

/* Parse a basic COFF type in NTYPE.  */

static debug_type
parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent,
		      dhandle)
     bfd *abfd;
     struct coff_symbols *symbols;
     struct coff_types *types;
     long coff_symno;
     int ntype;
     union internal_auxent *pauxent;
     PTR dhandle;
{
  debug_type ret;
  boolean set_basic;
  const char *name;
  debug_type *slot;

  if (ntype >= 0
      && ntype <= T_MAX
      && types->basic[ntype] != DEBUG_TYPE_NULL)
    return types->basic[ntype];

  set_basic = true;
  name = NULL;

  switch (ntype)
    {
    default:
      ret = debug_make_void_type (dhandle);
      break;

    case T_NULL:
    case T_VOID:
      ret = debug_make_void_type (dhandle);
      name = "void";
      break;

    case T_CHAR:
      ret = debug_make_int_type (dhandle, 1, false);
      name = "char";
      break;

    case T_SHORT:
      ret = debug_make_int_type (dhandle, 2, false);
      name = "short";
      break;

    case T_INT:
      /* FIXME: Perhaps the size should depend upon the architecture.  */
      ret = debug_make_int_type (dhandle, 4, false);
      name = "int";
      break;

    case T_LONG:
      ret = debug_make_int_type (dhandle, 4, false);
      name = "long";
      break;

    case T_FLOAT:
      ret = debug_make_float_type (dhandle, 4);
      name = "float";
      break;

    case T_DOUBLE:
      ret = debug_make_float_type (dhandle, 8);
      name = "double";
      break;

    case T_LNGDBL:
      ret = debug_make_float_type (dhandle, 12);
      name = "long double";
      break;

    case T_UCHAR:
      ret = debug_make_int_type (dhandle, 1, true);
      name = "unsigned char";
      break;

    case T_USHORT:
      ret = debug_make_int_type (dhandle, 2, true);
      name = "unsigned short";
      break;

    case T_UINT:
      ret = debug_make_int_type (dhandle, 4, true);
      name = "unsigned int";
      break;

    case T_ULONG:
      ret = debug_make_int_type (dhandle, 4, true);
      name = "unsigned long";
      break;

    case T_STRUCT:
      if (pauxent == NULL)
	ret = debug_make_struct_type (dhandle, true, 0,
				      (debug_field *) NULL);
      else
	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
				      dhandle);

      slot = coff_get_slot (types, coff_symno);
      *slot = ret;

      set_basic = false;
      break;

    case T_UNION:
      if (pauxent == NULL)
	ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL);
      else
	ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
				      dhandle);

      slot = coff_get_slot (types, coff_symno);
      *slot = ret;

      set_basic = false;
      break;

    case T_ENUM:
      if (pauxent == NULL)
	ret = debug_make_enum_type (dhandle, (const char **) NULL,
				    (bfd_signed_vma *) NULL);
      else
	ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);

      slot = coff_get_slot (types, coff_symno);
      *slot = ret;

      set_basic = false;
      break;
    }

  if (name != NULL)
    ret = debug_name_type (dhandle, name, ret);

  if (set_basic
      && ntype >= 0
      && ntype <= T_MAX)
    types->basic[ntype] = ret;

  return ret;
}

/* Parse a struct type.  */

static debug_type
parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle)
     bfd *abfd;
     struct coff_symbols *symbols;
     struct coff_types *types;
     int ntype;
     union internal_auxent *pauxent;
     PTR dhandle;
{
  long symend;
  int alloc;
  debug_field *fields;
  int count;
  boolean done;

  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;

  alloc = 10;
  fields = (debug_field *) xmalloc (alloc * sizeof *fields);
  count = 0;

  done = false;
  while (! done
	 && symbols->coff_symno < symend
	 && symbols->symno < symbols->symcount)
    {
      asymbol *sym;
      long this_coff_symno;
      struct internal_syment syment;
      union internal_auxent auxent;
      union internal_auxent *psubaux;
      bfd_vma bitpos = 0, bitsize = 0;

      sym = symbols->syms[symbols->symno];

      if (! bfd_coff_get_syment (abfd, sym, &syment))
	{
	  fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
		   program_name, bfd_errmsg (bfd_get_error ()));
	  return DEBUG_TYPE_NULL;
	}

      this_coff_symno = symbols->coff_symno;

      ++symbols->symno;
      symbols->coff_symno += 1 + syment.n_numaux;

      if (syment.n_numaux == 0)
	psubaux = NULL;
      else
	{
	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
	    {
	      fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"),
		       program_name, bfd_errmsg (bfd_get_error ()));
	      return DEBUG_TYPE_NULL;
	    }
	  psubaux = &auxent;
	}

      switch (syment.n_sclass)
	{
	case C_MOS:
	case C_MOU:
	  bitpos = 8 * bfd_asymbol_value (sym);
	  bitsize = 0;
	  break;

	case C_FIELD:
	  bitpos = bfd_asymbol_value (sym);
	  bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
	  break;

	case C_EOS:
	  done = true;
	  break;
	}

      if (! done)
	{
	  debug_type ftype;
	  debug_field f;

	  ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
				   syment.n_type, psubaux, true, dhandle);
	  f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
				bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
	  if (f == DEBUG_FIELD_NULL)
	    return DEBUG_TYPE_NULL;

	  if (count + 1 >= alloc)
	    {
	      alloc += 10;
	      fields = ((debug_field *)
			xrealloc (fields, alloc * sizeof *fields));
	    }

	  fields[count] = f;
	  ++count;
	}
    }

  fields[count] = DEBUG_FIELD_NULL;

  return debug_make_struct_type (dhandle, ntype == T_STRUCT,
				 pauxent->x_sym.x_misc.x_lnsz.x_size,
				 fields);
}

/* Parse an enum type.  */

static debug_type
parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle)
     bfd *abfd;
     struct coff_symbols *symbols;
     struct coff_types *types ATTRIBUTE_UNUSED;
     union internal_auxent *pauxent;
     PTR dhandle;
{
  long symend;
  int alloc;
  const char **names;
  bfd_signed_vma *vals;
  int count;
  boolean done;

  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;

  alloc = 10;
  names = (const char **) xmalloc (alloc * sizeof *names);
  vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
  count = 0;

  done = false;
  while (! done
	 && symbols->coff_symno < symend
	 && symbols->symno < symbols->symcount)
    {
      asymbol *sym;
      struct internal_syment syment;

      sym = symbols->syms[symbols->symno];

      if (! bfd_coff_get_syment (abfd, sym, &syment))
	{
	  fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
		   program_name, bfd_errmsg (bfd_get_error ()));
	  return DEBUG_TYPE_NULL;
	}

      ++symbols->symno;
      symbols->coff_symno += 1 + syment.n_numaux;

      switch (syment.n_sclass)
	{
	case C_MOE:
	  if (count + 1 >= alloc)
	    {
	      alloc += 10;
	      names = ((const char **)
		       xrealloc (names, alloc * sizeof *names));
	      vals = ((bfd_signed_vma *)
		      xrealloc (vals, alloc * sizeof *vals));
	    }

	  names[count] = bfd_asymbol_name (sym);
	  vals[count] = bfd_asymbol_value (sym);
	  ++count;
	  break;

	case C_EOS:
	  done = true;
	  break;
	}
    }

  names[count] = NULL;

  return debug_make_enum_type (dhandle, names, vals);
}

/* Handle a single COFF symbol.  */

static boolean
parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type,
		   within_function)
     bfd *abfd ATTRIBUTE_UNUSED;
     struct coff_types *types;
     asymbol *sym;
     long coff_symno;
     struct internal_syment *psyment;
     PTR dhandle;
     debug_type type;
     boolean within_function;
{
  switch (psyment->n_sclass)
    {
    case C_NULL:
      break;

    case C_AUTO:
      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
				   DEBUG_LOCAL, bfd_asymbol_value (sym)))
	return false;
      break;

    case C_EXT:
      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
				   DEBUG_GLOBAL, bfd_asymbol_value (sym)))
	return false;
      break;

    case C_STAT:
      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
				   (within_function
				    ? DEBUG_LOCAL_STATIC
				    : DEBUG_STATIC),
				   bfd_asymbol_value (sym)))
	return false;
      break;

    case C_REG:
      /* FIXME: We may need to convert the register number.  */
      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
				   DEBUG_REGISTER, bfd_asymbol_value (sym)))
	return false;
      break;

    case C_LABEL:
      break;

    case C_ARG:
      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
				    DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
	return false;
      break;

    case C_REGPARM:
      /* FIXME: We may need to convert the register number.  */
      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
				    DEBUG_PARM_REG, bfd_asymbol_value (sym)))
	return false;
      break;

    case C_TPDEF:
      type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
      if (type == DEBUG_TYPE_NULL)
	return false;
      break;

    case C_STRTAG:
    case C_UNTAG:
    case C_ENTAG:
      {
	debug_type *slot;

	type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
	if (type == DEBUG_TYPE_NULL)
	  return false;

	/* Store the named type into the slot, so that references get
           the name.  */
	slot = coff_get_slot (types, coff_symno);
	*slot = type;
      }
      break;

    default:
      break;
    }

  return true;				   
}

/* This is the main routine.  It looks through all the symbols and
   handles them.  */

boolean
parse_coff (abfd, syms, symcount, dhandle)
     bfd *abfd;
     asymbol **syms;
     long symcount;
     PTR dhandle;
{
  struct coff_symbols symbols;
  struct coff_types types;
  int i;
  long next_c_file;
  const char *fnname;
  int fnclass;
  int fntype;
  bfd_vma fnend;
  alent *linenos;
  boolean within_function;
  long this_coff_symno;

  symbols.syms = syms;
  symbols.symcount = symcount;
  symbols.symno = 0;
  symbols.coff_symno = 0;

  types.slots = NULL;
  for (i = 0; i <= T_MAX; i++)
    types.basic[i] = DEBUG_TYPE_NULL;

  next_c_file = -1;
  fnname = NULL;
  fnclass = 0;
  fntype = 0;
  fnend = 0;
  linenos = NULL;
  within_function = false;

  while (symbols.symno < symcount)
    {
      asymbol *sym;
      const char *name;
      struct internal_syment syment;
      union internal_auxent auxent;
      union internal_auxent *paux;
      debug_type type;

      sym = syms[symbols.symno];

      if (! bfd_coff_get_syment (abfd, sym, &syment))
	{
	  fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
		   program_name, bfd_errmsg (bfd_get_error ()));
	  return false;
	}

      name = bfd_asymbol_name (sym);

      this_coff_symno = symbols.coff_symno;

      ++symbols.symno;
      symbols.coff_symno += 1 + syment.n_numaux;

      /* We only worry about the first auxent, because that is the
	 only one which is relevant for debugging information.  */
      if (syment.n_numaux == 0)
	paux = NULL;
      else
	{
	  if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
	    {
	      fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"),
		       program_name, bfd_errmsg (bfd_get_error ()));
	      return false;
	    }
	  paux = &auxent;
	}

      if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
	{
	  /* The last C_FILE symbol points to the first external
             symbol.  */
	  if (! debug_set_filename (dhandle, "*globals*"))
	    return false;
	}

      switch (syment.n_sclass)
	{
	case C_EFCN:
	case C_EXTDEF:
	case C_ULABEL:
	case C_USTATIC:
	case C_LINE:
	case C_ALIAS:
	case C_HIDDEN:
	  /* Just ignore these classes.  */
	  break;

	case C_FILE:
	  next_c_file = syment.n_value;
	  if (! debug_set_filename (dhandle, name))
	    return false;
	  break;

	case C_STAT:
	  /* Ignore static symbols with a type of T_NULL.  These
             represent section entries.  */
	  if (syment.n_type == T_NULL)
	    break;
	  /* Fall through.  */
	case C_EXT:
	  if (ISFCN (syment.n_type))
	    {
	      fnname = name;
	      fnclass = syment.n_sclass;
	      fntype = syment.n_type;
	      if (syment.n_numaux > 0)
		fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
	      else
		fnend = 0;
	      linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
	      break;
	    }
	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
				  syment.n_type, paux, true, dhandle);
	  if (type == DEBUG_TYPE_NULL)
	    return false;
	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
				   dhandle, type, within_function))
	    return false;
	  break;

	case C_FCN:
	  if (strcmp (name, ".bf") == 0)
	    {
	      if (fnname == NULL)
		{
		  fprintf (stderr, _("%s: %ld: .bf without preceding function\n"),
			   program_name, this_coff_symno);
		  return false;
		}

	      type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
				      DECREF (fntype), paux, false, dhandle);
	      if (type == DEBUG_TYPE_NULL)
		return false;

	      if (! debug_record_function (dhandle, fnname, type,
					   fnclass == C_EXT,
					   bfd_asymbol_value (sym)))
		return false;

	      if (linenos != NULL)
		{
		  int base;
		  bfd_vma addr;

		  if (syment.n_numaux == 0)
		    base = 0;
		  else
		    base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;

		  addr = bfd_get_section_vma (abfd, bfd_get_section (sym));

		  ++linenos;

		  while (linenos->line_number != 0)
		    {
		      if (! debug_record_line (dhandle,
					       linenos->line_number + base,
					       linenos->u.offset + addr))
			return false;
		      ++linenos;
		    }
		}

	      fnname = NULL;
	      linenos = NULL;
	      fnclass = 0;
	      fntype = 0;

	      within_function = true;
	    }
	  else if (strcmp (name, ".ef") == 0)
	    {
	      if (! within_function)
		{
		  fprintf (stderr, _("%s: %ld: unexpected .ef\n"),
			   program_name, this_coff_symno);
		  return false;
		}

	      if (bfd_asymbol_value (sym) > fnend)
		fnend = bfd_asymbol_value (sym);
	      if (! debug_end_function (dhandle, fnend))
		return false;

	      fnend = 0;
	      within_function = false;
	    }
	  break;

	case C_BLOCK:
	  if (strcmp (name, ".bb") == 0)
	    {
	      if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
		return false;
	    }
	  else if (strcmp (name, ".eb") == 0)
	    {
	      if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
		return false;
	    }
	  break;

	default:
	  type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
				  syment.n_type, paux, true, dhandle);
	  if (type == DEBUG_TYPE_NULL)
	    return false;
	  if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
				   dhandle, type, within_function))
	    return false;
	  break;
	}
    }

  return true;
}
