elf32-sparc.c

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

C
2,014
字号
		      && (r_type == R_SPARC_8			  || r_type == R_SPARC_16			  || r_type == R_SPARC_32			  || r_type == R_SPARC_DISP8			  || r_type == R_SPARC_DISP16			  || r_type == R_SPARC_DISP32			  || r_type == R_SPARC_WDISP30			  || r_type == R_SPARC_WDISP22			  || r_type == R_SPARC_WDISP19			  || r_type == R_SPARC_WDISP16			  || r_type == R_SPARC_HI22			  || r_type == R_SPARC_22			  || r_type == R_SPARC_13			  || r_type == R_SPARC_LO10			  || r_type == R_SPARC_UA16			  || r_type == R_SPARC_UA32			  || r_type == R_SPARC_UA64			  || ((r_type == R_SPARC_PC10			       || r_type == R_SPARC_PC22)			      && strcmp (h->root.root.string,					 "_GLOBAL_OFFSET_TABLE_") != 0))))		{		  /* In these cases, we don't need the relocation                     value.  We check specially because in some                     obscure cases sec->output_section will be NULL.  */		  relocation = 0;		}	      else		relocation = (h->root.u.def.value			      + sec->output_section->vma			      + sec->output_offset);	    }	  else if (h->root.type == bfd_link_hash_undefweak)	    relocation = 0;	  else if (info->shared && !info->symbolic		   && !info->no_undefined		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)	    relocation = 0;	  else	    {	      if (! ((*info->callbacks->undefined_symbol)		     (info, h->root.root.string, input_bfd,		      input_section, rel->r_offset,		      (!info->shared || info->no_undefined		       || ELF_ST_VISIBILITY (h->other)))))		return false;	      relocation = 0;	    }	}      switch (r_type)	{	case R_SPARC_GOT10:	case R_SPARC_GOT13:	case R_SPARC_GOT22:	  /* Relocation is to the entry for this symbol in the global             offset table.  */	  if (sgot == NULL)	    {	      sgot = bfd_get_section_by_name (dynobj, ".got");	      BFD_ASSERT (sgot != NULL);	    }	  if (h != NULL)	    {	      bfd_vma off;	      off = h->got.offset;	      BFD_ASSERT (off != (bfd_vma) -1);	      if (! elf_hash_table (info)->dynamic_sections_created		  || (info->shared		      && (info->symbolic || h->dynindx == -1)		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))		{		  /* This is actually a static link, or it is a                     -Bsymbolic link and the symbol is defined                     locally, or the symbol was forced to be local                     because of a version file.  We must initialize                     this entry in the global offset table.  Since the                     offset must always be a multiple of 4, we use the                     least significant bit to record whether we have                     initialized it already.		     When doing a dynamic link, we create a .rela.got		     relocation entry to initialize the value.  This		     is done in the finish_dynamic_symbol routine.  */		  if ((off & 1) != 0)		    off &= ~1;		  else		    {		      bfd_put_32 (output_bfd, relocation,				  sgot->contents + off);		      h->got.offset |= 1;		    }		}	      relocation = sgot->output_offset + off - got_base;	    }	  else	    {	      bfd_vma off;	      BFD_ASSERT (local_got_offsets != NULL			  && local_got_offsets[r_symndx] != (bfd_vma) -1);	      off = local_got_offsets[r_symndx];	      /* The offset must always be a multiple of 4.  We use		 the least significant bit to record whether we have		 already processed this entry.  */	      if ((off & 1) != 0)		off &= ~1;	      else		{		  bfd_put_32 (output_bfd, relocation, sgot->contents + off);		  if (info->shared)		    {		      asection *srelgot;		      Elf_Internal_Rela outrel;		      /* We need to generate a R_SPARC_RELATIVE reloc			 for the dynamic linker.  */		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");		      BFD_ASSERT (srelgot != NULL);		      outrel.r_offset = (sgot->output_section->vma					 + sgot->output_offset					 + off);		      outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);		      outrel.r_addend = 0;		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,						 (((Elf32_External_Rela *)						   srelgot->contents)						  + srelgot->reloc_count));		      ++srelgot->reloc_count;		    }		  local_got_offsets[r_symndx] |= 1;		}	      relocation = sgot->output_offset + off - got_base;	    }	  break;	case R_SPARC_WPLT30:	  /* Relocation is to the entry for this symbol in the             procedure linkage table.  */	  /* The Solaris native assembler will generate a WPLT30 reloc	     for a local symbol if you assemble a call from one	     section to another when using -K pic.  We treat it as	     WDISP30.  */	  if (h == NULL)	    break;	  if (h->plt.offset == (bfd_vma) -1)	    {	      /* We didn't make a PLT entry for this symbol.  This                 happens when statically linking PIC code, or when                 using -Bsymbolic.  */	      break;	    }	  if (splt == NULL)	    {	      splt = bfd_get_section_by_name (dynobj, ".plt");	      BFD_ASSERT (splt != NULL);	    }	  relocation = (splt->output_section->vma			+ splt->output_offset			+ h->plt.offset);	  break;	case R_SPARC_PC10:	case R_SPARC_PC22:	  if (h != NULL	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)	    break;	  /* Fall through.  */	case R_SPARC_DISP8:	case R_SPARC_DISP16:	case R_SPARC_DISP32:	case R_SPARC_WDISP30:	case R_SPARC_WDISP22:	case R_SPARC_WDISP19:	case R_SPARC_WDISP16:	  if (h == NULL	      || (info->symbolic		  && (h->elf_link_hash_flags		      & ELF_LINK_HASH_DEF_REGULAR) != 0))	    break;	  /* Fall through.  */	case R_SPARC_8:	case R_SPARC_16:	case R_SPARC_32:	case R_SPARC_HI22:	case R_SPARC_22:	case R_SPARC_13:	case R_SPARC_LO10:	case R_SPARC_UA16:	case R_SPARC_UA32:	case R_SPARC_UA64:	  if (info->shared)	    {	      Elf_Internal_Rela outrel;	      boolean skip;	      /* When generating a shared object, these relocations                 are copied into the output file to be resolved at run                 time.  */	      if (sreloc == NULL)		{		  const char *name;		  name = (bfd_elf_string_from_elf_section			  (input_bfd,			   elf_elfheader (input_bfd)->e_shstrndx,			   elf_section_data (input_section)->rel_hdr.sh_name));		  if (name == NULL)		    return false;		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0			      && strcmp (bfd_get_section_name (input_bfd,							       input_section),					 name + 5) == 0);		  sreloc = bfd_get_section_by_name (dynobj, name);		  BFD_ASSERT (sreloc != NULL);		}	      skip = false;	      if (elf_section_data (input_section)->stab_info == NULL)		outrel.r_offset = rel->r_offset;	      else		{		  bfd_vma off;		  off = (_bfd_stab_section_offset			 (output_bfd, &elf_hash_table (info)->stab_info,			  input_section,			  &elf_section_data (input_section)->stab_info,			  rel->r_offset));		  if (off == (bfd_vma) -1)		    skip = true;		  outrel.r_offset = off;		}	      outrel.r_offset += (input_section->output_section->vma				  + input_section->output_offset);	      if (skip)		memset (&outrel, 0, sizeof outrel);	      /* h->dynindx may be -1 if the symbol was marked to                 become local.  */	      else if (h != NULL		       && ((! info->symbolic && h->dynindx != -1)			   || (h->elf_link_hash_flags			       & ELF_LINK_HASH_DEF_REGULAR) == 0))		{		  BFD_ASSERT (h->dynindx != -1);		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);		  outrel.r_addend = rel->r_addend;		}	      else		{		  if (r_type == R_SPARC_32)		    {		      outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);		      outrel.r_addend = relocation + rel->r_addend;		    }		  else		    {		      long indx;		      if (h == NULL)			sec = local_sections[r_symndx];		      else			{			  BFD_ASSERT (h->root.type == bfd_link_hash_defined				      || (h->root.type					  == bfd_link_hash_defweak));			  sec = h->root.u.def.section;			}		      if (sec != NULL && bfd_is_abs_section (sec))			indx = 0;		      else if (sec == NULL || sec->owner == NULL)			{			  bfd_set_error (bfd_error_bad_value);			  return false;			}		      else			{			  asection *osec;			  osec = sec->output_section;			  indx = elf_section_data (osec)->dynindx;			  /* FIXME: we really should be able to link non-pic			     shared libraries.  */			  if (indx == 0)			    {			      BFD_FAIL ();			      (*_bfd_error_handler)				(_("%s: probably compiled without -fPIC?"),				 bfd_get_filename (input_bfd));			      bfd_set_error (bfd_error_bad_value);			      return false;			    }			}		      outrel.r_info = ELF32_R_INFO (indx, r_type);		      outrel.r_addend = relocation + rel->r_addend;		    }		}	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,					 (((Elf32_External_Rela *)					   sreloc->contents)					  + sreloc->reloc_count));	      ++sreloc->reloc_count;	      /* This reloc will be computed at runtime, so there's no                 need to do anything now, unless this is a RELATIVE                 reloc in an unallocated section.  */	      if (skip		  || (input_section->flags & SEC_ALLOC) != 0		  || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE)		continue;	    }	  break;	default:	  break;	}      r = bfd_reloc_continue;      if (r_type == R_SPARC_WDISP16)	{	  bfd_vma x;	  relocation += rel->r_addend;	  relocation -= (input_section->output_section->vma			 + input_section->output_offset);	  relocation -= rel->r_offset;	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);	  x |= ((((relocation >> 2) & 0xc000) << 6)		| ((relocation >> 2) & 0x3fff));	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);	  if ((bfd_signed_vma) relocation < - 0x40000	      || (bfd_signed_vma) relocation > 0x3ffff)	    r = bfd_reloc_overflow;	  else	    r = bfd_reloc_ok;	}      else if (r_type == R_SPARC_REV32)	{	  bfd_vma x;	  relocation = relocation + rel->r_addend;	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);	  x = x + relocation;	  bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset);	  r = bfd_reloc_ok;	}      else if ((r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WPLT30)	       && SEC_DO_RELAX (input_section)	       && rel->r_offset + 4 < input_section->_raw_size)	{#define G0		0#define O7		15#define XCC		(2 << 20)#define COND(x)		(((x)&0xf)<<25)#define CONDA		COND(0x8)#define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)#define INSN_BA		(F2(0,2) | CONDA)#define INSN_OR		F3(2, 0x2, 0)#define INSN_NOP	F2(0,4)	  bfd_vma x, y;	  /* If the instruction is a call with either:	     restore	     arithmetic instruction with rd == %o7	     where rs1 != %o7 and rs2 if it is register != %o7	     then we can optimize if the call destination is near	     by changing the call into a branch always.  */	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);	  y = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);	  if ((x & OP(~0)) == OP(1) && (y & OP(~0)) == OP(2))	    {	      if (((y & OP3(~0)) == OP3(0x3d) /* restore */		   || ((y & OP3(0x28)) == 0 /* arithmetic */		       && (y & RD(~0)) == RD(O7)))		  && (y & RS1(~0)) != RS1(O7)

⌨️ 快捷键说明

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