cofflink.c

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

C
2,243
字号
	     FIXME: I don't think this will work in the case where	     there are two object files which use the constants as a	     literal and two object files which use it as a data	     initializer.  One or the other of the second object files	     is going to wind up with an inappropriate reference.  */	  if (obj_pe (abfd)	      && (classification == COFF_SYMBOL_GLOBAL		  || classification == COFF_SYMBOL_PE_SECTION)	      && section->comdat != NULL	      && strncmp (name, "??_", 3) == 0	      && strcmp (name, section->comdat->name) == 0)	    {	      if (*sym_hash == NULL)		*sym_hash = coff_link_hash_lookup (coff_hash_table (info),						   name, false, copy, false);	      if (*sym_hash != NULL		  && (*sym_hash)->root.type == bfd_link_hash_defined		  && (*sym_hash)->root.u.def.section->comdat != NULL		  && strcmp ((*sym_hash)->root.u.def.section->comdat->name,			     section->comdat->name) == 0)		addit = false;	    }	  if (addit)	    {	      if (! (bfd_coff_link_add_one_symbol		     (info, abfd, name, flags, section, value,		      (const char *) NULL, copy, false,		      (struct bfd_link_hash_entry **) sym_hash)))		goto error_return;	    }	  if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0)	    (*sym_hash)->coff_link_hash_flags |=	      COFF_LINK_HASH_PE_SECTION_SYMBOL;	  /* Limit the alignment of a common symbol to the possible             alignment of a section.  There is no point to permitting             a higher alignment for a common symbol: we can not             guarantee it, and it may cause us to allocate extra space             in the common section.  */	  if (section == bfd_com_section_ptr	      && (*sym_hash)->root.type == bfd_link_hash_common	      && ((*sym_hash)->root.u.c.p->alignment_power		  > bfd_coff_default_section_alignment_power (abfd)))	    (*sym_hash)->root.u.c.p->alignment_power	      = bfd_coff_default_section_alignment_power (abfd);	  if (info->hash->creator->flavour == bfd_get_flavour (abfd))	    {	      /* If we don't have any symbol information currently in                 the hash table, or if we are looking at a symbol                 definition, then update the symbol class and type in                 the hash table.  */  	      if (((*sym_hash)->class == C_NULL  		   && (*sym_hash)->type == T_NULL)  		  || sym.n_scnum != 0  		  || (sym.n_value != 0  		      && (*sym_hash)->root.type != bfd_link_hash_defined  		      && (*sym_hash)->root.type != bfd_link_hash_defweak))  		{  		  (*sym_hash)->class = sym.n_sclass;  		  if (sym.n_type != T_NULL)  		    {  		      /* We want to warn if the type changed, but not  			 if it changed from an unspecified type.  			 Testing the whole type byte may work, but the  			 change from (e.g.) a function of unspecified  			 type to function of known type also wants to  			 skip the warning.  */  		      if ((*sym_hash)->type != T_NULL  			  && (*sym_hash)->type != sym.n_type  		          && !(DTYPE ((*sym_hash)->type) == DTYPE (sym.n_type)  		               && (BTYPE ((*sym_hash)->type) == T_NULL  		                   || BTYPE (sym.n_type) == T_NULL)))  			(*_bfd_error_handler)  			  (_("Warning: type of symbol `%s' changed from %d to %d in %s"),  			   name, (*sym_hash)->type, sym.n_type,  			   bfd_get_filename (abfd));  		      /* We don't want to change from a meaningful  			 base type to a null one, but if we know  			 nothing, take what little we might now know.  */  		      if (BTYPE (sym.n_type) != T_NULL  			  || (*sym_hash)->type == T_NULL)			(*sym_hash)->type = sym.n_type;  		    }  		  (*sym_hash)->auxbfd = abfd;		  if (sym.n_numaux != 0)		    {		      union internal_auxent *alloc;		      unsigned int i;		      bfd_byte *eaux;		      union internal_auxent *iaux;		      (*sym_hash)->numaux = sym.n_numaux;		      alloc = ((union internal_auxent *)			       bfd_hash_allocate (&info->hash->table,						  (sym.n_numaux						   * sizeof (*alloc))));		      if (alloc == NULL)			goto error_return;		      for (i = 0, eaux = esym + symesz, iaux = alloc;			   i < sym.n_numaux;			   i++, eaux += symesz, iaux++)			bfd_coff_swap_aux_in (abfd, (PTR) eaux, sym.n_type,					      sym.n_sclass, i, sym.n_numaux,					      (PTR) iaux);		      (*sym_hash)->aux = alloc;		    }		}	    }	  if (classification == COFF_SYMBOL_PE_SECTION	      && (*sym_hash)->numaux != 0)	    {	      /* Some PE sections (such as .bss) have a zero size in                 the section header, but a non-zero size in the AUX                 record.  Correct that here.		 FIXME: This is not at all the right place to do this.		 For example, it won't help objdump.  This needs to be		 done when we swap in the section header.  */	      BFD_ASSERT ((*sym_hash)->numaux == 1);	      if (section->_raw_size == 0)		section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen;	      /* FIXME: We could test whether the section sizes                 matches the size in the aux entry, but apparently                 that sometimes fails unexpectedly.  */	    }	}      esym += (sym.n_numaux + 1) * symesz;      sym_hash += sym.n_numaux + 1;    }  /* If this is a non-traditional, non-relocateable link, try to     optimize the handling of any .stab/.stabstr sections.  */  if (! info->relocateable      && ! info->traditional_format      && info->hash->creator->flavour == bfd_get_flavour (abfd)      && (info->strip != strip_all && info->strip != strip_debugger))    {      asection *stab, *stabstr;      stab = bfd_get_section_by_name (abfd, ".stab");      if (stab != NULL)	{	  stabstr = bfd_get_section_by_name (abfd, ".stabstr");	  if (stabstr != NULL)	    {	      struct coff_link_hash_table *table;	      struct coff_section_tdata *secdata;	      secdata = coff_section_data (abfd, stab);	      if (secdata == NULL)		{		  stab->used_by_bfd =		    (PTR) bfd_zalloc (abfd,				      sizeof (struct coff_section_tdata));		  if (stab->used_by_bfd == NULL)		    goto error_return;		  secdata = coff_section_data (abfd, stab);		}	      table = coff_hash_table (info);	      if (! _bfd_link_section_stabs (abfd, &table->stab_info,					     stab, stabstr,					     &secdata->stab_info))		goto error_return;	    }	}    }  obj_coff_keep_syms (abfd) = keep_syms;  return true; error_return:  obj_coff_keep_syms (abfd) = keep_syms;  return false;}/* Do the final link step.  */boolean_bfd_coff_final_link (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  bfd_size_type symesz;  struct coff_final_link_info finfo;  boolean debug_merge_allocated;  boolean long_section_names;  asection *o;  struct bfd_link_order *p;  size_t max_sym_count;  size_t max_lineno_count;  size_t max_reloc_count;  size_t max_output_reloc_count;  size_t max_contents_size;  file_ptr rel_filepos;  unsigned int relsz;  file_ptr line_filepos;  unsigned int linesz;  bfd *sub;  bfd_byte *external_relocs = NULL;  char strbuf[STRING_SIZE_SIZE];  symesz = bfd_coff_symesz (abfd);  finfo.info = info;  finfo.output_bfd = abfd;  finfo.strtab = NULL;  finfo.section_info = NULL;  finfo.last_file_index = -1;  finfo.last_bf_index = -1;  finfo.internal_syms = NULL;  finfo.sec_ptrs = NULL;  finfo.sym_indices = NULL;  finfo.outsyms = NULL;  finfo.linenos = NULL;  finfo.contents = NULL;  finfo.external_relocs = NULL;  finfo.internal_relocs = NULL;  finfo.global_to_static = false;  debug_merge_allocated = false;  coff_data (abfd)->link_info = info;  finfo.strtab = _bfd_stringtab_init ();  if (finfo.strtab == NULL)    goto error_return;  if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))    goto error_return;  debug_merge_allocated = true;  /* Compute the file positions for all the sections.  */  if (! abfd->output_has_begun)    {      if (! bfd_coff_compute_section_file_positions (abfd))	goto error_return;    }  /* Count the line numbers and relocation entries required for the     output file.  Set the file positions for the relocs.  */  rel_filepos = obj_relocbase (abfd);  relsz = bfd_coff_relsz (abfd);  max_contents_size = 0;  max_lineno_count = 0;  max_reloc_count = 0;  long_section_names = false;  for (o = abfd->sections; o != NULL; o = o->next)    {      o->reloc_count = 0;      o->lineno_count = 0;      for (p = o->link_order_head; p != NULL; p = p->next)	{	  if (p->type == bfd_indirect_link_order)	    {	      asection *sec;	      sec = p->u.indirect.section;	      /* Mark all sections which are to be included in the		 link.  This will normally be every section.  We need		 to do this so that we can identify any sections which		 the linker has decided to not include.  */	      sec->linker_mark = true;	      if (info->strip == strip_none		  || info->strip == strip_some)		o->lineno_count += sec->lineno_count;	      if (info->relocateable)		o->reloc_count += sec->reloc_count;	      if (sec->_raw_size > max_contents_size)		max_contents_size = sec->_raw_size;	      if (sec->lineno_count > max_lineno_count)		max_lineno_count = sec->lineno_count;	      if (sec->reloc_count > max_reloc_count)		max_reloc_count = sec->reloc_count;	    }	  else if (info->relocateable		   && (p->type == bfd_section_reloc_link_order		       || p->type == bfd_symbol_reloc_link_order))	    ++o->reloc_count;	}      if (o->reloc_count == 0)	o->rel_filepos = 0;      else	{	  o->flags |= SEC_RELOC;	  o->rel_filepos = rel_filepos;	  rel_filepos += o->reloc_count * relsz;	}      if (bfd_coff_long_section_names (abfd)	  && strlen (o->name) > SCNNMLEN)	{	  /* This section has a long name which must go in the string             table.  This must correspond to the code in             coff_write_object_contents which puts the string index             into the s_name field of the section header.  That is why             we pass hash as false.  */	  if (_bfd_stringtab_add (finfo.strtab, o->name, false, false)	      == (bfd_size_type) -1)	    goto error_return;	  long_section_names = true;	}    }  /* If doing a relocateable link, allocate space for the pointers we     need to keep.  */  if (info->relocateable)    {      unsigned int i;      /* We use section_count + 1, rather than section_count, because         the target_index fields are 1 based.  */      finfo.section_info =	((struct coff_link_section_info *)	 bfd_malloc ((abfd->section_count + 1)		     * sizeof (struct coff_link_section_info)));      if (finfo.section_info == NULL)	goto error_return;      for (i = 0; i <= abfd->section_count; i++)	{	  finfo.section_info[i].relocs = NULL;	  finfo.section_info[i].rel_hashes = NULL;	}    }  /* We now know the size of the relocs, so we can determine the file     positions of the line numbers.  */  line_filepos = rel_filepos;  linesz = bfd_coff_linesz (abfd);  max_output_reloc_count = 0;  for (o = abfd->sections; o != NULL; o = o->next)    {      if (o->lineno_count == 0)	o->line_filepos = 0;      else	{	  o->line_filepos = line_filepos;	  line_filepos += o->lineno_count * linesz;	}      if (o->reloc_count != 0)	{	  /* We don't know the indices of global symbols until we have             written out all the local symbols.  For each section in             the output file, we keep an array of pointers to hash             table entries.  Each entry in the array corresponds to a             reloc.  When we find a reloc against a global symbol, we             set the corresponding entry in this array so that we can             fix up the symbol index after we have written out all the             local symbols.	     Because of this problem, we also keep the relocs in	     memory until the end of the link.  This wastes memory,	     but only when doing a relocateable link, which is not the	     common case.  */	  BFD_ASSERT (info->relocateable);	  finfo.section_info[o->target_index].relocs =	    ((struct internal_reloc *)	     bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));	  finfo.section_info[o->target_index].rel_hashes =	    ((struct coff_link_hash_entry **)	     bfd_malloc (o->reloc_count		     * sizeof (struct coff_link_hash_entry *)));	  if (finfo.section_info[o->target_index].relocs == NULL	      || finfo.section_info[o->target_index].rel_hashes == NULL)	    goto error_return;	  if (o->reloc_count > max_output_reloc_count)	    max_output_reloc_count = o->reloc_count;	}      /* Reset the reloc and lineno counts, so that we can use them to	 count the number of entries we have output so far.  */      o->reloc_count = 0;      o->lineno_count = 0;    }  obj_sym_filepos (abfd) = line_filepos;  /* Figure out the largest number of symbols in an input BFD.  Take     the opportunity to clear the output_has_begun fields of all the     input BFD's.  */  max_sym_count = 0;  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)    {      size_t sz;      sub->output_has_begun = false;      sz = obj_raw_syment_count (sub);      if (sz > max_sym_count)	max_sym_count = sz;    }  /* Allocate some buffers used while linking.  */  finfo.internal_syms = ((struct internal_syment *)			 bfd_malloc (max_sym_count				     * sizeof (struct internal_syment)));  finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count					     * sizeof (asection *));  finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));  finfo.outsyms = ((bfd_byte *)		   bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));  finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count				       * bfd_coff_linesz (abfd));  finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);  finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);  if (! info->relocateable)    finfo.internal_relocs = ((struct internal_reloc *)			     bfd_malloc (max_reloc_count					 * sizeof (struct internal_reloc)));  if ((finfo.internal_syms == NULL && max_sym_count > 0)      || (finfo.sec_ptrs == NULL && max_sym_count > 0)      || (finfo.sym_indices == NULL && max_sym_count > 0)      || finfo.outsyms == NULL      || (finfo.linenos == NULL && max_lineno_count > 0)      || (finfo.contents == NULL && max_contents_size > 0)      || (finfo.external_relocs == NULL && max_reloc_count > 0)      || (! info->relocateable	  && finfo.internal_relocs == NULL	  && max_reloc_count > 0))    goto error_return;  /* We now know the position of everything in the file, except that     we don't know the size of the symbol table and therefore we don't     know where the string table starts.  We just build the string     table in memory as we go along.  We process all the relocations     for a single input file at once.  */  obj_raw_syment_count (abfd) = 0;  if (coff_backend_info (abfd)->_bfd_coff_start_final_link)    {      if (! bfd_coff_start_final_link (abfd, info))	goto error_return;

⌨️ 快捷键说明

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