obj-coff.c

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

C
2,530
字号
  char name_end;  if (def_symbol_in_progress == NULL)    {      as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));      demand_empty_rest_of_line ();      return;    }  S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);  symbol_name = input_line_pointer;  name_end = get_symbol_end ();#ifdef tc_canonicalize_symbol_name  symbol_name = tc_canonicalize_symbol_name (symbol_name);#endif  /* Assume that the symbol referred to by .tag is always defined.     This was a bad assumption.  I've added find_or_make. xoxorich.  */  SA_SET_SYM_TAGNDX (def_symbol_in_progress,		     tag_find_or_make (symbol_name));  if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)    {      as_warn (_("tag not found for .tag %s"), symbol_name);    }				/* not defined */  SF_SET_TAGGED (def_symbol_in_progress);  *input_line_pointer = name_end;  demand_empty_rest_of_line ();}static voidobj_coff_type (ignore)     int ignore ATTRIBUTE_UNUSED;{  if (def_symbol_in_progress == NULL)    {      as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));      demand_empty_rest_of_line ();      return;    }				/* if not inside .def/.endef */  S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());  if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&      S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)    {      SF_SET_FUNCTION (def_symbol_in_progress);    }				/* is a function */  demand_empty_rest_of_line ();}static voidobj_coff_val (ignore)     int ignore ATTRIBUTE_UNUSED;{  if (def_symbol_in_progress == NULL)    {      as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));      demand_empty_rest_of_line ();      return;    }				/* if not inside .def/.endef */  if (is_name_beginner (*input_line_pointer))    {      char *symbol_name = input_line_pointer;      char name_end = get_symbol_end ();#ifdef tc_canonicalize_symbol_name  symbol_name = tc_canonicalize_symbol_name (symbol_name);#endif      if (!strcmp (symbol_name, "."))	{	  symbol_set_frag (def_symbol_in_progress, frag_now);	  S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());	  /* If the .val is != from the .def (e.g. statics) */	}      else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))	{	  expressionS exp;	  exp.X_op = O_symbol;	  exp.X_add_symbol = symbol_find_or_make (symbol_name);	  exp.X_op_symbol = NULL;	  exp.X_add_number = 0;	  symbol_set_value_expression (def_symbol_in_progress, &exp);	  /* If the segment is undefined when the forward reference is	     resolved, then copy the segment id from the forward	     symbol.  */	  SF_SET_GET_SEGMENT (def_symbol_in_progress);	  /* FIXME: gcc can generate address expressions here in	     unusual cases (search for "obscure" in sdbout.c).  We	     just ignore the offset here, thus generating incorrect	     debugging information.  We ignore the rest of the line	     just below.  */	}      /* Otherwise, it is the name of a non debug symbol and its value         will be calculated later.  */      *input_line_pointer = name_end;    }  else    {      S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());    }				/* if symbol based */  demand_empty_rest_of_line ();}voidcoff_obj_read_begin_hook (){  /* These had better be the same.  Usually 18 bytes.  */#ifndef BFD_HEADERS  know (sizeof (SYMENT) == sizeof (AUXENT));  know (SYMESZ == AUXESZ);#endif  tag_init ();}symbolS *coff_last_function;static symbolS *coff_last_bf;voidcoff_frob_symbol (symp, punt)     symbolS *symp;     int *punt;{  static symbolS *last_tagP;  static stack *block_stack;  static symbolS *set_end;  symbolS *next_set_end = NULL;  if (symp == &abs_symbol)    {      *punt = 1;      return;    }  if (current_lineno_sym)    coff_add_linesym ((symbolS *) 0);  if (!block_stack)    block_stack = stack_init (512, sizeof (symbolS*));  if (S_IS_WEAK (symp))    {#ifdef TE_PE      S_SET_STORAGE_CLASS (symp, C_NT_WEAK);#else      S_SET_STORAGE_CLASS (symp, C_WEAKEXT);#endif    }  if (!S_IS_DEFINED (symp)      && !S_IS_WEAK (symp)      && S_GET_STORAGE_CLASS (symp) != C_STAT)    S_SET_STORAGE_CLASS (symp, C_EXT);  if (!SF_GET_DEBUG (symp))    {      symbolS *real;      if (!SF_GET_LOCAL (symp)	  && !SF_GET_STATICS (symp)	  && S_GET_STORAGE_CLASS (symp) != C_LABEL	  && symbol_constant_p(symp)	  && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))	  && real != symp)	{	  c_symbol_merge (symp, real);	  *punt = 1;	  return;	}      if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))	{	  assert (S_GET_VALUE (symp) == 0);	  S_SET_EXTERNAL (symp);	}      else if (S_GET_STORAGE_CLASS (symp) == C_NULL)	{	  if (S_GET_SEGMENT (symp) == text_section	      && symp != seg_info (text_section)->sym)	    S_SET_STORAGE_CLASS (symp, C_LABEL);	  else	    S_SET_STORAGE_CLASS (symp, C_STAT);	}      if (SF_GET_PROCESS (symp))	{	  if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)	    {	      if (!strcmp (S_GET_NAME (symp), ".bb"))		stack_push (block_stack, (char *) &symp);	      else		{		  symbolS *begin;		  begin = *(symbolS **) stack_pop (block_stack);		  if (begin == 0)		    as_warn (_("mismatched .eb"));		  else		    next_set_end = begin;		}	    }	  if (coff_last_function == 0 && SF_GET_FUNCTION (symp))	    {	      union internal_auxent *auxp;	      coff_last_function = symp;	      if (S_GET_NUMBER_AUXILIARY (symp) < 1)		S_SET_NUMBER_AUXILIARY (symp, 1);	      auxp = SYM_AUXENT (symp);	      memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,		      sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));	    }	  if (S_GET_STORAGE_CLASS (symp) == C_EFCN)	    {	      if (coff_last_function == 0)		as_fatal (_("C_EFCN symbol out of scope"));	      SA_SET_SYM_FSIZE (coff_last_function,				(long) (S_GET_VALUE (symp)					- S_GET_VALUE (coff_last_function)));	      next_set_end = coff_last_function;	      coff_last_function = 0;	    }	}      if (S_IS_EXTERNAL (symp))	S_SET_STORAGE_CLASS (symp, C_EXT);      else if (SF_GET_LOCAL (symp))	*punt = 1;      if (SF_GET_FUNCTION (symp))	symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;      /* more ...  */    }  /* Double check weak symbols.  */  if (S_IS_WEAK (symp) && S_IS_COMMON (symp))    as_bad (_("Symbol `%s' can not be both weak and common"),	    S_GET_NAME (symp));  if (SF_GET_TAG (symp))    last_tagP = symp;  else if (S_GET_STORAGE_CLASS (symp) == C_EOS)    next_set_end = last_tagP;#ifdef OBJ_XCOFF  /* This is pretty horrible, but we have to set *punt correctly in     order to call SA_SET_SYM_ENDNDX correctly.  */  if (! symbol_used_in_reloc_p (symp)      && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0	  || (! S_IS_EXTERNAL (symp)	      && ! symbol_get_tc (symp)->output	      && S_GET_STORAGE_CLASS (symp) != C_FILE)))    *punt = 1;#endif  if (set_end != (symbolS *) NULL      && ! *punt      && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0	  || (S_IS_DEFINED (symp)	      && ! S_IS_COMMON (symp)	      && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))    {      SA_SET_SYM_ENDNDX (set_end, symp);      set_end = NULL;    }  if (next_set_end != NULL)    {      if (set_end != NULL)	as_warn ("Warning: internal error: forgetting to set endndx of %s",		 S_GET_NAME (set_end));      set_end = next_set_end;    }  if (! *punt      && S_GET_STORAGE_CLASS (symp) == C_FCN      && strcmp (S_GET_NAME (symp), ".bf") == 0)    {      if (coff_last_bf != NULL)	SA_SET_SYM_ENDNDX (coff_last_bf, symp);      coff_last_bf = symp;    }  if (coffsymbol (symbol_get_bfdsym (symp))->lineno)    {      int i;      struct line_no *lptr;      alent *l;      lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;      for (i = 0; lptr; lptr = lptr->next)	i++;      lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;      /* We need i entries for line numbers, plus 1 for the first	 entry which BFD will override, plus 1 for the last zero	 entry (a marker for BFD).  */      l = (alent *) xmalloc ((i + 2) * sizeof (alent));      coffsymbol (symbol_get_bfdsym (symp))->lineno = l;      l[i + 1].line_number = 0;      l[i + 1].u.sym = NULL;      for (; i > 0; i--)	{	  if (lptr->frag)	    lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;	  l[i] = lptr->l;	  lptr = lptr->next;	}    }}voidcoff_adjust_section_syms (abfd, sec, x)     bfd *abfd ATTRIBUTE_UNUSED;     asection *sec;     PTR x ATTRIBUTE_UNUSED;{  symbolS *secsym;  segment_info_type *seginfo = seg_info (sec);  int nlnno, nrelocs = 0;  /* RS/6000 gas creates a .debug section manually in ppc_frob_file in     tc-ppc.c.  Do not get confused by it.  */  if (seginfo == NULL)    return;  if (!strcmp (sec->name, ".text"))    nlnno = coff_n_line_nos;  else    nlnno = 0;  {    /* @@ Hope that none of the fixups expand to more than one reloc       entry...  */    fixS *fixp = seginfo->fix_root;    while (fixp)      {	if (! fixp->fx_done)	  nrelocs++;	fixp = fixp->fx_next;      }  }  if (bfd_get_section_size_before_reloc (sec) == 0      && nrelocs == 0      && nlnno == 0      && sec != text_section      && sec != data_section      && sec != bss_section)    return;  secsym = section_symbol (sec);  /* This is an estimate; we'll plug in the real value using     SET_SECTION_RELOCS later */  SA_SET_SCN_NRELOC (secsym, nrelocs);  SA_SET_SCN_NLINNO (secsym, nlnno);}voidcoff_frob_file_after_relocs (){  bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0);}/* * implement the .section pseudo op: *	.section name {, "flags"} *                ^         ^ *                |         +--- optional flags: 'b' for bss *                |                              'i' for info *                +-- section name               'l' for lib *                                               'n' for noload *                                               'o' for over *                                               'w' for data *						 'd' (apparently m88k for data) *                                               'x' for text *						 'r' for read-only data *						 's' for shared data (PE) * But if the argument is not a quoted string, treat it as a * subsegment number. */voidobj_coff_section (ignore)     int ignore ATTRIBUTE_UNUSED;{  /* Strip out the section name */  char *section_name;  char c;  char *name;  unsigned int exp;  flagword flags, oldflags;  asection *sec;  if (flag_mri)    {      char type;      s_mri_sect (&type);      return;    }  section_name = input_line_pointer;  c = get_symbol_end ();  name = xmalloc (input_line_pointer - section_name + 1);  strcpy (name, section_name);  *input_line_pointer = c;  SKIP_WHITESPACE ();  exp = 0;  flags = SEC_NO_FLAGS;  if (*input_line_pointer == ',')    {      ++input_line_pointer;      SKIP_WHITESPACE ();      if (*input_line_pointer != '"')	exp = get_absolute_expression ();      else	{	  ++input_line_pointer;	  while (*input_line_pointer != '"'		 && ! is_end_of_line[(unsigned char) *input_line_pointer])	    {	      switch (*input_line_pointer)		{		case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break;		case 'n': flags &=~ SEC_LOAD; flags |= SEC_NEVER_LOAD; break;		case 'd': flags |= SEC_DATA | SEC_LOAD; /* fall through */		case 'w': flags &=~ SEC_READONLY; break;		case 'x': flags |= SEC_CODE | SEC_LOAD; break;		case 'r': flags |= SEC_READONLY; break;		case 's': flags |= SEC_SHARED; break;		case 'i': /* STYP_INFO */		case 'l': /* STYP_LIB */		case 'o': /* STYP_OVER */		  as_warn (_("unsupported section attribute '%c'"),			   *input_line_pointer);		  break;		default:		  as_warn(_("unknown section attribute '%c'"),			  *input_line_pointer);		  break;		}	      ++input_line_pointer;	    }	  if (*input_line_pointer == '"')	    ++input_line_pointer;	}    }  sec = subseg_new (name, (subsegT) exp);  oldflags = bfd_get_section_flags (stdoutput, sec);  if (oldflags == SEC_NO_FLAGS)    {      /* Set section flags for a new section just created by subseg_new.         Provide a default if no flags were parsed.  */      if (flags == SEC_NO_FLAGS)	flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;#ifdef COFF_LONG_SECTION_NAMES      /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce         sections so adjust_reloc_syms in write.c will correctly handle         relocs which refer to non-local symbols in these sections.  */      if (strncmp (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1) == 0)        flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;#endif      if (! bfd_set_section_flags (stdoutput, sec, flags))        as_warn (_("error setting flags for \"%s\": %s"),                 bfd_section_name (stdoutput, sec),                 bfd_errmsg (bfd_get_error ()));    }  else if (flags != SEC_NO_FLAGS)    {      /* This section's attributes have already been set. Warn if the         attributes don't match.  */      flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE			     | SEC_DATA | SEC_SHARED | SEC_NEVER_LOAD);      if ((flags ^ oldflags) & matchflags)	as_warn (_("Ignoring changed section attributes for %s"), name);    }  demand_empty_rest_of_line ();}voidcoff_adjust_symtab (){  if (symbol_rootP == NULL      || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)    c_dot_file_symbol ("fake");}voidcoff_frob_section (sec)     segT sec;{  segT strsec;  char *p;

⌨️ 快捷键说明

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