elf32-m68k.c

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

C
2,163
字号
  fputc ('\n', file);  return true;}/* Look through the relocs for a section during the first phase, and   allocate space in the global offset table or procedure linkage   table.  */static booleanelf_m68k_check_relocs (abfd, info, sec, relocs)     bfd *abfd;     struct bfd_link_info *info;     asection *sec;     const Elf_Internal_Rela *relocs;{  bfd *dynobj;  Elf_Internal_Shdr *symtab_hdr;  struct elf_link_hash_entry **sym_hashes;  bfd_signed_vma *local_got_refcounts;  const Elf_Internal_Rela *rel;  const Elf_Internal_Rela *rel_end;  asection *sgot;  asection *srelgot;  asection *sreloc;  if (info->relocateable)    return true;  dynobj = elf_hash_table (info)->dynobj;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  sgot = NULL;  srelgot = NULL;  sreloc = NULL;  rel_end = relocs + sec->reloc_count;  for (rel = relocs; rel < rel_end; rel++)    {      unsigned long r_symndx;      struct elf_link_hash_entry *h;      r_symndx = ELF32_R_SYM (rel->r_info);      if (r_symndx < symtab_hdr->sh_info)	h = NULL;      else	h = sym_hashes[r_symndx - symtab_hdr->sh_info];      switch (ELF32_R_TYPE (rel->r_info))	{	case R_68K_GOT8:	case R_68K_GOT16:	case R_68K_GOT32:	  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:	  /* This symbol requires a global offset table entry.  */	  if (dynobj == NULL)	    {	      /* Create the .got section.  */	      elf_hash_table (info)->dynobj = dynobj = abfd;	      if (!_bfd_elf_create_got_section (dynobj, info))		return false;	    }	  if (sgot == NULL)	    {	      sgot = bfd_get_section_by_name (dynobj, ".got");	      BFD_ASSERT (sgot != NULL);	    }	  if (srelgot == NULL	      && (h != NULL || info->shared))	    {	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");	      if (srelgot == NULL)		{		  srelgot = bfd_make_section (dynobj, ".rela.got");		  if (srelgot == NULL		      || !bfd_set_section_flags (dynobj, srelgot,						 (SEC_ALLOC						  | SEC_LOAD						  | SEC_HAS_CONTENTS						  | SEC_IN_MEMORY						  | SEC_LINKER_CREATED						  | SEC_READONLY))		      || !bfd_set_section_alignment (dynobj, srelgot, 2))		    return false;		}	    }	  if (h != NULL)	    {	      if (h->got.refcount == -1)		{		  h->got.refcount = 1;		  /* Make sure this symbol is output as a dynamic symbol.  */		  if (h->dynindx == -1)		    {		      if (!bfd_elf32_link_record_dynamic_symbol (info, h))			return false;		    }		  /* Allocate space in the .got section.  */		  sgot->_raw_size += 4;		  /* Allocate relocation space.  */		  srelgot->_raw_size += sizeof (Elf32_External_Rela);		}	      else		h->got.refcount++;	    }	  else	    {	      /* This is a global offset table entry for a local symbol.  */	      if (local_got_refcounts == NULL)		{		  size_t size;		  size = symtab_hdr->sh_info * sizeof (bfd_signed_vma);		  local_got_refcounts = ((bfd_signed_vma *)					 bfd_alloc (abfd, size));		  if (local_got_refcounts == NULL)		    return false;		  elf_local_got_refcounts (abfd) = local_got_refcounts;		  memset (local_got_refcounts, -1, size);		}	      if (local_got_refcounts[r_symndx] == -1)		{		  local_got_refcounts[r_symndx] = 1;		  sgot->_raw_size += 4;		  if (info->shared)		    {		      /* If we are generating a shared object, we need to			 output a R_68K_RELATIVE reloc so that the dynamic			 linker can adjust this GOT entry.  */		      srelgot->_raw_size += sizeof (Elf32_External_Rela);		    }		}	      else		local_got_refcounts[r_symndx]++;	    }	  break;	case R_68K_PLT8:	case R_68K_PLT16:	case R_68K_PLT32:	  /* This symbol requires a procedure linkage table entry.  We	     actually build the entry in adjust_dynamic_symbol,             because this might be a case of linking PIC code which is             never referenced by a dynamic object, in which case we             don't need to generate a procedure linkage table entry             after all.  */	  /* If this is a local symbol, we resolve it directly without	     creating a procedure linkage table entry.  */	  if (h == NULL)	    continue;	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;	  if (h->plt.refcount == -1)	    h->plt.refcount = 1;	  else	    h->plt.refcount++;	  break;	case R_68K_PLT8O:	case R_68K_PLT16O:	case R_68K_PLT32O:	  /* This symbol requires a procedure linkage table entry.  */	  if (h == NULL)	    {	      /* It does not make sense to have this relocation for a		 local symbol.  FIXME: does it?  How to handle it if		 it does make sense?  */	      bfd_set_error (bfd_error_bad_value);	      return false;	    }	  /* Make sure this symbol is output as a dynamic symbol.  */	  if (h->dynindx == -1)	    {	      if (!bfd_elf32_link_record_dynamic_symbol (info, h))		return false;	    }	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;	  if (h->plt.refcount == -1)	    h->plt.refcount = 1;	  else	    h->plt.refcount++;	  break;	case R_68K_PC8:	case R_68K_PC16:	case R_68K_PC32:	  /* If we are creating a shared library and this is not a local	     symbol, we need to copy the reloc into the shared library.	     However when linking with -Bsymbolic and this is a global	     symbol which is defined in an object we are including in the	     link (i.e., DEF_REGULAR is set), then we can resolve the	     reloc directly.  At this point we have not seen all the input	     files, so it is possible that DEF_REGULAR is not set now but	     will be set later (it is never cleared).  We account for that	     possibility below by storing information in the	     pcrel_relocs_copied field of the hash table entry.  */	  if (!(info->shared		&& (sec->flags & SEC_ALLOC) != 0		&& h != NULL		&& (!info->symbolic		    || (h->elf_link_hash_flags			& ELF_LINK_HASH_DEF_REGULAR) == 0)))	    {	      if (h != NULL)		{		  /* Make sure a plt entry is created for this symbol if		     it turns out to be a function defined by a dynamic		     object.  */		  if (h->plt.refcount == -1)		    h->plt.refcount = 1;		  else		    h->plt.refcount++;		}	      break;	    }	  /* Fall through.  */	case R_68K_8:	case R_68K_16:	case R_68K_32:	  if (h != NULL)	    {	      /* Make sure a plt entry is created for this symbol if it		 turns out to be a function defined by a dynamic object.  */	      if (h->plt.refcount == -1)		h->plt.refcount = 1;	      else		h->plt.refcount++;	    }	  /* If we are creating a shared library, we need to copy the	     reloc into the shared library.  */	  if (info->shared	      && (sec->flags & SEC_ALLOC) != 0)	    {	      /* When creating a shared object, we must copy these		 reloc types into the output file.  We create a reloc		 section in dynobj and make room for this reloc.  */	      if (sreloc == NULL)		{		  const char *name;		  name = (bfd_elf_string_from_elf_section			  (abfd,			   elf_elfheader (abfd)->e_shstrndx,			   elf_section_data (sec)->rel_hdr.sh_name));		  if (name == NULL)		    return false;		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0			      && strcmp (bfd_get_section_name (abfd, sec),					 name + 5) == 0);		  sreloc = bfd_get_section_by_name (dynobj, name);		  if (sreloc == NULL)		    {		      sreloc = bfd_make_section (dynobj, name);		      if (sreloc == NULL			  || !bfd_set_section_flags (dynobj, sreloc,						     (SEC_ALLOC						      | SEC_LOAD						      | SEC_HAS_CONTENTS						      | SEC_IN_MEMORY						      | SEC_LINKER_CREATED						      | SEC_READONLY))			  || !bfd_set_section_alignment (dynobj, sreloc, 2))			return false;		    }		}	      sreloc->_raw_size += sizeof (Elf32_External_Rela);	      /* If we are linking with -Bsymbolic, we count the number of		 PC relative relocations we have entered for this symbol,		 so that we can discard them again if the symbol is later		 defined by a regular object.  Note that this function is		 only called if we are using an m68kelf linker hash table,		 which means that h is really a pointer to an		 elf_m68k_link_hash_entry.  */	      if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8 		   || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 		   || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)		  && info->symbolic)		{		  struct elf_m68k_link_hash_entry *eh;		  struct elf_m68k_pcrel_relocs_copied *p;		  eh = (struct elf_m68k_link_hash_entry *) h;		  for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)		    if (p->section == sreloc)		      break;		  if (p == NULL)		    {		      p = ((struct elf_m68k_pcrel_relocs_copied *)			   bfd_alloc (dynobj, sizeof *p));		      if (p == NULL)			return false;		      p->next = eh->pcrel_relocs_copied;		      eh->pcrel_relocs_copied = p;		      p->section = sreloc;		      p->count = 0;		    }		  ++p->count;		}	    }	  break;	  /* This relocation describes the C++ object vtable hierarchy.	     Reconstruct it for later use during GC.  */	case R_68K_GNU_VTINHERIT:	  if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))	    return false;	  break;	  /* This relocation describes which C++ vtable entries are actually	     used.  Record for later use during GC.  */	case R_68K_GNU_VTENTRY:	  if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))	    return false;	  break;	default:	  break;	}    }  return true;}/* Return the section that should be marked against GC for a given   relocation.  */static asection *elf_m68k_gc_mark_hook (abfd, info, rel, h, sym)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     Elf_Internal_Rela *rel;     struct elf_link_hash_entry *h;     Elf_Internal_Sym *sym;{  if (h != NULL)    {      switch (ELF32_R_TYPE (rel->r_info))	{	case R_68K_GNU_VTINHERIT:	case R_68K_GNU_VTENTRY:	  break;	default:	  switch (h->root.type)	    {	    default:	      break;	    case bfd_link_hash_defined:	    case bfd_link_hash_defweak:	      return h->root.u.def.section;	    case bfd_link_hash_common:	      return h->root.u.c.p->section;	    }	}    }  else    {      if (!(elf_bad_symtab (abfd)	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)		&& sym->st_shndx != SHN_COMMON))	{	  return bfd_section_from_elf_index (abfd, sym->st_shndx);	}    }  return NULL;}/* Update the got entry reference counts for the section being removed.  */static booleanelf_m68k_gc_sweep_hook (abfd, info, sec, relocs)     bfd *abfd;     struct bfd_link_info *info;     asection *sec;     const Elf_Internal_Rela *relocs;{  Elf_Internal_Shdr *symtab_hdr;  struct elf_link_hash_entry **sym_hashes;  bfd_signed_vma *local_got_refcounts;  const Elf_Internal_Rela *rel, *relend;  unsigned long r_symndx;  struct elf_link_hash_entry *h;  bfd *dynobj;  asection *sgot;  asection *srelgot;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  dynobj = elf_hash_table (info)->dynobj;  if (dynobj == NULL)    return true;  sgot = bfd_get_section_by_name (dynobj, ".got");  srelgot = bfd_get_section_by_name (dynobj, ".rela.got");  relend = relocs + sec->reloc_count;  for (rel = relocs; rel < relend; rel++)    {

⌨️ 快捷键说明

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