elf32-m68k.c

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

C
2,163
字号
      if (relocs)	{	  if (!bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)	      || !bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)	      || !bfd_elf32_add_dynamic_entry (info, DT_RELAENT,					       sizeof (Elf32_External_Rela)))	    return false;	}      if (reltext)	{	  if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))	    return false;	  info->flags |= DF_TEXTREL;	}    }  return true;}/* This function is called via elf_m68k_link_hash_traverse if we are   creating a shared object with -Bsymbolic.  It discards the space   allocated to copy PC relative relocs against symbols which are defined   in regular objects.  We allocated space for them in the check_relocs   routine, but we won't fill them in in the relocate_section routine.  */static booleanelf_m68k_discard_copies (h, ignore)     struct elf_m68k_link_hash_entry *h;     PTR ignore ATTRIBUTE_UNUSED;{  struct elf_m68k_pcrel_relocs_copied *s;  /* We only discard relocs for symbols defined in a regular object.  */  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)    return true;  for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)    s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela);  return true;}/* Relocate an M68K ELF section.  */static booleanelf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,			   contents, relocs, local_syms, local_sections)     bfd *output_bfd;     struct bfd_link_info *info;     bfd *input_bfd;     asection *input_section;     bfd_byte *contents;     Elf_Internal_Rela *relocs;     Elf_Internal_Sym *local_syms;     asection **local_sections;{  bfd *dynobj;  Elf_Internal_Shdr *symtab_hdr;  struct elf_link_hash_entry **sym_hashes;  bfd_vma *local_got_offsets;  asection *sgot;  asection *splt;  asection *sreloc;  Elf_Internal_Rela *rel;  Elf_Internal_Rela *relend;  dynobj = elf_hash_table (info)->dynobj;  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (input_bfd);  local_got_offsets = elf_local_got_offsets (input_bfd);  sgot = NULL;  splt = NULL;  sreloc = NULL;  rel = relocs;  relend = relocs + input_section->reloc_count;  for (; rel < relend; rel++)    {      int r_type;      reloc_howto_type *howto;      unsigned long r_symndx;      struct elf_link_hash_entry *h;      Elf_Internal_Sym *sym;      asection *sec;      bfd_vma relocation;      bfd_reloc_status_type r;      r_type = ELF32_R_TYPE (rel->r_info);      if (r_type < 0 || r_type >= (int) R_68K_max)	{	  bfd_set_error (bfd_error_bad_value);	  return false;	}      howto = howto_table + r_type;      r_symndx = ELF32_R_SYM (rel->r_info);      if (info->relocateable)	{	  /* This is a relocateable link.  We don't have to change	     anything, unless the reloc is against a section symbol,	     in which case we have to adjust according to where the	     section symbol winds up in the output section.  */	  if (r_symndx < symtab_hdr->sh_info)	    {	      sym = local_syms + r_symndx;	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)		{		  sec = local_sections[r_symndx];		  rel->r_addend += sec->output_offset + sym->st_value;		}	    }	  continue;	}      /* This is a final link.  */      h = NULL;      sym = NULL;      sec = NULL;      if (r_symndx < symtab_hdr->sh_info)	{	  sym = local_syms + r_symndx;	  sec = local_sections[r_symndx];	  relocation = (sec->output_section->vma			+ sec->output_offset			+ sym->st_value);	}      else	{	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];	  while (h->root.type == bfd_link_hash_indirect		 || h->root.type == bfd_link_hash_warning)	    h = (struct elf_link_hash_entry *) h->root.u.i.link;	  if (h->root.type == bfd_link_hash_defined	      || h->root.type == bfd_link_hash_defweak)	    {	      sec = h->root.u.def.section;	      if (((r_type == R_68K_PLT8		    || r_type == R_68K_PLT16		    || r_type == R_68K_PLT32		    || r_type == R_68K_PLT8O		    || r_type == R_68K_PLT16O		    || r_type == R_68K_PLT32O)		   && h->plt.offset != (bfd_vma) -1		   && elf_hash_table (info)->dynamic_sections_created)		  || ((r_type == R_68K_GOT8O		       || r_type == R_68K_GOT16O		       || r_type == R_68K_GOT32O		       || ((r_type == R_68K_GOT8			    || r_type == R_68K_GOT16			    || r_type == R_68K_GOT32)			   && strcmp (h->root.root.string,				      "_GLOBAL_OFFSET_TABLE_") != 0))		      && elf_hash_table (info)->dynamic_sections_created		      && (! info->shared			  || (! info->symbolic && h->dynindx != -1)			  || (h->elf_link_hash_flags			      & ELF_LINK_HASH_DEF_REGULAR) == 0))		  || (info->shared		      && ((! info->symbolic && h->dynindx != -1)			  || (h->elf_link_hash_flags			      & ELF_LINK_HASH_DEF_REGULAR) == 0)		      && ((input_section->flags & SEC_ALLOC) != 0			  /* DWARF will emit R_68K_32 relocations in its			     sections against symbols defined externally			     in shared libraries.  We can't do anything			     with them here.  */			  || ((input_section->flags & SEC_DEBUGGING) != 0			      && (h->elf_link_hash_flags				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0))		      && (r_type == R_68K_8			  || r_type == R_68K_16			  || r_type == R_68K_32			  || r_type == R_68K_PC8			  || r_type == R_68K_PC16			  || r_type == R_68K_PC32)))		{		  /* 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_68K_GOT8:	case R_68K_GOT16:	case R_68K_GOT32:	  /* Relocation is to the address of the entry for this symbol	     in the global offset table.  */	  if (h != NULL	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)	    break;	  /* Fall through.  */	case R_68K_GOT8O:	case R_68K_GOT16O:	case R_68K_GOT32O:	  /* Relocation is the offset of the entry for this symbol in	     the global offset table.  */	  {	    bfd_vma off;	    if (sgot == NULL)	      {		sgot = bfd_get_section_by_name (dynobj, ".got");		BFD_ASSERT (sgot != NULL);	      }	    if (h != NULL)	      {		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;		      }		  }	      }	    else	      {		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 generated the necessary reloc.  */		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;			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_68K_RELATIVE);			outrel.r_addend = relocation;			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;	    if (r_type == R_68K_GOT8O		|| r_type == R_68K_GOT16O		|| r_type == R_68K_GOT32O)	      {		/* This relocation does not use the addend.  */		rel->r_addend = 0;	      }	    else	      relocation += sgot->output_section->vma;	  }	  break;	case R_68K_PLT8:	case R_68K_PLT16:	case R_68K_PLT32:	  /* Relocation is to the entry for this symbol in the	     procedure linkage table.  */	  /* Resolve a PLTxx reloc against a local symbol directly,	     without using the procedure linkage table.  */	  if (h == NULL)	    break;	  if (h->plt.offset == (bfd_vma) -1	      || !elf_hash_table (info)->dynamic_sections_created)	    {	      /* 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_68K_PLT8O:	case R_68K_PLT16O:	case R_68K_PLT32O:	  /* Relocation is the offset of the entry for this symbol in	     the procedure linkage table.  */	  BFD_ASSERT (h != NULL && h->plt.offset != (bfd_vma) -1);	  if (splt == NULL)	    {	      splt = bfd_get_section_by_name (dynobj, ".plt");	      BFD_ASSERT (splt != NULL);	    }	  relocation = h->plt.offset;	  /* This relocation does not use the addend.  */	  rel->r_addend = 0;	  break;	case R_68K_PC8:	case R_68K_PC16:	case R_68K_PC32:	  if (h == NULL)	    break;	  /* Fall through.  */	case R_68K_8:	case R_68K_16:	case R_68K_32:	  if (info->shared	      && (input_section->flags & SEC_ALLOC) != 0	      && ((r_type != R_68K_PC8		   && r_type != R_68K_PC16		   && r_type != R_68K_PC32)		  || (!info->symbolic		      || (h->elf_link_hash_flags			  & ELF_LINK_HASH_DEF_REGULAR) == 0)))	    {	      Elf_Internal_Rela outrel;	      boolean skip, relocate;	      /* 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;		}

⌨️ 快捷键说明

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