ldmain.c

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

C
1,328
字号
/* Main program of GNU linker.   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000   Free Software Foundation, Inc.   Written by Steve Chamberlain steve@cygnus.comThis file is part of GLD, the Gnu Linker.GLD is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GLD is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GLD; see the file COPYING.  If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA.  */#include "bfd.h"#include "sysdep.h"#include <stdio.h>#include <ctype.h>#include "libiberty.h"#include "progress.h"#include "bfdlink.h"#include "filenames.h"#include "ld.h"#include "ldmain.h"#include "ldmisc.h"#include "ldwrite.h"#include "ldgram.h"#include "ldexp.h"#include "ldlang.h"#include "ldlex.h"#include "ldfile.h"#include "ldemul.h"#include "ldctor.h"/* Somewhere above, sys/stat.h got included . . . .  */#if !defined(S_ISDIR) && defined(S_IFDIR)#define	S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)#endif#include <string.h>#ifdef HAVE_SBRK#ifdef NEED_DECLARATION_SBRKextern PTR sbrk ();#endif#endifstatic char *get_emulation PARAMS ((int, char **));static void set_scripts_dir PARAMS ((void));/* EXPORTS */char *default_target;const char *output_filename = "a.out";/* Name this program was invoked by.  */char *program_name;/* The file that we're creating.  */bfd *output_bfd = 0;/* Set by -G argument, for MIPS ECOFF target.  */int g_switch_value = 8;/* Nonzero means print names of input files as processed.  */boolean trace_files;/* Nonzero means same, but note open failures, too.  */boolean trace_file_tries;/* Nonzero means version number was printed, so exit successfully   instead of complaining if no input files are given.  */boolean version_printed;/* Nonzero means link in every member of an archive.  */boolean whole_archive;/* True if we should demangle symbol names.  */boolean demangling;args_type command_line;ld_config_type config;static void remove_output PARAMS ((void));static boolean check_for_scripts_dir PARAMS ((char *dir));static boolean add_archive_element PARAMS ((struct bfd_link_info *, bfd *,					    const char *));static boolean multiple_definition PARAMS ((struct bfd_link_info *,					    const char *,					    bfd *, asection *, bfd_vma,					    bfd *, asection *, bfd_vma));static boolean multiple_common PARAMS ((struct bfd_link_info *,					const char *, bfd *,					enum bfd_link_hash_type, bfd_vma,					bfd *, enum bfd_link_hash_type,					bfd_vma));static boolean add_to_set PARAMS ((struct bfd_link_info *,				   struct bfd_link_hash_entry *,				   bfd_reloc_code_real_type,				   bfd *, asection *, bfd_vma));static boolean constructor_callback PARAMS ((struct bfd_link_info *,					     boolean constructor,					     const char *name,					     bfd *, asection *, bfd_vma));static boolean warning_callback PARAMS ((struct bfd_link_info *,					 const char *, const char *, bfd *,					 asection *, bfd_vma));static void warning_find_reloc PARAMS ((bfd *, asection *, PTR));static boolean undefined_symbol PARAMS ((struct bfd_link_info *,					 const char *, bfd *,					 asection *, bfd_vma, boolean));static boolean reloc_overflow PARAMS ((struct bfd_link_info *, const char *,				       const char *, bfd_vma,				       bfd *, asection *, bfd_vma));static boolean reloc_dangerous PARAMS ((struct bfd_link_info *, const char *,					bfd *, asection *, bfd_vma));static boolean unattached_reloc PARAMS ((struct bfd_link_info *,					 const char *, bfd *, asection *,					 bfd_vma));static boolean notice PARAMS ((struct bfd_link_info *, const char *,			       bfd *, asection *, bfd_vma));static struct bfd_link_callbacks link_callbacks = {  add_archive_element,  multiple_definition,  multiple_common,  add_to_set,  constructor_callback,  warning_callback,  undefined_symbol,  reloc_overflow,  reloc_dangerous,  unattached_reloc,  notice};struct bfd_link_info link_info;static voidremove_output (){  if (output_filename)    {      if (output_bfd && output_bfd->iostream)	fclose ((FILE *) (output_bfd->iostream));      if (delete_output_file_on_failure)	unlink (output_filename);    }}intmain (argc, argv)     int argc;     char **argv;{  char *emulation;  long start_time = get_run_time ();#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)  setlocale (LC_MESSAGES, "");#endif  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  program_name = argv[0];  xmalloc_set_program_name (program_name);  START_PROGRESS (program_name, 0);  bfd_init ();  bfd_set_error_program_name (program_name);  xatexit (remove_output);  /* Set the default BFD target based on the configured target.  Doing     this permits the linker to be configured for a particular target,     and linked against a shared BFD library which was configured for     a different target.  The macro TARGET is defined by Makefile.  */  if (! bfd_set_default_target (TARGET))    {      einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET);      xexit (1);    }  /* Initialize the data about options.  */  trace_files = trace_file_tries = version_printed = false;  whole_archive = false;  config.build_constructors = true;  config.dynamic_link = false;  config.has_shared = false;  config.split_by_reloc = (unsigned) -1;  config.split_by_file = (bfd_size_type) -1;  command_line.force_common_definition = false;  command_line.interpreter = NULL;  command_line.rpath = NULL;  command_line.warn_mismatch = true;  command_line.check_section_addresses = true;  /* We initialize DEMANGLING based on the environment variable     COLLECT_NO_DEMANGLE.  The gcc collect2 program will demangle the     output of the linker, unless COLLECT_NO_DEMANGLE is set in the     environment.  Acting the same way here lets us provide the same     interface by default.  */  demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL;  link_info.callbacks = &link_callbacks;  link_info.relocateable = false;  link_info.emitrelocations = false;  link_info.shared = false;  link_info.symbolic = false;  link_info.static_link = false;  link_info.traditional_format = false;  link_info.optimize = false;  link_info.no_undefined = false;  link_info.allow_shlib_undefined = false;  link_info.strip = strip_none;  link_info.discard = discard_none;  link_info.keep_memory = true;  link_info.input_bfds = NULL;  link_info.create_object_symbols_section = NULL;  link_info.hash = NULL;  link_info.keep_hash = NULL;  link_info.notice_all = false;  link_info.notice_hash = NULL;  link_info.wrap_hash = NULL;  link_info.mpc860c0 = 0;  /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init     and _fini symbols.  We are compatible.  */  link_info.init_function = "_init";  link_info.fini_function = "_fini";  link_info.new_dtags = false;  link_info.flags = (bfd_vma) 0;  link_info.flags_1 = (bfd_vma) 0;  ldfile_add_arch ("");  config.make_executable = true;  force_make_executable = false;  config.magic_demand_paged = true;  config.text_read_only = true;  emulation = get_emulation (argc, argv);  ldemul_choose_mode (emulation);  default_target = ldemul_choose_target ();  lang_init ();  ldemul_before_parse ();  lang_has_input_file = false;  parse_args (argc, argv);  ldemul_set_symbols ();  if (link_info.relocateable)    {      if (command_line.gc_sections)	einfo ("%P%F: --gc-sections and -r may not be used together\n");      if (link_info.mpc860c0)	einfo (_("%P%F: -r and --mpc860c0 may not be used together\n"));      else if (command_line.relax)	einfo (_("%P%F: --relax and -r may not be used together\n"));      if (link_info.shared)	einfo (_("%P%F: -r and -shared may not be used together\n"));    }  /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols).  I     don't see how else this can be handled, since in this case we     must preserve all externally visible symbols.  */  if (link_info.relocateable && link_info.strip == strip_all)    {      link_info.strip = strip_debugger;      if (link_info.discard == discard_none)	link_info.discard = discard_all;    }  /* This essentially adds another -L directory so this must be done after     the -L's in argv have been processed.  */  set_scripts_dir ();  if (had_script == false)    {      /* Read the emulation's appropriate default script.  */      int isfile;      char *s = ldemul_get_script (&isfile);      if (isfile)	ldfile_open_command_file (s);      else	{	  if (trace_file_tries)	    {	      info_msg (_("using internal linker script:\n"));	      info_msg ("==================================================\n");	      info_msg (s);	      info_msg ("\n==================================================\n");	    }	  lex_string = s;	  lex_redirect (s);	}      parser_input = input_script;      yyparse ();      lex_string = NULL;    }  lang_final ();  if (lang_has_input_file == false)    {      if (version_printed)	xexit (0);      einfo (_("%P%F: no input files\n"));    }  if (trace_files)    {      info_msg (_("%P: mode %s\n"), emulation);    }  ldemul_after_parse ();  if (config.map_filename)    {      if (strcmp (config.map_filename, "-") == 0)	{	  config.map_file = stdout;	}      else	{	  config.map_file = fopen (config.map_filename, FOPEN_WT);	  if (config.map_file == (FILE *) NULL)	    {	      bfd_set_error (bfd_error_system_call);	      einfo (_("%P%F: cannot open map file %s: %E\n"),		     config.map_filename);	    }	}    }  lang_process ();  /* Print error messages for any missing symbols, for any warning     symbols, and possibly multiple definitions.  */  if (! link_info.relocateable)    {      /* Look for a text section and switch the readonly attribute in it.  */      asection *found = bfd_get_section_by_name (output_bfd, ".text");      if (found != (asection *) NULL)	{	  if (config.text_read_only)	    found->flags |= SEC_READONLY;	  else	    found->flags &= ~SEC_READONLY;	}    }  if (link_info.relocateable)    output_bfd->flags &= ~EXEC_P;  else    output_bfd->flags |= EXEC_P;  ldwrite ();  if (config.map_file != NULL)    lang_map ();  if (command_line.cref)    output_cref (config.map_file != NULL ? config.map_file : stdout);  if (nocrossref_list != NULL)    check_nocrossrefs ();  /* Even if we're producing relocateable output, some non-fatal errors should     be reported in the exit status.  (What non-fatal errors, if any, do we     want to ignore for relocateable output?)  */  if (config.make_executable == false && force_make_executable == false)    {      if (trace_files == true)	{	  einfo (_("%P: link errors found, deleting executable `%s'\n"),		 output_filename);	}      /* The file will be removed by remove_output.  */      xexit (1);    }  else    {      if (! bfd_close (output_bfd))	einfo (_("%F%B: final close failed: %E\n"), output_bfd);      /* If the --force-exe-suffix is enabled, and we're making an	 executable file and it doesn't end in .exe, copy it to one	 which does.  */      if (! link_info.relocateable && command_line.force_exe_suffix)	{	  int len = strlen (output_filename);	  if (len < 4	      || (strcasecmp (output_filename + len - 4, ".exe") != 0		  && strcasecmp (output_filename + len - 4, ".dll") != 0))	    {	      FILE *src;	      FILE *dst;	      const int bsize = 4096;	      char *buf = xmalloc (bsize);	      int l;	      char *dst_name = xmalloc (len + 5);	      strcpy (dst_name, output_filename);	      strcat (dst_name, ".exe");	      src = fopen (output_filename, FOPEN_RB);	      dst = fopen (dst_name, FOPEN_WB);	      if (!src)		einfo (_("%X%P: unable to open for source of copy `%s'\n"), output_filename);	      if (!dst)		einfo (_("%X%P: unable to open for destination of copy `%s'\n"), dst_name);	      while ((l = fread (buf, 1, bsize, src)) > 0)		{		  int done = fwrite (buf, 1, l, dst);		  if (done != l)		    {		      einfo (_("%P: Error writing file `%s'\n"), dst_name);		    }		}	      fclose (src);	      if (fclose (dst) == EOF)		{		  einfo (_("%P: Error closing file `%s'\n"), dst_name);		}	      free (dst_name);	      free (buf);	    }	}

⌨️ 快捷键说明

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