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