symbols.c

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

C
2,503
字号
/* symbols.c -symbol table-   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,   1999, 2000, 2001   Free Software Foundation, Inc.   This file is part of GAS, the GNU Assembler.   GAS 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, or (at your option)   any later version.   GAS 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 GAS; see the file COPYING.  If not, write to the Free   Software Foundation, 59 Temple Place - Suite 330, Boston, MA   02111-1307, USA.  *//* #define DEBUG_SYMS / * to debug symbol list maintenance.  */#include <ctype.h>#include "as.h"#include "obstack.h"		/* For "symbols.h" */#include "subsegs.h"#include "struc-symbol.h"/* This is non-zero if symbols are case sensitive, which is the   default.  */int symbols_case_sensitive = 1;#ifndef WORKING_DOT_WORDextern int new_broken_words;#endif/* symbol-name => struct symbol pointer */static struct hash_control *sy_hash;/* Table of local symbols.  */static struct hash_control *local_hash;/* Below are commented in "symbols.h".  */symbolS *symbol_rootP;symbolS *symbol_lastP;symbolS abs_symbol;#ifdef DEBUG_SYMS#define debug_verify_symchain verify_symbol_chain#else#define debug_verify_symchain(root, last) ((void) 0)#endif#define DOLLAR_LABEL_CHAR	'\001'#define LOCAL_LABEL_CHAR	'\002'struct obstack notes;static void fb_label_init PARAMS ((void));static long dollar_label_instance PARAMS ((long));static long fb_label_instance PARAMS ((long));static void print_binary PARAMS ((FILE *, const char *, expressionS *));/* Return a pointer to a new symbol.  Die if we can't make a new   symbol.  Fill in the symbol's values.  Add symbol to end of symbol   chain.   This function should be called in the general case of creating a   symbol.  However, if the output file symbol table has already been   set, and you are certain that this symbol won't be wanted in the   output file, you can call symbol_create.  */symbolS *symbol_new (name, segment, valu, frag)     const char *name;     segT segment;     valueT valu;     fragS *frag;{  symbolS *symbolP = symbol_create (name, segment, valu, frag);  /* Link to end of symbol chain.  */#ifdef BFD_ASSEMBLER  {    extern int symbol_table_frozen;    if (symbol_table_frozen)      abort ();  }#endif  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);  return symbolP;}/* Save a symbol name on a permanent obstack, and convert it according   to the object file format.  */static char *save_symbol_name (name)     const char *name;{  unsigned int name_length;  char *ret;  name_length = strlen (name) + 1;	/* +1 for \0.  */  obstack_grow (&notes, name, name_length);  ret = obstack_finish (&notes);#ifdef STRIP_UNDERSCORE  if (ret[0] == '_')    ++ret;#endif#ifdef tc_canonicalize_symbol_name  ret = tc_canonicalize_symbol_name (ret);#endif  if (! symbols_case_sensitive)    {      unsigned char *s;      for (s = (unsigned char *) ret; *s != '\0'; s++)	if (islower (*s))	  *s = toupper (*s);    }  return ret;}symbolS *symbol_create (name, segment, valu, frag)     const char *name;		/* It is copied, the caller can destroy/modify.  */     segT segment;		/* Segment identifier (SEG_<something>).  */     valueT valu;		/* Symbol value.  */     fragS *frag;		/* Associated fragment.  */{  char *preserved_copy_of_name;  symbolS *symbolP;  preserved_copy_of_name = save_symbol_name (name);  symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));  /* symbol must be born in some fixed state.  This seems as good as any.  */  memset (symbolP, 0, sizeof (symbolS));#ifdef BFD_ASSEMBLER  symbolP->bsym = bfd_make_empty_symbol (stdoutput);  if (symbolP->bsym == NULL)    as_perror ("%s", "bfd_make_empty_symbol");  symbolP->bsym->udata.p = (PTR) symbolP;#endif  S_SET_NAME (symbolP, preserved_copy_of_name);  S_SET_SEGMENT (symbolP, segment);  S_SET_VALUE (symbolP, valu);  symbol_clear_list_pointers (symbolP);  symbolP->sy_frag = frag;#ifndef BFD_ASSEMBLER  symbolP->sy_number = ~0;  symbolP->sy_name_offset = (unsigned int) ~0;#endif  obj_symbol_new_hook (symbolP);#ifdef tc_symbol_new_hook  tc_symbol_new_hook (symbolP);#endif  return symbolP;}#ifdef BFD_ASSEMBLER/* Local symbol support.  If we can get away with it, we keep only a   small amount of information for local symbols.  */static struct local_symbol *local_symbol_make PARAMS ((const char *, segT,						       valueT, fragS *));static symbolS *local_symbol_convert PARAMS ((struct local_symbol *));/* Used for statistics.  */static unsigned long local_symbol_count;static unsigned long local_symbol_conversion_count;/* This macro is called with a symbol argument passed by reference.   It returns whether this is a local symbol.  If necessary, it   changes its argument to the real symbol.  */#define LOCAL_SYMBOL_CHECK(s)						\  (s->bsym == NULL							\   ? (local_symbol_converted_p ((struct local_symbol *) s)		\      ? (s = local_symbol_get_real_symbol ((struct local_symbol *) s),	\	 0)								\      : 1)								\   : 0)/* Create a local symbol and insert it into the local hash table.  */static struct local_symbol *local_symbol_make (name, section, offset, frag)     const char *name;     segT section;     valueT offset;     fragS *frag;{  char *name_copy;  struct local_symbol *ret;  ++local_symbol_count;  name_copy = save_symbol_name (name);  ret = (struct local_symbol *) obstack_alloc (&notes, sizeof *ret);  ret->lsy_marker = NULL;  ret->lsy_name = name_copy;  ret->lsy_section = section;  local_symbol_set_frag (ret, frag);  ret->lsy_offset = offset;  hash_jam (local_hash, name_copy, (PTR) ret);  return ret;}/* Convert a local symbol into a real symbol.  Note that we do not   reclaim the space used by the local symbol.  */static symbolS *local_symbol_convert (locsym)     struct local_symbol *locsym;{  symbolS *ret;  assert (locsym->lsy_marker == NULL);  if (local_symbol_converted_p (locsym))    return local_symbol_get_real_symbol (locsym);  ++local_symbol_conversion_count;  ret = symbol_new (locsym->lsy_name, locsym->lsy_section, locsym->lsy_offset,		    local_symbol_get_frag (locsym));  if (local_symbol_resolved_p (locsym))    ret->sy_resolved = 1;  /* Local symbols are always either defined or used.  */  ret->sy_used = 1;  symbol_table_insert (ret);  local_symbol_mark_converted (locsym);  local_symbol_set_real_symbol (locsym, ret);  hash_jam (local_hash, locsym->lsy_name, NULL);  return ret;}#else /* ! BFD_ASSEMBLER */#define LOCAL_SYMBOL_CHECK(s) 0#define local_symbol_convert(s) ((symbolS *) s)#endif /* ! BFD_ASSEMBLER *//* We have just seen "<name>:".   Creates a struct symbol unless it already exists.   Gripes if we are redefining a symbol incompatibly (and ignores it).  */symbolS *colon (sym_name)		/* Just seen "x:" - rattle symbols & frags.  */     const char *sym_name;	/* Symbol name, as a cannonical string.  */     /* We copy this string: OK to alter later.  */{  register symbolS *symbolP;	/* Symbol we are working with.  */  /* Sun local labels go out of scope whenever a non-local symbol is     defined.  */  if (LOCAL_LABELS_DOLLAR)    {      int local;#ifdef BFD_ASSEMBLER      local = bfd_is_local_label_name (stdoutput, sym_name);#else      local = LOCAL_LABEL (sym_name);#endif      if (! local)	dollar_label_clear ();    }#ifndef WORKING_DOT_WORD  if (new_broken_words)    {      struct broken_word *a;      int possible_bytes;      fragS *frag_tmp;      char *frag_opcode;      extern const int md_short_jump_size;      extern const int md_long_jump_size;      possible_bytes = (md_short_jump_size			+ new_broken_words * md_long_jump_size);      frag_tmp = frag_now;      frag_opcode = frag_var (rs_broken_word,			      possible_bytes,			      possible_bytes,			      (relax_substateT) 0,			      (symbolS *) broken_words,			      (offsetT) 0,			      NULL);      /* We want to store the pointer to where to insert the jump	 table in the fr_opcode of the rs_broken_word frag.  This	 requires a little hackery.  */      while (frag_tmp	     && (frag_tmp->fr_type != rs_broken_word		 || frag_tmp->fr_opcode))	frag_tmp = frag_tmp->fr_next;      know (frag_tmp);      frag_tmp->fr_opcode = frag_opcode;      new_broken_words = 0;      for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)	a->dispfrag = frag_tmp;    }#endif /* WORKING_DOT_WORD */  if ((symbolP = symbol_find (sym_name)) != 0)    {#ifdef RESOLVE_SYMBOL_REDEFINITION      if (RESOLVE_SYMBOL_REDEFINITION (symbolP))	return symbolP;#endif      /* Now check for undefined symbols.  */      if (LOCAL_SYMBOL_CHECK (symbolP))	{#ifdef BFD_ASSEMBLER	  struct local_symbol *locsym = (struct local_symbol *) symbolP;	  if (locsym->lsy_section != undefined_section	      && (local_symbol_get_frag (locsym) != frag_now		  || locsym->lsy_section != now_seg		  || locsym->lsy_offset != frag_now_fix ()))	    {	      as_bad (_("Symbol %s already defined."), sym_name);	      return symbolP;	    }	  locsym->lsy_section = now_seg;	  local_symbol_set_frag (locsym, frag_now);	  locsym->lsy_offset = frag_now_fix ();#endif	}      else if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))	{	  if (S_GET_VALUE (symbolP) == 0)	    {	      symbolP->sy_frag = frag_now;#ifdef OBJ_VMS	      S_SET_OTHER (symbolP, const_flag);#endif	      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());	      S_SET_SEGMENT (symbolP, now_seg);#ifdef N_UNDF	      know (N_UNDF == 0);#endif /* if we have one, it better be zero.  */	    }	  else	    {	      /* There are still several cases to check:		 A .comm/.lcomm symbol being redefined as initialized		 data is OK		 A .comm/.lcomm symbol being redefined with a larger		 size is also OK		 This only used to be allowed on VMS gas, but Sun cc		 on the sparc also depends on it.  */	      if (((!S_IS_DEBUG (symbolP)		    && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))		    && S_IS_EXTERNAL (symbolP))		   || S_GET_SEGMENT (symbolP) == bss_section)		  && (now_seg == data_section		      || now_seg == S_GET_SEGMENT (symbolP)))		{		  /* Select which of the 2 cases this is.  */		  if (now_seg != data_section)		    {		      /* New .comm for prev .comm symbol.			 If the new size is larger we just change its			 value.  If the new size is smaller, we ignore			 this symbol.  */		      if (S_GET_VALUE (symbolP)			  < ((unsigned) frag_now_fix ()))			{			  S_SET_VALUE (symbolP, (valueT) frag_now_fix ());			}		    }		  else		    {		      /* It is a .comm/.lcomm being converted to initialized			 data.  */		      symbolP->sy_frag = frag_now;#ifdef OBJ_VMS		      S_SET_OTHER (symbolP, const_flag);#endif		      S_SET_VALUE (symbolP, (valueT) frag_now_fix ());		      S_SET_SEGMENT (symbolP, now_seg);	/* Keep N_EXT bit.  */		    }		}	      else		{#if (!defined (OBJ_AOUT) && !defined (OBJ_MAYBE_AOUT) \     && !defined (OBJ_BOUT) && !defined (OBJ_MAYBE_BOUT))		  static const char *od_buf = "";#else		  char od_buf[100];		  od_buf[0] = '\0';#ifdef BFD_ASSEMBLER		  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)#endif		    sprintf(od_buf, "%d.%d.",			    S_GET_OTHER (symbolP),			    S_GET_DESC (symbolP));#endif		  as_bad (_("Symbol \"%s\" is already defined as \"%s\"/%s%ld."),			    sym_name,			    segment_name (S_GET_SEGMENT (symbolP)),			    od_buf,			    (long) S_GET_VALUE (symbolP));		}	    }			/* if the undefined symbol has no value  */	}      else	{	  /* Don't blow up if the definition is the same.  */	  if (!(frag_now == symbolP->sy_frag		&& S_GET_VALUE (symbolP) == frag_now_fix ()		&& S_GET_SEGMENT (symbolP) == now_seg))	    as_bad (_("Symbol %s already defined."), sym_name);	}    }#ifdef BFD_ASSEMBLER  else if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, sym_name))    {      symbolP = (symbolS *) local_symbol_make (sym_name, now_seg,					       (valueT) frag_now_fix (),					       frag_now);    }#endif /* BFD_ASSEMBLER */  else    {      symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),			    frag_now);#ifdef OBJ_VMS      S_SET_OTHER (symbolP, const_flag);#endif /* OBJ_VMS */      symbol_table_insert (symbolP);    }  if (mri_common_symbol != NULL)    {      /* This symbol is actually being defined within an MRI common         section.  This requires special handling.  */      if (LOCAL_SYMBOL_CHECK (symbolP))	symbolP = local_symbol_convert ((struct local_symbol *) symbolP);      symbolP->sy_value.X_op = O_symbol;      symbolP->sy_value.X_add_symbol = mri_common_symbol;      symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);      symbolP->sy_frag = &zero_address_frag;      S_SET_SEGMENT (symbolP, expr_section);      symbolP->sy_mri_common = 1;    }#ifdef tc_frob_label  tc_frob_label (symbolP);#endif#ifdef obj_frob_label  obj_frob_label (symbolP);#endif  return symbolP;}/* Die if we can't insert the symbol.  */voidsymbol_table_insert (symbolP)     symbolS *symbolP;{  register const char *error_string;  know (symbolP);  know (S_GET_NAME (symbolP));  if (LOCAL_SYMBOL_CHECK (symbolP))    {      error_string = hash_jam (local_hash, S_GET_NAME (symbolP),			       (PTR) symbolP);      if (error_string != NULL)	as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),		  S_GET_NAME (symbolP), error_string);      return;    }  if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))    {      as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),		S_GET_NAME (symbolP), error_string);    }				/* on error  */}/* If a symbol name does not exist, create it as undefined, and insert   it into the symbol table.  Return a pointer to it.  */symbolS *symbol_find_or_make (name)     const char *name;{  register symbolS *symbolP;  symbolP = symbol_find (name);  if (symbolP == NULL)    {#ifdef BFD_ASSEMBLER      if (! flag_keep_locals && bfd_is_local_label_name (stdoutput, name))	{	  symbolP = md_undefined_symbol ((char *) name);	  if (symbolP != NULL)	    return symbolP;	  symbolP = (symbolS *) local_symbol_make (name, undefined_section,						   (valueT) 0,						   &zero_address_frag);	  return symbolP;	}#endif      symbolP = symbol_make (name);      symbol_table_insert (symbolP);    }				/* if symbol wasn't found */  return (symbolP);}symbolS *symbol_make (name)     CONST char *name;{  symbolS *symbolP;  /* Let the machine description default it, e.g. for register names.  */  symbolP = md_undefined_symbol ((char *) name);  if (!symbolP)    symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);  return (symbolP);}/* Implement symbol table lookup.   In:	A symbol's name as a string: '\0' can't be part of a symbol name.   Out:	NULL if the name was not in the symbol table, else the address   of a struct symbol associated with that name.  */symbolS *symbol_find (name)     CONST char *name;{#ifdef STRIP_UNDERSCORE  return (symbol_find_base (name, 1));#else /* STRIP_UNDERSCORE */  return (symbol_find_base (name, 0));#endif /* STRIP_UNDERSCORE */}symbolS *symbol_find_base (name, strip_underscore)     CONST char *name;     int strip_underscore;{  if (strip_underscore && *name == '_')    name++;#ifdef tc_canonicalize_symbol_name  {    char *copy;    size_t len = strlen (name) + 1;    copy = (char *) alloca (len);    memcpy (copy, name, len);    name = tc_canonicalize_symbol_name (copy);  }#endif  if (! symbols_case_sensitive)    {      char *copy;      const char *orig;      unsigned char c;      orig = name;      name = copy = (char *) alloca (strlen (name) + 1);      while ((c = *orig++) != '\0')

⌨️ 快捷键说明

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