elf32-hppa.c

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

C
2,142
字号
	    }	}    }  return true;}/* Return the section that should be marked against garbage collection   for a given relocation.  */static asection *elf32_hppa_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 ((unsigned int) ELF32_R_TYPE (rel->r_info))	{	case R_PARISC_GNU_VTINHERIT:	case R_PARISC_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 and plt entry reference counts for the section being   removed.  */static booleanelf32_hppa_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;  bfd_signed_vma *local_plt_refcounts;  const Elf_Internal_Rela *rel, *relend;  unsigned long r_symndx;  struct elf_link_hash_entry *h;  struct elf32_hppa_link_hash_table *hplink;  bfd *dynobj;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  local_plt_refcounts = local_got_refcounts;  if (local_plt_refcounts != NULL)    local_plt_refcounts += symtab_hdr->sh_info;  hplink = hppa_link_hash_table (info);  dynobj = hplink->root.dynobj;  if (dynobj == NULL)    return true;  relend = relocs + sec->reloc_count;  for (rel = relocs; rel < relend; rel++)    switch ((unsigned int) ELF32_R_TYPE (rel->r_info))      {      case R_PARISC_DLTIND14F:      case R_PARISC_DLTIND14R:      case R_PARISC_DLTIND21L:	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 -= 1;	  }	else if (local_got_refcounts != NULL)	  {	    if (local_got_refcounts[r_symndx] > 0)	      local_got_refcounts[r_symndx] -= 1;	  }	break;      case R_PARISC_PCREL12F:      case R_PARISC_PCREL17C:      case R_PARISC_PCREL17F:      case R_PARISC_PCREL22F:	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 -= 1;	  }	break;      case R_PARISC_PLABEL14R:      case R_PARISC_PLABEL21L:      case R_PARISC_PLABEL32:	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 -= 1;	  }	else if (local_plt_refcounts != NULL)	  {	    if (local_plt_refcounts[r_symndx] > 0)	      local_plt_refcounts[r_symndx] -= 1;	  }	break;      default:	break;      }  return true;}/* Our own version of hide_symbol, so that we can keep plt entries for   plabels.  */static voidelf32_hppa_hide_symbol (info, h)     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf_link_hash_entry *h;{  if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)    h->dynindx = -1;  if (! ((struct elf32_hppa_link_hash_entry *) h)->plabel)    {      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;      h->plt.offset = (bfd_vma) -1;    }}/* This is the condition under which elf32_hppa_finish_dynamic_symbol   will be called from elflink.h.  If elflink.h doesn't call our   finish_dynamic_symbol routine, we'll need to do something about   initializing any .plt and .got entries in elf32_hppa_relocate_section.  */#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \  ((DYN)								\   && ((INFO)->shared							\       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)	\   && ((H)->dynindx != -1						\       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))/* 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_hppa_adjust_dynamic_symbol (info, h)     struct bfd_link_info *info;     struct elf_link_hash_entry *h;{  bfd *dynobj;  struct elf32_hppa_link_hash_table *hplink;  asection *s;  hplink = hppa_link_hash_table (info);  dynobj = hplink->root.dynobj;  /* If this is a function, put it in the procedure linkage table.  We     will fill in the contents of the procedure linkage table later,     when we know the address of the .got section.  */  if (h->type == STT_FUNC      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)    {      if (!info->shared	  && h->plt.refcount > 0	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0	  && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0)	{	  ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;	}      if (h->plt.refcount <= 0	  || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0	      && h->root.type != bfd_link_hash_defweak	      && ! ((struct elf32_hppa_link_hash_entry *) h)->plabel	      && (!info->shared || info->symbolic)))	{	  /* The .plt entry is not needed when:	     a) Garbage collection has removed all references to the	     symbol, or	     b) We know for certain the symbol is defined in this	     object, and it's not a weak definition, nor is the symbol	     used by a plabel relocation.  Either this object is the	     application or we are doing a shared symbolic link.  */	  /* As a special sop to the hppa ABI, we keep a .plt entry	     for functions in sections containing PIC code.  */	  if (((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call)	    ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;	  else	    {	      h->plt.offset = (bfd_vma) -1;	      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;	      return true;	    }	}      if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)	{	  /* Make sure this symbol is output as a dynamic symbol.  */	  if (h->dynindx == -1	      && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)	    {	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))		return false;	    }	}      return true;    }  /* If this is a weak symbol, and there is a real definition, the     processor independent code will have arranged for us to see the     real definition first, and we can just use the same value.  */  if (h->weakdef != NULL)    {      if (h->weakdef->root.type != bfd_link_hash_defined	  && h->weakdef->root.type != bfd_link_hash_defweak)	abort ();      h->root.u.def.section = h->weakdef->root.u.def.section;      h->root.u.def.value = h->weakdef->root.u.def.value;      return true;    }  /* This is a reference to a symbol defined by a dynamic object which     is not a function.  */  /* If we are creating a shared library, we must presume that the     only references to the symbol are via the global offset table.     For such cases we need not do anything here; the relocations will     be handled correctly by relocate_section.  */  if (info->shared)    return true;  /* If there are no references to this symbol that do not use the     GOT, we don't need to generate a copy reloc.  */  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)    return true;  /* We must allocate the symbol in our .dynbss section, which will     become part of the .bss section of the executable.  There will be     an entry for this symbol in the .dynsym section.  The dynamic     object will contain position independent code, so all references     from the dynamic object to this symbol will go through the global     offset table.  The dynamic linker will use the .dynsym entry to     determine the address it must put in the global offset table, so     both the dynamic object and the regular object will refer to the     same memory location for the variable.  */  s = hplink->sdynbss;  /* We must generate a COPY reloc to tell the dynamic linker to     copy the initial value out of the dynamic object and into the     runtime process image.  We need to remember the offset into the     .rela.bss section we are going to use.  */  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)    {      asection *srel;      srel = hplink->srelbss;      srel->_raw_size += sizeof (Elf32_External_Rela);      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;    }  {    /* We need to figure out the alignment required for this symbol.  I       have no idea how other ELF linkers handle this.  */    unsigned int power_of_two;    power_of_two = bfd_log2 (h->size);    if (power_of_two > 3)      power_of_two = 3;    /* Apply the required alignment.  */    s->_raw_size = BFD_ALIGN (s->_raw_size,			      (bfd_size_type) (1 << power_of_two));    if (power_of_two > bfd_get_section_alignment (dynobj, s))      {	if (! bfd_set_section_alignment (dynobj, s, power_of_two))	  return false;      }  }  /* Define the symbol as being at this point in the section.  */  h->root.u.def.section = s;  h->root.u.def.value = s->_raw_size;  /* Increment the section size to make room for the symbol.  */  s->_raw_size += h->size;  return true;}/* Called via elf_link_hash_traverse to create .plt entries for an   application that uses statically linked PIC functions.  Similar to   the first part of elf32_hppa_adjust_dynamic_symbol.  */static booleanhppa_handle_PIC_calls (h, inf)     struct elf_link_hash_entry *h;     PTR inf ATTRIBUTE_UNUSED;{  if (! (h->plt.refcount > 0	 && (h->root.type == bfd_link_hash_defined	     || h->root.type == bfd_link_hash_defweak)	 && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0))    {      h->plt.offset = (bfd_vma) -1;      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;      return true;    }  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;  ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;  ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;  return true;}/* Allocate space in .plt, .got and associated reloc sections for   global syms.  */static booleanallocate_plt_and_got (h, inf)     struct elf_link_hash_entry *h;     PTR inf;{  struct bfd_link_info *info;  struct elf32_hppa_link_hash_table *hplink;  asection *s;  if (h->root.type == bfd_link_hash_indirect      || h->root.type == bfd_link_hash_warning)    return true;  info = (struct bfd_link_info *) inf;  hplink = hppa_link_hash_table (info);  if ((hplink->root.dynamic_sections_created       && h->plt.refcount > 0)      || ((struct elf32_hppa_link_hash_entry *) h)->pic_call)    {      /* Make an entry in the .plt section.  */      s = hplink->splt;      h->plt.offset = s->_raw_size;      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE	  && ((struct elf32_hppa_link_hash_entry *) h)->plabel	  && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)	{	  /* Add some extra space for the dynamic linker to use.  */	  s->_raw_size += PLABEL_PLT_ENTRY_SIZE;	}      else	s->_raw_size += PLT_ENTRY_SIZE;      if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call	  && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))	{	  /* We also need to make an entry in the .rela.plt section.  */	  hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);	  hplink->need_plt_stub = 1;	}    }  else    {      h->plt.offset = (bfd_vma) -1;      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;    }  if (h->got.refcount > 0)    {      boolean dyn;      s = hplink->sgot;      h->got.offset = s->_raw_size;      s->_raw_size += GOT_ENTRY_SIZE;      dyn = hplink->root.dynamic_sections_created;      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))	hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);    }  else    h->got.offset = (bfd_vma) -1;  return true;}#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \     || RELATIVE_DYNAMIC_RELOCS)/* This function is called via elf_link_hash_traverse to discard space   we allocated for relocs that it turned out we didn't need.  */static booleanhppa_discard_copies (h, inf)     struct elf_link_hash_entry *h;     PTR inf

⌨️ 快捷键说明

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