elflink.h
来自「基于4个mips核的noc设计」· C头文件 代码 · 共 2,075 行 · 第 1/5 页
H
2,075 行
free (defined); free (included); return true; error_return: if (defined != (boolean *) NULL) free (defined); if (included != (boolean *) NULL) free (included); return false;}/* This function is called when we want to define a new symbol. It handles the various cases which arise when we find a definition in a dynamic object, or when there is already a definition in a dynamic object. The new symbol is described by NAME, SYM, PSEC, and PVALUE. We set SYM_HASH to the hash table entry. We set OVERRIDE if the old symbol is overriding a new definition. We set TYPE_CHANGE_OK if it is OK for the type to change. We set SIZE_CHANGE_OK if it is OK for the size to change. By OK to change, we mean that we shouldn't warn if the type or size does change. DT_NEEDED indicates if it comes from a DT_NEEDED entry of a shared object. */static booleanelf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, override, type_change_ok, size_change_ok, dt_needed) bfd *abfd; struct bfd_link_info *info; const char *name; Elf_Internal_Sym *sym; asection **psec; bfd_vma *pvalue; struct elf_link_hash_entry **sym_hash; boolean *override; boolean *type_change_ok; boolean *size_change_ok; boolean dt_needed;{ asection *sec; struct elf_link_hash_entry *h; int bind; bfd *oldbfd; boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; *override = false; sec = *psec; bind = ELF_ST_BIND (sym->st_info); if (! bfd_is_und_section (sec)) h = elf_link_hash_lookup (elf_hash_table (info), name, true, false, false); else h = ((struct elf_link_hash_entry *) bfd_wrapped_link_hash_lookup (abfd, info, name, true, false, false)); if (h == NULL) return false; *sym_hash = h; /* This code is for coping with dynamic objects, and is only useful if we are doing an ELF link. */ if (info->hash->creator != abfd->xvec) return true; /* For merging, we only care about real symbols. */ 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; /* If we just created the symbol, mark it as being an ELF symbol. Other than that, there is nothing to do--there is no merge issue with a newly defined symbol--so we just return. */ if (h->root.type == bfd_link_hash_new) { h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF; return true; } /* OLDBFD is a BFD associated with the existing symbol. */ switch (h->root.type) { default: oldbfd = NULL; break; case bfd_link_hash_undefined: case bfd_link_hash_undefweak: oldbfd = h->root.u.undef.abfd; break; case bfd_link_hash_defined: case bfd_link_hash_defweak: oldbfd = h->root.u.def.section->owner; break; case bfd_link_hash_common: oldbfd = h->root.u.c.p->section->owner; break; } /* In cases involving weak versioned symbols, we may wind up trying to merge a symbol with itself. Catch that here, to avoid the confusion that results if we try to override a symbol with itself. The additional tests catch cases like _GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a dynamic object, which we do want to handle here. */ if (abfd == oldbfd && ((abfd->flags & DYNAMIC) == 0 || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) return true; /* NEWDYN and OLDDYN indicate whether the new or old symbol, respectively, is from a dynamic object. */ if ((abfd->flags & DYNAMIC) != 0) newdyn = true; else newdyn = false; if (oldbfd != NULL) olddyn = (oldbfd->flags & DYNAMIC) != 0; else { asection *hsec; /* This code handles the special SHN_MIPS_{TEXT,DATA} section indices used by MIPS ELF. */ switch (h->root.type) { default: hsec = NULL; break; case bfd_link_hash_defined: case bfd_link_hash_defweak: hsec = h->root.u.def.section; break; case bfd_link_hash_common: hsec = h->root.u.c.p->section; break; } if (hsec == NULL) olddyn = false; else olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0; } /* NEWDEF and OLDDEF indicate whether the new or old symbol, respectively, appear to be a definition rather than reference. */ if (bfd_is_und_section (sec) || bfd_is_com_section (sec)) newdef = false; else newdef = true; if (h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_common) olddef = false; else olddef = true; /* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old symbol, respectively, appears to be a common symbol in a dynamic object. If a symbol appears in an uninitialized section, and is not weak, and is not a function, then it may be a common symbol which was resolved when the dynamic object was created. We want to treat such symbols specially, because they raise special considerations when setting the symbol size: if the symbol appears as a common symbol in a regular object, and the size in the regular object is larger, we must make sure that we use the larger size. This problematic case can always be avoided in C, but it must be handled correctly when using Fortran shared libraries. Note that if NEWDYNCOMMON is set, NEWDEF will be set, and likewise for OLDDYNCOMMON and OLDDEF. Note that this test is just a heuristic, and that it is quite possible to have an uninitialized symbol in a shared object which is really a definition, rather than a common symbol. This could lead to some minor confusion when the symbol really is a common symbol in some regular object. However, I think it will be harmless. */ if (newdyn && newdef && (sec->flags & SEC_ALLOC) != 0 && (sec->flags & SEC_LOAD) == 0 && sym->st_size > 0 && bind != STB_WEAK && ELF_ST_TYPE (sym->st_info) != STT_FUNC) newdyncommon = true; else newdyncommon = false; if (olddyn && olddef && h->root.type == bfd_link_hash_defined && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (h->root.u.def.section->flags & SEC_ALLOC) != 0 && (h->root.u.def.section->flags & SEC_LOAD) == 0 && h->size > 0 && h->type != STT_FUNC) olddyncommon = true; else olddyncommon = false; /* It's OK to change the type if either the existing symbol or the new symbol is weak 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 ((! dt_needed && h->root.type == bfd_link_hash_defweak) || h->root.type == bfd_link_hash_undefweak || bind == STB_WEAK) *type_change_ok = true; /* It's OK to change the size if either the existing symbol or the new symbol is weak, or if the old symbol is undefined. */ if (*type_change_ok || h->root.type == bfd_link_hash_undefined) *size_change_ok = true; /* If both the old and the new symbols look like common symbols in a dynamic object, set the size of the symbol to the larger of the two. */ if (olddyncommon && newdyncommon && sym->st_size != h->size) { /* Since we think we have two common symbols, issue a multiple common warning if desired. Note that we only warn if the size is different. If the size is the same, we simply let the old symbol override the new one as normally happens with symbols defined in dynamic objects. */ if (! ((*info->callbacks->multiple_common) (info, h->root.root.string, oldbfd, bfd_link_hash_common, h->size, abfd, bfd_link_hash_common, sym->st_size))) return false; if (sym->st_size > h->size) h->size = sym->st_size; *size_change_ok = true; } /* If we are looking at a dynamic object, and we have found a definition, we need to see if the symbol was already defined by some other object. If so, we want to use the existing definition, and we do not want to report a multiple symbol definition error; we do this by clobbering *PSEC to be bfd_und_section_ptr. We treat a common symbol as a definition if the symbol in the shared library is a function, since common symbols always represent variables; this can cause confusion in principle, but any such confusion would seem to indicate an erroneous program or shared library. We also permit a common symbol in a regular object to override a weak symbol in a shared object. We prefer a non-weak definition in a shared library to a weak definition in the executable 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 (newdyn && newdef && (olddef || (h->root.type == bfd_link_hash_common && (bind == STB_WEAK || ELF_ST_TYPE (sym->st_info) == STT_FUNC))) && (h->root.type != bfd_link_hash_defweak || dt_needed || bind == STB_WEAK)) { *override = true; newdef = false; newdyncommon = false; *psec = sec = bfd_und_section_ptr; *size_change_ok = true; /* If we get here when the old symbol is a common symbol, then we are explicitly letting it override a weak symbol or function in a dynamic object, and we don't want to warn about a type change. If the old symbol is a defined symbol, a type change warning may still be appropriate. */ if (h->root.type == bfd_link_hash_common) *type_change_ok = true; } /* Handle the special case of an old common symbol merging with a new symbol which looks like a common symbol in a shared object. We change *PSEC and *PVALUE to make the new symbol look like a common symbol, and let _bfd_generic_link_add_one_symbol will do the right thing. */ if (newdyncommon && h->root.type == bfd_link_hash_common) { *override = true; newdef = false; newdyncommon = false; *pvalue = sym->st_size; *psec = sec = bfd_com_section_ptr; *size_change_ok = true; } /* If the old symbol is from a dynamic object, and the new symbol is a definition which is not from a dynamic object, then the new symbol overrides the old symbol. Symbols from regular files always take precedence over symbols from dynamic objects, even if they are defined after the dynamic object in the link. As above, we again permit a common symbol in a regular object to override a definition in a shared object if the shared object symbol is a function or is weak. As above, we permit a non-weak definition in a shared object to override a weak definition in a regular object. */ if (! newdyn && (newdef || (bfd_is_com_section (sec) && (h->root.type == bfd_link_hash_defweak || h->type == STT_FUNC))) && olddyn && olddef && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (bind != STB_WEAK || h->root.type == bfd_link_hash_defweak)) { /* Change the hash table entry to undefined, and let _bfd_generic_link_add_one_symbol do the right thing with the new definition. */ h->root.type = bfd_link_hash_undefined; h->root.u.undef.abfd = h->root.u.def.section->owner; *size_change_ok = true; olddef = false; olddyncommon = false; /* We again permit a type change when a common symbol may be overriding a function. */ if (bfd_is_com_section (sec)) *type_change_ok = true; /* This union may have been set to be non-NULL when this symbol was seen in a dynamic object. We must force the union to be NULL, so that it is correct for a regular symbol. */ h->verinfo.vertree = NULL; /* In this special case, if H is the target of an indirection, we want the caller to frob with H rather than with the indirect symbol. That will permit the caller to redefine the target of the indirection, rather than the indirect symbol itself. FIXME: This will break the -y option if we store a symbol with a different name. */ *sym_hash = h; } /* Handle the special case of a new common symbol merging with an old symbol that looks like it might be a common symbol defined in a shared object. Note that we have already handled the case in which a new common symbol should simply override the definition in the shared library. */ if (! newdyn && bfd_is_com_section (sec) && olddyncommon) { /* It would be best if we could set the hash table entry to a common symbol, but we don't know what to use for the section or the alignment. */ if (! ((*info->callbacks->multiple_common) (info, h->root.root.string, oldbfd, bfd_link_hash_common, h->size, abfd, bfd_link_hash_common, sym->st_size))) return false; /* If the predumed common symbol in the dynamic object is larger, pretend that the new symbol has its size. */ if (h->size > *pvalue) *pvalue = h->size; /* FIXME: We no longer know the alignment required by the symbol in the dynamic object, so we just wind up using the one from the regular object. */ olddef = false; olddyncommon = false; h->root.type = bfd_link_hash_undefined; h->root.u.undef.abfd = h->root.u.def.section->owner; *size_change_ok = true; *type_change_ok = true; h->verinfo.vertree = NULL; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?