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