elflink.h

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

H
2,075
字号
/* ELF linker support.   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  *//* ELF linker code.  *//* This struct is used to pass information to routines called via   elf_link_hash_traverse which must return failure.  */struct elf_info_failed{  boolean failed;  struct bfd_link_info *info;};static boolean elf_link_add_object_symbols  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf_link_add_archive_symbols  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf_merge_symbol  PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,	   asection **, bfd_vma *, struct elf_link_hash_entry **,	   boolean *, boolean *, boolean *, boolean));static boolean elf_export_symbol  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_fix_symbol_flags  PARAMS ((struct elf_link_hash_entry *, struct elf_info_failed *));static boolean elf_adjust_dynamic_symbol  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_link_find_version_dependencies  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_link_find_version_dependencies  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_link_assign_sym_version  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_collect_hash_codes  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf_link_read_relocs_from_section  PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *));static void elf_link_output_relocs  PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));static boolean elf_link_size_reloc_section  PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));static void elf_link_adjust_relocs  PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int,	   struct elf_link_hash_entry **));/* Given an ELF BFD, add symbols to the global hash table as   appropriate.  */booleanelf_bfd_link_add_symbols (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  switch (bfd_get_format (abfd))    {    case bfd_object:      return elf_link_add_object_symbols (abfd, info);    case bfd_archive:      return elf_link_add_archive_symbols (abfd, info);    default:      bfd_set_error (bfd_error_wrong_format);      return false;    }}/* Return true iff this is a non-common, definition of a non-function symbol.  */static booleanis_global_data_symbol_definition (abfd, sym)     bfd * abfd ATTRIBUTE_UNUSED;     Elf_Internal_Sym * sym;{  /* Local symbols do not count, but target specific ones might.  */  if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL      && ELF_ST_BIND (sym->st_info) < STB_LOOS)    return false;  /* Function symbols do not count.  */  if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)    return false;  /* If the section is undefined, then so is the symbol.  */  if (sym->st_shndx == SHN_UNDEF)    return false;  /* If the symbol is defined in the common section, then     it is a common definition and so does not count.  */  if (sym->st_shndx == SHN_COMMON)    return false;  /* If the symbol is in a target specific section then we     must rely upon the backend to tell us what it is.  */  if (sym->st_shndx >= SHN_LORESERVE && sym->st_shndx < SHN_ABS)    /* FIXME - this function is not coded yet:       return _bfd_is_global_symbol_definition (abfd, sym);       Instead for now assume that the definition is not global,       Even if this is wrong, at least the linker will behave       in the same way that it used to do.  */    return false;  return true;}/* Search the symbol table of the archive element of the archive ABFD   whose archive map contains a mention of SYMDEF, and determine if   the symbol is defined in this element.  */static booleanelf_link_is_defined_archive_symbol (abfd, symdef)     bfd * abfd;     carsym * symdef;{  Elf_Internal_Shdr * hdr;  Elf_External_Sym *  esym;  Elf_External_Sym *  esymend;  Elf_External_Sym *  buf = NULL;  size_t symcount;  size_t extsymcount;  size_t extsymoff;  boolean result = false;  abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);  if (abfd == (bfd *) NULL)    return false;  if (! bfd_check_format (abfd, bfd_object))    return false;  /* If we have already included the element containing this symbol in the     link then we do not need to include it again.  Just claim that any symbol     it contains is not a definition, so that our caller will not decide to     (re)include this element.  */  if (abfd->archive_pass)    return false;  /* Select the appropriate symbol table.  */  if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)    hdr = &elf_tdata (abfd)->symtab_hdr;  else    hdr = &elf_tdata (abfd)->dynsymtab_hdr;  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.  */  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)    return false;  /* Read in the symbol table.     FIXME:  This ought to be cached somewhere.  */  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)))    {      free (buf);      return false;    }  /* Scan the symbol table looking for SYMDEF.  */  esymend = buf + extsymcount;  for (esym = buf;       esym < esymend;       esym++)    {      Elf_Internal_Sym sym;      const char * name;      elf_swap_symbol_in (abfd, esym, & sym);      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);      if (name == (const char *) NULL)	break;      if (strcmp (name, symdef->name) == 0)	{	  result = is_global_data_symbol_definition (abfd, & sym);	  break;	}    }  free (buf);  return result;}/* Add symbols from an ELF archive file to the linker hash table.  We   don't use _bfd_generic_link_add_archive_symbols because of a   problem which arises on UnixWare.  The UnixWare libc.so is an   archive which includes an entry libc.so.1 which defines a bunch of   symbols.  The libc.so archive also includes a number of other   object files, which also define symbols, some of which are the same   as those defined in libc.so.1.  Correct linking requires that we   consider each object file in turn, and include it if it defines any   symbols we need.  _bfd_generic_link_add_archive_symbols does not do   this; it looks through the list of undefined symbols, and includes   any object file which defines them.  When this algorithm is used on   UnixWare, it winds up pulling in libc.so.1 early and defining a   bunch of symbols.  This means that some of the other objects in the   archive are not included in the link, which is incorrect since they   precede libc.so.1 in the archive.   Fortunately, ELF archive handling is simpler than that done by   _bfd_generic_link_add_archive_symbols, which has to allow for a.out   oddities.  In ELF, if we find a symbol in the archive map, and the   symbol is currently undefined, we know that we must pull in that   object file.   Unfortunately, we do have to make multiple passes over the symbol   table until nothing further is resolved.  */static booleanelf_link_add_archive_symbols (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  symindex c;  boolean *defined = NULL;  boolean *included = NULL;  carsym *symdefs;  boolean loop;  if (! bfd_has_map (abfd))    {      /* An empty archive is a special case.  */      if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)	return true;      bfd_set_error (bfd_error_no_armap);      return false;    }  /* Keep track of all symbols we know to be already defined, and all     files we know to be already included.  This is to speed up the     second and subsequent passes.  */  c = bfd_ardata (abfd)->symdef_count;  if (c == 0)    return true;  defined = (boolean *) bfd_malloc (c * sizeof (boolean));  included = (boolean *) bfd_malloc (c * sizeof (boolean));  if (defined == (boolean *) NULL || included == (boolean *) NULL)    goto error_return;  memset (defined, 0, c * sizeof (boolean));  memset (included, 0, c * sizeof (boolean));  symdefs = bfd_ardata (abfd)->symdefs;  do    {      file_ptr last;      symindex i;      carsym *symdef;      carsym *symdefend;      loop = false;      last = -1;      symdef = symdefs;      symdefend = symdef + c;      for (i = 0; symdef < symdefend; symdef++, i++)	{	  struct elf_link_hash_entry *h;	  bfd *element;	  struct bfd_link_hash_entry *undefs_tail;	  symindex mark;	  if (defined[i] || included[i])	    continue;	  if (symdef->file_offset == last)	    {	      included[i] = true;	      continue;	    }	  h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,				    false, false, false);	  if (h == NULL)	    {	      char *p, *copy;	      /* If this is a default version (the name contains @@),		 look up the symbol again without the version.  The		 effect is that references to the symbol without the		 version will be matched by the default symbol in the		 archive.  */	      p = strchr (symdef->name, ELF_VER_CHR);	      if (p == NULL || p[1] != ELF_VER_CHR)		continue;	      copy = bfd_alloc (abfd, p - symdef->name + 1);	      if (copy == NULL)		goto error_return;	      memcpy (copy, symdef->name, p - symdef->name);	      copy[p - symdef->name] = '\0';	      h = elf_link_hash_lookup (elf_hash_table (info), copy,					false, false, false);	      bfd_release (abfd, copy);	    }	  if (h == NULL)	    continue;	  if (h->root.type == bfd_link_hash_common)	    {	      /* We currently have a common symbol.  The archive map contains		 a reference to this symbol, so we may want to include it.  We		 only want to include it however, if this archive element		 contains a definition of the symbol, not just another common		 declaration of it.		 Unfortunately some archivers (including GNU ar) will put		 declarations of common symbols into their archive maps, as		 well as real definitions, so we cannot just go by the archive		 map alone.  Instead we must read in the element's symbol		 table and check that to see what kind of symbol definition		 this is.  */	      if (! elf_link_is_defined_archive_symbol (abfd, symdef))		continue;	    }	  else if (h->root.type != bfd_link_hash_undefined)	    {	      if (h->root.type != bfd_link_hash_undefweak)		defined[i] = true;	      continue;	    }	  /* We need to include this archive member.  */	  element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);	  if (element == (bfd *) NULL)	    goto error_return;	  if (! bfd_check_format (element, bfd_object))	    goto error_return;	  /* Doublecheck that we have not included this object	     already--it should be impossible, but there may be	     something wrong with the archive.  */	  if (element->archive_pass != 0)	    {	      bfd_set_error (bfd_error_bad_value);	      goto error_return;	    }	  element->archive_pass = 1;	  undefs_tail = info->hash->undefs_tail;	  if (! (*info->callbacks->add_archive_element) (info, element,							 symdef->name))	    goto error_return;	  if (! elf_link_add_object_symbols (element, info))	    goto error_return;	  /* If there are any new undefined symbols, we need to make	     another pass through the archive in order to see whether	     they can be defined.  FIXME: This isn't perfect, because	     common symbols wind up on undefs_tail and because an	     undefined symbol which is defined later on in this pass	     does not require another pass.  This isn't a bug, but it	     does make the code less efficient than it could be.  */	  if (undefs_tail != info->hash->undefs_tail)	    loop = true;	  /* Look backward to mark all symbols from this object file	     which we have already seen in this pass.  */	  mark = i;	  do	    {	      included[mark] = true;	      if (mark == 0)		break;	      --mark;	    }	  while (symdefs[mark].file_offset == symdef->file_offset);	  /* We mark subsequent symbols from this object file as we go	     on through the loop.  */	  last = symdef->file_offset;	}    }  while (loop);

⌨️ 快捷键说明

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