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