elf64-sparc.c

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

C
2,055
字号
  if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols,					  dynamic))    return false;  if (rel_hdr2      && !sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols,					     dynamic))    return false;  return true;}/* Canonicalize the dynamic relocation entries.  Note that we return   the dynamic relocations as a single block, although they are   actually associated with particular sections; the interface, which   was designed for SunOS style shared libraries, expects that there   is only one set of dynamic relocs.  Any section that was actually   installed in the BFD, and has type SHT_REL or SHT_RELA, and uses   the dynamic symbol table, is considered to be a dynamic reloc   section.  */static longsparc64_elf_canonicalize_dynamic_reloc (abfd, storage, syms)     bfd *abfd;     arelent **storage;     asymbol **syms;{  asection *s;  long ret;  if (elf_dynsymtab (abfd) == 0)    {      bfd_set_error (bfd_error_invalid_operation);      return -1;    }  ret = 0;  for (s = abfd->sections; s != NULL; s = s->next)    {      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)	  && (elf_section_data (s)->this_hdr.sh_type == SHT_RELA))	{	  arelent *p;	  long count, i;	  if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, true))	    return -1;	  count = s->reloc_count;	  p = s->relocation;	  for (i = 0; i < count; i++)	    *storage++ = p++;	  ret += count;	}    }  *storage = NULL;  return ret;}/* Write out the relocs.  */static voidsparc64_elf_write_relocs (abfd, sec, data)     bfd *abfd;     asection *sec;     PTR data;{  boolean *failedp = (boolean *) data;  Elf_Internal_Shdr *rela_hdr;  Elf64_External_Rela *outbound_relocas, *src_rela;  unsigned int idx, count;  asymbol *last_sym = 0;  int last_sym_idx = 0;  /* If we have already failed, don't do anything.  */  if (*failedp)    return;  if ((sec->flags & SEC_RELOC) == 0)    return;  /* The linker backend writes the relocs out itself, and sets the     reloc_count field to zero to inhibit writing them here.  Also,     sometimes the SEC_RELOC flag gets set even when there aren't any     relocs.  */  if (sec->reloc_count == 0)    return;  /* We can combine two relocs that refer to the same address     into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the     latter is R_SPARC_13 with no associated symbol.  */  count = 0;  for (idx = 0; idx < sec->reloc_count; idx++)    {      bfd_vma addr;      ++count;      addr = sec->orelocation[idx]->address;      if (sec->orelocation[idx]->howto->type == R_SPARC_LO10	  && idx < sec->reloc_count - 1)	{	  arelent *r = sec->orelocation[idx + 1];	  if (r->howto->type == R_SPARC_13	      && r->address == addr	      && bfd_is_abs_section ((*r->sym_ptr_ptr)->section)	      && (*r->sym_ptr_ptr)->value == 0)	    ++idx;	}    }  rela_hdr = &elf_section_data (sec)->rel_hdr;  rela_hdr->sh_size = rela_hdr->sh_entsize * count;  rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);  if (rela_hdr->contents == NULL)    {      *failedp = true;      return;    }  /* Figure out whether the relocations are RELA or REL relocations.  */  if (rela_hdr->sh_type != SHT_RELA)    abort ();  /* orelocation has the data, reloc_count has the count...  */  outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents;  src_rela = outbound_relocas;  for (idx = 0; idx < sec->reloc_count; idx++)    {      Elf_Internal_Rela dst_rela;      arelent *ptr;      asymbol *sym;      int n;      ptr = sec->orelocation[idx];      /* The address of an ELF reloc is section relative for an object	 file, and absolute for an executable file or shared library.	 The address of a BFD reloc is always section relative.  */      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)	dst_rela.r_offset = ptr->address;      else	dst_rela.r_offset = ptr->address + sec->vma;      sym = *ptr->sym_ptr_ptr;      if (sym == last_sym)	n = last_sym_idx;      else if (bfd_is_abs_section (sym->section) && sym->value == 0)	n = STN_UNDEF;      else	{	  last_sym = sym;	  n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);	  if (n < 0)	    {	      *failedp = true;	      return;	    }	  last_sym_idx = n;	}      if ((*ptr->sym_ptr_ptr)->the_bfd != NULL	  && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec	  && ! _bfd_elf_validate_reloc (abfd, ptr))	{	  *failedp = true;	  return;	}      if (ptr->howto->type == R_SPARC_LO10	  && idx < sec->reloc_count - 1)	{	  arelent *r = sec->orelocation[idx + 1];	  if (r->howto->type == R_SPARC_13	      && r->address == ptr->address	      && bfd_is_abs_section ((*r->sym_ptr_ptr)->section)	      && (*r->sym_ptr_ptr)->value == 0)	    {	      idx++;	      dst_rela.r_info		= ELF64_R_INFO (n, ELF64_R_TYPE_INFO (r->addend,						      R_SPARC_OLO10));	    }	  else	    dst_rela.r_info = ELF64_R_INFO (n, R_SPARC_LO10);	}      else	dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type);      dst_rela.r_addend = ptr->addend;      bfd_elf64_swap_reloca_out (abfd, &dst_rela, src_rela);      ++src_rela;    }}/* Sparc64 ELF linker hash table.  */struct sparc64_elf_app_reg{  unsigned char bind;  unsigned short shndx;  bfd *abfd;  char *name;};struct sparc64_elf_link_hash_table{  struct elf_link_hash_table root;  struct sparc64_elf_app_reg app_regs [4];};/* Get the Sparc64 ELF linker hash table from a link_info structure.  */#define sparc64_elf_hash_table(p) \  ((struct sparc64_elf_link_hash_table *) ((p)->hash))/* Create a Sparc64 ELF linker hash table.  */static struct bfd_link_hash_table *sparc64_elf_bfd_link_hash_table_create (abfd)     bfd *abfd;{  struct sparc64_elf_link_hash_table *ret;  ret = ((struct sparc64_elf_link_hash_table *)	 bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));  if (ret == (struct sparc64_elf_link_hash_table *) NULL)    return NULL;  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,				       _bfd_elf_link_hash_newfunc))    {      bfd_release (abfd, ret);      return NULL;    }  return &ret->root.root;}/* Utility for performing the standard initial work of an instruction   relocation.   *PRELOCATION will contain the relocated item.   *PINSN will contain the instruction from the input stream.   If the result is `bfd_reloc_other' the caller can continue with   performing the relocation.  Otherwise it must stop and return the   value to its caller.  */static bfd_reloc_status_typeinit_insn_reloc (abfd,		 reloc_entry,		 symbol,		 data,		 input_section,		 output_bfd,		 prelocation,		 pinsn)     bfd *abfd;     arelent *reloc_entry;     asymbol *symbol;     PTR data;     asection *input_section;     bfd *output_bfd;     bfd_vma *prelocation;     bfd_vma *pinsn;{  bfd_vma relocation;  reloc_howto_type *howto = reloc_entry->howto;  if (output_bfd != (bfd *) NULL      && (symbol->flags & BSF_SECTION_SYM) == 0      && (! howto->partial_inplace	  || reloc_entry->addend == 0))    {      reloc_entry->address += input_section->output_offset;      return bfd_reloc_ok;    }  /* This works because partial_inplace == false.  */  if (output_bfd != NULL)    return bfd_reloc_continue;  if (reloc_entry->address > input_section->_cooked_size)    return bfd_reloc_outofrange;  relocation = (symbol->value		+ symbol->section->output_section->vma		+ symbol->section->output_offset);  relocation += reloc_entry->addend;  if (howto->pc_relative)    {      relocation -= (input_section->output_section->vma		     + input_section->output_offset);      relocation -= reloc_entry->address;    }  *prelocation = relocation;  *pinsn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);  return bfd_reloc_other;}/* For unsupported relocs.  */static bfd_reloc_status_typesparc_elf_notsup_reloc (abfd,			reloc_entry,			symbol,			data,			input_section,			output_bfd,			error_message)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *reloc_entry ATTRIBUTE_UNUSED;     asymbol *symbol ATTRIBUTE_UNUSED;     PTR data ATTRIBUTE_UNUSED;     asection *input_section ATTRIBUTE_UNUSED;     bfd *output_bfd ATTRIBUTE_UNUSED;     char **error_message ATTRIBUTE_UNUSED;{  return bfd_reloc_notsupported;}/* Handle the WDISP16 reloc.  */static bfd_reloc_status_typesparc_elf_wdisp16_reloc (abfd, reloc_entry, symbol, data, input_section,			 output_bfd, error_message)     bfd *abfd;     arelent *reloc_entry;     asymbol *symbol;     PTR data;     asection *input_section;     bfd *output_bfd;     char **error_message ATTRIBUTE_UNUSED;{  bfd_vma relocation;  bfd_vma insn;  bfd_reloc_status_type status;  status = init_insn_reloc (abfd, reloc_entry, symbol, data,			    input_section, output_bfd, &relocation, &insn);  if (status != bfd_reloc_other)    return status;  insn = (insn & ~0x303fff) | ((((relocation >> 2) & 0xc000) << 6)			       | ((relocation >> 2) & 0x3fff));  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);  if ((bfd_signed_vma) relocation < - 0x40000      || (bfd_signed_vma) relocation > 0x3ffff)    return bfd_reloc_overflow;  else    return bfd_reloc_ok;}/* Handle the HIX22 reloc.  */static bfd_reloc_status_typesparc_elf_hix22_reloc (abfd,		       reloc_entry,		       symbol,		       data,		       input_section,		       output_bfd,		       error_message)     bfd *abfd;     arelent *reloc_entry;     asymbol *symbol;     PTR data;     asection *input_section;     bfd *output_bfd;     char **error_message ATTRIBUTE_UNUSED;{  bfd_vma relocation;  bfd_vma insn;  bfd_reloc_status_type status;  status = init_insn_reloc (abfd, reloc_entry, symbol, data,			    input_section, output_bfd, &relocation, &insn);  if (status != bfd_reloc_other)    return status;  relocation ^= MINUS_ONE;  insn = (insn & ~0x3fffff) | ((relocation >> 10) & 0x3fffff);  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);  if ((relocation & ~ (bfd_vma) 0xffffffff) != 0)    return bfd_reloc_overflow;  else    return bfd_reloc_ok;}/* Handle the LOX10 reloc.  */static bfd_reloc_status_typesparc_elf_lox10_reloc (abfd,		       reloc_entry,		       symbol,		       data,		       input_section,		       output_bfd,		       error_message)     bfd *abfd;     arelent *reloc_entry;     asymbol *symbol;

⌨️ 快捷键说明

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