elf32-hppa.c

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

C
2,142
字号
	 loading the upper bits of the target address into a register,	 then branching with "be" which adds in the lower bits.	 The "be" has its delay slot nullified.  */      sym_value = (stub_entry->target_value		   + stub_entry->target_section->output_offset		   + stub_entry->target_section->output_section->vma);      val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_lrsel);      insn = hppa_rebuild_insn ((int) LDIL_R1, val, 21);      bfd_put_32 (stub_bfd, insn, loc);      val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_rrsel) >> 2;      insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);      bfd_put_32 (stub_bfd, insn, loc + 4);#if ! LONG_BRANCH_PIC_IN_SHLIB      if (info->shared)	{	  /* Output a dynamic relocation for this stub.  We only	     output one PCREL21L reloc per stub, trusting that the	     dynamic linker will also fix the implied PCREL17R for the	     second instruction.  PCREL21L dynamic relocs had better	     never be emitted for some other purpose...  */	  asection *srel;	  Elf_Internal_Rela outrel;	  if (stub_entry->h == NULL)	    {	      (*_bfd_error_handler)		(_("%s(%s+0x%lx): cannot relocate %s, recompile with -ffunction-sections"),		 bfd_get_filename (stub_entry->target_section->owner),		 stub_sec->name,		 (long) stub_entry->stub_offset,		 stub_entry->root.string);	      bfd_set_error (bfd_error_bad_value);	      return false;	    }	  srel = stub_entry->reloc_sec;	  if (srel == NULL)	    {	      (*_bfd_error_handler)		(_("Could not find relocation section for %s"),		 stub_sec->name);	      bfd_set_error (bfd_error_bad_value);	      return false;	    }	  outrel.r_offset = (stub_entry->stub_offset			     + stub_sec->output_offset			     + stub_sec->output_section->vma);	  outrel.r_info = ELF32_R_INFO (0, R_PARISC_PCREL21L);	  outrel.r_addend = sym_value;	  bfd_elf32_swap_reloca_out (stub_sec->output_section->owner,				     &outrel,				     ((Elf32_External_Rela *)				      srel->contents + srel->reloc_count));	  ++srel->reloc_count;	}#endif      size = 8;      break;    case hppa_stub_long_branch_shared:      /* Branches are relative.  This is where we are going to.  */      sym_value = (stub_entry->target_value		   + stub_entry->target_section->output_offset		   + stub_entry->target_section->output_section->vma);      /* And this is where we are coming from, more or less.  */      sym_value -= (stub_entry->stub_offset		    + stub_sec->output_offset		    + stub_sec->output_section->vma);      bfd_put_32 (stub_bfd, (bfd_vma) BL_R1, loc);      val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_lrsel);      insn = hppa_rebuild_insn ((int) ADDIL_R1, val, 21);      bfd_put_32 (stub_bfd, insn, loc + 4);      val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_rrsel) >> 2;      insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);      bfd_put_32 (stub_bfd, insn, loc + 8);      size = 12;      break;    case hppa_stub_import:    case hppa_stub_import_shared:      off = stub_entry->h->elf.plt.offset;      if (off >= (bfd_vma) -2)	abort ();      off &= ~ (bfd_vma) 1;      sym_value = (off		   + hplink->splt->output_offset		   + hplink->splt->output_section->vma		   - elf_gp (hplink->splt->output_section->owner));      insn = ADDIL_DP;#if R19_STUBS      if (stub_entry->stub_type == hppa_stub_import_shared)	insn = ADDIL_R19;#endif      val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_lrsel),      insn = hppa_rebuild_insn ((int) insn, val, 21);      bfd_put_32 (stub_bfd, insn, loc);      /* It is critical to use lrsel/rrsel here because we are using	 two different offsets (+0 and +4) from sym_value.  If we use	 lsel/rsel then with unfortunate sym_values we will round	 sym_value+4 up to the next 2k block leading to a mis-match	 between the lsel and rsel value.  */      val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_rrsel);      insn = hppa_rebuild_insn ((int) LDW_R1_R21, val, 14);      bfd_put_32 (stub_bfd, insn, loc + 4);      if (hplink->multi_subspace)	{	  val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);	  insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);	  bfd_put_32 (stub_bfd, insn, loc + 8);	  bfd_put_32 (stub_bfd, (bfd_vma) LDSID_R21_R1, loc + 12);	  bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1,      loc + 16);	  bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_R21,   loc + 20);	  bfd_put_32 (stub_bfd, (bfd_vma) STW_RP,       loc + 24);	  size = 28;	}      else	{	  bfd_put_32 (stub_bfd, (bfd_vma) BV_R0_R21, loc + 8);	  val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);	  insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);	  bfd_put_32 (stub_bfd, insn, loc + 12);	  size = 16;	}      if (!info->shared	  && stub_entry->h != NULL	  && stub_entry->h->pic_call)	{	  /* Build the .plt entry needed to call a PIC function from	     statically linked code.  We don't need any relocs.  */	  bfd *dynobj;	  struct elf32_hppa_link_hash_entry *eh;	  bfd_vma value;	  dynobj = hplink->root.dynobj;	  eh = (struct elf32_hppa_link_hash_entry *) stub_entry->h;	  if (eh->elf.root.type != bfd_link_hash_defined	      && eh->elf.root.type != bfd_link_hash_defweak)	    abort ();	  value = (eh->elf.root.u.def.value		   + eh->elf.root.u.def.section->output_offset		   + eh->elf.root.u.def.section->output_section->vma);	  /* Fill in the entry in the procedure linkage table.	     The format of a plt entry is	     <funcaddr>	     <__gp>.  */	  bfd_put_32 (hplink->splt->owner, value,		      hplink->splt->contents + off);	  value = elf_gp (hplink->splt->output_section->owner);	  bfd_put_32 (hplink->splt->owner, value,		      hplink->splt->contents + off + 4);	}      break;    case hppa_stub_export:      /* Branches are relative.  This is where we are going to.  */      sym_value = (stub_entry->target_value		   + stub_entry->target_section->output_offset		   + stub_entry->target_section->output_section->vma);      /* And this is where we are coming from.  */      sym_value -= (stub_entry->stub_offset		    + stub_sec->output_offset		    + stub_sec->output_section->vma);      if (sym_value - 8 + 0x40000 >= 0x80000)	{	  (*_bfd_error_handler)	    (_("%s(%s+0x%lx): cannot reach %s, recompile with -ffunction-sections"),	     bfd_get_filename (stub_entry->target_section->owner),	     stub_sec->name,	     (long) stub_entry->stub_offset,	     stub_entry->root.string);	  bfd_set_error (bfd_error_bad_value);	  return false;	}      val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_fsel) >> 2;      insn = hppa_rebuild_insn ((int) BL_RP, val, 17);      bfd_put_32 (stub_bfd, insn, loc);      bfd_put_32 (stub_bfd, (bfd_vma) NOP,         loc + 4);      bfd_put_32 (stub_bfd, (bfd_vma) LDW_RP,      loc + 8);      bfd_put_32 (stub_bfd, (bfd_vma) LDSID_RP_R1, loc + 12);      bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1,     loc + 16);      bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_RP,   loc + 20);      /* Point the function symbol at the stub.  */      stub_entry->h->elf.root.u.def.section = stub_sec;      stub_entry->h->elf.root.u.def.value = stub_sec->_raw_size;      size = 24;      break;    default:      BFD_FAIL ();      return false;    }  stub_sec->_raw_size += size;  return true;}#undef LDIL_R1#undef BE_SR4_R1#undef BL_R1#undef ADDIL_R1#undef DEPI_R1#undef ADDIL_DP#undef LDW_R1_R21#undef LDW_R1_DLT#undef LDW_R1_R19#undef ADDIL_R19#undef LDW_R1_DP#undef LDSID_R21_R1#undef MTSP_R1#undef BE_SR0_R21#undef STW_RP#undef BV_R0_R21#undef BL_RP#undef NOP#undef LDW_RP#undef LDSID_RP_R1#undef BE_SR0_RP/* As above, but don't actually build the stub.  Just bump offset so   we know stub section sizes.  */static booleanhppa_size_one_stub (gen_entry, in_arg)     struct bfd_hash_entry *gen_entry;     PTR in_arg;{  struct elf32_hppa_stub_hash_entry *stub_entry;  struct elf32_hppa_link_hash_table *hplink;  int size;  /* Massage our args to the form they really have.  */  stub_entry = (struct elf32_hppa_stub_hash_entry *) gen_entry;  hplink = (struct elf32_hppa_link_hash_table *) in_arg;  if (stub_entry->stub_type == hppa_stub_long_branch)    {#if ! LONG_BRANCH_PIC_IN_SHLIB      if (stub_entry->reloc_sec != NULL)	stub_entry->reloc_sec->_raw_size += sizeof (Elf32_External_Rela);#endif      size = 8;    }  else if (stub_entry->stub_type == hppa_stub_long_branch_shared)    size = 12;  else if (stub_entry->stub_type == hppa_stub_export)    size = 24;  else /* hppa_stub_import or hppa_stub_import_shared.  */    {      if (hplink->multi_subspace)	size = 28;      else	size = 16;    }  stub_entry->stub_sec->_raw_size += size;  return true;}/* Return nonzero if ABFD represents an HPPA ELF32 file.   Additionally we set the default architecture and machine.  */static booleanelf32_hppa_object_p (abfd)     bfd *abfd;{  Elf_Internal_Ehdr * i_ehdrp;  unsigned int flags;  i_ehdrp = elf_elfheader (abfd);  if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)    {      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX)	return false;    }  else    {      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)	return false;    }  flags = i_ehdrp->e_flags;  switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))    {    case EFA_PARISC_1_0:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 10);    case EFA_PARISC_1_1:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);    case EFA_PARISC_2_0:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);    case EFA_PARISC_2_0 | EF_PARISC_WIDE:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);    }  return true;}/* Undo the generic ELF code's subtraction of section->vma from the   value of each external symbol.  */static booleanelf32_hppa_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)     bfd *abfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     const Elf_Internal_Sym *sym ATTRIBUTE_UNUSED;     const char **namep ATTRIBUTE_UNUSED;     flagword *flagsp ATTRIBUTE_UNUSED;     asection **secp;     bfd_vma *valp;{  *valp += (*secp)->vma;  return true;}/* Create the .plt and .got sections, and set up our hash table   short-cuts to various dynamic sections.  */static booleanelf32_hppa_create_dynamic_sections (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  struct elf32_hppa_link_hash_table *hplink;  /* Don't try to create the .plt and .got twice.  */  hplink = hppa_link_hash_table (info);  if (hplink->splt != NULL)    return true;  /* Call the generic code to do most of the work.  */  if (! _bfd_elf_create_dynamic_sections (abfd, info))    return false;  hplink->splt = bfd_get_section_by_name (abfd, ".plt");  hplink->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");  hplink->sgot = bfd_get_section_by_name (abfd, ".got");  hplink->srelgot = bfd_make_section (abfd, ".rela.got");  if (hplink->srelgot == NULL      || ! bfd_set_section_flags (abfd, hplink->srelgot,				  (SEC_ALLOC				   | SEC_LOAD				   | SEC_HAS_CONTENTS				   | SEC_IN_MEMORY				   | SEC_LINKER_CREATED				   | SEC_READONLY))      || ! bfd_set_section_alignment (abfd, hplink->srelgot, 2))    return false;  hplink->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");  hplink->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");  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.  At this point we haven't necessarily read all the input   files.  */static booleanelf32_hppa_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;  struct elf32_hppa_link_hash_table *hplink;  asection *sreloc;  asection *stubreloc;  if (info->relocateable)    return true;  hplink = hppa_link_hash_table (info);  dynobj = hplink->root.dynobj;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  sreloc = NULL;  stubreloc = NULL;  rel_end = relocs + sec->reloc_count;  for (rel = relocs; rel < rel_end; rel++)    {      enum {	NEED_GOT = 1,	NEED_PLT = 2,	NEED_DYNREL = 4,#if LONG_BRANCH_PIC_IN_SHLIB	NEED_STUBREL = 0,  /* We won't be needing them in this case.  */#else	NEED_STUBREL = 8,#endif	PLT_PLABEL = 16      };      unsigned int r_symndx, r_type;      struct elf32_hppa_link_hash_entry *h;

⌨️ 快捷键说明

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