rdcoff.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 908 行 · 第 1/2 页

C
908
字号
/* stabs.c -- Parse COFF debugging information   Copyright 1996, 2000 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));static boolean external_coff_symbol_p PARAMS ((int sym_class));/* 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_typeparse_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	{	  non_fatal (_("parse_coff_type: Bad type code 0x%x"), 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_typeparse_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_typeparse_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))	{	  non_fatal (_("bfd_coff_get_syment failed: %s"),		     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))	    {	      non_fatal (_("bfd_coff_get_auxent failed: %s"),			 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:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?