elf32-sparc.c

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

C
2,014
字号
		  && ((y & F3I(~0))		      || (y & RS2(~0)) != RS2(O7)))		{		  bfd_vma reloc;		  reloc = relocation + rel->r_addend - rel->r_offset;		  reloc -= (input_section->output_section->vma			   + input_section->output_offset);		  /* Ensure the reloc fits into simm22.  */		  if ((reloc & 3) == 0		      && ((reloc & ~(bfd_vma)0x7fffff) == 0			  || ((reloc | 0x7fffff) == ~(bfd_vma)0)))		    {		      reloc >>= 2;		      /* Check whether it fits into simm19 on v9.  */		      if (((reloc & 0x3c0000) == 0			   || (reloc & 0x3c0000) == 0x3c0000)			  && (elf_elfheader (output_bfd)->e_flags & EF_SPARC_32PLUS))			x = INSN_BPA | (reloc & 0x7ffff); /* ba,pt %xcc */		      else			x = INSN_BA | (reloc & 0x3fffff); /* ba */		      bfd_put_32 (input_bfd, x, contents + rel->r_offset);		      r = bfd_reloc_ok;		      if (rel->r_offset >= 4			  && (y & (0xffffffff ^ RS1(~0)))			      == (INSN_OR | RD(O7) | RS2(G0)))			{			  bfd_vma z;			  unsigned int reg;			  z = bfd_get_32 (input_bfd,					  contents + rel->r_offset - 4);			  if ((z & (0xffffffff ^ RD(~0)))			      != (INSN_OR | RS1(O7) | RS2(G0)))			    break;			  /* The sequence was			     or %o7, %g0, %rN			     call foo			     or %rN, %g0, %o7			     If call foo was replaced with ba, replace			     or %rN, %g0, %o7 with nop.  */			  reg = (y & RS1(~0)) >> 14;			  if (reg != ((z & RD(~0)) >> 25)			      || reg == G0 || reg == O7)			    break;			  bfd_put_32 (input_bfd, INSN_NOP,				      contents + rel->r_offset + 4);			}		    }		}	    }	}      if (r == bfd_reloc_continue)	r = _bfd_final_link_relocate (howto, input_bfd, input_section,				      contents, rel->r_offset,				      relocation, rel->r_addend);      if (r != bfd_reloc_ok)	{	  switch (r)	    {	    default:	    case bfd_reloc_outofrange:	      abort ();	    case bfd_reloc_overflow:	      {		const char *name;		if (h != NULL)		  name = h->root.root.string;		else		  {		    name = bfd_elf_string_from_elf_section (input_bfd,							    symtab_hdr->sh_link,							    sym->st_name);		    if (name == NULL)		      return false;		    if (*name == '\0')		      name = bfd_section_name (input_bfd, sec);		  }		if (! ((*info->callbacks->reloc_overflow)		       (info, name, howto->name, (bfd_vma) 0,			input_bfd, input_section, rel->r_offset)))		  return false;	      }	      break;	    }	}    }  return true;}/* Finish up dynamic symbol handling.  We set the contents of various   dynamic sections here.  */static booleanelf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym)     bfd *output_bfd;     struct bfd_link_info *info;     struct elf_link_hash_entry *h;     Elf_Internal_Sym *sym;{  bfd *dynobj;  dynobj = elf_hash_table (info)->dynobj;  if (h->plt.offset != (bfd_vma) -1)    {      asection *splt;      asection *srela;      Elf_Internal_Rela rela;      /* This symbol has an entry in the procedure linkage table.  Set         it up.  */      BFD_ASSERT (h->dynindx != -1);      splt = bfd_get_section_by_name (dynobj, ".plt");      srela = bfd_get_section_by_name (dynobj, ".rela.plt");      BFD_ASSERT (splt != NULL && srela != NULL);      /* Fill in the entry in the procedure linkage table.  */      bfd_put_32 (output_bfd,		  PLT_ENTRY_WORD0 + h->plt.offset,		  splt->contents + h->plt.offset);      bfd_put_32 (output_bfd,		  (PLT_ENTRY_WORD1		   + (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)),		  splt->contents + h->plt.offset + 4);      bfd_put_32 (output_bfd, PLT_ENTRY_WORD2,		  splt->contents + h->plt.offset + 8);      /* Fill in the entry in the .rela.plt section.  */      rela.r_offset = (splt->output_section->vma		       + splt->output_offset		       + h->plt.offset);      rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT);      rela.r_addend = 0;      bfd_elf32_swap_reloca_out (output_bfd, &rela,				 ((Elf32_External_Rela *) srela->contents				  + h->plt.offset / PLT_ENTRY_SIZE - 4));      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)	{	  /* Mark the symbol as undefined, rather than as defined in	     the .plt section.  Leave the value alone.  */	  sym->st_shndx = SHN_UNDEF;	  /* If the symbol is weak, we do need to clear the value.	     Otherwise, the PLT entry would provide a definition for	     the symbol even if the symbol wasn't defined anywhere,	     and so the symbol would never be NULL.  */	  if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)	      == 0)	    sym->st_value = 0;	}    }  if (h->got.offset != (bfd_vma) -1)    {      asection *sgot;      asection *srela;      Elf_Internal_Rela rela;      /* This symbol has an entry in the global offset table.  Set it         up.  */      sgot = bfd_get_section_by_name (dynobj, ".got");      srela = bfd_get_section_by_name (dynobj, ".rela.got");      BFD_ASSERT (sgot != NULL && srela != NULL);      rela.r_offset = (sgot->output_section->vma		       + sgot->output_offset		       + (h->got.offset &~ 1));      /* If this is a -Bsymbolic link, and the symbol is defined	 locally, we just want to emit a RELATIVE reloc.  Likewise if	 the symbol was forced to be local because of a version file.	 The entry in the global offset table will already have been	 initialized in the relocate_section function.  */      if (info->shared	  && (info->symbolic || h->dynindx == -1)	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))	rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);      else	{	  bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);	  rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT);	}      rela.r_addend = 0;      bfd_elf32_swap_reloca_out (output_bfd, &rela,				 ((Elf32_External_Rela *) srela->contents				  + srela->reloc_count));      ++srela->reloc_count;    }  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)    {      asection *s;      Elf_Internal_Rela rela;      /* This symbols needs a copy reloc.  Set it up.  */      BFD_ASSERT (h->dynindx != -1);      s = bfd_get_section_by_name (h->root.u.def.section->owner,				   ".rela.bss");      BFD_ASSERT (s != NULL);      rela.r_offset = (h->root.u.def.value		       + h->root.u.def.section->output_section->vma		       + h->root.u.def.section->output_offset);      rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_COPY);      rela.r_addend = 0;      bfd_elf32_swap_reloca_out (output_bfd, &rela,				 ((Elf32_External_Rela *) s->contents				  + s->reloc_count));      ++s->reloc_count;    }  /* Mark some specially defined symbols as absolute.  */  if (strcmp (h->root.root.string, "_DYNAMIC") == 0      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)    sym->st_shndx = SHN_ABS;  return true;}/* Finish up the dynamic sections.  */static booleanelf32_sparc_finish_dynamic_sections (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  bfd *dynobj;  asection *sdyn;  asection *sgot;  dynobj = elf_hash_table (info)->dynobj;  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");  if (elf_hash_table (info)->dynamic_sections_created)    {      asection *splt;      Elf32_External_Dyn *dyncon, *dynconend;      splt = bfd_get_section_by_name (dynobj, ".plt");      BFD_ASSERT (splt != NULL && sdyn != NULL);      dyncon = (Elf32_External_Dyn *) sdyn->contents;      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);      for (; dyncon < dynconend; dyncon++)	{	  Elf_Internal_Dyn dyn;	  const char *name;	  boolean size;	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);	  switch (dyn.d_tag)	    {	    case DT_PLTGOT:   name = ".plt"; size = false; break;	    case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;	    case DT_JMPREL:   name = ".rela.plt"; size = false; break;	    default:	  name = NULL; size = false; break;	    }	  if (name != NULL)	    {	      asection *s;	      s = bfd_get_section_by_name (output_bfd, name);	      if (s == NULL)		dyn.d_un.d_val = 0;	      else		{		  if (! size)		    dyn.d_un.d_ptr = s->vma;		  else		    {		      if (s->_cooked_size != 0)			dyn.d_un.d_val = s->_cooked_size;		      else			dyn.d_un.d_val = s->_raw_size;		    }		}	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);	    }	}      /* Clear the first four entries in the procedure linkage table,	 and put a nop in the last four bytes.  */      if (splt->_raw_size > 0)	{	  memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);	  bfd_put_32 (output_bfd, SPARC_NOP,		      splt->contents + splt->_raw_size - 4);	}      elf_section_data (splt->output_section)->this_hdr.sh_entsize =	PLT_ENTRY_SIZE;    }  /* Set the first entry in the global offset table to the address of     the dynamic section.  */  sgot = bfd_get_section_by_name (dynobj, ".got");  BFD_ASSERT (sgot != NULL);  if (sgot->_raw_size > 0)    {      if (sdyn == NULL)	bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);      else	bfd_put_32 (output_bfd,		    sdyn->output_section->vma + sdyn->output_offset,		    sgot->contents);    }  elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;  return true;}/* Functions for dealing with the e_flags field.   We don't define set_private_flags or copy_private_bfd_data because   the only currently defined values are based on the bfd mach number,   so we use the latter instead and defer setting e_flags until the   file is written out.  *//* Merge backend specific data from an object file to the output   object file when linking.  */static booleanelf32_sparc_merge_private_bfd_data (ibfd, obfd)     bfd *ibfd;     bfd *obfd;{  boolean error;  /* FIXME: This should not be static.  */  static unsigned long previous_ibfd_e_flags = (unsigned long) -1;  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)    return true;  error = false;  if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)    {      error = true;      (*_bfd_error_handler)	(_("%s: compiled for a 64 bit system and target is 32 bit"),	 bfd_get_filename (ibfd));    }  else if ((ibfd->flags & DYNAMIC) == 0)    {      if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))	bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));    }  if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA)       != previous_ibfd_e_flags)      && previous_ibfd_e_flags != (unsigned long) -1)    {      (*_bfd_error_handler)	(_("%s: linking little endian files with big endian files"),	 bfd_get_filename (ibfd));      error = true;    }  previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA;  if (error)    {      bfd_set_error (bfd_error_bad_value);      return false;    }  return true;}/* Set the right machine number.  */static booleanelf32_sparc_object_p (abfd)     bfd *abfd;{  if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)    {      if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3)	return bfd_def

⌨️ 快捷键说明

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