mpw-elfmips.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,443 行 · 第 1/4 页

C
1,443
字号
	}    }}/* See if an input file matches a DT_NEEDED entry by running stat on   the file.  */static voidgldelf32ebmip_stat_needed (s)     lang_input_statement_type *s;{  struct stat st;  const char *suffix;  const char *soname;  const char *f;  if (global_found)    return;  if (s->the_bfd == NULL)    return;  if (bfd_stat (s->the_bfd, &st) != 0)    {      einfo (_("%P:%B: bfd_stat failed: %E\n"), s->the_bfd);      return;    }  if (st.st_dev == global_stat.st_dev      && st.st_ino == global_stat.st_ino)    {      global_found = true;      return;    }  /* We issue a warning if it looks like we are including two     different versions of the same shared library.  For example,     there may be a problem if -lc picks up libc.so.6 but some other     shared library has a DT_NEEDED entry of libc.so.5.  This is a     hueristic test, and it will only work if the name looks like     NAME.so.VERSION.  FIXME: Depending on file names is error-prone.     If we really want to issue warnings about mixing version numbers     of shared libraries, we need to find a better way.  */  if (strchr (global_needed->name, '/') != NULL)    return;  suffix = strstr (global_needed->name, ".so.");  if (suffix == NULL)    return;  suffix += sizeof ".so." - 1;  soname = bfd_elf_get_dt_soname (s->the_bfd);  if (soname == NULL)    soname = s->filename;  f = strrchr (soname, '/');  if (f != NULL)    ++f;  else    f = soname;  if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0)    einfo (_("%P: warning: %s, needed by %B, may conflict with %s\n"),	   global_needed->name, global_needed->by, f);}/* This is called after the sections have been attached to output   sections, but before any sizes or addresses have been set.  */static voidgldelf32ebmip_before_allocation (){  const char *rpath;  asection *sinterp;  /* If we are going to make any variable assignments, we need to let     the ELF backend know about them in case the variables are     referred to by dynamic objects.  */  lang_for_each_statement (gldelf32ebmip_find_statement_assignment);  /* Let the ELF backend work out the sizes of any sections required     by dynamic linking.  */  rpath = command_line.rpath;  if (rpath == NULL)    rpath = (const char *) getenv ("LD_RUN_PATH");  if (! (bfd_elf32_size_dynamic_sections	 (output_bfd, command_line.soname, rpath,	  command_line.export_dynamic, command_line.filter_shlib,	  (const char * const *) command_line.auxiliary_filters,	  &link_info, &sinterp, lang_elf_version_info)))    einfo (_("%P%F: failed to set dynamic section sizes: %E\n"));  /* Let the user override the dynamic linker we are using.  */  if (command_line.interpreter != NULL      && sinterp != NULL)    {      sinterp->contents = (bfd_byte *) command_line.interpreter;      sinterp->_raw_size = strlen (command_line.interpreter) + 1;    }  /* Look for any sections named .gnu.warning.  As a GNU extensions,     we treat such sections as containing warning messages.  We print     out the warning message, and then zero out the section size so     that it does not get copied into the output file.  */  {    LANG_FOR_EACH_INPUT_STATEMENT (is)      {	asection *s;	bfd_size_type sz;	char *msg;	boolean ret;	if (is->just_syms_flag)	  continue;	s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");	if (s == NULL)	  continue;	sz = bfd_section_size (is->the_bfd, s);	msg = xmalloc ((size_t) sz + 1);	if (! bfd_get_section_contents (is->the_bfd, s, msg, (file_ptr) 0, sz))	  einfo (_("%F%B: Can't read contents of section .gnu.warning: %E\n"),		 is->the_bfd);	msg[sz] = '\0';	ret = link_info.callbacks->warning (&link_info, msg,					    (const char *) NULL,					    is->the_bfd, (asection *) NULL,					    (bfd_vma) 0);	ASSERT (ret);	free (msg);	/* Clobber the section size, so that we don't waste copying the	   warning into the output file.  */	s->_raw_size = 0;      }  }}/* This is called by the before_allocation routine via   lang_for_each_statement.  It locates any assignment statements, and   tells the ELF backend about them, in case they are assignments to   symbols which are referred to by dynamic objects.  */static voidgldelf32ebmip_find_statement_assignment (s)     lang_statement_union_type *s;{  if (s->header.type == lang_assignment_statement_enum)    gldelf32ebmip_find_exp_assignment (s->assignment_statement.exp);}/* Look through an expression for an assignment statement.  */static voidgldelf32ebmip_find_exp_assignment (exp)     etree_type *exp;{  struct bfd_link_hash_entry *h;  switch (exp->type.node_class)    {    case etree_provide:    case etree_provided:      h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,				false, false, false);      if (h == NULL)	break;      /* We call record_link_assignment even if the symbol is defined.	 This is because if it is defined by a dynamic object, we	 actually want to use the value defined by the linker script,	 not the value from the dynamic object (because we are setting	 symbols like etext).  If the symbol is defined by a regular	 object, then, as it happens, calling record_link_assignment	 will do no harm.  */      /* Fall through.  */    case etree_assign:      if (strcmp (exp->assign.dst, ".") != 0)	{	  if (! (bfd_elf32_record_link_assignment		 (output_bfd, &link_info, exp->assign.dst,		  exp->type.node_class != etree_assign ? true : false)))	    einfo (_("%P%F: failed to record assignment to %s: %E\n"),		   exp->assign.dst);	}      gldelf32ebmip_find_exp_assignment (exp->assign.src);      break;    case etree_binary:      gldelf32ebmip_find_exp_assignment (exp->binary.lhs);      gldelf32ebmip_find_exp_assignment (exp->binary.rhs);      break;    case etree_trinary:      gldelf32ebmip_find_exp_assignment (exp->trinary.cond);      gldelf32ebmip_find_exp_assignment (exp->trinary.lhs);      gldelf32ebmip_find_exp_assignment (exp->trinary.rhs);      break;    case etree_unary:      gldelf32ebmip_find_exp_assignment (exp->unary.child);      break;    default:      break;    }}/* Place an orphan section.  We use this to put random SHF_ALLOC   sections in the right segment.  */static asection *hold_section;static lang_output_section_statement_type *hold_use;static lang_output_section_statement_type *hold_text;static lang_output_section_statement_type *hold_rodata;static lang_output_section_statement_type *hold_data;static lang_output_section_statement_type *hold_bss;static lang_output_section_statement_type *hold_rel;/*ARGSUSED*/static booleangldelf32ebmip_place_orphan (file, s)     lang_input_statement_type *file;     asection *s;{  lang_output_section_statement_type *place;  asection *snew, **pps;  lang_statement_list_type *old;  lang_statement_list_type add;  etree_type *address;  const char *secname, *ps;  lang_output_section_statement_type *os;  if ((s->flags & SEC_ALLOC) == 0)    return false;  /* Look through the script to see where to place this section.  */  hold_section = s;  hold_use = NULL;  lang_for_each_statement (gldelf32ebmip_place_section);  if (hold_use != NULL)    {      /* We have already placed a section with this name.  */      wild_doit (&hold_use->children, s, hold_use, file);      return true;    }  secname = bfd_get_section_name (s->owner, s);  /* If this is a final link, then always put .gnu.warning.SYMBOL     sections into the .text section to get them out of the way.  */  if (! link_info.shared      && ! link_info.relocateable      && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0      && hold_text != NULL)    {      wild_doit (&hold_text->children, s, hold_text, file);      return true;    }  /* Decide which segment the section should go in based on the     section name and section flags.  */  place = NULL;  if ((s->flags & SEC_HAS_CONTENTS) == 0      && hold_bss != NULL)    place = hold_bss;  else if ((s->flags & SEC_READONLY) == 0	   && hold_data != NULL)    place = hold_data;  else if (strncmp (secname, ".rel", 4) == 0	   && hold_rel != NULL)    place = hold_rel;  else if ((s->flags & SEC_CODE) == 0	   && (s->flags & SEC_READONLY) != 0	   && hold_rodata != NULL)    place = hold_rodata;  else if ((s->flags & SEC_READONLY) != 0	   && hold_text != NULL)    place = hold_text;  if (place == NULL)    return false;  /* Create the section in the output file, and put it in the right     place.  This shuffling is to make the output file look neater.  */  snew = bfd_make_section (output_bfd, secname);  if (snew == NULL)      einfo (_("%P%F: output format %s cannot represent section called %s\n"),	     output_bfd->xvec->name, secname);  if (place->bfd_section != NULL)    {      for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)	;      *pps = snew->next;      snew->next = place->bfd_section->next;      place->bfd_section->next = snew;    }  /* Start building a list of statements for this section.  */  old = stat_ptr;  stat_ptr = &add;  lang_list_init (stat_ptr);  /* If the name of the section is representable in C, then create     symbols to mark the start and the end of the section.  */  for (ps = secname; *ps != '\0'; ps++)    if (! isalnum (*ps) && *ps != '_')      break;  if (*ps == '\0' && config.build_constructors)    {      char *symname;      symname = (char *) xmalloc (ps - secname + sizeof "__start_");      sprintf (symname, "__start_%s", secname);      lang_add_assignment (exp_assop ('=', symname,				      exp_unop (ALIGN_K,						exp_intop ((bfd_vma) 1							   << s->alignment_power))));    }  if (! link_info.relocateable)    address = NULL;  else    address = exp_intop ((bfd_vma) 0);  lang_enter_output_section_statement (secname, address, 0,				       (bfd_vma) 0,				       (etree_type *) NULL,				       (etree_type *) NULL,				       (etree_type *) NULL);  os = lang_output_section_statement_lookup (secname);  wild_doit (&os->children, s, os, file);  lang_leave_output_section_statement    ((bfd_vma) 0, "*default*",     (struct lang_output_section_phdr_list *) NULL, "*default*");  stat_ptr = &add;  if (*ps == '\0' && config.build_constructors)    {      char *symname;      symname = (char *) xmalloc (ps - secname + sizeof "__stop_");      sprintf (symname, "__stop_%s", secname);      lang_add_assignment (exp_assop ('=', symname,				      exp_nameop (NAME, ".")));    }  /* Now stick the new statement list right after PLACE.  */  *add.tail = place->header.next;  place->header.next = add.head;  stat_ptr = old;  return true;}static void

⌨️ 快捷键说明

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