elf64-sparc.c

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

C
2,055
字号
}/* Set the sizes of the dynamic sections.  */static booleansparc64_elf_size_dynamic_sections (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  bfd *dynobj;  asection *s;  boolean reltext;  boolean relplt;  dynobj = elf_hash_table (info)->dynobj;  BFD_ASSERT (dynobj != NULL);  if (elf_hash_table (info)->dynamic_sections_created)    {      /* Set the contents of the .interp section to the interpreter.  */      if (! info->shared)	{	  s = bfd_get_section_by_name (dynobj, ".interp");	  BFD_ASSERT (s != NULL);	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;	}    }  else    {      /* We may have created entries in the .rela.got section.         However, if we are not creating the dynamic sections, we will         not actually use these entries.  Reset the size of .rela.got,         which will cause it to get stripped from the output file         below.  */      s = bfd_get_section_by_name (dynobj, ".rela.got");      if (s != NULL)	s->_raw_size = 0;    }  /* The check_relocs and adjust_dynamic_symbol entry points have     determined the sizes of the various dynamic sections.  Allocate     memory for them.  */  reltext = false;  relplt = false;  for (s = dynobj->sections; s != NULL; s = s->next)    {      const char *name;      boolean strip;      if ((s->flags & SEC_LINKER_CREATED) == 0)	continue;      /* It's OK to base decisions on the section name, because none	 of the dynobj section names depend upon the input files.  */      name = bfd_get_section_name (dynobj, s);      strip = false;      if (strncmp (name, ".rela", 5) == 0)	{	  if (s->_raw_size == 0)	    {	      /* If we don't need this section, strip it from the		 output file.  This is to handle .rela.bss and		 .rel.plt.  We must create it in		 create_dynamic_sections, because it must be created		 before the linker maps input sections to output		 sections.  The linker does that before		 adjust_dynamic_symbol is called, and it is that		 function which decides whether anything needs to go		 into these sections.  */	      strip = true;	    }	  else	    {	      const char *outname;	      asection *target;	      /* If this relocation section applies to a read only		 section, then we probably need a DT_TEXTREL entry.  */	      outname = bfd_get_section_name (output_bfd,					      s->output_section);	      target = bfd_get_section_by_name (output_bfd, outname + 5);	      if (target != NULL		  && (target->flags & SEC_READONLY) != 0)		reltext = true;	      if (strcmp (name, ".rela.plt") == 0)		relplt = true;	      /* We use the reloc_count field as a counter if we need		 to copy relocs into the output file.  */	      s->reloc_count = 0;	    }	}      else if (strcmp (name, ".plt") != 0	       && strncmp (name, ".got", 4) != 0)	{	  /* It's not one of our sections, so don't allocate space.  */	  continue;	}      if (strip)	{	  _bfd_strip_section_from_output (info, s);	  continue;	}      /* Allocate memory for the section contents.  Zero the memory	 for the benefit of .rela.plt, which has 4 unused entries	 at the beginning, and we don't want garbage.  */      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);      if (s->contents == NULL && s->_raw_size != 0)	return false;    }  if (elf_hash_table (info)->dynamic_sections_created)    {      /* Add some entries to the .dynamic section.  We fill in the	 values later, in sparc64_elf_finish_dynamic_sections, but we	 must add the entries now so that we get the correct size for	 the .dynamic section.  The DT_DEBUG entry is filled in by the	 dynamic linker and used by the debugger.  */      int reg;      struct sparc64_elf_app_reg * app_regs;      struct bfd_strtab_hash *dynstr;      struct elf_link_hash_table *eht = elf_hash_table (info);      if (! info->shared)	{	  if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))	    return false;	}      if (relplt)	{	  if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0)	      || ! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)	      || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)	      || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))	    return false;	}      if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)	  || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)	  || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,					    sizeof (Elf64_External_Rela)))	return false;      if (reltext)	{	  if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))	    return false;	  info->flags |= DF_TEXTREL;	}      /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER	 entries if needed.  */      app_regs = sparc64_elf_hash_table (info)->app_regs;      dynstr = eht->dynstr;      for (reg = 0; reg < 4; reg++)	if (app_regs [reg].name != NULL)	  {	    struct elf_link_local_dynamic_entry *entry, *e;	    if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0))	      return false;	    entry = (struct elf_link_local_dynamic_entry *)	      bfd_hash_allocate (&info->hash->table, sizeof (*entry));	    if (entry == NULL)	      return false;	    /* We cheat here a little bit: the symbol will not be local, so we	       put it at the end of the dynlocal linked list.  We will fix it	       later on, as we have to fix other fields anyway.  */	    entry->isym.st_value = reg < 2 ? reg + 2 : reg + 4;	    entry->isym.st_size = 0;	    if (*app_regs [reg].name != '\0')	      entry->isym.st_name		= _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false);	    else	      entry->isym.st_name = 0;	    entry->isym.st_other = 0;	    entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,					       STT_REGISTER);	    entry->isym.st_shndx = app_regs [reg].shndx;	    entry->next = NULL;	    entry->input_bfd = output_bfd;	    entry->input_indx = -1;	    if (eht->dynlocal == NULL)	      eht->dynlocal = entry;	    else	      {		for (e = eht->dynlocal; e->next; e = e->next)		  ;		e->next = entry;	      }	    eht->dynsymcount++;	  }    }  return true;}#define SET_SEC_DO_RELAX(section) do { elf_section_data(section)->tdata = (void *)1; } while (0)#define SEC_DO_RELAX(section) (elf_section_data(section)->tdata == (void *)1)static booleansparc64_elf_relax_section (abfd, section, link_info, again)     bfd *abfd ATTRIBUTE_UNUSED;     asection *section ATTRIBUTE_UNUSED;     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;     boolean *again;{  *again = false;  SET_SEC_DO_RELAX (section);  return true;}/* Relocate a SPARC64 ELF section.  */static booleansparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,			      contents, relocs, local_syms, local_sections)     bfd *output_bfd;     struct bfd_link_info *info;     bfd *input_bfd;     asection *input_section;     bfd_byte *contents;     Elf_Internal_Rela *relocs;     Elf_Internal_Sym *local_syms;     asection **local_sections;{  bfd *dynobj;  Elf_Internal_Shdr *symtab_hdr;  struct elf_link_hash_entry **sym_hashes;  bfd_vma *local_got_offsets;  bfd_vma got_base;  asection *sgot;  asection *splt;  asection *sreloc;  Elf_Internal_Rela *rel;  Elf_Internal_Rela *relend;  dynobj = elf_hash_table (info)->dynobj;  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (input_bfd);  local_got_offsets = elf_local_got_offsets (input_bfd);  if (elf_hash_table(info)->hgot == NULL)    got_base = 0;  else    got_base = elf_hash_table (info)->hgot->root.u.def.value;  sgot = splt = sreloc = NULL;  rel = relocs;  relend = relocs + NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr);  for (; rel < relend; rel++)    {      int r_type;      reloc_howto_type *howto;      unsigned long r_symndx;      struct elf_link_hash_entry *h;      Elf_Internal_Sym *sym;      asection *sec;      bfd_vma relocation;      bfd_reloc_status_type r;      r_type = ELF64_R_TYPE_ID (rel->r_info);      if (r_type < 0 || r_type >= (int) R_SPARC_max_std)	{	  bfd_set_error (bfd_error_bad_value);	  return false;	}      howto = sparc64_elf_howto_table + r_type;      r_symndx = ELF64_R_SYM (rel->r_info);      if (info->relocateable)	{	  /* This is a relocateable link.  We don't have to change	     anything, unless the reloc is against a section symbol,	     in which case we have to adjust according to where the	     section symbol winds up in the output section.  */	  if (r_symndx < symtab_hdr->sh_info)	    {	      sym = local_syms + r_symndx;	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)		{		  sec = local_sections[r_symndx];		  rel->r_addend += sec->output_offset + sym->st_value;		}	    }	  continue;	}      /* This is a final link.  */      h = NULL;      sym = NULL;      sec = NULL;      if (r_symndx < symtab_hdr->sh_info)	{	  sym = local_syms + r_symndx;	  sec = local_sections[r_symndx];	  relocation = (sec->output_section->vma			+ sec->output_offset			+ sym->st_value);	}      else	{	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];	  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->root.type == bfd_link_hash_defined	      || h->root.type == bfd_link_hash_defweak)	    {	      boolean skip_it = false;	      sec = h->root.u.def.section;	      switch (r_type)		{		case R_SPARC_WPLT30:		case R_SPARC_PLT32:		case R_SPARC_HIPLT22:		case R_SPARC_LOPLT10:		case R_SPARC_PCPLT32:		case R_SPARC_PCPLT22:		case R_SPARC_PCPLT10:		case R_SPARC_PLT64:		  if (h->plt.offset != (bfd_vma) -1)		    skip_it = true;		  break;		case R_SPARC_GOT10:		case R_SPARC_GOT13:		case R_SPARC_GOT22:		  if (elf_hash_table(info)->dynamic_sections_created		      && (!info->shared			  || (!info->symbolic && h->dynindx != -1)			  || !(h->elf_link_hash_flags			       & ELF_LINK_HASH_DEF_REGULAR)))		    skip_it = true;		  break;		case R_SPARC_PC10:		case R_SPARC_PC22:		case R_SPARC_PC_HH22:		case R_SPARC_PC_HM10:		case R_SPARC_PC_LM22:		  if (!strcmp(h->root.root.string, "_GLOBAL_OFFSET_TABLE_"))		    break;		  /* FALLTHRU */		case R_SPARC_8:		case R_SPARC_16:		case R_SPARC_32:		case R_SPARC_DISP8:		case R_SPARC_DISP16:		case R_SPARC_DISP32:		case R_SPARC_WDISP30:		case R_SPARC_WDISP22:		case R_SPARC_HI22:		case R_SPARC_22:		case R_SPARC_13:		case R_SPARC_LO10:		case R_SPARC_UA32:		case R_SPARC_10:		case R_SPARC_11:		case R_SPARC_64:		case R_SPARC_OLO10:		case R_SPARC_HH22:		case R_SPARC_HM10:		case R_SPARC_LM22:		case R_SPARC_WDISP19:		case R_SPARC_WDISP16:		case R_SPARC_7:		case R_SPARC_5:		case R_SPARC_6:		case R_SPARC_DISP64:		case R_SPARC_HIX22:		case R_SPARC_LOX10:		case R_SPARC_H44:		case R_SPARC_M44:		case R_SPARC_L44:		case R_SPARC_UA64:		case R_SPARC_UA16:		  if (info->shared		      && ((!info->symbolic && h->dynindx != -1)			  || !(h->elf_link_hash_flags			       & ELF_LINK_HASH_DEF_REGULAR)))		    skip_it = true;		  break;		}	      if (skip_it)		{		  /* In these cases, we don't need the relocation                     value.  We check specially because in some                     obscure cases sec->output_section will be NULL.  */		  relocation = 0;		}	      else		{

⌨️ 快捷键说明

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