elf32-m68k.c

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

C
2,163
字号
	      outrel.r_offset += (input_section->output_section->vma				  + input_section->output_offset);	      if (skip)		{		  memset (&outrel, 0, sizeof outrel);		  relocate = false;		}	      /* 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);		  relocate = false;		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);		  outrel.r_addend = relocation + rel->r_addend;		}	      else		{		  if (r_type == R_68K_32)		    {		      relocate = true;		      outrel.r_info = ELF32_R_INFO (0, R_68K_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;			  BFD_ASSERT (indx > 0);			}		      relocate = 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, except for R_68K_32                 relocations that have been turned into                 R_68K_RELATIVE.  */	      if (!relocate)		continue;	    }	  break;	case R_68K_GNU_VTINHERIT:	case R_68K_GNU_VTENTRY:	  /* These are no-ops in the end.  */	  continue;	default:	  break;	}      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 booleanelf_m68k_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;  int plt_off1, plt_off2, plt_off3;  dynobj = elf_hash_table (info)->dynobj;  if (h->plt.offset != (bfd_vma) -1)    {      asection *splt;      asection *sgot;      asection *srela;      bfd_vma plt_index;      bfd_vma got_offset;      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");      sgot = bfd_get_section_by_name (dynobj, ".got.plt");      srela = bfd_get_section_by_name (dynobj, ".rela.plt");      BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL);      /* Get the index in the procedure linkage table which	 corresponds to this symbol.  This is the index of this symbol	 in all the symbols for which we are making plt entries.  The	 first entry in the procedure linkage table is reserved.  */      if ( CPU32_FLAG (output_bfd))        plt_index = h->plt.offset / PLT_CPU32_ENTRY_SIZE - 1;      else        plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;      /* Get the offset into the .got table of the entry that	 corresponds to this function.  Each .got entry is 4 bytes.	 The first three are reserved.  */      got_offset = (plt_index + 3) * 4;      if ( CPU32_FLAG (output_bfd))        {          /* Fill in the entry in the procedure linkage table.  */          memcpy (splt->contents + h->plt.offset, elf_cpu32_plt_entry,	          PLT_CPU32_ENTRY_SIZE);          plt_off1 = 4;          plt_off2 = 12;          plt_off3 = 18;        }      else        {          /* Fill in the entry in the procedure linkage table.  */          memcpy (splt->contents + h->plt.offset, elf_m68k_plt_entry,	          PLT_ENTRY_SIZE);          plt_off1 = 4;          plt_off2 = 10;          plt_off3 = 16;        }      /* The offset is relative to the first extension word.  */      bfd_put_32 (output_bfd,		  (sgot->output_section->vma		   + sgot->output_offset		   + got_offset		   - (splt->output_section->vma		      + h->plt.offset + 2)),		  splt->contents + h->plt.offset + plt_off1);      bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),		  splt->contents + h->plt.offset + plt_off2);      bfd_put_32 (output_bfd, - (h->plt.offset + plt_off3),		  splt->contents + h->plt.offset + plt_off3);      /* Fill in the entry in the global offset table.  */      bfd_put_32 (output_bfd,		  (splt->output_section->vma		   + splt->output_offset		   + h->plt.offset		   + 8),		  sgot->contents + got_offset);      /* Fill in the entry in the .rela.plt section.  */      rela.r_offset = (sgot->output_section->vma		       + sgot->output_offset		       + got_offset);      rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_JMP_SLOT);      rela.r_addend = 0;      bfd_elf32_swap_reloca_out (output_bfd, &rela,				 ((Elf32_External_Rela *) srela->contents				  + plt_index));      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 (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_68K_RELATIVE);	  rela.r_addend = bfd_get_signed_32 (output_bfd,					     (sgot->contents					      + (h->got.offset & ~1)));	}      else	{	  bfd_put_32 (output_bfd, (bfd_vma) 0,		      sgot->contents + (h->got.offset & ~1));	  rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_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 symbol needs a copy reloc.  Set it up.  */      BFD_ASSERT (h->dynindx != -1		  && (h->root.type == bfd_link_hash_defined		      || h->root.type == bfd_link_hash_defweak));      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_68K_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 _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */  if (strcmp (h->root.root.string, "_DYNAMIC") == 0      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)    sym->st_shndx = SHN_ABS;  return true;}/* Finish up the dynamic sections.  */static booleanelf_m68k_finish_dynamic_sections (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  bfd *dynobj;  asection *sgot;  asection *sdyn;  dynobj = elf_hash_table (info)->dynobj;  sgot = bfd_get_section_by_name (dynobj, ".got.plt");  BFD_ASSERT (sgot != NULL);  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;	  asection *s;	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);	  switch (dyn.d_tag)	    {	    default:	      break;	    case DT_PLTGOT:	      name = ".got";	      goto get_vma;	    case DT_JMPREL:	      name = ".rela.plt";	    get_vma:	      s = bfd_get_section_by_name (output_bfd, name);	      BFD_ASSERT (s != NULL);	      dyn.d_un.d_ptr = s->vma;	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);	      break;	    case DT_PLTRELSZ:	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");	      BFD_ASSERT (s != NULL);	      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);	      break;	    case DT_RELASZ:	      /* The procedure linkage table relocs (DT_JMPREL) should		 not be included in the overall relocs (DT_RELA).		 Therefore, we override the DT_RELASZ entry here to		 make it not include the JMPREL relocs.  Since the		 linker script arranges for .rela.plt to follow all		 other relocation sections, we don't have to worry		 about changing the DT_RELA entry.  */	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");	      if (s != NULL)		{		  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);	      break;	    }	}      /* Fill in the first entry in the procedure linkage table.  */      if (splt->_raw_size > 0)	{          if (!CPU32_FLAG (output_bfd))            {	      memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE);	      bfd_put_32 (output_bfd,		          (sgot->output_section->vma		           + sgot->output_offset + 4		           - (splt->output_section->vma + 2)),		          splt->contents + 4);	      bfd_put_32 (output_bfd,		          (sgot->output_section->vma		           + sgot->output_offset + 8		           - (splt->output_section->vma + 10)),		          splt->contents + 12);              elf_section_data (splt->output_section)->this_hdr.sh_entsize               = PLT_ENTRY_SIZE;            }          else /* cpu32 */            {              memcpy (splt->contents, elf_cpu32_plt0_entry, PLT_CPU32_ENTRY_SIZE);	      bfd_put_32 (output_bfd,		          (sgot->output_section->vma		           + sgot->output_offset + 4		           - (splt->output_section->vma + 2)),		          splt->contents + 4);	      bfd_put_32 (output_bfd,		          (sgot->output_section->vma		           + sgot->output_offset + 8		           - (splt->output_section->vma + 10)),		          splt->contents + 12);             

⌨️ 快捷键说明

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