elf32-sparc.c

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

C
2,014
字号
	    }	  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.offset != (bfd_vma) -1)		{		  /* We have already allocated space in the .got.  */		  break;		}	      h->got.offset = sgot->_raw_size;	      /* 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;		}	      srelgot->_raw_size += sizeof (Elf32_External_Rela);	    }	  else	    {	      /* This is a global offset table entry for a local                 symbol.  */	      if (local_got_offsets == NULL)		{		  size_t size;		  register unsigned int i;		  size = symtab_hdr->sh_info * sizeof (bfd_vma);		  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);		  if (local_got_offsets == NULL)		    return false;		  elf_local_got_offsets (abfd) = local_got_offsets;		  for (i = 0; i < symtab_hdr->sh_info; i++)		    local_got_offsets[i] = (bfd_vma) -1;		}	      if (local_got_offsets[r_symndx] != (bfd_vma) -1)		{		  /* We have already allocated space in the .got.  */		  break;		}	      local_got_offsets[r_symndx] = sgot->_raw_size;	      if (info->shared)		{		  /* If we are generating a shared object, we need to                     output a R_SPARC_RELATIVE reloc so that the                     dynamic linker can adjust this GOT entry.  */		  srelgot->_raw_size += sizeof (Elf32_External_Rela);		}	    }	  sgot->_raw_size += 4;	  /* If the .got section is more than 0x1000 bytes, we add	     0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13	     bit relocations have a greater chance of working.  */	  if (sgot->_raw_size >= 0x1000	      && elf_hash_table (info)->hgot->root.u.def.value == 0)	    elf_hash_table (info)->hgot->root.u.def.value = 0x1000;	  break;	case R_SPARC_WPLT30:	  /* 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 without             linking in any dynamic objects, in which case we don't             need to generate a procedure linkage table after all.  */	  if (h == NULL)	    {	      /* 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.  */	      break;	    }	  /* 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;	  break;	case R_SPARC_PC10:	case R_SPARC_PC22:	  if (h != NULL)	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;	  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)	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;	  /* If we are linking with -Bsymbolic, we do not need to copy             a PC relative reloc against a global symbol which is             defined in an object we are including in the link (i.e.,             DEF_REGULAR is set).  FIXME: 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).  This needs to be handled as in             elf32-i386.c.  */	  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 (h != NULL)	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;	  if (info->shared)	    {	      /* When creating a shared object, we must copy these                 relocs into the output file.  We create a reloc                 section in dynobj and make room for the 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)		    {		      flagword flags;		      sreloc = bfd_make_section (dynobj, name);		      flags = (SEC_HAS_CONTENTS | SEC_READONLY			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);		      if ((sec->flags & SEC_ALLOC) != 0)			flags |= SEC_ALLOC | SEC_LOAD;		      if (sreloc == NULL			  || ! bfd_set_section_flags (dynobj, sreloc, flags)			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))			return false;		    }		}	      sreloc->_raw_size += sizeof (Elf32_External_Rela);	    }	  break;        case R_SPARC_GNU_VTINHERIT:          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))            return false;          break;        case R_SPARC_GNU_VTENTRY:          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))            return false;          break;	default:	  break;	}    }  return true;}static asection *elf32_sparc_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_SPARC_GNU_VTINHERIT:      case R_SPARC_GNU_VTENTRY:        break;      default:        switch (h->root.type)          {          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;	  default:	    break;          }       }     }   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 booleanelf32_sparc_gc_sweep_hook (abfd, info, sec, relocs)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     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;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  relend = relocs + sec->reloc_count;  for (rel = relocs; rel < relend; rel++)    switch (ELF32_R_TYPE (rel->r_info))      {      case R_SPARC_GOT10:      case R_SPARC_GOT13:      case R_SPARC_GOT22:	r_symndx = ELF32_R_SYM (rel->r_info);	if (r_symndx >= symtab_hdr->sh_info)	  {	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];	    if (h->got.refcount > 0)	      h->got.refcount--;	  }	else	  {	    if (local_got_refcounts[r_symndx] > 0)	      local_got_refcounts[r_symndx]--;	  }        break;      case R_SPARC_PLT32:      case R_SPARC_HIPLT22:      case R_SPARC_LOPLT10:      case R_SPARC_PCPLT32:      case R_SPARC_PCPLT10:	r_symndx = ELF32_R_SYM (rel->r_info);	if (r_symndx >= symtab_hdr->sh_info)	  {	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];	    if (h->plt.refcount > 0)	      h->plt.refcount--;	  }	break;      default:	break;      }  return true;}/* Adjust a symbol defined by a dynamic object and referenced by a   regular object.  The current definition is in some section of the   dynamic object, but we're not including those sections.  We have to   change the definition to something the rest of the link can   understand.  */static booleanelf32_sparc_adjust_dynamic_symbol (info, h)     struct bfd_link_info *info;     struct elf_link_hash_entry *h;{  bfd *dynobj;  asection *s;  unsigned int power_of_two;  dynobj = elf_hash_table (info)->dynobj;  /* Make sure we know what is going on here.  */  BFD_ASSERT (dynobj != NULL	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)		  || h->weakdef != NULL		  || ((h->elf_link_hash_flags		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0		      && (h->elf_link_hash_flags			  & ELF_LINK_HASH_REF_REGULAR) != 0		      && (h->elf_link_hash_flags			  & ELF_LINK_HASH_DEF_REGULAR) == 0)));  /* If this is a function, put it in the procedure linkage table.  We     will fill in the contents of the procedure linkage table later     (although we could actually do it here).  The STT_NOTYPE     condition is a hack specifically for the Oracle libraries     delivered for Solaris; for some inexplicable reason, they define     some of their functions as STT_NOTYPE when they really should be     STT_FUNC.  */  if (h->type == STT_FUNC      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0      || (h->type == STT_NOTYPE	  && (h->root.type == bfd_link_hash_defined	      || h->root.type == bfd_link_hash_defweak)	  && (h->root.u.def.section->flags & SEC_CODE) != 0))    {      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) != 0))	{	  /* This case can occur if we saw a WPLT30 reloc in an input	     file, but none of the input files were dynamic objects.	     Or, when linking the main application or a -Bsymbolic	     shared library against PIC code.  Or when a global symbol	     has been made private, e.g. via versioning.	     In these cases we know what value the symbol will resolve	     to, so we don't actually need to build a procedure linkage	     table, and we can just do a WDISP30 reloc instead.  */	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;	  return true;	}      s = bfd_get_section_by_name (dynobj, ".plt");      BFD_ASSERT (s != NULL);      /* The first four entries in .plt are reserved.  */      if (s->_raw_size == 0)	s->_raw_size = 4 * PLT_ENTRY_SIZE;      /* The procedure linkage table has a maximum size.  */      if (s->_raw_size >= 0x400000)	{	  bfd_set_error (bfd_error_bad_value);	  return false;	}     /* If this symbol is not defined in a regular file, and we are       not generating a shared library, then set the symbol to this       location in the .plt.  This is required to make function

⌨️ 快捷键说明

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