elfxx-ia64.c

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

C
2,106
字号
     bfd *abfd ATTRIBUTE_UNUSED;     bfd_reloc_code_real_type bfd_code;{  unsigned int rtype;  switch (bfd_code)    {    case BFD_RELOC_NONE:		rtype = R_IA64_NONE; break;    case BFD_RELOC_IA64_IMM14:		rtype = R_IA64_IMM14; break;    case BFD_RELOC_IA64_IMM22:		rtype = R_IA64_IMM22; break;    case BFD_RELOC_IA64_IMM64:		rtype = R_IA64_IMM64; break;    case BFD_RELOC_IA64_DIR32MSB:	rtype = R_IA64_DIR32MSB; break;    case BFD_RELOC_IA64_DIR32LSB:	rtype = R_IA64_DIR32LSB; break;    case BFD_RELOC_IA64_DIR64MSB:	rtype = R_IA64_DIR64MSB; break;    case BFD_RELOC_IA64_DIR64LSB:	rtype = R_IA64_DIR64LSB; break;    case BFD_RELOC_IA64_GPREL22:	rtype = R_IA64_GPREL22; break;    case BFD_RELOC_IA64_GPREL64I:	rtype = R_IA64_GPREL64I; break;    case BFD_RELOC_IA64_GPREL32MSB:	rtype = R_IA64_GPREL32MSB; break;    case BFD_RELOC_IA64_GPREL32LSB:	rtype = R_IA64_GPREL32LSB; break;    case BFD_RELOC_IA64_GPREL64MSB:	rtype = R_IA64_GPREL64MSB; break;    case BFD_RELOC_IA64_GPREL64LSB:	rtype = R_IA64_GPREL64LSB; break;    case BFD_RELOC_IA64_LTOFF22:	rtype = R_IA64_LTOFF22; break;    case BFD_RELOC_IA64_LTOFF64I:	rtype = R_IA64_LTOFF64I; break;    case BFD_RELOC_IA64_PLTOFF22:	rtype = R_IA64_PLTOFF22; break;    case BFD_RELOC_IA64_PLTOFF64I:	rtype = R_IA64_PLTOFF64I; break;    case BFD_RELOC_IA64_PLTOFF64MSB:	rtype = R_IA64_PLTOFF64MSB; break;    case BFD_RELOC_IA64_PLTOFF64LSB:	rtype = R_IA64_PLTOFF64LSB; break;    case BFD_RELOC_IA64_FPTR64I:	rtype = R_IA64_FPTR64I; break;    case BFD_RELOC_IA64_FPTR32MSB:	rtype = R_IA64_FPTR32MSB; break;    case BFD_RELOC_IA64_FPTR32LSB:	rtype = R_IA64_FPTR32LSB; break;    case BFD_RELOC_IA64_FPTR64MSB:	rtype = R_IA64_FPTR64MSB; break;    case BFD_RELOC_IA64_FPTR64LSB:	rtype = R_IA64_FPTR64LSB; break;    case BFD_RELOC_IA64_PCREL21B:	rtype = R_IA64_PCREL21B; break;    case BFD_RELOC_IA64_PCREL21BI:	rtype = R_IA64_PCREL21BI; break;    case BFD_RELOC_IA64_PCREL21M:	rtype = R_IA64_PCREL21M; break;    case BFD_RELOC_IA64_PCREL21F:	rtype = R_IA64_PCREL21F; break;    case BFD_RELOC_IA64_PCREL22:	rtype = R_IA64_PCREL22; break;    case BFD_RELOC_IA64_PCREL60B:	rtype = R_IA64_PCREL60B; break;    case BFD_RELOC_IA64_PCREL64I:	rtype = R_IA64_PCREL64I; break;    case BFD_RELOC_IA64_PCREL32MSB:	rtype = R_IA64_PCREL32MSB; break;    case BFD_RELOC_IA64_PCREL32LSB:	rtype = R_IA64_PCREL32LSB; break;    case BFD_RELOC_IA64_PCREL64MSB:	rtype = R_IA64_PCREL64MSB; break;    case BFD_RELOC_IA64_PCREL64LSB:	rtype = R_IA64_PCREL64LSB; break;    case BFD_RELOC_IA64_LTOFF_FPTR22:	rtype = R_IA64_LTOFF_FPTR22; break;    case BFD_RELOC_IA64_LTOFF_FPTR64I:	rtype = R_IA64_LTOFF_FPTR64I; break;    case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;    case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;    case BFD_RELOC_IA64_SEGREL32MSB:	rtype = R_IA64_SEGREL32MSB; break;    case BFD_RELOC_IA64_SEGREL32LSB:	rtype = R_IA64_SEGREL32LSB; break;    case BFD_RELOC_IA64_SEGREL64MSB:	rtype = R_IA64_SEGREL64MSB; break;    case BFD_RELOC_IA64_SEGREL64LSB:	rtype = R_IA64_SEGREL64LSB; break;    case BFD_RELOC_IA64_SECREL32MSB:	rtype = R_IA64_SECREL32MSB; break;    case BFD_RELOC_IA64_SECREL32LSB:	rtype = R_IA64_SECREL32LSB; break;    case BFD_RELOC_IA64_SECREL64MSB:	rtype = R_IA64_SECREL64MSB; break;    case BFD_RELOC_IA64_SECREL64LSB:	rtype = R_IA64_SECREL64LSB; break;    case BFD_RELOC_IA64_REL32MSB:	rtype = R_IA64_REL32MSB; break;    case BFD_RELOC_IA64_REL32LSB:	rtype = R_IA64_REL32LSB; break;    case BFD_RELOC_IA64_REL64MSB:	rtype = R_IA64_REL64MSB; break;    case BFD_RELOC_IA64_REL64LSB:	rtype = R_IA64_REL64LSB; break;    case BFD_RELOC_IA64_LTV32MSB:	rtype = R_IA64_LTV32MSB; break;    case BFD_RELOC_IA64_LTV32LSB:	rtype = R_IA64_LTV32LSB; break;    case BFD_RELOC_IA64_LTV64MSB:	rtype = R_IA64_LTV64MSB; break;    case BFD_RELOC_IA64_LTV64LSB:	rtype = R_IA64_LTV64LSB; break;    case BFD_RELOC_IA64_IPLTMSB:	rtype = R_IA64_IPLTMSB; break;    case BFD_RELOC_IA64_IPLTLSB:	rtype = R_IA64_IPLTLSB; break;    case BFD_RELOC_IA64_COPY:		rtype = R_IA64_COPY; break;    case BFD_RELOC_IA64_LTOFF22X:	rtype = R_IA64_LTOFF22X; break;    case BFD_RELOC_IA64_LDXMOV:		rtype = R_IA64_LDXMOV; break;    case BFD_RELOC_IA64_TPREL22:	rtype = R_IA64_TPREL22; break;    case BFD_RELOC_IA64_TPREL64MSB:	rtype = R_IA64_TPREL64MSB; break;    case BFD_RELOC_IA64_TPREL64LSB:	rtype = R_IA64_TPREL64LSB; break;    case BFD_RELOC_IA64_LTOFF_TP22:	rtype = R_IA64_LTOFF_TP22; break;    default: return 0;    }  return lookup_howto (rtype);}/* Given a ELF reloc, return the matching HOWTO structure.  */static voidelfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *bfd_reloc;     ElfNN_Internal_Rela *elf_reloc;{  bfd_reloc->howto = lookup_howto (ELFNN_R_TYPE (elf_reloc->r_info));}#define PLT_HEADER_SIZE		(3 * 16)#define PLT_MIN_ENTRY_SIZE	(1 * 16)#define PLT_FULL_ENTRY_SIZE	(2 * 16)#define PLT_RESERVED_WORDS	3static const bfd_byte plt_header[PLT_HEADER_SIZE] ={  0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21,  /*   [MMI]       mov r2=r14;;       */  0xe0, 0x00, 0x08, 0x00, 0x48, 0x00,  /*               addl r14=0,r2      */  0x00, 0x00, 0x04, 0x00,              /*               nop.i 0x0;;        */  0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14,  /*   [MMI]       ld8 r16=[r14],8;;  */  0x10, 0x41, 0x38, 0x30, 0x28, 0x00,  /*               ld8 r17=[r14],8    */  0x00, 0x00, 0x04, 0x00,              /*               nop.i 0x0;;        */  0x11, 0x08, 0x00, 0x1c, 0x18, 0x10,  /*   [MIB]       ld8 r1=[r14]       */  0x60, 0x88, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r17         */  0x60, 0x00, 0x80, 0x00               /*               br.few b6;;        */};static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] ={  0x11, 0x78, 0x00, 0x00, 0x00, 0x24,  /*   [MIB]       mov r15=0          */  0x00, 0x00, 0x00, 0x02, 0x00, 0x00,  /*               nop.i 0x0          */  0x00, 0x00, 0x00, 0x40               /*               br.few 0 <PLT0>;;  */};static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] ={  0x0b, 0x78, 0x00, 0x02, 0x00, 0x24,  /*   [MMI]       addl r15=0,r1;;    */  0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0,  /*               ld8 r16=[r15],8    */  0x01, 0x08, 0x00, 0x84,              /*               mov r14=r1;;       */  0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,  /*   [MIB]       ld8 r1=[r15]       */  0x60, 0x80, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r16         */  0x60, 0x00, 0x80, 0x00               /*               br.few b6;;        */};#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"/* Select out of range branch fixup type.  Note that Itanium does   not support brl, and so it gets emulated by the kernel.  */#undef USE_BRLstatic const bfd_byte oor_brl[16] ={  0x05, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*               brl.sptk.few tgt;; */  0x00, 0x00, 0x00, 0xc0};static const bfd_byte oor_ip[48] ={  0x04, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,  /*               movl r15=0         */  0x01, 0x00, 0x00, 0x60,  0x03, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MII]        nop.m 0            */  0x00, 0x01, 0x00, 0x60, 0x00, 0x00,  /*               mov r16=ip;;       */  0xf2, 0x80, 0x00, 0x80,              /*               add r16=r15,r16;;  */  0x11, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MIB]        nop.m 0            */  0x60, 0x80, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r16         */  0x60, 0x00, 0x80, 0x00               /*               br b6;;            */};/* These functions do relaxation for IA-64 ELF.   This is primarily to support branches to targets out of range;   relaxation of R_IA64_LTOFF22X and R_IA64_LDXMOV not yet supported.  */static booleanelfNN_ia64_relax_section (abfd, sec, link_info, again)     bfd *abfd;     asection *sec;     struct bfd_link_info *link_info;     boolean *again;{  struct one_fixup    {      struct one_fixup *next;      asection *tsec;      bfd_vma toff;      bfd_vma trampoff;    };  Elf_Internal_Shdr *symtab_hdr;  Elf_Internal_Rela *internal_relocs;  Elf_Internal_Rela *free_relocs = NULL;  Elf_Internal_Rela *irel, *irelend;  bfd_byte *contents;  bfd_byte *free_contents = NULL;  ElfNN_External_Sym *extsyms;  ElfNN_External_Sym *free_extsyms = NULL;  struct elfNN_ia64_link_hash_table *ia64_info;  struct one_fixup *fixups = NULL;  boolean changed_contents = false;  boolean changed_relocs = false;  /* Assume we're not going to change any sizes, and we'll only need     one pass.  */  *again = false;  /* Nothing to do if there are no relocations.  */  if ((sec->flags & SEC_RELOC) == 0      || sec->reloc_count == 0)    return true;  /* If this is the first time we have been called for this section,     initialize the cooked size.  */  if (sec->_cooked_size == 0)    sec->_cooked_size = sec->_raw_size;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  /* Load the relocations for this section.  */  internal_relocs = (_bfd_elfNN_link_read_relocs		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,		      link_info->keep_memory));  if (internal_relocs == NULL)    goto error_return;  if (! link_info->keep_memory)    free_relocs = internal_relocs;  ia64_info = elfNN_ia64_hash_table (link_info);  irelend = internal_relocs + sec->reloc_count;  for (irel = internal_relocs; irel < irelend; irel++)    if (ELFNN_R_TYPE (irel->r_info) == (int) R_IA64_PCREL21B)      break;  /* No branch-type relocations.  */  if (irel == irelend)    {      if (free_relocs != NULL)	free (free_relocs);      return true;    }  /* Get the section contents.  */  if (elf_section_data (sec)->this_hdr.contents != NULL)    contents = elf_section_data (sec)->this_hdr.contents;  else    {      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);      if (contents == NULL)	goto error_return;      free_contents = contents;      if (! bfd_get_section_contents (abfd, sec, contents,				      (file_ptr) 0, sec->_raw_size))	goto error_return;    }  /* Read this BFD's symbols.  */  if (symtab_hdr->contents != NULL)    extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;  else    {      extsyms = (ElfNN_External_Sym *) bfd_malloc (symtab_hdr->sh_size);      if (extsyms == NULL)	goto error_return;      free_extsyms = extsyms;      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0	  || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)	      != symtab_hdr->sh_size))	goto error_return;    }  for (; irel < irelend; irel++)    {      bfd_vma symaddr, reladdr, trampoff, toff, roff;      Elf_Internal_Sym isym;      asection *tsec;      struct one_fixup *f;      if (ELFNN_R_TYPE (irel->r_info) != (int) R_IA64_PCREL21B)	continue;      /* Get the value of the symbol referred to by the reloc.  */      if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)	{	  /* A local symbol.  */	  bfd_elfNN_swap_symbol_in (abfd,				    extsyms + ELFNN_R_SYM (irel->r_info),				    &isym);	  if (isym.st_shndx == SHN_UNDEF)	    continue;	/* We can't do anthing with undefined symbols.  */	  else if (isym.st_shndx == SHN_ABS)	    tsec = bfd_abs_section_ptr;	  else if (isym.st_shndx == SHN_COMMON)	    tsec = bfd_com_section_ptr;	  else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)	    tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);	  else	    continue;	/* who knows.  */	  toff = isym.st_value;	}      else	{	  unsigned long indx;	  struct elf_link_hash_entry *h;          struct elfNN_ia64_dyn_sym_info *dyn_i;	  indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info;	  h = elf_sym_hashes (abfd)[indx];	  BFD_ASSERT (h != NULL);	  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;	  dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, false);	  /* For branches to dynamic symbols, we're interested instead	     in a branch to the PLT entry.  */	  if (dyn_i && dyn_i->want_plt2)	    {	      tsec = ia64_info->plt_sec;	      toff = dyn_i->plt2_offset;	    }	  else	    {	      /* We can't do anthing with undefined symbols.  */	      if (h->root.type == bfd_link_hash_undefined		  || h->root.type == bfd_link_hash_undefweak)		continue;	      tsec = h->root.u.def.section;	      toff = h->root.u.def.value;	    }	}      symaddr = (tsec->output_section->vma		 + tsec->output_offset		 + toff		 + irel->r_addend);      roff = irel->r_offset;      reladdr = (sec->output_section->vma		 + sec->output_offset		 + roff) & -4;      /* If the branch is in range, no need to do anything.  */      if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000	  && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)	continue;      /* If the branch and target are in the same section, you've	 got one honking big section and we can't help you.  You'll	 get an error message later.  */      if (tsec == sec)	continue;      /* Look for an existing fixup to this address.  */      for (f = fixups; f ; f = f->next)	if (f->tsec == tsec && f->toff == toff)	  break;      if (f == NULL)	{	  /* Two alternatives: If it's a branch to a PLT entry, we can	     make a copy of the FULL_PLT entry.  Otherwise, we'll have	     to use a `brl' insn to get where we're going.  */	  int size;	  if (tsec == ia64_info->plt_sec)	    size = sizeof (plt_full_entry);	  else	    {#ifdef USE_BRL	      size = sizeof (oor_brl);#else	      size = sizeof (oor_ip);#endif	    }	  /* Resize the current section to make room for the new branch.  */	  trampoff = (sec->_cooked_size + 15) & -16;	  contents = (bfd_byte *) bfd_realloc (contents, trampoff + size);	  if (contents == NULL)	    goto error_return;	  sec->_cooked_size = trampoff + size;	  if (tsec == ia64_info->plt_sec)	    {	      memcpy (contents + trampoff, plt_full_entry, size);	      /* Hijack the old relocation for use as the PLTOFF reloc.  */	      irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),					   R_IA64_PLTOFF22);	      irel->r_offset = trampoff;	    }	  else	    {#ifdef USE_BRL	      memcpy (contents + trampoff, oor_brl, size);	      irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),					   R_IA64_PCREL60B);	      irel->r_offset = trampoff + 2;#else	      memcpy (contents + trampoff, oor_ip, size);	      irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),					   R_IA64_PCREL64I);	      irel->r_addend -= 16;	      irel->r_offset = trampoff + 2;#endif	    }	  /* Record the fixup so we don't do it again this section.  */	  f = (struct one_fixup *) bfd_malloc (sizeof (*f));	  f->next = fixups;	  f->tsec = tsec;	  f->toff = toff;	  f->trampoff = trampoff;	  fixups = f;	}      else	{	  /* Nop out the reloc, since we're finalizing things here.  */	  irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);	}

⌨️ 快捷键说明

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