⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linker.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
	      h->type = bfd_link_hash_defined;	    h->u.def.section = section;	    h->u.def.value = value;	    /* If we have been asked to, we act like collect2 and	       identify all functions that might be global	       constructors and destructors and pass them up in a	       callback.  We only do this for certain object file	       types, since many object file types can handle this	       automatically.  */	    if (collect && name[0] == '_')	      {		const char *s;		/* A constructor or destructor name starts like this:		   _+GLOBAL_[_.$][ID][_.$] where the first [_.$] and		   the second are the same character (we accept any		   character there, in case a new object file format		   comes along with even worse naming restrictions).  */#define CONS_PREFIX "GLOBAL_"#define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1)		s = name + 1;		while (*s == '_')		  ++s;		if (s[0] == 'G'		    && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)		  {		    char c;		    c = s[CONS_PREFIX_LEN + 1];		    if ((c == 'I' || c == 'D')			&& s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])		      {			/* If this is a definition of a symbol which                           was previously weakly defined, we are in                           trouble.  We have already added a                           constructor entry for the weak defined                           symbol, and now we are trying to add one                           for the new symbol.  Fortunately, this case                           should never arise in practice.  */			if (oldtype == bfd_link_hash_defweak)			  abort ();			if (! ((*info->callbacks->constructor)			       (info,				c == 'I' ? true : false,				h->root.string, abfd, section, value)))			  return false;		      }		  }	      }	  }	  break;	case COM:	  /* We have found a common definition for a symbol.  */	  if (h->type == bfd_link_hash_new)	    bfd_link_add_undef (info->hash, h);	  h->type = bfd_link_hash_common;	  h->u.c.p =	    ((struct bfd_link_hash_common_entry *)	     bfd_hash_allocate (&info->hash->table,				sizeof (struct bfd_link_hash_common_entry)));	  if (h->u.c.p == NULL)	    return false;	  h->u.c.size = value;	  /* Select a default alignment based on the size.  This may             be overridden by the caller.  */	  {	    unsigned int power;	    power = bfd_log2 (value);	    if (power > 4)	      power = 4;	    h->u.c.p->alignment_power = power;	  }	  /* The section of a common symbol is only used if the common             symbol is actually allocated.  It basically provides a             hook for the linker script to decide which output section             the common symbols should be put in.  In most cases, the             section of a common symbol will be bfd_com_section_ptr,             the code here will choose a common symbol section named             "COMMON", and the linker script will contain *(COMMON) in             the appropriate place.  A few targets use separate common             sections for small symbols, and they require special             handling.  */	  if (section == bfd_com_section_ptr)	    {	      h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");	      h->u.c.p->section->flags = SEC_ALLOC;	    }	  else if (section->owner != abfd)	    {	      h->u.c.p->section = bfd_make_section_old_way (abfd,							    section->name);	      h->u.c.p->section->flags = SEC_ALLOC;	    }	  else	    h->u.c.p->section = section;	  break;	case REF:	  /* A reference to a defined symbol.  */	  if (h->next == NULL && info->hash->undefs_tail != h)	    h->next = h;	  break;	case BIG:	  /* We have found a common definition for a symbol which	     already had a common definition.  Use the maximum of the	     two sizes.  */	  BFD_ASSERT (h->type == bfd_link_hash_common);	  if (! ((*info->callbacks->multiple_common)		 (info, h->root.string,		  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,		  abfd, bfd_link_hash_common, value)))	    return false;	  if (value > h->u.c.size)	    {	      unsigned int power;	      h->u.c.size = value;	      /* Select a default alignment based on the size.  This may		 be overridden by the caller.  */	      power = bfd_log2 (value);	      if (power > 4)		power = 4;	      h->u.c.p->alignment_power = power;	    }	  break;	case CREF:	  {	    bfd *obfd;	    /* We have found a common definition for a symbol which	       was already defined.  FIXME: It would nice if we could	       report the BFD which defined an indirect symbol, but we	       don't have anywhere to store the information.  */	    if (h->type == bfd_link_hash_defined		|| h->type == bfd_link_hash_defweak)	      obfd = h->u.def.section->owner;	    else	      obfd = NULL;	    if (! ((*info->callbacks->multiple_common)		   (info, h->root.string, obfd, h->type, (bfd_vma) 0,		    abfd, bfd_link_hash_common, value)))	      return false;	  }	  break;	case MIND:	  /* Multiple indirect symbols.  This is OK if they both point	     to the same symbol.  */	  if (strcmp (h->u.i.link->root.string, string) == 0)	    break;	  /* Fall through.  */	case MDEF:	  /* Handle a multiple definition.  */	  {	    asection *msec = NULL;	    bfd_vma mval = 0;	    switch (h->type)	      {	      case bfd_link_hash_defined:		msec = h->u.def.section;		mval = h->u.def.value;		break;	      case bfd_link_hash_indirect:		msec = bfd_ind_section_ptr;		mval = 0;		break;	      default:		abort ();	      }	    /* Ignore a redefinition of an absolute symbol to the same               value; it's harmless.  */	    if (h->type == bfd_link_hash_defined		&& bfd_is_abs_section (msec)		&& bfd_is_abs_section (section)		&& value == mval)	      break;	    if (! ((*info->callbacks->multiple_definition)		   (info, h->root.string, msec->owner, msec, mval, abfd,		    section, value)))	      return false;	  }	  break;	case CIND:	  /* Create an indirect symbol from an existing common symbol.  */	  BFD_ASSERT (h->type == bfd_link_hash_common);	  if (! ((*info->callbacks->multiple_common)		 (info, h->root.string,		  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,		  abfd, bfd_link_hash_indirect, (bfd_vma) 0)))	    return false;	  /* Fall through.  */	case IND:	  /* Create an indirect symbol.  */	  {	    struct bfd_link_hash_entry *inh;	    /* STRING is the name of the symbol we want to indirect	       to.  */	    inh = bfd_wrapped_link_hash_lookup (abfd, info, string, true,						copy, false);	    if (inh == (struct bfd_link_hash_entry *) NULL)	      return false;	    if (inh->type == bfd_link_hash_indirect		&& inh->u.i.link == h)	      {		(*_bfd_error_handler)		  (_("%s: indirect symbol `%s' to `%s' is a loop"),  		   bfd_get_filename (abfd), name, string);		bfd_set_error (bfd_error_invalid_operation);		return false;	      }	    if (inh->type == bfd_link_hash_new)	      {		inh->type = bfd_link_hash_undefined;		inh->u.undef.abfd = abfd;		bfd_link_add_undef (info->hash, inh);	      }	    /* If the indirect symbol has been referenced, we need to	       push the reference down to the symbol we are	       referencing.  */	    if (h->type != bfd_link_hash_new)	      {		row = UNDEF_ROW;		cycle = true;	      }	    h->type = bfd_link_hash_indirect;	    h->u.i.link = inh;	  }	  break;	case SET:	  /* Add an entry to a set.  */	  if (! (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,						abfd, section, value))	    return false;	  break;	case WARNC:	  /* Issue a warning and cycle.  */	  if (h->u.i.warning != NULL)	    {	      if (! (*info->callbacks->warning) (info, h->u.i.warning,						 h->root.string, abfd,						 (asection *) NULL,						 (bfd_vma) 0))		return false;	      /* Only issue a warning once.  */	      h->u.i.warning = NULL;	    }	  /* Fall through.  */	case CYCLE:	  /* Try again with the referenced symbol.  */	  h = h->u.i.link;	  cycle = true;	  break;	case REFC:	  /* A reference to an indirect symbol.  */	  if (h->next == NULL && info->hash->undefs_tail != h)	    h->next = h;	  h = h->u.i.link;	  cycle = true;	  break;	case WARN:	  /* Issue a warning.  */	  if (! (*info->callbacks->warning) (info, string, h->root.string,					     hash_entry_bfd (h),					     (asection *) NULL, (bfd_vma) 0))	    return false;	  break;	case CWARN:	  /* Warn if this symbol has been referenced already,	     otherwise add a warning.  A symbol has been referenced if	     the next field is not NULL, or it is the tail of the	     undefined symbol list.  The REF case above helps to	     ensure this.  */	  if (h->next != NULL || info->hash->undefs_tail == h)	    {	      if (! (*info->callbacks->warning) (info, string, h->root.string,						 hash_entry_bfd (h),						 (asection *) NULL,						 (bfd_vma) 0))		return false;	      break;	    }	  /* Fall through.  */	case MWARN:	  /* Make a warning symbol.  */	  {	    struct bfd_link_hash_entry *sub;	    /* STRING is the warning to give.  */	    sub = ((struct bfd_link_hash_entry *)		   ((*info->hash->table.newfunc)		    ((struct bfd_hash_entry *) NULL, &info->hash->table,		     h->root.string)));	    if (sub == NULL)	      return false;	    *sub = *h;	    sub->type = bfd_link_hash_warning;	    sub->u.i.link = h;	    if (! copy)	      sub->u.i.warning = string;	    else	      {		char *w;		w = bfd_hash_allocate (&info->hash->table,				       strlen (string) + 1);		if (w == NULL)		  return false;		strcpy (w, string);		sub->u.i.warning = w;	      }	    bfd_hash_replace (&info->hash->table,			      (struct bfd_hash_entry *) h,			      (struct bfd_hash_entry *) sub);	    if (hashp != NULL)	      *hashp = sub;	  }	  break;	}    }  while (cycle);  return true;}/* Generic final link routine.  */boolean_bfd_generic_final_link (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  bfd *sub;  asection *o;  struct bfd_link_order *p;  size_t outsymalloc;  struct generic_write_global_symbol_info wginfo;  bfd_get_outsymbols (abfd) = (asymbol **) NULL;  bfd_get_symcount (abfd) = 0;  outsymalloc = 0;  /* Mark all sections which will be included in the output file.  */  for (o = abfd->sections; o != NULL; o = o->next)    for (p = o->link_order_head; p != NULL; p = p->next)      if (p->type == bfd_indirect_link_order)	p->u.indirect.section->linker_mark = true;  /* Build the output symbol table.  */  for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)    if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))      return false;  /* Accumulate the global symbols.  */  wginfo.info = info;  wginfo.output_bfd = abfd;  wginfo.psymalloc = &outsymalloc;  _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info),				   _bfd_generic_link_write_global_symbol,				   (PTR) &wginfo);  /* Make sure we have a trailing NULL pointer on OUTSYMBOLS.  We     shouldn't really need one, since we have SYMCOUNT, but some old     code still expects one.  */  if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))    return false;  if (info->relocateable)    {      /* Allocate space for the output relocs for each section.  */      for (o = abfd->se

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -