elf64-hppa.c

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

C
2,237
字号
	  /* FPTRs are not allocated by the dynamic linker for PA64, though	     it is possible that will change in the future.  */	  /* This could be a local function that had its address taken, in	     which case H will be NULL.  */	  if (h)	    h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;	}      /* Add a new dynamic relocation to the chain of dynamic	 relocations for this symbol.  */      if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))	{	  if (! hppa_info->other_rel_sec	      && ! get_reloc_section (abfd, hppa_info, sec))	    goto err_out;	  if (!count_dyn_reloc (abfd, dyn_h, dynrel_type, sec,				sec_symndx, rel->r_offset, rel->r_addend))	    goto err_out;	  /* If we are building a shared library and we just recorded	     a dynamic R_PARISC_FPTR64 relocation, then make sure the	     section symbol for this section ends up in the dynamic	     symbol table.  */	  if (info->shared && dynrel_type == R_PARISC_FPTR64	      && ! (_bfd_elf64_link_record_local_dynamic_symbol		    (info, abfd, sec_symndx)))	    return false;	}    }  if (buf)    free (buf);  return true; err_out:  if (buf)    free (buf);  return false;}struct elf64_hppa_allocate_data{  struct bfd_link_info *info;  bfd_size_type ofs;};/* Should we do dynamic things to this symbol?  */static booleanelf64_hppa_dynamic_symbol_p (h, info)     struct elf_link_hash_entry *h;     struct bfd_link_info *info;{  if (h == NULL)    return false;  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->dynindx == -1)    return false;  if (h->root.type == bfd_link_hash_undefweak      || h->root.type == bfd_link_hash_defweak)    return true;  if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')    return false;  if ((info->shared && !info->symbolic)      || ((h->elf_link_hash_flags	   & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))	  == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))    return true;  return false;}/* Mark all funtions exported by this file so that we can later allocate   entries in .opd for them.  */static booleanelf64_hppa_mark_exported_functions (h, data)     struct elf_link_hash_entry *h;     PTR data;{  struct bfd_link_info *info = (struct bfd_link_info *)data;  struct elf64_hppa_link_hash_table *hppa_info;  hppa_info = elf64_hppa_hash_table (info);  if (h      && (h->root.type == bfd_link_hash_defined	  || h->root.type == bfd_link_hash_defweak)      && h->root.u.def.section->output_section != NULL      && h->type == STT_FUNC)    {       struct elf64_hppa_dyn_hash_entry *dyn_h;      /* Add this symbol to the PA64 linker hash table.  */      dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,					  h->root.root.string, true, true);      BFD_ASSERT (dyn_h);      dyn_h->h = h;      if (! hppa_info->opd_sec	  && ! get_opd (hppa_info->root.dynobj, info, hppa_info))	return false;      dyn_h->want_opd = 1;      /* Put a flag here for output_symbol_hook.  */      dyn_h->st_shndx = -1;      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;    }  return true;}/* Allocate space for a DLT entry.  */static booleanallocate_global_data_dlt (dyn_h, data)     struct elf64_hppa_dyn_hash_entry *dyn_h;     PTR data;{  struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;  if (dyn_h->want_dlt)    {      struct elf_link_hash_entry *h = dyn_h->h;      if (x->info->shared)	{	  /* Possibly add the symbol to the local dynamic symbol	     table since we might need to create a dynamic relocation	     against it.  */	  if (! h	      || (h && h->dynindx == -1))	    {	      bfd *owner;	      owner = (h ? h->root.u.def.section->owner : dyn_h->owner);	      if (!_bfd_elf64_link_record_local_dynamic_symbol		    (x->info, owner, dyn_h->sym_indx))		return false;	    }	}      dyn_h->dlt_offset = x->ofs;      x->ofs += DLT_ENTRY_SIZE;    }  return true;}/* Allocate space for a DLT.PLT entry.  */static booleanallocate_global_data_plt (dyn_h, data)     struct elf64_hppa_dyn_hash_entry *dyn_h;     PTR data;{  struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;  if (dyn_h->want_plt      && elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info)      && !((dyn_h->h->root.type == bfd_link_hash_defined	    || dyn_h->h->root.type == bfd_link_hash_defweak)	   && dyn_h->h->root.u.def.section->output_section != NULL))    {      dyn_h->plt_offset = x->ofs;      x->ofs += PLT_ENTRY_SIZE;      if (dyn_h->plt_offset < 0x2000)	elf64_hppa_hash_table (x->info)->gp_offset = dyn_h->plt_offset;    }  else    dyn_h->want_plt = 0;  return true;}/* Allocate space for a STUB entry.  */static booleanallocate_global_data_stub (dyn_h, data)     struct elf64_hppa_dyn_hash_entry *dyn_h;     PTR data;{  struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;  if (dyn_h->want_stub      && elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info)      && !((dyn_h->h->root.type == bfd_link_hash_defined	    || dyn_h->h->root.type == bfd_link_hash_defweak)	   && dyn_h->h->root.u.def.section->output_section != NULL))    {      dyn_h->stub_offset = x->ofs;      x->ofs += sizeof (plt_stub);    }  else    dyn_h->want_stub = 0;  return true;}/* Allocate space for a FPTR entry.  */static booleanallocate_global_data_opd (dyn_h, data)     struct elf64_hppa_dyn_hash_entry *dyn_h;     PTR data;{  struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;  if (dyn_h->want_opd)    {      struct elf_link_hash_entry *h = dyn_h->h;      if (h)	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;      /* We never need an opd entry for a symbol which is not	 defined by this output file.  */      if (h && h->root.type == bfd_link_hash_undefined)	dyn_h->want_opd = 0;      /* If we are creating a shared library, took the address of a local	 function or might export this function from this object file, then	 we have to create an opd descriptor.  */      else if (x->info->shared	       || h == NULL	       || h->dynindx == -1	       || ((h->root.type == bfd_link_hash_defined		    || h->root.type == bfd_link_hash_defweak)		   && h->root.u.def.section->output_section != NULL))	{	  /* If we are creating a shared library, then we will have to	     create a runtime relocation for the symbol to properly	     initialize the .opd entry.  Make sure the symbol gets	     added to the dynamic symbol table.  */	  if (x->info->shared	      && (h == NULL || (h->dynindx == -1)))	    {	      bfd *owner;	      owner = (h ? h->root.u.def.section->owner : dyn_h->owner);	      if (!_bfd_elf64_link_record_local_dynamic_symbol		    (x->info, owner, dyn_h->sym_indx))		return false;	    }	  /* This may not be necessary or desirable anymore now that	     we have some support for dealing with section symbols	     in dynamic relocs.  But name munging does make the result	     much easier to debug.  ie, the EPLT reloc will reference	     a symbol like .foobar, instead of .text + offset.  */	  if (x->info->shared && h)	    {	      char *new_name;	      struct elf_link_hash_entry *nh;	      new_name = alloca (strlen (h->root.root.string) + 2);	      new_name[0] = '.';	      strcpy (new_name + 1, h->root.root.string);	      nh = elf_link_hash_lookup (elf_hash_table (x->info),					 new_name, true, true, true);	      nh->root.type = h->root.type;	      nh->root.u.def.value = h->root.u.def.value;	      nh->root.u.def.section = h->root.u.def.section;	      if (! bfd_elf64_link_record_dynamic_symbol (x->info, nh))		return false;	     }	  dyn_h->opd_offset = x->ofs;	  x->ofs += OPD_ENTRY_SIZE;	}      /* Otherwise we do not need an opd entry.  */      else	dyn_h->want_opd = 0;    }  return true;}/* HP requires the EI_OSABI field to be filled in.  The assignment to   EI_ABIVERSION may not be strictly necessary.  */static voidelf64_hppa_post_process_headers (abfd, link_info)     bfd * abfd;     struct bfd_link_info * link_info ATTRIBUTE_UNUSED;{  Elf_Internal_Ehdr * i_ehdrp;  i_ehdrp = elf_elfheader (abfd);  if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)    {      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;    }  else    {      i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;      i_ehdrp->e_ident[EI_ABIVERSION] = 1;    }}/* Create function descriptor section (.opd).  This section is called .opd   because it contains "official prodecure descriptors".  The "official"   refers to the fact that these descriptors are used when taking the address   of a procedure, thus ensuring a unique address for each procedure.  */static booleanget_opd (abfd, info, hppa_info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf64_hppa_link_hash_table *hppa_info;{  asection *opd;  bfd *dynobj;  opd = hppa_info->opd_sec;  if (!opd)    {      dynobj = hppa_info->root.dynobj;      if (!dynobj)	hppa_info->root.dynobj = dynobj = abfd;      opd = bfd_make_section (dynobj, ".opd");      if (!opd	  || !bfd_set_section_flags (dynobj, opd,				     (SEC_ALLOC				      | SEC_LOAD				      | SEC_HAS_CONTENTS				      | SEC_IN_MEMORY				      | SEC_LINKER_CREATED))	  || !bfd_set_section_alignment (abfd, opd, 3))	{	  BFD_ASSERT (0);	  return false;	}      hppa_info->opd_sec = opd;    }  return true;}/* Create the PLT section.  */static booleanget_plt (abfd, info, hppa_info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf64_hppa_link_hash_table *hppa_info;{  asection *plt;  bfd *dynobj;  plt = hppa_info->plt_sec;  if (!plt)    {      dynobj = hppa_info->root.dynobj;      if (!dynobj)	hppa_info->root.dynobj = dynobj = abfd;      plt = bfd_make_section (dynobj, ".plt");      if (!plt	  || !bfd_set_section_flags (dynobj, plt,				     (SEC_ALLOC				      | SEC_LOAD				      | SEC_HAS_CONTENTS				      | SEC_IN_MEMORY				      | SEC_LINKER_CREATED))	  || !bfd_set_section_alignment (abfd, plt, 3))	{	  BFD_ASSERT (0);	  return false;	}      hppa_info->plt_sec = plt;    }  return true;}/* Create the DLT section.  */static booleanget_dlt (abfd, info, hppa_info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf64_hppa_link_hash_table *hppa_info;{  asection *dlt;  bfd *dynobj;  dlt = hppa_info->dlt_sec;  if (!dlt)    {      dynobj = hppa_info->root.dynobj;      if (!dynobj)	hppa_info->root.dynobj = dynobj = abfd;      dlt = bfd_make_section (dynobj, ".dlt");      if (!dlt	  || !bfd_set_section_flags (dynobj, dlt,				     (SEC_ALLOC				      | SEC_LOAD				      | SEC_HAS_CONTENTS				      | SEC_IN_MEMORY				      | SEC_LINKER_CREATED))	  || !bfd_set_section_alignment (abfd, dlt, 3))	{	  BFD_ASSERT (0);	  return false;	}      hppa_info->dlt_sec = dlt;    }  return true;}/* Create the stubs section.  */static booleanget_stub (abfd, info, hppa_info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf64_hppa_link_hash_table *hppa_info;{  asection *stub;  bfd *dynobj;  stub = hppa_info->stub_sec;  if (!stub)    {      dynobj = hppa_info->root.dynobj;      if (!dynobj)	hppa_info->root.dynobj = dynobj = abfd;

⌨️ 快捷键说明

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