elflink.h

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

H
2,075
字号
  /* Handle the special case of a weak definition in a regular object     followed by a non-weak definition in a shared object.  In this     case, we prefer the definition in the shared object unless it     comes from a DT_NEEDED entry of a shared object, in which case,     the DT_NEEDED entry may not be required at the run time.  */  if (olddef      && ! dt_needed      && h->root.type == bfd_link_hash_defweak      && newdef      && newdyn      && bind != STB_WEAK)    {      /* To make this work we have to frob the flags so that the rest         of the code does not think we are using the regular         definition.  */      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)	h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;      else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)	h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;      h->elf_link_hash_flags &= ~ (ELF_LINK_HASH_DEF_REGULAR				   | ELF_LINK_HASH_DEF_DYNAMIC);      /* If H is the target of an indirection, we want the caller to         use H rather than the indirect symbol.  Otherwise if we are         defining a new indirect symbol we will wind up attaching it         to the entry we are overriding.  */      *sym_hash = h;    }  /* Handle the special case of a non-weak definition in a shared     object followed by a weak definition in a regular object.  In     this case we prefer to definition in the shared object.  To make     this work we have to tell the caller to not treat the new symbol     as a definition.  */  if (olddef      && olddyn      && h->root.type != bfd_link_hash_defweak      && newdef      && ! newdyn      && bind == STB_WEAK)    *override = true;  return true;}/* Add symbols from an ELF object file to the linker hash table.  */static booleanelf_link_add_object_symbols (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  boolean (*add_symbol_hook) PARAMS ((bfd *, struct bfd_link_info *,				      const Elf_Internal_Sym *,				      const char **, flagword *,				      asection **, bfd_vma *));  boolean (*check_relocs) PARAMS ((bfd *, struct bfd_link_info *,				   asection *, const Elf_Internal_Rela *));  boolean collect;  Elf_Internal_Shdr *hdr;  size_t symcount;  size_t extsymcount;  size_t extsymoff;  Elf_External_Sym *buf = NULL;  struct elf_link_hash_entry **sym_hash;  boolean dynamic;  Elf_External_Versym *extversym = NULL;  Elf_External_Versym *ever;  Elf_External_Dyn *dynbuf = NULL;  struct elf_link_hash_entry *weaks;  Elf_External_Sym *esym;  Elf_External_Sym *esymend;  struct elf_backend_data *bed;  boolean dt_needed;  bed = get_elf_backend_data (abfd);  add_symbol_hook = bed->elf_add_symbol_hook;  collect = bed->collect;  if ((abfd->flags & DYNAMIC) == 0)    dynamic = false;  else    {      dynamic = true;      /* You can't use -r against a dynamic object.  Also, there's no	 hope of using a dynamic object which does not exactly match	 the format of the output file.  */      if (info->relocateable || info->hash->creator != abfd->xvec)	{	  bfd_set_error (bfd_error_invalid_operation);	  goto error_return;	}    }  /* As a GNU extension, any input sections which are named     .gnu.warning.SYMBOL are treated as warning symbols for the given     symbol.  This differs from .gnu.warning sections, which generate     warnings when they are included in an output file.  */  if (! info->shared)    {      asection *s;      for (s = abfd->sections; s != NULL; s = s->next)	{	  const char *name;	  name = bfd_get_section_name (abfd, s);	  if (strncmp (name, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0)	    {	      char *msg;	      bfd_size_type sz;	      name += sizeof ".gnu.warning." - 1;	      /* If this is a shared object, then look up the symbol		 in the hash table.  If it is there, and it is already		 been defined, then we will not be using the entry		 from this shared object, so we don't need to warn.		 FIXME: If we see the definition in a regular object		 later on, we will warn, but we shouldn't.  The only		 fix is to keep track of what warnings we are supposed		 to emit, and then handle them all at the end of the		 link.  */	      if (dynamic && abfd->xvec == info->hash->creator)		{		  struct elf_link_hash_entry *h;		  h = elf_link_hash_lookup (elf_hash_table (info), name,					    false, false, true);		  /* FIXME: What about bfd_link_hash_common?  */		  if (h != NULL		      && (h->root.type == bfd_link_hash_defined			  || h->root.type == bfd_link_hash_defweak))		    {		      /* We don't want to issue this warning.  Clobber                         the section size so that the warning does not                         get copied into the output file.  */		      s->_raw_size = 0;		      continue;		    }		}	      sz = bfd_section_size (abfd, s);	      msg = (char *) bfd_alloc (abfd, sz + 1);	      if (msg == NULL)		goto error_return;	      if (! bfd_get_section_contents (abfd, s, msg, (file_ptr) 0, sz))		goto error_return;	      msg[sz] = '\0';	      if (! (_bfd_generic_link_add_one_symbol		     (info, abfd, name, BSF_WARNING, s, (bfd_vma) 0, msg,		      false, collect, (struct bfd_link_hash_entry **) NULL)))		goto error_return;	      if (! info->relocateable)		{		  /* Clobber the section size so that the warning does                     not get copied into the output file.  */		  s->_raw_size = 0;		}	    }	}    }  /* If this is a dynamic object, we always link against the .dynsym     symbol table, not the .symtab symbol table.  The dynamic linker     will only see the .dynsym symbol table, so there is no reason to     look at .symtab for a dynamic object.  */  if (! dynamic || elf_dynsymtab (abfd) == 0)    hdr = &elf_tdata (abfd)->symtab_hdr;  else    hdr = &elf_tdata (abfd)->dynsymtab_hdr;  if (dynamic)    {      /* Read in any version definitions.  */      if (! _bfd_elf_slurp_version_tables (abfd))	goto error_return;      /* Read in the symbol versions, but don't bother to convert them         to internal format.  */      if (elf_dynversym (abfd) != 0)	{	  Elf_Internal_Shdr *versymhdr;	  versymhdr = &elf_tdata (abfd)->dynversym_hdr;	  extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);	  if (extversym == NULL)	    goto error_return;	  if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0	      || (bfd_read ((PTR) extversym, 1, versymhdr->sh_size, abfd)		  != versymhdr->sh_size))	    goto error_return;	}    }  symcount = hdr->sh_size / sizeof (Elf_External_Sym);  /* The sh_info field of the symtab header tells us where the     external symbols start.  We don't care about the local symbols at     this point.  */  if (elf_bad_symtab (abfd))    {      extsymcount = symcount;      extsymoff = 0;    }  else    {      extsymcount = symcount - hdr->sh_info;      extsymoff = hdr->sh_info;    }  buf = ((Elf_External_Sym *)	 bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));  if (buf == NULL && extsymcount != 0)    goto error_return;  /* We store a pointer to the hash table entry for each external     symbol.  */  sym_hash = ((struct elf_link_hash_entry **)	      bfd_alloc (abfd,			 extsymcount * sizeof (struct elf_link_hash_entry *)));  if (sym_hash == NULL)    goto error_return;  elf_sym_hashes (abfd) = sym_hash;  dt_needed = false;  if (! dynamic)    {      /* If we are creating a shared library, create all the dynamic         sections immediately.  We need to attach them to something,         so we attach them to this BFD, provided it is the right         format.  FIXME: If there are no input BFD's of the same         format as the output, we can't make a shared library.  */      if (info->shared	  && ! elf_hash_table (info)->dynamic_sections_created	  && abfd->xvec == info->hash->creator)	{	  if (! elf_link_create_dynamic_sections (abfd, info))	    goto error_return;	}    }  else    {      asection *s;      boolean add_needed;      const char *name;      bfd_size_type oldsize;      bfd_size_type strindex;      /* Find the name to use in a DT_NEEDED entry that refers to this	 object.  If the object has a DT_SONAME entry, we use it.	 Otherwise, if the generic linker stuck something in	 elf_dt_name, we use that.  Otherwise, we just use the file	 name.  If the generic linker put a null string into	 elf_dt_name, we don't make a DT_NEEDED entry at all, even if	 there is a DT_SONAME entry.  */      add_needed = true;      name = bfd_get_filename (abfd);      if (elf_dt_name (abfd) != NULL)	{	  name = elf_dt_name (abfd);	  if (*name == '\0')	    {	      if (elf_dt_soname (abfd) != NULL)	        dt_needed = true;	      add_needed = false;	    }	}      s = bfd_get_section_by_name (abfd, ".dynamic");      if (s != NULL)	{	  Elf_External_Dyn *extdyn;	  Elf_External_Dyn *extdynend;	  int elfsec;	  unsigned long link;	  int rpath;	  int runpath;	  dynbuf = (Elf_External_Dyn *) bfd_malloc ((size_t) s->_raw_size);	  if (dynbuf == NULL)	    goto error_return;	  if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf,					  (file_ptr) 0, s->_raw_size))	    goto error_return;	  elfsec = _bfd_elf_section_from_bfd_section (abfd, s);	  if (elfsec == -1)	    goto error_return;	  link = elf_elfsections (abfd)[elfsec]->sh_link;	  {	    /* The shared libraries distributed with hpux11 have a bogus	       sh_link field for the ".dynamic" section.  This code detects	       when LINK refers to a section that is not a string table and	       tries to find the string table for the ".dynsym" section	       instead.  */	    Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[link];	    if (hdr->sh_type != SHT_STRTAB)	      {		asection *s = bfd_get_section_by_name (abfd, ".dynsym");		int elfsec = _bfd_elf_section_from_bfd_section (abfd, s);		if (elfsec == -1)		  goto error_return;		link = elf_elfsections (abfd)[elfsec]->sh_link;	      }	  }	  extdyn = dynbuf;	  extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);	  rpath = 0;	  runpath = 0;	  for (; extdyn < extdynend; extdyn++)	    {	      Elf_Internal_Dyn dyn;	      elf_swap_dyn_in (abfd, extdyn, &dyn);	      if (dyn.d_tag == DT_SONAME)		{		  name = bfd_elf_string_from_elf_section (abfd, link,							  dyn.d_un.d_val);		  if (name == NULL)		    goto error_return;		}	      if (dyn.d_tag == DT_NEEDED)		{		  struct bfd_link_needed_list *n, **pn;		  char *fnm, *anm;		  n = ((struct bfd_link_needed_list *)		       bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));		  fnm = bfd_elf_string_from_elf_section (abfd, link,							 dyn.d_un.d_val);		  if (n == NULL || fnm == NULL)		    goto error_return;		  anm = bfd_alloc (abfd, strlen (fnm) + 1);		  if (anm == NULL)		    goto error_return;		  strcpy (anm, fnm);		  n->name = anm;		  n->by = abfd;		  n->next = NULL;		  for (pn = &elf_hash_table (info)->needed;		       *pn != NULL;		       pn = &(*pn)->next)		    ;		  *pn = n;		}	      if (dyn.d_tag == DT_RUNPATH)		{		  struct bfd_link_needed_list *n, **pn;		  char *fnm, *anm;		  /* When we see DT_RPATH before DT_RUNPATH, we have		     to clear runpath.  Do _NOT_ bfd_release, as that		     frees all more recently bfd_alloc'd blocks as		     well.  */		  if (rpath && elf_hash_table (info)->runpath)		    elf_hash_table (info)->runpath = NULL;		  n = ((struct bfd_link_needed_list *)		       bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));		  fnm = bfd_elf_string_from_elf_section (abfd, link,							 dyn.d_un.d_val);		  if (n == NULL || fnm == NULL)		    goto error_return;		  anm = bfd_alloc (abfd, strlen (fnm) + 1);		  if (anm == NULL)		    goto error_return;		  strcpy (anm, fnm);		  n->name = anm;		  n->by = abfd;		  n->next = NULL;		  for (pn = &elf_hash_table (info)->runpath;		       *pn != NULL;		       pn = &(*pn)->next)		    ;		  *pn = n;		  runpath = 1;		  rpath = 0;		}	      /* Ignore DT_RPATH if we have seen DT_RUNPATH.  */	      if (!runpath && dyn.d_tag == DT_RPATH)	        {		  struct bfd_link_needed_list *n, **pn;		  char *fnm, *anm;		  n = ((struct bfd_link_needed_list *)		       bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));		  fnm = bfd_elf_string_from_elf_section (abfd, link,							 dyn.d_un.d_val);		  if (n == NULL || fnm == NULL)		    goto error_return;		  anm = bfd_alloc (abfd, strlen (fnm) + 1);		  if (anm == NULL)		    goto error_return;		  strcpy (anm, fnm);		  n->name = anm;		  n->by = abfd;		  n->next = NULL;		  for (pn = &elf_hash_table (info)->runpath;		       *pn != NULL;		       pn = &(*pn)->next)		    ;

⌨️ 快捷键说明

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