📄 collect2.c
字号:
/* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@cygnus.com), 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* Build tables of static constructors and destructors and run ld. */#include "config.h"#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#define COLLECT#include "demangle.h"#include "obstack.h"#ifndef errnoextern int errno;#endif#ifndef HAVE_STRERROR#if defined(bsd4_4) extern const char *const sys_errlist[];#elseextern char *sys_errlist[];#endifextern int sys_nerr;#elsechar *strerror();#endif/* Obstack allocation and deallocation routines. */#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free#if !defined (__STDC__) && !defined (const)#define const#endif#ifdef USG#define vfork fork#endif/* Add prototype support. */#ifndef PROTO#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)#define PROTO(ARGS) ARGS#else#define PROTO(ARGS) ()#endif#endif#ifndef R_OK#define R_OK 4#define W_OK 2#define X_OK 1#endif#ifndef WIFSIGNALED#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)#endif#ifndef WTERMSIG#define WTERMSIG(S) ((S) & 0x7f)#endif#ifndef WIFEXITED#define WIFEXITED(S) (((S) & 0xff) == 0)#endif#ifndef WEXITSTATUS#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)#endif/* On MSDOS, write temp files in current dir because there's no place else we can expect to use. */#ifdef __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. Likewise, the names of the utilities aren't correct for a cross-compiler; we have to hope that cross-versions are in the proper directories. */#ifdef CROSS_COMPILE#undef SUNOS4_SHARED_LIBRARIES#undef OBJECT_FORMAT_COFF#undef OBJECT_FORMAT_ROSE#undef MD_EXEC_PREFIX#undef REAL_LD_FILE_NAME#undef REAL_NM_FILE_NAME#undef REAL_STRIP_FILE_NAME#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/* Many versions of ldfcn.h define these. */#ifdef FREAD#undef FREAD#undef FWRITE#endif#include <ldfcn.h>/* Some systems have an ISCOFF macro, but others do not. In some cases the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines that either do not have an ISCOFF macro in /usr/include or for those where it is wrong. */#ifndef MY_ISCOFF#define MY_ISCOFF(X) ISCOFF (X)#endif#ifdef XCOFF_DEBUGGING_INFO#define XCOFF_SCAN_LIBS#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 *//* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to give the same symbol without quotes for an alternative entry point. You must define both, or neither. */#ifndef NAME__MAIN#define NAME__MAIN "__main"#define SYMBOL__MAIN __main#endif#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES || defined(XCOFF_SCAN_LIBS)#define SCAN_LIBRARIES#endif#ifdef USE_COLLECT2int do_collecting = 1;#elseint do_collecting = 0;#endif/* 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_OBJ, /* individual objects */ PASS_LIB, /* looking for shared libraries */ PASS_SECOND /* with constructors linked in */};#ifndef NO_SYS_SIGLIST#ifndef DONT_DECLARE_SYS_SIGLISTextern char *sys_siglist[];#endif#endifextern char *version_string;int vflag; /* true if -v */static int rflag; /* true if -r */static int strip_flag; /* true if -s */int debug; /* true if -debug */static int shared_obj; /* true if -shared */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 *export_file; /* <xxx>.x for AIX export list. */char *ldout; /* File for ld errors. */static char *output_file; /* Output file for ld. */static char *nm_file_name; /* pathname of nm */static char *ldd_file_name; /* pathname of ldd (or equivalent) */static char *strip_file_name; /* pathname of strip */char *c_file_name; /* pathname of gcc */static char *initname, *fininame; /* names of init and fini funcs */static struct head constructors; /* list of constructors found */static struct head destructors; /* list of destructors found */static struct head exports; /* list of exported symbols */struct obstack temporary_obstack;struct obstack permanent_obstack;char * temporary_firstobj;/* Defined in the automatically-generated underscore.c. */extern int prepends_underscore;extern char *getenv ();extern char *mktemp ();extern FILE *fdopen ();/* Structure to hold all the directories in which to search for files to execute. */struct prefix_list{ char *prefix; /* String to prepend to the path. */ struct prefix_list *next; /* Next in linked list. */};struct path_prefix{ struct prefix_list *plist; /* List of prefixes to try */ int max_len; /* Max length of a prefix in PLIST */ char *name; /* Name of this list (used in config stuff) */};void collect_exit PROTO((int));void collect_execute PROTO((char *, char **, char *));void dump_file PROTO((char *));static void handler PROTO((int));static int is_ctor_dtor PROTO((char *));static void choose_temp_base PROTO((void));static int is_in_prefix_list PROTO((struct path_prefix *, char *, int));static char *find_a_file PROTO((struct path_prefix *, char *));static void add_prefix PROTO((struct path_prefix *, char *));static void prefix_from_env PROTO((char *, struct path_prefix *));static void prefix_from_string PROTO((char *, struct path_prefix *));static void do_wait PROTO((char *));static void fork_execute PROTO((char *, char **));static void maybe_unlink PROTO((char *));static void add_to_list PROTO((struct head *, char *));static void write_list PROTO((FILE *, char *, struct id *));static void write_list_with_asm PROTO((FILE *, char *, struct id *));static void write_c_file PROTO((FILE *, char *));static void write_export_file PROTO((FILE *));static void scan_prog_file PROTO((char *, enum pass));static void scan_libraries PROTO((char *));char *xcalloc ();char *xmalloc ();extern char *index ();extern char *rindex ();extern void free ();#ifdef NO_DUP2intdup2 (oldfd, newfd) int oldfd; int newfd;{ int fdtmp[256]; int fdx = 0; int fd; if (oldfd == newfd) return oldfd; close (newfd); while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */ fdtmp[fdx++] = fd; while (fdx > 0) close (fdtmp[--fdx]); return fd;}#endifchar *my_strerror (e) int e;{#ifdef HAVE_STRERROR return strerror (e);#else 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;#endif}/* Delete tempfiles and exit function. */voidcollect_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); if (export_file != 0 && export_file[0]) maybe_unlink (export_file); if (ldout != 0 && ldout[0]) { dump_file (ldout); maybe_unlink (ldout); } if (status != 0 && output_file != 0 && output_file[0]) maybe_unlink (output_file); exit (status);}/* Die when sys call fails. */voidfatal_perror (string, arg1, arg2, arg3) char *string, *arg1, *arg2, *arg3;{ int e = errno; fprintf (stderr, "collect2: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, ": %s\n", my_strerror (e)); collect_exit (1);}/* Just die. */voidfatal (string, arg1, arg2, arg3) char *string, *arg1, *arg2, *arg3;{ fprintf (stderr, "collect2: "); fprintf (stderr, string, arg1, arg2, arg3); fprintf (stderr, "\n"); collect_exit (1);}/* Write error message. */voiderror (string, arg1, arg2, arg3, arg4) char *string, *arg1, *arg2, *arg3, *arg4;{ fprintf (stderr, "collect2: "); 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 && c_file[0]) maybe_unlink (c_file); if (o_file != 0 && o_file[0]) maybe_unlink (o_file); if (ldout != 0 && ldout[0]) maybe_unlink (ldout); signal (signo, SIG_DFL); kill (getpid (), signo);}char *xcalloc (size1, size2) int size1, size2;{ char *ptr = (char *) calloc (size1, size2); if (ptr) return ptr; fatal ("out of memory"); return (char *)0;}char *xmalloc (size) unsigned size;{ char *ptr = (char *) malloc (size); if (ptr) return ptr; fatal ("out of memory"); return (char *)0;}char *xrealloc (ptr, size) char *ptr; unsigned size;{ register char *value = (char *) realloc (ptr, size); if (value == 0) fatal ("virtual memory exhausted"); return value;}intfile_exists (name) char *name;{ return access (name, R_OK) == 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;}voiddump_file (name) char *name;{ FILE *stream = fopen (name, "r"); int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); if (stream == 0) return; while (1) { int c; while (c = getc (stream), c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.')) obstack_1grow (&temporary_obstack, c); if (obstack_object_size (&temporary_obstack) > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -