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