elfxx-ia64.c

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

C
2,106
字号
      /* Fix up the existing branch to hit the trampoline.  Hope like	 hell this doesn't overflow too.  */      if (elfNN_ia64_install_value (abfd, contents + roff,				    f->trampoff - (roff & -4),				    R_IA64_PCREL21B) != bfd_reloc_ok)	goto error_return;      changed_contents = true;      changed_relocs = true;    }  /* Clean up and go home.  */  while (fixups)    {      struct one_fixup *f = fixups;      fixups = fixups->next;      free (f);    }  if (changed_relocs)    elf_section_data (sec)->relocs = internal_relocs;  else if (free_relocs != NULL)    free (free_relocs);  if (changed_contents)    elf_section_data (sec)->this_hdr.contents = contents;  else if (free_contents != NULL)    {      if (! link_info->keep_memory)	free (free_contents);      else	{	  /* Cache the section contents for elf_link_input_bfd.  */	  elf_section_data (sec)->this_hdr.contents = contents;	}    }  if (free_extsyms != NULL)    {      if (! link_info->keep_memory)	free (free_extsyms);      else	{	  /* Cache the symbols for elf_link_input_bfd.  */	  symtab_hdr->contents = extsyms;	}    }  *again = changed_contents || changed_relocs;  return true; error_return:  if (free_relocs != NULL)    free (free_relocs);  if (free_contents != NULL)    free (free_contents);  if (free_extsyms != NULL)    free (free_extsyms);  return false;}/* Return true if NAME is an unwind table section name.  */static inline booleanis_unwind_section_name (name)	const char *name;{  size_t len1, len2, len3;  len1 = sizeof (ELF_STRING_ia64_unwind) - 1;  len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;  len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;  return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0	   && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)	  || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);}/* Handle an IA-64 specific section when reading an object file.  This   is called when elfcode.h finds a section with an unknown type.  */static booleanelfNN_ia64_section_from_shdr (abfd, hdr, name)     bfd *abfd;     ElfNN_Internal_Shdr *hdr;     char *name;{  asection *newsect;  /* There ought to be a place to keep ELF backend specific flags, but     at the moment there isn't one.  We just keep track of the     sections by their name, instead.  Fortunately, the ABI gives     suggested names for all the MIPS specific sections, so we will     probably get away with this.  */  switch (hdr->sh_type)    {    case SHT_IA_64_UNWIND:      break;    case SHT_IA_64_EXT:      if (strcmp (name, ELF_STRING_ia64_archext) != 0)	return false;      break;    default:      return false;    }  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))    return false;  newsect = hdr->bfd_section;  return true;}/* Convert IA-64 specific section flags to bfd internal section flags.  *//* ??? There is no bfd internal flag equivalent to the SHF_IA_64_NORECOV   flag.  */static booleanelfNN_ia64_section_flags (flags, hdr)     flagword *flags;     ElfNN_Internal_Shdr *hdr;{  if (hdr->sh_flags & SHF_IA_64_SHORT)    *flags |= SEC_SMALL_DATA;  return true;}/* Set the correct type for an IA-64 ELF section.  We do this by the   section name, which is a hack, but ought to work.  */static booleanelfNN_ia64_fake_sections (abfd, hdr, sec)     bfd *abfd ATTRIBUTE_UNUSED;     ElfNN_Internal_Shdr *hdr;     asection *sec;{  register const char *name;  name = bfd_get_section_name (abfd, sec);  if (is_unwind_section_name (name))    {      /* We don't have the sections numbered at this point, so sh_info	 is set later, in elfNN_ia64_final_write_processing.  */      hdr->sh_type = SHT_IA_64_UNWIND;      hdr->sh_flags |= SHF_LINK_ORDER;    }  else if (strcmp (name, ELF_STRING_ia64_archext) == 0)    hdr->sh_type = SHT_IA_64_EXT;  else if (strcmp (name, ".reloc") == 0)    /*     * This is an ugly, but unfortunately necessary hack that is     * needed when producing EFI binaries on IA-64. It tells     * elf.c:elf_fake_sections() not to consider ".reloc" as a section     * containing ELF relocation info.  We need this hack in order to     * be able to generate ELF binaries that can be translated into     * EFI applications (which are essentially COFF objects).  Those     * files contain a COFF ".reloc" section inside an ELFNN object,     * which would normally cause BFD to segfault because it would     * attempt to interpret this section as containing relocation     * entries for section "oc".  With this hack enabled, ".reloc"     * will be treated as a normal data section, which will avoid the     * segfault.  However, you won't be able to create an ELFNN binary     * with a section named "oc" that needs relocations, but that's     * the kind of ugly side-effects you get when detecting section     * types based on their names...  In practice, this limitation is     * unlikely to bite.     */    hdr->sh_type = SHT_PROGBITS;  if (sec->flags & SEC_SMALL_DATA)    hdr->sh_flags |= SHF_IA_64_SHORT;  return true;}/* The final processing done just before writing out an IA-64 ELF   object file.  */static voidelfNN_ia64_final_write_processing (abfd, linker)     bfd *abfd;     boolean linker ATTRIBUTE_UNUSED;{  Elf_Internal_Shdr *hdr;  const char *sname;  asection *text_sect, *s;  size_t len;  for (s = abfd->sections; s; s = s->next)    {      hdr = &elf_section_data (s)->this_hdr;      switch (hdr->sh_type)	{	case SHT_IA_64_UNWIND:	  /* See comments in gas/config/tc-ia64.c:dot_endp on why we	     have to do this.  */	  sname = bfd_get_section_name (abfd, s);	  len = sizeof (ELF_STRING_ia64_unwind) - 1;	  if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)	    {	      sname += len;	      if (sname[0] == '\0')		/* .IA_64.unwind -> .text */		text_sect = bfd_get_section_by_name (abfd, ".text");	      else		/* .IA_64.unwindFOO -> FOO */		text_sect = bfd_get_section_by_name (abfd, sname);	    }	  else if (sname		   && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,		       strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)	    {	      /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */	      size_t len2 = sizeof (".gnu.linkonce.t.") - 1;	      char *once_name = alloca (len2 + strlen (sname) - len + 1);	      memcpy (once_name, ".gnu.linkonce.t.", len2);	      strcpy (once_name + len2, sname + len);	      text_sect = bfd_get_section_by_name (abfd, once_name);	    }	  else	    /* last resort: fall back on .text */	    text_sect = bfd_get_section_by_name (abfd, ".text");	  if (text_sect)	    {	      /* The IA-64 processor-specific ABI requires setting		 sh_link to the unwind section, whereas HP-UX requires		 sh_info to do so.  For maximum compatibility, we'll		 set both for now... */	      hdr->sh_link = elf_section_data (text_sect)->this_idx;	      hdr->sh_info = elf_section_data (text_sect)->this_idx;	    }	  break;	}    }}/* Hook called by the linker routine which adds symbols from an object   file.  We use it to put .comm items in .sbss, and not .bss.  */static booleanelfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)     bfd *abfd;     struct bfd_link_info *info;     const Elf_Internal_Sym *sym;     const char **namep ATTRIBUTE_UNUSED;     flagword *flagsp ATTRIBUTE_UNUSED;     asection **secp;     bfd_vma *valp;{  if (sym->st_shndx == SHN_COMMON      && !info->relocateable      && sym->st_size <= (unsigned) bfd_get_gp_size (abfd))    {      /* Common symbols less than or equal to -G nn bytes are	 automatically put into .sbss.  */      asection *scomm = bfd_get_section_by_name (abfd, ".scommon");      if (scomm == NULL)	{	  scomm = bfd_make_section (abfd, ".scommon");	  if (scomm == NULL	      || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC						       | SEC_IS_COMMON						       | SEC_LINKER_CREATED)))	    return false;	}      *secp = scomm;      *valp = sym->st_size;    }  return true;}/* Return the number of additional phdrs we will need.  */static intelfNN_ia64_additional_program_headers (abfd)     bfd *abfd;{  asection *s;  int ret = 0;  /* See if we need a PT_IA_64_ARCHEXT segment.  */  s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);  if (s && (s->flags & SEC_LOAD))    ++ret;  /* Count how many PT_IA_64_UNWIND segments we need.  */  for (s = abfd->sections; s; s = s->next)    if (is_unwind_section_name(s->name) && (s->flags & SEC_LOAD))      ++ret;  return ret;}static booleanelfNN_ia64_modify_segment_map (abfd)     bfd *abfd;{  struct elf_segment_map *m, **pm;  Elf_Internal_Shdr *hdr;  asection *s;  /* If we need a PT_IA_64_ARCHEXT segment, it must come before     all PT_LOAD segments.  */  s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_archext);  if (s && (s->flags & SEC_LOAD))    {      for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)	if (m->p_type == PT_IA_64_ARCHEXT)	  break;      if (m == NULL)	{	  m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);	  if (m == NULL)	    return false;	  m->p_type = PT_IA_64_ARCHEXT;	  m->count = 1;	  m->sections[0] = s;	  /* We want to put it after the PHDR and INTERP segments.  */	  pm = &elf_tdata (abfd)->segment_map;	  while (*pm != NULL		 && ((*pm)->p_type == PT_PHDR		     || (*pm)->p_type == PT_INTERP))	    pm = &(*pm)->next;	  m->next = *pm;	  *pm = m;	}    }  /* Install PT_IA_64_UNWIND segments, if needed.  */  for (s = abfd->sections; s; s = s->next)    {      hdr = &elf_section_data (s)->this_hdr;      if (hdr->sh_type != SHT_IA_64_UNWIND)	continue;      if (s && (s->flags & SEC_LOAD))	{	  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)	    if (m->p_type == PT_IA_64_UNWIND && m->sections[0] == s)	      break;	  if (m == NULL)	    {	      m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);	      if (m == NULL)		return false;	      m->p_type = PT_IA_64_UNWIND;	      m->count = 1;	      m->sections[0] = s;	      m->next = NULL;	      /* We want to put it last.  */	      pm = &elf_tdata (abfd)->segment_map;	      while (*pm != NULL)		pm = &(*pm)->next;	      *pm = m;	    }	}    }  /* Turn on PF_IA_64_NORECOV if needed.  This involves traversing all of     the input sections for each output section in the segment and testing     for SHF_IA_64_NORECOV on each.  */  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)    if (m->p_type == PT_LOAD)      {	int i;	for (i = m->count - 1; i >= 0; --i)	  {	    struct bfd_link_order *order = m->sections[i]->link_order_head;	    while (order)	      {		if (order->type == bfd_indirect_link_order)		  {		    asection *is = order->u.indirect.section;		    bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;		    if (flags & SHF_IA_64_NORECOV)		      {			m->p_flags |= PF_IA_64_NORECOV;			goto found;		      }		  }		order = order->next;	      }	  }      found:;      }  return true;}/* According to the Tahoe assembler spec, all labels starting with a   '.' are local.  */static booleanelfNN_ia64_is_local_label_name (abfd, name)     bfd *abfd ATTRIBUTE_UNUSED;     const char *name;{  return name[0] == '.';}/* Should we do dynamic things to this symbol?  */static booleanelfNN_ia64_dynamic_symbol_p (h, info)

⌨️ 快捷键说明

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