coffgen.c

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

C
2,343
字号
  if (free_external != NULL)    {      free (free_external);      free_external = NULL;    }  if (cache && free_internal != NULL)    {      if (coff_section_data (abfd, sec) == NULL)	{	  sec->used_by_bfd =	    (PTR) bfd_zalloc (abfd,			      sizeof (struct coff_section_tdata));	  if (sec->used_by_bfd == NULL)	    goto error_return;	  coff_section_data (abfd, sec)->contents = NULL;	}      coff_section_data (abfd, sec)->relocs = free_internal;    }  return internal_relocs; error_return:  if (free_external != NULL)    free (free_external);  if (free_internal != NULL)    free (free_internal);  return NULL;}/* Set lineno_count for the output sections of a COFF file.  */intcoff_count_linenumbers (abfd)     bfd *abfd;{  unsigned int limit = bfd_get_symcount (abfd);  unsigned int i;  int total = 0;  asymbol **p;  asection *s;  if (limit == 0)    {      /* This may be from the backend linker, in which case the         lineno_count in the sections is correct.  */      for (s = abfd->sections; s != NULL; s = s->next)	total += s->lineno_count;      return total;    }  for (s = abfd->sections; s != NULL; s = s->next)    BFD_ASSERT (s->lineno_count == 0);  for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)    {      asymbol *q_maybe = *p;      if (bfd_family_coff (bfd_asymbol_bfd (q_maybe)))	{	  coff_symbol_type *q = coffsymbol (q_maybe);	  /* The AIX 4.1 compiler can sometimes generate line numbers             attached to debugging symbols.  We try to simply ignore             those here.  */	  if (q->lineno != NULL	      && q->symbol.section->owner != NULL)	    {	      /* This symbol has line numbers.  Increment the owning	         section's linenumber count.  */	      alent *l = q->lineno;	      ++q->symbol.section->output_section->lineno_count;	      ++total;	      ++l;	      while (l->line_number != 0)		{		  ++total;		  ++q->symbol.section->output_section->lineno_count;		  ++l;		}	    }	}    }  return total;}/* Takes a bfd and a symbol, returns a pointer to the coff specific   area of the symbol if there is one.  */coff_symbol_type *coff_symbol_from (ignore_abfd, symbol)     bfd *ignore_abfd ATTRIBUTE_UNUSED;     asymbol *symbol;{  if (!bfd_family_coff (bfd_asymbol_bfd (symbol)))    return (coff_symbol_type *) NULL;  if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL)    return (coff_symbol_type *) NULL;  return (coff_symbol_type *) symbol;}static voidfixup_symbol_value (abfd, coff_symbol_ptr, syment)     bfd *abfd;     coff_symbol_type *coff_symbol_ptr;     struct internal_syment *syment;{  /* Normalize the symbol flags */  if (bfd_is_com_section (coff_symbol_ptr->symbol.section))    {      /* a common symbol is undefined with a value */      syment->n_scnum = N_UNDEF;      syment->n_value = coff_symbol_ptr->symbol.value;    }  else if ((coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) != 0	   && (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING_RELOC) == 0)    {      syment->n_value = coff_symbol_ptr->symbol.value;    }  else if (bfd_is_und_section (coff_symbol_ptr->symbol.section))    {      syment->n_scnum = N_UNDEF;      syment->n_value = 0;    }  /* FIXME: Do we need to handle the absolute section here?  */  else    {      if (coff_symbol_ptr->symbol.section)	{	  syment->n_scnum =	    coff_symbol_ptr->symbol.section->output_section->target_index;	  syment->n_value = (coff_symbol_ptr->symbol.value			     + coff_symbol_ptr->symbol.section->output_offset);	  if (! obj_pe (abfd))            {              syment->n_value += (syment->n_sclass == C_STATLAB)                ? coff_symbol_ptr->symbol.section->output_section->lma                : coff_symbol_ptr->symbol.section->output_section->vma;            }	}      else	{	  BFD_ASSERT (0);	  /* This can happen, but I don't know why yet (steve@cygnus.com) */	  syment->n_scnum = N_ABS;	  syment->n_value = coff_symbol_ptr->symbol.value;	}    }}/* Run through all the symbols in the symbol table and work out what   their indexes into the symbol table will be when output.   Coff requires that each C_FILE symbol points to the next one in the   chain, and that the last one points to the first external symbol. We   do that here too.  */booleancoff_renumber_symbols (bfd_ptr, first_undef)     bfd *bfd_ptr;     int *first_undef;{  unsigned int symbol_count = bfd_get_symcount (bfd_ptr);  asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;  unsigned int native_index = 0;  struct internal_syment *last_file = (struct internal_syment *) NULL;  unsigned int symbol_index;  /* COFF demands that undefined symbols come after all other symbols.     Since we don't need to impose this extra knowledge on all our     client programs, deal with that here.  Sort the symbol table;     just move the undefined symbols to the end, leaving the rest     alone.  The O'Reilly book says that defined global symbols come     at the end before the undefined symbols, so we do that here as     well.  */  /* @@ Do we have some condition we could test for, so we don't always     have to do this?  I don't think relocatability is quite right, but     I'm not certain.  [raeburn:19920508.1711EST]  */  {    asymbol **newsyms;    unsigned int i;    newsyms = (asymbol **) bfd_alloc (bfd_ptr,				      sizeof (asymbol *) * (symbol_count + 1));    if (!newsyms)      return false;    bfd_ptr->outsymbols = newsyms;    for (i = 0; i < symbol_count; i++)      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0	  || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)	      && !bfd_is_com_section (symbol_ptr_ptr[i]->section)	      && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0		  || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))		      == 0))))	*newsyms++ = symbol_ptr_ptr[i];    for (i = 0; i < symbol_count; i++)      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0	  && !bfd_is_und_section (symbol_ptr_ptr[i]->section)	  && (bfd_is_com_section (symbol_ptr_ptr[i]->section)	      || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0		  && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))		      != 0))))	*newsyms++ = symbol_ptr_ptr[i];    *first_undef = newsyms - bfd_ptr->outsymbols;    for (i = 0; i < symbol_count; i++)      if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0	  && bfd_is_und_section (symbol_ptr_ptr[i]->section))	*newsyms++ = symbol_ptr_ptr[i];    *newsyms = (asymbol *) NULL;    symbol_ptr_ptr = bfd_ptr->outsymbols;  }  for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)    {      coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);      symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;      if (coff_symbol_ptr && coff_symbol_ptr->native)	{	  combined_entry_type *s = coff_symbol_ptr->native;	  int i;	  if (s->u.syment.n_sclass == C_FILE)	    {	      if (last_file != (struct internal_syment *) NULL)		last_file->n_value = native_index;	      last_file = &(s->u.syment);	    }	  else	    {	      /* Modify the symbol values according to their section and	         type */	      fixup_symbol_value (bfd_ptr, coff_symbol_ptr, &(s->u.syment));	    }	  for (i = 0; i < s->u.syment.n_numaux + 1; i++)	    s[i].offset = native_index++;	}      else	{	  native_index++;	}    }  obj_conv_table_size (bfd_ptr) = native_index;  return true;}/* Run thorough the symbol table again, and fix it so that all   pointers to entries are changed to the entries' index in the output   symbol table.  */voidcoff_mangle_symbols (bfd_ptr)     bfd *bfd_ptr;{  unsigned int symbol_count = bfd_get_symcount (bfd_ptr);  asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;  unsigned int symbol_index;  for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)    {      coff_symbol_type *coff_symbol_ptr =      coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]);      if (coff_symbol_ptr && coff_symbol_ptr->native)	{	  int i;	  combined_entry_type *s = coff_symbol_ptr->native;	  if (s->fix_value)	    {	      /* FIXME: We should use a union here.  */	      s->u.syment.n_value =		((combined_entry_type *) s->u.syment.n_value)->offset;	      s->fix_value = 0;	    }	  if (s->fix_line)	    {	      /* The value is the offset into the line number entries                 for the symbol's section.  On output, the symbol's                 section should be N_DEBUG.  */	      s->u.syment.n_value =		(coff_symbol_ptr->symbol.section->output_section->line_filepos		 + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));	      coff_symbol_ptr->symbol.section =		coff_section_from_bfd_index (bfd_ptr, N_DEBUG);	      BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING);	    }	  for (i = 0; i < s->u.syment.n_numaux; i++)	    {	      combined_entry_type *a = s + i + 1;	      if (a->fix_tag)		{		  a->u.auxent.x_sym.x_tagndx.l =		    a->u.auxent.x_sym.x_tagndx.p->offset;		  a->fix_tag = 0;		}	      if (a->fix_end)		{		  a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l =		    a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset;		  a->fix_end = 0;		}	      if (a->fix_scnlen)		{		  a->u.auxent.x_csect.x_scnlen.l =		    a->u.auxent.x_csect.x_scnlen.p->offset;		  a->fix_scnlen = 0;		}	    }	}    }}static voidcoff_fix_symbol_name (abfd, symbol, native, string_size_p,		      debug_string_section_p, debug_string_size_p)     bfd *abfd;     asymbol *symbol;     combined_entry_type *native;     bfd_size_type *string_size_p;     asection **debug_string_section_p;     bfd_size_type *debug_string_size_p;{  unsigned int name_length;  union internal_auxent *auxent;  char *name = (char *) (symbol->name);  if (name == (char *) NULL)    {      /* coff symbols always have names, so we'll make one up */      symbol->name = "strange";      name = (char *) symbol->name;    }  name_length = strlen (name);  if (native->u.syment.n_sclass == C_FILE      && native->u.syment.n_numaux > 0)    {      unsigned int filnmlen;      if (bfd_coff_force_symnames_in_strings (abfd))	{          native->u.syment._n._n_n._n_offset =	      (*string_size_p + STRING_SIZE_SIZE);	  native->u.syment._n._n_n._n_zeroes = 0;	  *string_size_p += 6;  /* strlen(".file") + 1 */	}      else  	strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);      auxent = &(native + 1)->u.auxent;      filnmlen = bfd_coff_filnmlen (abfd);      if (bfd_coff_long_filenames (abfd))	{	  if (name_length <= filnmlen)	    {	      strncpy (auxent->x_file.x_fname, name, filnmlen);	    }	  else	    {	      auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;	      auxent->x_file.x_n.x_zeroes = 0;	      *string_size_p += name_length + 1;	    }	}      else	{	  strncpy (auxent->x_file.x_fname, name, filnmlen);	  if (name_length > filnmlen)	    name[filnmlen] = '\0';	}    }  else    {      if (name_length <= SYMNMLEN && !bfd_coff_force_symnames_in_strings (abfd))	{	  /* This name will fit into the symbol neatly */	  strncpy (native->u.syment._n._n_name, symbol->name, SYMNMLEN);	}      else if (!bfd_coff_symname_in_debug (abfd, &native->u.syment))	{	  native->u.syment._n._n_n._n_offset = (*string_size_p						+ STRING_SIZE_SIZE);	  native->u.syment._n._n_n._n_zeroes = 0;	  *string_size_p += name_length + 1;	}      else	{	  long filepos;	  bfd_byte buf[4];	  int prefix_len = bfd_coff_debug_string_prefix_length (abfd);	  /* This name should be written into the .debug section.  For	     some reason each name is preceded by a two byte length	     and also followed by a null byte.  FIXME: We assume that	     the .debug section has already been created, and that it	     is large enough.  */	  if (*debug_string_section_p == (asection *) NULL)	    *debug_string_section_p = bfd_get_section_by_name (abfd, ".debug");	  filepos = bfd_tell (abfd);	  if (prefix_len == 4)	    bfd_put_32 (abfd, name_length + 1, buf);	  else	    bfd_put_16 (abfd, name_length + 1, buf);	  if (!bfd_set_section_contents (abfd,					 *debug_string_section_p,					 (PTR) buf,					 (file_ptr) *debug_string_size_p,					 (bfd_size_type) prefix_len)	      || !bfd_set_section_contents (abfd,					    *debug_string_section_p,					    (PTR) symbol->name,					    ((file_ptr) *debug_string_size_p					     + prefix_len),					    (bfd_size_type) name_length + 1))	    abort ();	  if (bfd_seek (abfd, filepos, SEEK_SET) != 0)	    abort ();	  native->u.syment._n._n_n._n_offset =	      *debug_string_size_p + prefix_len;	  native->u.syment._n._n_n._n_zeroes = 0;	  *debug_string_size_p += name_length + 1 + prefix_len;	}    }}/* We need to keep track of the symbol index so that when we write out   the relocs we can get the index for a symbol.  This method is a   hack.  FIXME.  */#define set_index(symbol, idx)	((symbol)->udata.i = (idx))/* Write a symbol out to a COFF file.  */static booleancoff_write_symbol (abfd, symbol, native, written, string_size_p,		   debug_string_section_p, debug_string_size_p)     bfd *abfd;     asymbol *symbol;     combined_entry_type *native;     unsigned int *written;     bfd_size_type *string_size_p;     asection **debug_string_section_p;     bfd_size_type *debug_string_size_p;{  unsigned int numaux = native->u.syment.n_numaux;  int type = native->u.syment.n_type;  int class = native->u.syment.n_sclass;  PTR buf;  bfd_size_type symesz;  if (native->u.syment.n_sclass == C_FILE)    symbol->flags |= BSF_DEBUGGING;  if (symbol->flags & BSF_DEBUGGING

⌨️ 快捷键说明

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