ldmain.c

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

C
1,328
字号
    }  END_PROGRESS (program_name);  if (config.stats)    {#ifdef HAVE_SBRK      char *lim = (char *) sbrk (0);#endif      long run_time = get_run_time () - start_time;      fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"),	       program_name, run_time / 1000000, run_time % 1000000);#ifdef HAVE_SBRK      fprintf (stderr, _("%s: data size %ld\n"), program_name,	       (long) (lim - (char *) &environ));#endif    }  /* Prevent remove_output from doing anything, after a successful link.  */  output_filename = NULL;  xexit (0);  return 0;}/* We need to find any explicitly given emulation in order to initialize the   state that's needed by the lex&yacc argument parser (parse_args).  */static char *get_emulation (argc, argv)     int argc;     char **argv;{  char *emulation;  int i;  emulation = getenv (EMULATION_ENVIRON);  if (emulation == NULL)    emulation = DEFAULT_EMULATION;  for (i = 1; i < argc; i++)    {      if (!strncmp (argv[i], "-m", 2))	{	  if (argv[i][2] == '\0')	    {	      /* -m EMUL */	      if (i < argc - 1)		{		  emulation = argv[i + 1];		  i++;		}	      else		{		  einfo (_("%P%F: missing argument to -m\n"));		}	    }	  else if (strcmp (argv[i], "-mips1") == 0		   || strcmp (argv[i], "-mips2") == 0		   || strcmp (argv[i], "-mips3") == 0		   || strcmp (argv[i], "-mips4") == 0)	    {	      /* FIXME: The arguments -mips1, -mips2 and -mips3 are		 passed to the linker by some MIPS compilers.  They		 generally tell the linker to use a slightly different		 library path.  Perhaps someday these should be		 implemented as emulations; until then, we just ignore		 the arguments and hope that nobody ever creates		 emulations named ips1, ips2 or ips3.  */	    }	  else if (strcmp (argv[i], "-m486") == 0)	    {	      /* FIXME: The argument -m486 is passed to the linker on		 some Linux systems.  Hope that nobody creates an		 emulation named 486.  */	    }	  else	    {	      /* -mEMUL */	      emulation = &argv[i][2];	    }	}    }  return emulation;}/* If directory DIR contains an "ldscripts" subdirectory,   add DIR to the library search path and return true,   else return false.  */static booleancheck_for_scripts_dir (dir)     char *dir;{  size_t dirlen;  char *buf;  struct stat s;  boolean res;  dirlen = strlen (dir);  /* sizeof counts the terminating NUL.  */  buf = (char *) xmalloc (dirlen + sizeof ("/ldscripts"));  sprintf (buf, "%s/ldscripts", dir);  res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);  free (buf);  if (res)    ldfile_add_library_path (dir, false);  return res;}/* Set the default directory for finding script files.   Libraries will be searched for here too, but that's ok.   We look for the "ldscripts" directory in:   SCRIPTDIR (passed from Makefile)   the dir where this program is (for using it from the build tree)   the dir where this program is/../lib (for installing the tool suite elsewhere) */static voidset_scripts_dir (){  char *end, *dir;  size_t dirlen;  if (check_for_scripts_dir (SCRIPTDIR))    /* We've been installed normally.  */    return;  /* Look for "ldscripts" in the dir where our binary is.  */  end = strrchr (program_name, '/');#ifdef HAVE_DOS_BASED_FILE_SYSTEM  {    /* We could have \foo\bar, or /foo\bar.  */    char *bslash = strrchr (program_name, '\\');    if (end == NULL || (bslash != NULL && bslash > end))      end = bslash;  }#endif  if (end == NULL)    {      /* Don't look for ldscripts in the current directory.  There is         too much potential for confusion.  */      return;    }  dirlen = end - program_name;  /* Make a copy of program_name in dir.     Leave room for later "/../lib".  */  dir = (char *) xmalloc (dirlen + 8);  strncpy (dir, program_name, dirlen);  dir[dirlen] = '\0';  if (check_for_scripts_dir (dir))    /* Don't free dir.  */    return;  /* Look for "ldscripts" in <the dir where our binary is>/../lib.  */  strcpy (dir + dirlen, "/../lib");  if (check_for_scripts_dir (dir))    return;  /* Well, we tried.  */  free (dir);}voidadd_ysym (name)     const char *name;{  if (link_info.notice_hash == (struct bfd_hash_table *) NULL)    {      link_info.notice_hash = ((struct bfd_hash_table *)			       xmalloc (sizeof (struct bfd_hash_table)));      if (! bfd_hash_table_init_n (link_info.notice_hash,				   bfd_hash_newfunc,				   61))	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));    }  if (bfd_hash_lookup (link_info.notice_hash, name, true, true)      == (struct bfd_hash_entry *) NULL)    einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));}/* Record a symbol to be wrapped, from the --wrap option.  */voidadd_wrap (name)     const char *name;{  if (link_info.wrap_hash == NULL)    {      link_info.wrap_hash = ((struct bfd_hash_table *)			     xmalloc (sizeof (struct bfd_hash_table)));      if (! bfd_hash_table_init_n (link_info.wrap_hash,				   bfd_hash_newfunc,				   61))	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));    }  if (bfd_hash_lookup (link_info.wrap_hash, name, true, true) == NULL)    einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));}/* Handle the -retain-symbols-file option.  */voidadd_keepsyms_file (filename)     const char *filename;{  FILE *file;  char *buf;  size_t bufsize;  int c;  if (link_info.strip == strip_some)    einfo (_("%X%P: error: duplicate retain-symbols-file\n"));  file = fopen (filename, "r");  if (file == (FILE *) NULL)    {      bfd_set_error (bfd_error_system_call);      einfo ("%X%P: %s: %E\n", filename);      return;    }  link_info.keep_hash = ((struct bfd_hash_table *)			 xmalloc (sizeof (struct bfd_hash_table)));  if (! bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc))    einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));  bufsize = 100;  buf = (char *) xmalloc (bufsize);  c = getc (file);  while (c != EOF)    {      while (isspace (c))	c = getc (file);      if (c != EOF)	{	  size_t len = 0;	  while (! isspace (c) && c != EOF)	    {	      buf[len] = c;	      ++len;	      if (len >= bufsize)		{		  bufsize *= 2;		  buf = xrealloc (buf, bufsize);		}	      c = getc (file);	    }	  buf[len] = '\0';	  if (bfd_hash_lookup (link_info.keep_hash, buf, true, true)	      == (struct bfd_hash_entry *) NULL)	    einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n"));	}    }  if (link_info.strip != strip_none)    einfo (_("%P: `-retain-symbols-file' overrides `-s' and `-S'\n"));  link_info.strip = strip_some;}/* Callbacks from the BFD linker routines.  *//* This is called when BFD has decided to include an archive member in   a link.  */static booleanadd_archive_element (info, abfd, name)     struct bfd_link_info *info ATTRIBUTE_UNUSED;     bfd *abfd;     const char *name;{  lang_input_statement_type *input;  input = ((lang_input_statement_type *)	   xmalloc (sizeof (lang_input_statement_type)));  input->filename = abfd->filename;  input->local_sym_name = abfd->filename;  input->the_bfd = abfd;  input->asymbols = NULL;  input->next = NULL;  input->just_syms_flag = false;  input->loaded = false;  input->search_dirs_flag = false;  /* FIXME: The following fields are not set: header.next,     header.type, closed, passive_position, symbol_count,     next_real_file, is_archive, target, real.  This bit of code is     from the old decode_library_subfile function.  I don't know     whether any of those fields matters.  */  ldlang_add_file (input);  if (config.map_file != (FILE *) NULL)    {      static boolean header_printed;      struct bfd_link_hash_entry *h;      bfd *from;      int len;      h = bfd_link_hash_lookup (link_info.hash, name, false, false, true);      if (h == NULL)	from = NULL;      else	{	  switch (h->type)	    {	    default:	      from = NULL;	      break;	    case bfd_link_hash_defined:	    case bfd_link_hash_defweak:	      from = h->u.def.section->owner;	      break;	    case bfd_link_hash_undefined:	    case bfd_link_hash_undefweak:	      from = h->u.undef.abfd;	      break;	    case bfd_link_hash_common:	      from = h->u.c.p->section->owner;	      break;	    }	}      if (! header_printed)	{	  char buf[100];	  sprintf (buf, "%-29s %s\n\n", _("Archive member included"),		   _("because of file (symbol)"));	  minfo ("%s", buf);	  header_printed = true;	}      if (bfd_my_archive (abfd) == NULL)	{	  minfo ("%s", bfd_get_filename (abfd));	  len = strlen (bfd_get_filename (abfd));	}      else	{	  minfo ("%s(%s)", bfd_get_filename (bfd_my_archive (abfd)),		 bfd_get_filename (abfd));	  len = (strlen (bfd_get_filename (bfd_my_archive (abfd)))		 + strlen (bfd_get_filename (abfd))		 + 2);	}      if (len >= 29)	{	  print_nl ();	  len = 0;	}      while (len < 30)	{	  print_space ();	  ++len;	}      if (from != NULL)	minfo ("%B ", from);      if (h != NULL)	minfo ("(%T)\n", h->root.string);      else	minfo ("(%s)\n", name);    }  if (trace_files || trace_file_tries)    info_msg ("%I\n", input);  return true;}/* This is called when BFD has discovered a symbol which is defined   multiple times.  */static booleanmultiple_definition (info, name, obfd, osec, oval, nbfd, nsec, nval)     struct bfd_link_info *info ATTRIBUTE_UNUSED;     const char *name;     bfd *obfd;     asection *osec;     bfd_vma oval;     bfd *nbfd;     asection *nsec;     bfd_vma nval;{  /* If either section has the output_section field set to     bfd_abs_section_ptr, it means that the section is being     discarded, and this is not really a multiple definition at all.     FIXME: It would be cleaner to somehow ignore symbols defined in     sections which are being discarded.  */  if ((osec->output_section != NULL       && ! bfd_is_abs_section (osec)       && bfd_is_abs_section (osec->output_section))      || (nsec->output_section != NULL	  && ! bfd_is_abs_section (nsec)	  && bfd_is_abs_section (nsec->output_section)))    return true;  einfo (_("%X%C: multiple definition of `%T'\n"),	 nbfd, nsec, nval, name);  if (obfd != (bfd *) NULL)    einfo (_("%D: first defined here\n"), obfd, osec, oval);  if (command_line.relax)    {      einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n"));      command_line.relax = 0;    }  return true;}/* This is called when there is a definition of a common symbol, or   when a common symbol is found for a symbol that is already defined,   or when two common symbols are found.  We only do something if   -warn-common was used.  */static booleanmultiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize)     struct bfd_link_info *info ATTRIBUTE_UNUSED;     const char *name;     bfd *obfd;     enum bfd_link_hash_type otype;     bfd_vma osize;     bfd *nbfd;

⌨️ 快捷键说明

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