elflink.h

来自「基于4个mips核的noc设计」· C头文件 代码 · 共 2,075 行 · 第 1/5 页

H
2,075
字号
		  *pn = n;		  rpath = 1;		}	    }	  free (dynbuf);	  dynbuf = NULL;	}      /* We do not want to include any of the sections in a dynamic	 object in the output file.  We hack by simply clobbering the	 list of sections in the BFD.  This could be handled more	 cleanly by, say, a new section flag; the existing	 SEC_NEVER_LOAD flag is not the one we want, because that one	 still implies that the section takes up space in the output	 file.  */      abfd->sections = NULL;      abfd->section_count = 0;      /* If this is the first dynamic object found in the link, create	 the special sections required for dynamic linking.  */      if (! elf_hash_table (info)->dynamic_sections_created)	{	  if (! elf_link_create_dynamic_sections (abfd, info))	    goto error_return;	}      if (add_needed)	{	  /* Add a DT_NEEDED entry for this dynamic object.  */	  oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);	  strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,					 true, false);	  if (strindex == (bfd_size_type) -1)	    goto error_return;	  if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))	    {	      asection *sdyn;	      Elf_External_Dyn *dyncon, *dynconend;	      /* The hash table size did not change, which means that		 the dynamic object name was already entered.  If we		 have already included this dynamic object in the		 link, just ignore it.  There is no reason to include		 a particular dynamic object more than once.  */	      sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,					      ".dynamic");	      BFD_ASSERT (sdyn != NULL);	      dyncon = (Elf_External_Dyn *) sdyn->contents;	      dynconend = (Elf_External_Dyn *) (sdyn->contents +						sdyn->_raw_size);	      for (; dyncon < dynconend; dyncon++)		{		  Elf_Internal_Dyn dyn;		  elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon,				   &dyn);		  if (dyn.d_tag == DT_NEEDED		      && dyn.d_un.d_val == strindex)		    {		      if (buf != NULL)			free (buf);		      if (extversym != NULL)			free (extversym);		      return true;		    }		}	    }	  if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))	    goto error_return;	}      /* Save the SONAME, if there is one, because sometimes the         linker emulation code will need to know it.  */      if (*name == '\0')	name = bfd_get_filename (abfd);      elf_dt_name (abfd) = name;    }  if (bfd_seek (abfd,		hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),		SEEK_SET) != 0      || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)	  != extsymcount * sizeof (Elf_External_Sym)))    goto error_return;  weaks = NULL;  ever = extversym != NULL ? extversym + extsymoff : NULL;  esymend = buf + extsymcount;  for (esym = buf;       esym < esymend;       esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))    {      Elf_Internal_Sym sym;      int bind;      bfd_vma value;      asection *sec;      flagword flags;      const char *name;      struct elf_link_hash_entry *h;      boolean definition;      boolean size_change_ok, type_change_ok;      boolean new_weakdef;      unsigned int old_alignment;      elf_swap_symbol_in (abfd, esym, &sym);      flags = BSF_NO_FLAGS;      sec = NULL;      value = sym.st_value;      *sym_hash = NULL;      bind = ELF_ST_BIND (sym.st_info);      if (bind == STB_LOCAL)	{	  /* This should be impossible, since ELF requires that all	     global symbols follow all local symbols, and that sh_info	     point to the first global symbol.  Unfortunatealy, Irix 5	     screws this up.  */	  continue;	}      else if (bind == STB_GLOBAL)	{	  if (sym.st_shndx != SHN_UNDEF	      && sym.st_shndx != SHN_COMMON)	    flags = BSF_GLOBAL;	}      else if (bind == STB_WEAK)	flags = BSF_WEAK;      else	{	  /* Leave it up to the processor backend.  */	}      if (sym.st_shndx == SHN_UNDEF)	sec = bfd_und_section_ptr;      else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)	{	  sec = section_from_elf_index (abfd, sym.st_shndx);	  if (sec == NULL)	    sec = bfd_abs_section_ptr;	  else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)	    value -= sec->vma;	}      else if (sym.st_shndx == SHN_ABS)	sec = bfd_abs_section_ptr;      else if (sym.st_shndx == SHN_COMMON)	{	  sec = bfd_com_section_ptr;	  /* What ELF calls the size we call the value.  What ELF	     calls the value we call the alignment.  */	  value = sym.st_size;	}      else	{	  /* Leave it up to the processor backend.  */	}      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);      if (name == (const char *) NULL)	goto error_return;      if (add_symbol_hook)	{	  if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,				    &value))	    goto error_return;	  /* The hook function sets the name to NULL if this symbol	     should be skipped for some reason.  */	  if (name == (const char *) NULL)	    continue;	}      /* Sanity check that all possibilities were handled.  */      if (sec == (asection *) NULL)	{	  bfd_set_error (bfd_error_bad_value);	  goto error_return;	}      if (bfd_is_und_section (sec)	  || bfd_is_com_section (sec))	definition = false;      else	definition = true;      size_change_ok = false;      type_change_ok = get_elf_backend_data (abfd)->type_change_ok;      old_alignment = 0;      if (info->hash->creator->flavour == bfd_target_elf_flavour)	{	  Elf_Internal_Versym iver;	  unsigned int vernum = 0;	  boolean override;	  if (ever != NULL)	    {	      _bfd_elf_swap_versym_in (abfd, ever, &iver);	      vernum = iver.vs_vers & VERSYM_VERSION;	      /* If this is a hidden symbol, or if it is not version                 1, we append the version name to the symbol name.                 However, we do not modify a non-hidden absolute                 symbol, because it might be the version symbol                 itself.  FIXME: What if it isn't?  */	      if ((iver.vs_vers & VERSYM_HIDDEN) != 0		  || (vernum > 1 && ! bfd_is_abs_section (sec)))		{		  const char *verstr;		  int namelen, newlen;		  char *newname, *p;		  if (sym.st_shndx != SHN_UNDEF)		    {		      if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)			{			  (*_bfd_error_handler)			    (_("%s: %s: invalid version %u (max %d)"),			     bfd_get_filename (abfd), name, vernum,			     elf_tdata (abfd)->dynverdef_hdr.sh_info);			  bfd_set_error (bfd_error_bad_value);			  goto error_return;			}		      else if (vernum > 1)			verstr =			  elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;		      else			verstr = "";		    }		  else		    {		      /* We cannot simply test for the number of			 entries in the VERNEED section since the			 numbers for the needed versions do not start			 at 0.  */		      Elf_Internal_Verneed *t;		      verstr = NULL;		      for (t = elf_tdata (abfd)->verref;			   t != NULL;			   t = t->vn_nextref)			{			  Elf_Internal_Vernaux *a;			  for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)			    {			      if (a->vna_other == vernum)				{				  verstr = a->vna_nodename;				  break;				}			    }			  if (a != NULL)			    break;			}		      if (verstr == NULL)			{			  (*_bfd_error_handler)			    (_("%s: %s: invalid needed version %d"),			     bfd_get_filename (abfd), name, vernum);			  bfd_set_error (bfd_error_bad_value);			  goto error_return;			}		    }		  namelen = strlen (name);		  newlen = namelen + strlen (verstr) + 2;		  if ((iver.vs_vers & VERSYM_HIDDEN) == 0)		    ++newlen;		  newname = (char *) bfd_alloc (abfd, newlen);		  if (newname == NULL)		    goto error_return;		  strcpy (newname, name);		  p = newname + namelen;		  *p++ = ELF_VER_CHR;		  /* If this is a defined non-hidden version symbol,		     we add another @ to the name.  This indicates the		     default version of the symbol.  */		  if ((iver.vs_vers & VERSYM_HIDDEN) == 0		      && sym.st_shndx != SHN_UNDEF)		    *p++ = ELF_VER_CHR;		  strcpy (p, verstr);		  name = newname;		}	    }	  if (! elf_merge_symbol (abfd, info, name, &sym, &sec, &value,				  sym_hash, &override, &type_change_ok,				  &size_change_ok, dt_needed))	    goto error_return;	  if (override)	    definition = false;	  h = *sym_hash;	  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;	  /* Remember the old alignment if this is a common symbol, so             that we don't reduce the alignment later on.  We can't             check later, because _bfd_generic_link_add_one_symbol             will set a default for the alignment which we want to             override.  */	  if (h->root.type == bfd_link_hash_common)	    old_alignment = h->root.u.c.p->alignment_power;	  if (elf_tdata (abfd)->verdef != NULL	      && ! override	      && vernum > 1	      && definition)	    h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];	}      if (! (_bfd_generic_link_add_one_symbol	     (info, abfd, name, flags, sec, value, (const char *) NULL,	      false, collect, (struct bfd_link_hash_entry **) sym_hash)))	goto error_return;      h = *sym_hash;      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;      *sym_hash = h;      new_weakdef = false;      if (dynamic	  && definition	  && (flags & BSF_WEAK) != 0	  && ELF_ST_TYPE (sym.st_info) != STT_FUNC	  && info->hash->creator->flavour == bfd_target_elf_flavour	  && h->weakdef == NULL)	{	  /* Keep a list of all weak defined non function symbols from	     a dynamic object, using the weakdef field.  Later in this	     function we will set the weakdef field to the correct	     value.  We only put non-function symbols from dynamic	     objects on this list, because that happens to be the only	     time we need to know the normal symbol corresponding to a	     weak symbol, and the information is time consuming to	     figure out.  If the weakdef field is not already NULL,	     then this symbol was already defined by some previous	     dynamic object, and we will be using that previous	     definition anyhow.  */	  h->weakdef = weaks;	  weaks = h;	  new_weakdef = true;	}      /* Set the alignment of a common symbol.  */      if (sym.st_shndx == SHN_COMMON	  && h->root.type == bfd_link_hash_common)	{	  unsigned int align;	  align = bfd_log2 (sym.st_value);	  if (align > old_alignment	      /* Permit an alignment power of zero if an alignment of one		 is specified and no other alignments have been specified.  */	      || (sym.st_value == 1 && old_alignment == 0))	    h->root.u.c.p->alignment_power = align;	}      if (info->hash->creator->flavour == bfd_target_elf_flavour)	{	  int old_flags;	  boolean dynsym;	  int new_flag;	  /* Remember the symbol size and type.  */	  if (sym.st_size != 0	      && (definition || h->size == 0))	    {	      if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)		(*_bfd_error_handler)		  (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"),		   name, (unsigned long) h->size, (unsigned long) sym.st_size,		   bfd_get_filename (abfd));	      h->size = sym.st_size;	    }	  /* If this is a common symbol, then we always want H->SIZE             to be the size of the common symbol.  The code just above             won't fix the size if a common symbol becomes larger.  We             don't warn about a size change here, because that is             covered by --warn-common.  */	  if (h->root.type == bfd_link_hash_common)	    h->size = h->root.u.c.size;	  if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE	      && (definition || h->type == STT_NOTYPE))	    {	      if (h->type != STT_NOTYPE		  && h->type != ELF_ST_TYPE (sym.st_info)		  && ! type_change_ok)		(*_bfd_error_handler)		  (_("Warning: type of symbol `%s' changed from %d to %d in %s"),		   name, h->type, ELF_ST_TYPE (sym.st_info),		   bfd_get_filename (abfd));	      h->type = ELF_ST_TYPE (sym.st_info);	    }	  /* If st_other has a processor-specific meaning, specific code	     might be needed here.  */	  if (sym.st_other != 0)

⌨️ 快捷键说明

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