📄 collect2.c
字号:
/* If we look for a program in the compiler directories, we just use the short name, since these directories are already system-specific. But it we look for a took in the system directories, we need to qualify the program name with the target machine. */ full_ld_suffix = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1); strcpy (full_ld_suffix, target_machine); strcat (full_ld_suffix, "-"); strcat (full_ld_suffix, ld_suffix); full_real_ld_suffix = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1); strcpy (full_real_ld_suffix, target_machine); strcat (full_real_ld_suffix, "-"); strcat (full_real_ld_suffix, real_ld_suffix);#if 0 full_gld_suffix = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1); strcpy (full_gld_suffix, target_machine); strcat (full_gld_suffix, "-"); strcat (full_gld_suffix, gld_suffix);#endif full_nm_suffix = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1); strcpy (full_nm_suffix, target_machine); strcat (full_nm_suffix, "-"); strcat (full_nm_suffix, nm_suffix); full_gnm_suffix = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1); strcpy (full_gnm_suffix, target_machine); strcat (full_gnm_suffix, "-"); strcat (full_gnm_suffix, gnm_suffix);#ifdef LDD_SUFFIX full_ldd_suffix = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1); strcpy (full_ldd_suffix, target_machine); strcat (full_ldd_suffix, "-"); strcat (full_ldd_suffix, ldd_suffix);#endif full_strip_suffix = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1); strcpy (full_strip_suffix, target_machine); strcat (full_strip_suffix, "-"); strcat (full_strip_suffix, strip_suffix); full_gstrip_suffix = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1); strcpy (full_gstrip_suffix, target_machine); strcat (full_gstrip_suffix, "-"); strcat (full_gstrip_suffix, gstrip_suffix);#endif /* CROSS_COMPILE */ /* Try to discover a valid linker/nm/strip to use. */ /* Maybe we know the right file to use (if not cross). */#ifdef REAL_LD_FILE_NAME ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME); if (ld_file_name == 0)#endif /* Search the (target-specific) compiler dirs for ld'. */ ld_file_name = find_a_file (&cpath, real_ld_suffix); /* Likewise for `collect-ld'. */ if (ld_file_name == 0) ld_file_name = find_a_file (&cpath, collect_ld_suffix); /* Search the compiler directories for `ld'. We have protection against recursive calls in find_a_file. */ if (ld_file_name == 0) ld_file_name = find_a_file (&cpath, ld_suffix); /* Search the ordinary system bin directories for `ld' (if native linking) or `TARGET-ld' (if cross). */ if (ld_file_name == 0) ld_file_name = find_a_file (&path, full_ld_suffix); /* If we've invoked ourselves, try again with LD_FILE_NAME. */ if (collect_names != 0) { if (ld_file_name != 0) { argv[0] = ld_file_name; execvp (argv[0], argv); } fatal ("cannot find `ld'"); }#ifdef REAL_NM_FILE_NAME nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); if (nm_file_name == 0)#endif nm_file_name = find_a_file (&cpath, gnm_suffix); if (nm_file_name == 0) nm_file_name = find_a_file (&path, full_gnm_suffix); if (nm_file_name == 0) nm_file_name = find_a_file (&cpath, nm_suffix); if (nm_file_name == 0) nm_file_name = find_a_file (&path, full_nm_suffix);#ifdef LDD_SUFFIX ldd_file_name = find_a_file (&cpath, ldd_suffix); if (ldd_file_name == 0) ldd_file_name = find_a_file (&path, full_ldd_suffix);#endif#ifdef REAL_STRIP_FILE_NAME strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME); if (strip_file_name == 0)#endif strip_file_name = find_a_file (&cpath, gstrip_suffix); if (strip_file_name == 0) strip_file_name = find_a_file (&path, full_gstrip_suffix); if (strip_file_name == 0) strip_file_name = find_a_file (&cpath, strip_suffix); if (strip_file_name == 0) strip_file_name = find_a_file (&path, full_strip_suffix); /* Determine the full path name of the C compiler to use. */ c_file_name = getenv ("COLLECT_GCC"); if (c_file_name == 0) {#ifdef CROSS_COMPILE c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1); strcpy (c_file_name, target_machine); strcat (c_file_name, "-gcc");#else c_file_name = "gcc";#endif } p = find_a_file (&cpath, c_file_name); /* Here it should be safe to use the system search path since we should have already qualified the name of the compiler when it is needed. */ if (p == 0) p = find_a_file (&path, c_file_name); if (p) c_file_name = p; *ld1++ = *ld2++ = ld_file_name; /* Make temp file names. */ temp_filename = choose_temp_base (); temp_filename_length = strlen (temp_filename); c_file = xcalloc (temp_filename_length + sizeof (".c"), 1); o_file = xcalloc (temp_filename_length + sizeof (".o"), 1); export_file = xmalloc (temp_filename_length + sizeof (".x")); ldout = xmalloc (temp_filename_length + sizeof (".ld")); sprintf (ldout, "%s.ld", temp_filename); sprintf (c_file, "%s.c", temp_filename); sprintf (o_file, "%s.o", temp_filename); sprintf (export_file, "%s.x", temp_filename); *c_ptr++ = c_file_name; *c_ptr++ = "-c"; *c_ptr++ = "-o"; *c_ptr++ = o_file; /* !!! When GCC calls collect2, it does not know whether it is calling collect2 or ld. So collect2 cannot meaningfully understand any options except those ld understands. If you propose to make GCC pass some other option, just imagine what will happen if ld is really ld!!! */ /* Parse arguments. Remember output file spec, pass the rest to ld. */ /* After the first file, put in the c++ rt0. */ first_file = 1; while ((arg = *++argv) != (char *) 0) { *ld1++ = *ld2++ = arg; if (arg[0] == '-') { switch (arg[1]) { case 'd': if (!strcmp (arg, "-debug")) { debug = 1; vflag = 1; ld1--; ld2--; } break; case 'l': if (first_file) { /* place o_file BEFORE this argument! */ first_file = 0; ld2--; *ld2++ = o_file; *ld2++ = arg; } break; case 'o': if (arg[2] == '\0') output_file = *ld1++ = *ld2++ = *++argv; else output_file = &arg[2]; break; case 'r': if (arg[2] == '\0') rflag = 1; break; case 's': if (arg[2] == '\0' && do_collecting) { /* We must strip after the nm run, otherwise C++ linking won't work. Thus we strip in the second ld run, or else with strip if there is no second ld run. */ strip_flag = 1; ld1--; } break; case 'v': if (arg[2] == '\0') vflag = 1; break; } } else if ((p = rindex (arg, '.')) != (char *) 0 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0)) { if (first_file) { first_file = 0; if (p[1] == 'o') *ld2++ = o_file; else { /* place o_file BEFORE this argument! */ ld2--; *ld2++ = o_file; *ld2++ = arg; } } if (p[1] == 'o') *object++ = arg; } } /* Get any options that the upper GCC wants to pass to the sub-GCC. */ p = (char *) getenv ("COLLECT_GCC_OPTIONS"); while (p && *p) { char *q = extract_string (&p); if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); if (strncmp (q, "-shared", sizeof ("shared") - 1) == 0) shared_obj = 1; } obstack_free (&temporary_obstack, temporary_firstobj); *c_ptr++ = "-fno-exceptions";#ifdef COLLECT_EXPORT_LIST /* The AIX linker will discard static constructors in object files if nothing else in the file is referenced, so look at them first. */ while (object_lst < object) scan_prog_file (*object_lst++, PASS_OBJ); { char *buf = alloca (strlen (export_file) + 5); sprintf (buf, "-bE:%s", export_file); *ld1++ = buf; *ld2++ = buf; exportf = fopen (export_file, "w"); if (exportf == (FILE *) 0) fatal_perror ("%s", export_file); write_export_file (exportf); if (fclose (exportf)) fatal_perror ("closing %s", export_file); }#endif *c_ptr++ = c_file; *object = *c_ptr = *ld1 = (char *) 0; if (vflag) { fprintf (stderr, "collect2 version %s", version_string);#ifdef TARGET_VERSION TARGET_VERSION;#endif fprintf (stderr, "\n"); } if (debug) { char *ptr; fprintf (stderr, "ld_file_name = %s\n", (ld_file_name ? ld_file_name : "not found")); fprintf (stderr, "c_file_name = %s\n", (c_file_name ? c_file_name : "not found")); fprintf (stderr, "nm_file_name = %s\n", (nm_file_name ? nm_file_name : "not found"));#ifdef LDD_SUFFIX fprintf (stderr, "ldd_file_name = %s\n", (ldd_file_name ? ldd_file_name : "not found"));#endif fprintf (stderr, "strip_file_name = %s\n", (strip_file_name ? strip_file_name : "not found")); fprintf (stderr, "c_file = %s\n", (c_file ? c_file : "not found")); fprintf (stderr, "o_file = %s\n", (o_file ? o_file : "not found")); ptr = getenv ("COLLECT_NAMES"); if (ptr) fprintf (stderr, "COLLECT_NAMES = %s\n", ptr); ptr = getenv ("COLLECT_GCC_OPTIONS"); if (ptr) fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr); ptr = getenv ("COLLECT_GCC"); if (ptr) fprintf (stderr, "COLLECT_GCC = %s\n", ptr); ptr = getenv ("COMPILER_PATH"); if (ptr) fprintf (stderr, "COMPILER_PATH = %s\n", ptr); ptr = getenv ("LIBRARY_PATH"); if (ptr) fprintf (stderr, "LIBRARY_PATH = %s\n", ptr); fprintf (stderr, "\n"); } /* Load the program, searching all libraries. */ collect_execute ("ld", ld1_argv, ldout); do_wait ("ld"); dump_file (ldout); unlink (ldout); /* If -r or they'll be run via some other method, don't build the constructor or destructor list, just return now. */ if (rflag || ! do_collecting) return 0; /* Examine the namelist with nm and search it for static constructors and destructors to call. Write the constructor and destructor tables to a .s file and reload. */ scan_prog_file (output_file, PASS_FIRST);#ifdef SCAN_LIBRARIES scan_libraries (output_file);#endif if (debug) { fprintf (stderr, "%d constructor(s) found\n", constructors.number); fprintf (stderr, "%d destructor(s) found\n", destructors.number); } if (constructors.number == 0 && destructors.number == 0 && frame_tables.number == 0#ifdef SCAN_LIBRARIES /* If we will be running these functions ourselves, we want to emit stubs into the shared library so that we don't have to relink dependent programs when we add static objects. */ && ! shared_obj#endif ) { /* Strip now if it was requested on the command line. */ if (strip_flag) { char **strip_argv = (char **) xcalloc (sizeof (char *), 3); strip_argv[0] = strip_file_name; strip_argv[1] = output_file; strip_argv[2] = (char *) 0; fork_execute ("strip", strip_argv); }#ifdef COLLECT_EXPORT_LIST maybe_unlink (export_file);#endif return 0; } maybe_unlink(output_file); outf = fopen (c_file, "w"); if (outf == (FILE *) 0) fatal_perror ("%s", c_file); write_c_file (outf, c_file); if (fclose (outf)) fatal_perror ("closing %s", c_file); /* Tell the linker that we have initializer and finalizer functions. */#ifdef LD_INIT_SWITCH *ld2++ = LD_INIT_SWITCH; *ld2++ = initname; *ld2++ = LD_FINI_SWITCH; *ld2++ = fininame;#endif *ld2 = (char*) 0;#ifdef COLLECT_EXPORT_LIST if (shared_obj) { add_to_list (&exports, initname); add_to_list (&exports, fininame); add_to_list (&exports, "_GLOBAL__DI"); add_to_list (&exports, "_GLOBAL__DD"); exportf = fopen (export_file, "w"); if (exportf == (FILE *) 0) fatal_perror ("%s", export_file); write_export_file (exportf); if (fclose (exportf)) fatal_perror ("closing %s", export_file); }#endif if (debug) { fprintf (stderr, "\n========== output_file = %s, c_file = %s\n", output_file, c_file); write_c_file (stderr, "stderr"); fprintf (stderr, "========== end of c_file\n\n");#ifdef COLLECT_EXPORT_LIST fprintf (stderr, "\n========== export_file = %s\n", export_file); write_export_file (stderr); fprintf (stderr, "========== end of export_file\n\n");#endif } /* Assemble the constructor and destructor tables. Link the tables in with the rest of the program. */ fork_execute ("gcc", c_argv); fork_execute ("ld", ld2_argv); /* Let scan_prog_file do any final mods (OSF/rose needs this for constructors/destructors in shared libraries. */ scan_prog_file (output_file, PASS_SECOND); maybe_unlink (c_file); maybe_unlink (o_file); maybe_unlink (export_file); return 0;}/* Wait for a process to finish, and exit if a non-zero status is found. */intcollect_wait (prog) char *prog;{ int status; wait (&status); if (status) { if (WIFSIGNALED (status)) { int sig = WTERMSIG (status);#ifdef NO_SYS_SIGLIST error ("%s terminated with signal %d %s", prog, sig, (status & 0200) ? ", core dumped" : "");#else error ("%s terminated with signal %d [%s]%s", prog, sig, sys_siglist[sig], (status & 0200) ? ", core dumped" : "");#endif collect_exit (FATAL_EXIT_CODE); } if (WIFEXITED (status)) return WEXITSTATUS (status); } return 0;}static voiddo_wait (prog) char *prog;{ int ret = collect_wait (prog); if (ret != 0) { error ("%s returned %d exit status", prog, ret); collect_exit (ret); }}/* Fork and execute a program, and wait for the reply. */voidcollect_execute (prog, argv, redir) char *prog; char **argv; char *redir;{ int pid; if (vflag || debug) { char **p_argv; char *str; if (argv[0]) fprintf (stderr, "%s", argv[0]); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -