xcofflink.c

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

C
2,198
字号
      this = (max + min) / 2;      raddr = relocs[this].r_vaddr;      if (raddr > address)	max = this;      else if (raddr < address)	min = this;      else	{	  min = this;	  break;	}    }  if (relocs[min].r_vaddr < address)    return min + 1;  while (min > 0	 && relocs[min - 1].r_vaddr == address)    --min;  return min;}/* Add all the symbols from an object file to the hash table.   XCOFF is a weird format.  A normal XCOFF .o files will have three   COFF sections--.text, .data, and .bss--but each COFF section will   contain many csects.  These csects are described in the symbol   table.  From the linker's point of view, each csect must be   considered a section in its own right.  For example, a TOC entry is   handled as a small XMC_TC csect.  The linker must be able to merge   different TOC entries together, which means that it must be able to   extract the XMC_TC csects from the .data section of the input .o   file.   From the point of view of our linker, this is, of course, a hideous   nightmare.  We cope by actually creating sections for each csect,   and discarding the original sections.  We then have to handle the   relocation entries carefully, since the only way to tell which   csect they belong to is to examine the address.  */static booleanxcoff_link_add_symbols (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  unsigned int n_tmask;  unsigned int n_btshft;  boolean default_copy;  bfd_size_type symcount;  struct xcoff_link_hash_entry **sym_hash;  asection **csect_cache;  bfd_size_type linesz;  asection *o;  asection *last_real;  boolean keep_syms;  asection *csect;  unsigned int csect_index;  asection *first_csect;  bfd_size_type symesz;  bfd_byte *esym;  bfd_byte *esym_end;  struct reloc_info_struct    {      struct internal_reloc *relocs;      asection **csects;      bfd_byte *linenos;    } *reloc_info = NULL;  keep_syms = obj_coff_keep_syms (abfd);  if ((abfd->flags & DYNAMIC) != 0      && ! info->static_link)    {      if (! xcoff_link_add_dynamic_symbols (abfd, info))	return false;    }  if (info->hash->creator == abfd->xvec)    {      /* We need to build a .loader section, so we do it here.  This	 won't work if we're producing an XCOFF output file with no	 XCOFF input files.  FIXME.  */      if (xcoff_hash_table (info)->loader_section == NULL)	{	  asection *lsec;	  lsec = bfd_make_section_anyway (abfd, ".loader");	  if (lsec == NULL)	    goto error_return;	  xcoff_hash_table (info)->loader_section = lsec;	  lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;	}      /* Likewise for the linkage section.  */      if (xcoff_hash_table (info)->linkage_section == NULL)	{	  asection *lsec;	  lsec = bfd_make_section_anyway (abfd, ".gl");	  if (lsec == NULL)	    goto error_return;	  xcoff_hash_table (info)->linkage_section = lsec;	  lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS			  | SEC_IN_MEMORY);	  lsec->alignment_power = 2;	}      /* Likewise for the TOC section.  */      if (xcoff_hash_table (info)->toc_section == NULL)	{	  asection *tsec;	  tsec = bfd_make_section_anyway (abfd, ".tc");	  if (tsec == NULL)	    goto error_return;	  xcoff_hash_table (info)->toc_section = tsec;	  tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS			  | SEC_IN_MEMORY);	  tsec->alignment_power = 2;	}      /* Likewise for the descriptor section.  */      if (xcoff_hash_table (info)->descriptor_section == NULL)	{	  asection *dsec;	  dsec = bfd_make_section_anyway (abfd, ".ds");	  if (dsec == NULL)	    goto error_return;	  xcoff_hash_table (info)->descriptor_section = dsec;	  dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS			  | SEC_IN_MEMORY);	  dsec->alignment_power = 2;	}      /* Likewise for the .debug section.  */      if (xcoff_hash_table (info)->debug_section == NULL	  && info->strip != strip_all)	{	  asection *dsec;	  dsec = bfd_make_section_anyway (abfd, ".debug");	  if (dsec == NULL)	    goto error_return;	  xcoff_hash_table (info)->debug_section = dsec;	  dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;	}    }  if ((abfd->flags & DYNAMIC) != 0      && ! info->static_link)    return true;  n_tmask = coff_data (abfd)->local_n_tmask;  n_btshft = coff_data (abfd)->local_n_btshft;  /* Define macros so that ISFCN, et. al., macros work correctly.  */#define N_TMASK n_tmask#define N_BTSHFT n_btshft  if (info->keep_memory)    default_copy = false;  else    default_copy = true;  symcount = obj_raw_syment_count (abfd);  /* We keep a list of the linker hash table entries that correspond     to each external symbol.  */  sym_hash = ((struct xcoff_link_hash_entry **)	      bfd_alloc (abfd,			 (symcount			  * sizeof (struct xcoff_link_hash_entry *))));  if (sym_hash == NULL && symcount != 0)    goto error_return;  coff_data (abfd)->sym_hashes = (struct coff_link_hash_entry **) sym_hash;  memset (sym_hash, 0,	  (size_t) symcount * sizeof (struct xcoff_link_hash_entry *));  /* Because of the weird stuff we are doing with XCOFF csects, we can     not easily determine which section a symbol is in, so we store     the information in the tdata for the input file.  */  csect_cache = ((asection **)		 bfd_alloc (abfd, symcount * sizeof (asection *)));  if (csect_cache == NULL && symcount != 0)    goto error_return;  xcoff_data (abfd)->csects = csect_cache;  memset (csect_cache, 0, (size_t) symcount * sizeof (asection *));  /* While splitting sections into csects, we need to assign the     relocs correctly.  The relocs and the csects must both be in     order by VMA within a given section, so we handle this by     scanning along the relocs as we process the csects.  We index     into reloc_info using the section target_index.  */  reloc_info = ((struct reloc_info_struct *)		bfd_malloc ((abfd->section_count + 1)			    * sizeof (struct reloc_info_struct)));  if (reloc_info == NULL)    goto error_return;  memset ((PTR) reloc_info, 0,	  (abfd->section_count + 1) * sizeof (struct reloc_info_struct));  /* Read in the relocs and line numbers for each section.  */  linesz = bfd_coff_linesz (abfd);  last_real = NULL;  for (o = abfd->sections; o != NULL; o = o->next)    {      last_real = o;      if ((o->flags & SEC_RELOC) != 0)	{	  reloc_info[o->target_index].relocs =	    xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,					false, (struct internal_reloc *) NULL);	  reloc_info[o->target_index].csects =	    (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));	  if (reloc_info[o->target_index].csects == NULL)	    goto error_return;	  memset (reloc_info[o->target_index].csects, 0,		  o->reloc_count * sizeof (asection *));	}      if ((info->strip == strip_none || info->strip == strip_some)	  && o->lineno_count > 0)	{	  bfd_byte *linenos;	  linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);	  if (linenos == NULL)	    goto error_return;	  reloc_info[o->target_index].linenos = linenos;	  if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0	      || (bfd_read (linenos, linesz, o->lineno_count, abfd)		  != linesz * o->lineno_count))	    goto error_return;	}    }  /* Don't let the linker relocation routines discard the symbols.  */  obj_coff_keep_syms (abfd) = true;  csect = NULL;  csect_index = 0;  first_csect = NULL;  symesz = bfd_coff_symesz (abfd);  BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));  esym = (bfd_byte *) obj_coff_external_syms (abfd);  esym_end = esym + symcount * symesz;  while (esym < esym_end)    {      struct internal_syment sym;      union internal_auxent aux;      const char *name;      char buf[SYMNMLEN + 1];      int smtyp;      flagword flags;      asection *section;      bfd_vma value;      struct xcoff_link_hash_entry *set_toc;      bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);      /* In this pass we are only interested in symbols with csect         information.  */      if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)	{	  if (sym.n_sclass == C_FILE && csect != NULL)	    {	      xcoff_section_data (abfd, csect)->last_symndx =		((esym		  - (bfd_byte *) obj_coff_external_syms (abfd))		 / symesz);	      csect = NULL;	    }	  if (csect != NULL)	    *csect_cache = csect;	  else if (first_csect == NULL || sym.n_sclass == C_FILE)	    *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);	  else	    *csect_cache = NULL;	  esym += (sym.n_numaux + 1) * symesz;	  sym_hash += sym.n_numaux + 1;	  csect_cache += sym.n_numaux + 1;	  continue;	}      name = _bfd_coff_internal_syment_name (abfd, &sym, buf);      if (name == NULL)	goto error_return;      /* If this symbol has line number information attached to it,         and we're not stripping it, count the number of entries and         add them to the count for this csect.  In the final link pass         we are going to attach line number information by symbol,         rather than by section, in order to more easily handle         garbage collection.  */      if ((info->strip == strip_none || info->strip == strip_some)	  && sym.n_numaux > 1	  && csect != NULL	  && ISFCN (sym.n_type))	{	  union internal_auxent auxlin;	  bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),				sym.n_type, sym.n_sclass,				0, sym.n_numaux, (PTR) &auxlin);	  if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)	    {	      asection *enclosing;	      bfd_size_type linoff;	      enclosing = xcoff_section_data (abfd, csect)->enclosing;	      if (enclosing == NULL)		{		  (*_bfd_error_handler)		    (_("%s: `%s' has line numbers but no enclosing section"),		     bfd_get_filename (abfd), name);		  bfd_set_error (bfd_error_bad_value);		  goto error_return;		}	      linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr			- enclosing->line_filepos);	      if (linoff < enclosing->lineno_count * linesz)		{		  struct internal_lineno lin;		  bfd_byte *linpstart;		  linpstart = (reloc_info[enclosing->target_index].linenos			       + linoff);		  bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);		  if (lin.l_lnno == 0		      && ((bfd_size_type) lin.l_addr.l_symndx			  == ((esym			       - (bfd_byte *) obj_coff_external_syms (abfd))			      / symesz)))		    {		      bfd_byte *linpend, *linp;		      linpend = (reloc_info[enclosing->target_index].linenos				 + enclosing->lineno_count * linesz);		      for (linp = linpstart + linesz;			   linp < linpend;			   linp += linesz)			{			  bfd_coff_swap_lineno_in (abfd, (PTR) linp,						   (PTR) &lin);			  if (lin.l_lnno == 0)			    break;			}		      csect->lineno_count += (linp - linpstart) / linesz;		      /* The setting of line_filepos will only be                         useful if all the line number entries for a                         csect are contiguous; this only matters for                         error reporting.  */		      if (csect->line_filepos == 0)			csect->line_filepos =			  auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;		    }		}	    }	}      /* Pick up the csect auxiliary information.  */      if (sym.n_numaux == 0)	{	  (*_bfd_error_handler)	    (_("%s: class %d symbol `%s' has no aux entries"),	     bfd_get_filename (abfd), sym.n_sclass, name);	  bfd_set_error (bfd_error_bad_value);	  goto error_return;	}      bfd_coff_swap_aux_in (abfd,			    (PTR) (esym + symesz * sym.n_numaux),			    sym.n_type, sym.n_sclass,			    sym.n_numaux - 1, sym.n_numaux,			    (PTR) &aux);      smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);      flags = BSF_GLOBAL;      section = NULL;      value = 0;      set_toc = NULL;      switch (smtyp)	{	default:	  (*_bfd_error_handler)	    (_("%s: symbol `%s' has unrecognized csect type %d"),	     bfd_get_filename (abfd), name, smtyp);	  bfd_set_error (bfd_error_bad_value);	  goto error_return;	case XTY_ER:	  /* This is an external reference.  */	  if (sym.n_sclass == C_HIDEXT	      || sym.n_scnum != N_UNDEF	      || aux.x_csect.x_scnlen.l != 0)	    {	      (*_bfd_error_handler)		(_("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"),		 bfd_get_filename (abfd), name, sym.n_sclass, sym.n_scnum,		 aux.x_csect.x_scnlen.l);	      bfd_set_error (bfd_error_bad_value);	      goto error_return;	    }	  /* An XMC_XO external reference is actually a reference to             an absolute location.  */	  if (aux.x_csect.x_smclas != XMC_XO)	    section = bfd_und_section_ptr;	  else	    {	      section = bfd_abs_section_ptr;	      value = sym.n_value;	    }	  break;	case XTY_SD:	  /* This is a csect definition.  */	  if (csect != NULL)	    {	      xcoff_section_data (abfd, csect)->last_symndx =		((esym		  - (bfd_byte *) obj_coff_external_syms (abfd))		 / symesz);	    }	  csect = NULL;	  csect_index = -1;	  /* When we see a TOC anchor, we record the TOC value.  */	  if (aux.x_csect.x_smclas == XMC_TC0)	    {	      if (sym.n_sclass != C_HIDEXT		  || aux.x_csect.x_scnlen.l != 0)		{		  (*_bfd_error_handler)

⌨️ 快捷键说明

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