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 + -
显示快捷键?