symbols.c

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

C
2,503
字号
	{	  if (islower (c))	    c = toupper (c);	  *copy++ = c;	}      *copy = '\0';    }#ifdef BFD_ASSEMBLER  {    struct local_symbol *locsym;    locsym = (struct local_symbol *) hash_find (local_hash, name);    if (locsym != NULL)      return (symbolS *) locsym;  }#endif  return ((symbolS *) hash_find (sy_hash, name));}/* Once upon a time, symbols were kept in a singly linked list.  At   least coff needs to be able to rearrange them from time to time, for   which a doubly linked list is much more convenient.  Loic did these   as macros which seemed dangerous to me so they're now functions.   xoxorich.  *//* Link symbol ADDME after symbol TARGET in the chain.  */voidsymbol_append (addme, target, rootPP, lastPP)     symbolS *addme;     symbolS *target;     symbolS **rootPP;     symbolS **lastPP;{  if (LOCAL_SYMBOL_CHECK (addme))    abort ();  if (target != NULL && LOCAL_SYMBOL_CHECK (target))    abort ();  if (target == NULL)    {      know (*rootPP == NULL);      know (*lastPP == NULL);      addme->sy_next = NULL;#ifdef SYMBOLS_NEED_BACKPOINTERS      addme->sy_previous = NULL;#endif      *rootPP = addme;      *lastPP = addme;      return;    }				/* if the list is empty  */  if (target->sy_next != NULL)    {#ifdef SYMBOLS_NEED_BACKPOINTERS      target->sy_next->sy_previous = addme;#endif /* SYMBOLS_NEED_BACKPOINTERS */    }  else    {      know (*lastPP == target);      *lastPP = addme;    }				/* if we have a next  */  addme->sy_next = target->sy_next;  target->sy_next = addme;#ifdef SYMBOLS_NEED_BACKPOINTERS  addme->sy_previous = target;#endif /* SYMBOLS_NEED_BACKPOINTERS */  debug_verify_symchain (symbol_rootP, symbol_lastP);}/* Set the chain pointers of SYMBOL to null.  */voidsymbol_clear_list_pointers (symbolP)     symbolS *symbolP;{  if (LOCAL_SYMBOL_CHECK (symbolP))    abort ();  symbolP->sy_next = NULL;#ifdef SYMBOLS_NEED_BACKPOINTERS  symbolP->sy_previous = NULL;#endif}#ifdef SYMBOLS_NEED_BACKPOINTERS/* Remove SYMBOLP from the list.  */voidsymbol_remove (symbolP, rootPP, lastPP)     symbolS *symbolP;     symbolS **rootPP;     symbolS **lastPP;{  if (LOCAL_SYMBOL_CHECK (symbolP))    abort ();  if (symbolP == *rootPP)    {      *rootPP = symbolP->sy_next;    }				/* if it was the root  */  if (symbolP == *lastPP)    {      *lastPP = symbolP->sy_previous;    }				/* if it was the tail  */  if (symbolP->sy_next != NULL)    {      symbolP->sy_next->sy_previous = symbolP->sy_previous;    }				/* if not last  */  if (symbolP->sy_previous != NULL)    {      symbolP->sy_previous->sy_next = symbolP->sy_next;    }				/* if not first  */  debug_verify_symchain (*rootPP, *lastPP);}/* Link symbol ADDME before symbol TARGET in the chain.  */voidsymbol_insert (addme, target, rootPP, lastPP)     symbolS *addme;     symbolS *target;     symbolS **rootPP;     symbolS **lastPP ATTRIBUTE_UNUSED;{  if (LOCAL_SYMBOL_CHECK (addme))    abort ();  if (LOCAL_SYMBOL_CHECK (target))    abort ();  if (target->sy_previous != NULL)    {      target->sy_previous->sy_next = addme;    }  else    {      know (*rootPP == target);      *rootPP = addme;    }				/* if not first  */  addme->sy_previous = target->sy_previous;  target->sy_previous = addme;  addme->sy_next = target;  debug_verify_symchain (*rootPP, *lastPP);}#endif /* SYMBOLS_NEED_BACKPOINTERS */voidverify_symbol_chain (rootP, lastP)     symbolS *rootP;     symbolS *lastP;{  symbolS *symbolP = rootP;  if (symbolP == NULL)    return;  for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))    {#ifdef BFD_ASSEMBLER      assert (symbolP->bsym != NULL);#endif#ifdef SYMBOLS_NEED_BACKPOINTERS      assert (symbolP->sy_next->sy_previous == symbolP);#else      /* Walk the list anyways, to make sure pointers are still good.  */      ;#endif /* SYMBOLS_NEED_BACKPOINTERS */    }  assert (lastP == symbolP);}voidverify_symbol_chain_2 (sym)     symbolS *sym;{  symbolS *p = sym, *n = sym;#ifdef SYMBOLS_NEED_BACKPOINTERS  while (symbol_previous (p))    p = symbol_previous (p);#endif  while (symbol_next (n))    n = symbol_next (n);  verify_symbol_chain (p, n);}/* Resolve the value of a symbol.  This is called during the final   pass over the symbol table to resolve any symbols with complex   values.  */valueTresolve_symbol_value (symp, finalize)     symbolS *symp;     int finalize;{  int resolved;  valueT final_val;  segT final_seg;#ifdef BFD_ASSEMBLER  if (LOCAL_SYMBOL_CHECK (symp))    {      struct local_symbol *locsym = (struct local_symbol *) symp;      if (local_symbol_resolved_p (locsym))	return locsym->lsy_offset / bfd_octets_per_byte (stdoutput);      final_val = (local_symbol_get_frag (locsym)->fr_address		   + locsym->lsy_offset) / bfd_octets_per_byte (stdoutput);      if (finalize)	{	  locsym->lsy_offset = final_val;	  local_symbol_mark_resolved (locsym);	}      return final_val;    }#endif  if (symp->sy_resolved)    {      if (symp->sy_value.X_op == O_constant)	return (valueT) symp->sy_value.X_add_number;      else	return 0;    }  resolved = 0;  final_seg = S_GET_SEGMENT (symp);  if (symp->sy_resolving)    {      if (finalize)	as_bad (_("Symbol definition loop encountered at %s"),		S_GET_NAME (symp));      final_val = 0;      resolved = 1;    }  else    {      symbolS *add_symbol, *op_symbol;      offsetT left, right;      segT seg_left, seg_right;      operatorT op;      symp->sy_resolving = 1;      /* Help out with CSE.  */      add_symbol = symp->sy_value.X_add_symbol;      op_symbol = symp->sy_value.X_op_symbol;      final_val = symp->sy_value.X_add_number;      op = symp->sy_value.X_op;      switch (op)	{	default:	  BAD_CASE (op);	  break;	case O_absent:	  final_val = 0;	  /* Fall through.  */	case O_constant:	  final_val += symp->sy_frag->fr_address / OCTETS_PER_BYTE;	  if (final_seg == expr_section)	    final_seg = absolute_section;	  resolved = 1;	  break;	case O_symbol:	case O_symbol_rva:	  left = resolve_symbol_value (add_symbol, finalize);	do_symbol:	  if (symp->sy_mri_common)	    {	      /* This is a symbol inside an MRI common section.  The                 relocation routines are going to handle it specially.                 Don't change the value.  */	      resolved = symbol_resolved_p (add_symbol);	      break;	    }	  if (finalize && final_val == 0)	    {	      if (LOCAL_SYMBOL_CHECK (add_symbol))		add_symbol = local_symbol_convert ((struct local_symbol *)						   add_symbol);	      copy_symbol_attributes (symp, add_symbol);	    }	  /* If we have equated this symbol to an undefined symbol, we             keep X_op set to O_symbol, and we don't change             X_add_number.  This permits the routine which writes out             relocation to detect this case, and convert the             relocation to be against the symbol to which this symbol             is equated.  */	  if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))	    {	      if (finalize)		{		  S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));		  symp->sy_value.X_op = O_symbol;		  symp->sy_value.X_add_symbol = add_symbol;		  symp->sy_value.X_add_number = final_val;		}	      final_val = 0;	      resolved = symbol_resolved_p (add_symbol);	      goto exit_dont_set_value;	    }	  else	    {	      final_val += symp->sy_frag->fr_address + left;	      if (final_seg == expr_section || final_seg == undefined_section)		final_seg = S_GET_SEGMENT (add_symbol);	    }	  resolved = symbol_resolved_p (add_symbol);	  break;	case O_uminus:	case O_bit_not:	case O_logical_not:	  left = resolve_symbol_value (add_symbol, finalize);	  if (op == O_uminus)	    left = -left;	  else if (op == O_logical_not)	    left = !left;	  else	    left = ~left;	  final_val += left + symp->sy_frag->fr_address;	  if (final_seg == expr_section || final_seg == undefined_section)	    final_seg = absolute_section;	  resolved = symbol_resolved_p (add_symbol);	  break;	case O_multiply:	case O_divide:	case O_modulus:	case O_left_shift:	case O_right_shift:	case O_bit_inclusive_or:	case O_bit_or_not:	case O_bit_exclusive_or:	case O_bit_and:	case O_add:	case O_subtract:	case O_eq:	case O_ne:	case O_lt:	case O_le:	case O_ge:	case O_gt:	case O_logical_and:	case O_logical_or:	  left = resolve_symbol_value (add_symbol, finalize);	  right = resolve_symbol_value (op_symbol, finalize);	  seg_left = S_GET_SEGMENT (add_symbol);	  seg_right = S_GET_SEGMENT (op_symbol);	  /* Simplify addition or subtraction of a constant by folding the	     constant into X_add_number.  */	  if (op == O_add || op == O_subtract)	    {	      if (seg_right == absolute_section)		{		  if (op == O_add)		    final_val += right;		  else		    final_val -= right;		  op = O_symbol;		  op_symbol = NULL;		  goto do_symbol;		}	      else if (seg_left == absolute_section && op == O_add)		{		  op = O_symbol;		  final_val += left;		  add_symbol = op_symbol;		  left = right;		  op_symbol = NULL;		  goto do_symbol;		}	    }	  /* Subtraction is permitted if both operands are in the same	     section.  Otherwise, both operands must be absolute.  We	     already handled the case of addition or subtraction of a	     constant above.  This will probably need to be changed	     for an object file format which supports arbitrary	     expressions, such as IEEE-695.  */	  /* Don't emit messages unless we're finalizing the symbol value,	     otherwise we may get the same message multiple times.  */	  if ((seg_left != absolute_section	       || seg_right != absolute_section)	      && (op != O_subtract		  || seg_left != seg_right		  || seg_left == undefined_section)	      && finalize)	    {	      char *file;	      unsigned int line;	      if (expr_symbol_where (symp, &file, &line))		{		  if (seg_left == undefined_section)		    as_bad_where (file, line,				  _("undefined symbol %s in operation"),				  S_GET_NAME (symp->sy_value.X_add_symbol));		  if (seg_right == undefined_section)		    as_bad_where (file, line,				  _("undefined symbol %s in operation"),				  S_GET_NAME (symp->sy_value.X_op_symbol));		  if (seg_left != undefined_section		      && seg_right != undefined_section)		    as_bad_where (file, line,				  _("invalid section for operation"));		}	      else		{		  if (seg_left == undefined_section)		    as_bad (_("undefined symbol %s in operation setting %s"),			    S_GET_NAME (symp->sy_value.X_add_symbol),			    S_GET_NAME (symp));		  if (seg_right == undefined_section)		    as_bad (_("undefined symbol %s in operation setting %s"),			    S_GET_NAME (symp->sy_value.X_op_symbol),			    S_GET_NAME (symp));		  if (seg_left != undefined_section		      && seg_right != undefined_section)		    as_bad (_("invalid section for operation setting %s"),			    S_GET_NAME (symp));		}	    }	  /* Check for division by zero.  */	  if ((op == O_divide || op == O_modulus) && right == 0)	    {	      /* If seg_right is not absolute_section, then we've                 already issued a warning about using a bad symbol.  */	      if (seg_right == absolute_section && finalize)		{		  char *file;		  unsigned int line;		  if (expr_symbol_where (symp, &file, &line))		    as_bad_where (file, line, _("division by zero"));		  else		    as_bad (_("division by zero when setting %s"),			    S_GET_NAME (symp));		}	      right = 1;	    }	  switch (symp->sy_value.X_op)	    {	    case O_multiply:		left *= right; break;	    case O_divide:		left /= right; break;	    case O_modulus:		left %= right; break;	    case O_left_shift:		left <<= right; break;	    case O_right_shift:		left >>= right; break;	    case O_bit_inclusive_or:	left |= right; break;	    case O_bit_or_not:		left |= ~right; break;	    case O_bit_exclusive_or:	left ^= right; break;	    case O_bit_and:		left &= right; break;	    case O_add:			left += right; break;	    case O_subtract:		left -= right; break;	    case O_eq:	left = left == right ? ~ (offsetT) 0 : 0; break;	    case O_ne:	left = left != right ? ~ (offsetT) 0 : 0; break;	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;	    case O_gt:	left = left >  right ? ~ (offsetT) 0 : 0; break;	    case O_logical_and:	left = left && right; break;	    case O_logical_or:	left = left || right; break;	    default:		abort ();	    }	  final_val += symp->sy_frag->fr_address + left;	  if (final_seg == expr_section || final_seg == undefined_section)	    final_seg = absolute_section;	  resolved = (symbol_resolved_p (add_symbol)		      && symbol_resolved_p (op_symbol));	  break;	case O_register:	case O_big:	case O_illegal:	  /* Give an error (below) if not in expr_section.  We don't	     want to worry about expr_section symbols, because they	     are fictional (they are created as part of expression	     resolution), and any problems may not actually mean	     anything.  */	  break;	}      symp->sy_resolving = 0;    }  if (finalize)    {      S_SET_VALUE (symp, final_val);#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)      /* The old a.out backend does not handle S_SET_SEGMENT correctly         for a stab symbol, so we use this bad hack.  */      if (final_seg != S_GET_SEGMENT (symp))#endif	S_SET_SEGMENT (symp, final_seg);    }exit_dont_set_value:  /* Don't worry if we can't resolve an expr_section symbol.  */  if (finalize)    {      if (resolved)	symp->sy_resolved = 1;      else if (S_GET_SEGMENT (symp) != expr_section)	{	  as_bad (_("can't resolve value for symbol \"%s\""),		  S_GET_NAME (symp));	  symp->sy_resolved = 1;	}    }  return final_val;}#ifdef BFD_ASSEMBLERstatic void resolve_local_symbol PARAMS ((const char *, PTR));/* A static function passed to hash_traverse.  */static voidresolve_local_symbol (key, value)     const char *key ATTRIBUTE_UNUSED;     PTR value;{  if (value != NULL)    resolve_symbol_value (value, 1);}#endif/* Resolve all local symbols.  */voidresolve_local_symbol_values (){#ifdef BFD_ASSEMBLER  hash_traverse (local_hash, resolve_local_symbol);#endif}/* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".   They are *really* local.  That is, they go out of scope whenever we see a   label that isn't local.  Also, like fb labels, there can be multiple   instances of a dollar label.  Therefor, we name encode each instance with   the instance number, keep a list of defined symbols separate from the real   symbol table, and we treat these buggers as a sparse array.  */static long *dollar_labels;static long *dollar_label_instances;static char *dollar_label_defines;static unsigned long dollar_label_count;static unsigned long dollar_label_max;intdollar_label_defined (label)     long label;{  long *i;  know ((dollar_labels != NULL) || (dollar_label_count == 0));  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)    if (*i == label)      return dollar_label_defines[i - dollar_labels];  /* If we get here, label isn't defined.  */  return 0;}static longdollar_label_instance (label)     long label;{  long *i;  know ((dollar_labels != NULL) || (dollar_label_count == 0));  for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)    if (*i == label)      return (dollar_label_instances[i - dollar_labels]);  /* If we get here, we haven't seen the label before.     Therefore its instance count is zero.  */  return 0;}voiddollar_label_clear (){  memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);}#define DOLLAR_LABEL_BUMP_BY 10

⌨️ 快捷键说明

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