📄 collect2.c
字号:
/* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. Copyright (C) 1992 Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@osf.org), Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).This file is part of GNU CC.GNU CC 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.GNU CC 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 GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* Build tables of static constructors and destructors and run ld. */#include <sys/types.h>#include <stdio.h>#include <ctype.h>#include <errno.h>#include <signal.h>#include <sys/file.h>#include <sys/stat.h>#ifdef NO_WAIT_H#include <sys/wait.h>#endif#ifndef errnoextern int errno;#endif#define COLLECT#include "config.h"#ifndef __STDC__#define generic char#define const#else#define generic void#endif#ifdef USG#define vfork fork#endif#ifndef R_OK#define R_OK 4#define W_OK 2#define X_OK 1#endif/* On MSDOS, write temp files in current dir because there's no place else we can expect to use. */#if __MSDOS__#ifndef P_tmpdir#define P_tmpdir "./"#endif#endif/* On certain systems, we have code that works by scanning the object file directly. But this code uses system-specific header files and library functions, so turn it off in a cross-compiler. */#ifdef CROSS_COMPILE#undef OBJECT_FORMAT_COFF#undef OBJECT_FORMAT_ROSE#endif/* If we can't use a special method, use the ordinary one: run nm to find what symbols are present. In a cross-compiler, this means you need a cross nm, but that isn't quite as unpleasant as special headers. */#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)#define OBJECT_FORMAT_NONE#endif#ifdef OBJECT_FORMAT_COFF#include <a.out.h>#include <ar.h>#ifdef UMAX#include <sgs.h>#endif#ifdef _AIX#define ISCOFF(magic) \ ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC)#endif/* Many versions of ldfcn.h define these. */#ifdef FREAD#undef FREAD#undef FWRITE#endif#include <ldfcn.h>/* Mips-news overrides this macro. */#ifndef MY_ISCOFF#define MY_ISCOFF(X) ISCOFF (X)#endif#endif /* OBJECT_FORMAT_COFF */#ifdef OBJECT_FORMAT_ROSE#ifdef _OSF_SOURCE#define USE_MMAP#endif#ifdef USE_MMAP#include <sys/mman.h>#endif#include <unistd.h>#include <mach_o_format.h>#include <mach_o_header.h>#include <mach_o_vals.h>#include <mach_o_types.h>#endif /* OBJECT_FORMAT_ROSE */#ifdef OBJECT_FORMAT_NONE/* Default flags to pass to nm. */#ifndef NM_FLAGS#define NM_FLAGS "-p"#endif#endif /* OBJECT_FORMAT_NONE *//* Linked lists of constructor and destructor names. */struct id { struct id *next; int sequence; char name[1];};struct head{ struct id *first; struct id *last; int number;};/* Enumeration giving which pass this is for scanning the program file. */enum pass { PASS_FIRST, /* without constructors */ PASS_SECOND /* with constructors linked in */};#ifndef NO_SYS_SIGLISTextern char *sys_siglist[];#endifextern char *version_string;static int vflag; /* true if -v */static int rflag; /* true if -r */static int strip_flag; /* true if -s */static int debug; /* true if -debug */static int temp_filename_length; /* Length of temp_filename */static char *temp_filename; /* Base of temp filenames */static char *c_file; /* <xxx>.c for constructor/destructor list. */static char *o_file; /* <xxx>.o for constructor/destructor list. */static char *nm_file_name; /* pathname of nm */static char *strip_file_name; /* pathname of strip */static struct head constructors; /* list of constructors found */static struct head destructors; /* list of destructors found */extern char *getenv ();extern char *mktemp ();static void add_to_list ();static void scan_prog_file ();static void fork_execute ();static void do_wait ();static void write_c_file ();static void my_exit ();static void handler ();static void maybe_unlink ();static void choose_temp_base ();generic *xcalloc ();generic *xmalloc ();extern char *index ();extern char *rindex ();#ifdef NO_DUP2dup2 (oldfd, newfd) int oldfd; int newfd;{ int fdtmp[256]; int fdx = 0; int fd; if (oldfd == newfd) return 0; close (newfd); while ((fd = dup (oldfd)) != newfd) /* good enough for low fd's */ fdtmp[fdx++] = fd; while (fdx > 0) close (fdtmp[--fdx]);}#endifchar *my_strerror (e) int e;{ extern char *sys_errlist[]; extern int sys_nerr; static char buffer[30]; if (!e) return ""; if (e > 0 && e < sys_nerr) return sys_errlist[e]; sprintf (buffer, "Unknown error %d", e); return buffer;}/* Delete tempfiles and exit function. */static voidmy_exit (status) int status;{ if (c_file != 0 && c_file[0]) maybe_unlink (c_file); if (o_file != 0 && o_file[0]) maybe_unlink (o_file); exit (status);}/* Die when sys call fails. */static voidfatal_perror (string, arg1, arg2, arg3) char *string;{ int e = errno; fprintf (stderr, "collect: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, ": %s\n", my_strerror (e)); my_exit (1);}/* Just die. */static voidfatal (string, arg1, arg2, arg3) char *string;{ fprintf (stderr, "collect: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, "\n"); my_exit (1);}/* Write error message. */static voiderror (string, arg1, arg2, arg3, arg4) char *string;{ fprintf (stderr, "collect: "); fprintf (stderr, string, arg1, arg2, arg3, arg4); fprintf (stderr, "\n");}/* In case obstack is linked in, and abort is defined to fancy_abort, provide a default entry. */voidfancy_abort (){ fatal ("internal error");}static voidhandler (signo) int signo;{ if (c_file[0]) maybe_unlink (c_file); if (o_file[0]) maybe_unlink (o_file); signal (signo, SIG_DFL); kill (getpid (), signo);}generic *xcalloc (size1, size2) int size1, size2;{ generic *ptr = (generic *) calloc (size1, size2); if (ptr) return ptr; fatal ("out of memory"); return (generic *)0;}generic *xmalloc (size) int size;{ generic *ptr = (generic *) malloc (size); if (ptr) return ptr; fatal ("out of memory"); return (generic *)0;}/* Make a copy of a string INPUT with size SIZE. */char *savestring (input, size) char *input; int size;{ char *output = (char *) xmalloc (size + 1); bcopy (input, output, size); output[size] = 0; return output;}/* Decide whether the given symbol is: a constructor (1), a destructor (2), or neither (0). */static intis_ctor_dtor (s) char *s;{ struct names { char *name; int len; int ret; int two_underscores; }; register struct names *p; register int ch; register char *orig_s = s; static struct names special[] = {#ifdef NO_DOLLAR_IN_LABEL { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 }, { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },#else { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 }, { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },#endif#ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions. cfront has its own linker procedure to collect them; if collect2 gets them too, they get collected twice when the cfront procedure is run and the compiler used for linking happens to be GCC. */ { "sti__", sizeof ("sti__")-1, 1, 1 }, { "std__", sizeof ("std__")-1, 2, 1 },#endif /* CFRONT_LOSSAGE */ { NULL, 0, 0, 0 } }; while ((ch = *s) == '_') ++s; if (s == orig_s) return 0; for (p = &special[0]; p->len > 0; p++) { if (ch == p->name[0] && (!p->two_underscores || ((s - orig_s) >= 2)) && strncmp(s, p->name, p->len) == 0) { return p->ret; } } return 0;}/* Compute a string to use as the base of all temporary file names. It is substituted for %g. */static voidchoose_temp_base (){ char *base = getenv ("TMPDIR"); int len; if (base == (char *)0) {#ifdef P_tmpdir if (access (P_tmpdir, R_OK | W_OK) == 0) base = P_tmpdir;#endif if (base == (char *)0) { if (access ("/usr/tmp", R_OK | W_OK) == 0) base = "/usr/tmp/"; else base = "/tmp/"; } } len = strlen (base); temp_filename = xmalloc (len + sizeof("/ccXXXXXX")); strcpy (temp_filename, base); if (len > 0 && temp_filename[len-1] != '/') temp_filename[len++] = '/'; strcpy (temp_filename + len, "ccXXXXXX"); mktemp (temp_filename); temp_filename_length = strlen (temp_filename);}/* Main program. */intmain (argc, argv) int argc; char *argv[];{ char *outfile = "a.out"; char *arg; FILE *outf; char *ld_file_name; char *c_file_name; char *p; char *prefix; char **c_argv; char **c_ptr; char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2); char **ld1 = ld1_argv; char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+5); char **ld2 = ld2_argv; int first_file; int num_c_args = argc+7; int len; int clen;#ifdef DEBUG debug = 1; vflag = 1;#endif p = (char *) getenv ("COLLECT_GCC_OPTIONS"); if (p) while (*p) { char *q = p; while (*q && *q != ' ') q++; if (*p == '-' && p[1] == 'm') num_c_args++; if (*q) q++; p = q;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -