📄 collect2.c
字号:
if (c == '\0') break; ++p; if (backquote) obstack_1grow (&temporary_obstack, c); else if (! inside && c == ' ') break; else if (! inside && c == '\\') backquote = 1; else if (c == '\'') inside = !inside; else obstack_1grow (&temporary_obstack, c); } obstack_1grow (&temporary_obstack, '\0'); *pp = p; return obstack_finish (&temporary_obstack);}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) { char *word, *p, *result; obstack_1grow (&temporary_obstack, '\0'); word = obstack_finish (&temporary_obstack); if (*word == '.') ++word, putc ('.', stderr); p = word; if (*p == '_' && prepends_underscore) ++p; if (no_demangle) result = 0; else result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI); if (result) { int diff; fputs (result, stderr); diff = strlen (word) - strlen (result); while (diff > 0) --diff, putc (' ', stderr); while (diff < 0 && c == ' ') ++diff, c = getc (stream); free (result); } else fputs (word, stderr); fflush (stderr); obstack_free (&temporary_obstack, temporary_firstobj); } if (c == EOF) break; putc (c, stderr); } fclose (stream);}/* 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#ifdef NO_DOT_IN_LABEL { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },#else { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 }, { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 }, { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 },#endif#else { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 }, { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 }, { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 },#endif { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },#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;}/* Routine to add variables to the environment. */#ifndef HAVE_PUTENVintputenv (str) char *str;{#ifndef VMS /* nor about VMS */ extern char **environ; char **old_environ = environ; char **envp; int num_envs = 0; int name_len = 1; char *p = str; int ch; while ((ch = *p++) != '\0' && ch != '=') name_len++; if (!ch) abort (); /* Search for replacing an existing environment variable, and count the number of total environment variables. */ for (envp = old_environ; *envp; envp++) { num_envs++; if (!strncmp (str, *envp, name_len)) { *envp = str; return 0; } } /* Add a new environment variable */ environ = (char **) xmalloc (sizeof (char *) * (num_envs+2)); *environ = str; bcopy ((char *) old_environ, (char *) (environ + 1), sizeof (char *) * (num_envs+1)); return 0;#endif /* VMS */}#endif /* HAVE_PUTENV *//* By default, colon separates directories in a path. */#ifndef PATH_SEPARATOR#define PATH_SEPARATOR ':'#endif/* We maintain two prefix lists: one from COMPILER_PATH environment variable and one from the PATH variable. */static struct path_prefix cpath, path;#ifdef CROSS_COMPILE/* This is the name of the target machine. We use it to form the name of the files to execute. */static char *target_machine = TARGET_MACHINE;#endif/* Names under which we were executed. Never return one of those files in our searches. */static struct path_prefix our_file_names;/* Determine if STRING is in PPREFIX. This utility is currently only used to look up file names. Prefix lists record directory names. This matters to us because the latter has a trailing slash, so I've added a flag to handle both. */static intis_in_prefix_list (pprefix, string, filep) struct path_prefix *pprefix; char *string; int filep;{ struct prefix_list *pl; if (filep) { int len = strlen (string); for (pl = pprefix->plist; pl; pl = pl->next) { if (strncmp (pl->prefix, string, len) == 0 && strcmp (pl->prefix + len, "/") == 0) return 1; } } else { for (pl = pprefix->plist; pl; pl = pl->next) { if (strcmp (pl->prefix, string) == 0) return 1; } } return 0;}/* Search for NAME using prefix list PPREFIX. We only look for executable files. Return 0 if not found, otherwise return its name, allocated with malloc. */static char *find_a_file (pprefix, name) struct path_prefix *pprefix; char *name;{ char *temp; struct prefix_list *pl; int len = pprefix->max_len + strlen (name) + 1;#ifdef EXECUTABLE_SUFFIX len += strlen (EXECUTABLE_SUFFIX);#endif temp = xmalloc (len); /* Determine the filename to execute (special case for absolute paths). */ if (*name == '/') { if (access (name, X_OK) == 0) { strcpy (temp, name); return temp; } } else for (pl = pprefix->plist; pl; pl = pl->next) { strcpy (temp, pl->prefix); strcat (temp, name); if (! is_in_prefix_list (&our_file_names, temp, 1) /* This is a kludge, but there seems no way around it. */ && strcmp (temp, "./ld") != 0 && access (temp, X_OK) == 0) return temp;#ifdef EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ strcat (temp, EXECUTABLE_SUFFIX); if (! is_in_prefix_list (&our_file_names, temp, 1) && access (temp, X_OK) == 0) return temp;#endif } free (temp); return 0;}/* Add an entry for PREFIX to prefix list PPREFIX. */static voidadd_prefix (pprefix, prefix) struct path_prefix *pprefix; char *prefix;{ struct prefix_list *pl, **prev; int len; if (pprefix->plist) { for (pl = pprefix->plist; pl->next; pl = pl->next) ; prev = &pl->next; } else prev = &pprefix->plist; /* Keep track of the longest prefix */ len = strlen (prefix); if (len > pprefix->max_len) pprefix->max_len = len; pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); pl->prefix = savestring (prefix, len); if (*prev) pl->next = *prev; else pl->next = (struct prefix_list *) 0; *prev = pl;}/* Take the value of the environment variable ENV, break it into a path, and add of the entries to PPREFIX. */static voidprefix_from_env (env, pprefix) char *env; struct path_prefix *pprefix;{ char *p = getenv (env); if (p) prefix_from_string (p, pprefix);}static voidprefix_from_string (p, pprefix) char *p; struct path_prefix *pprefix;{ char *startp, *endp; char *nstore = (char *) xmalloc (strlen (p) + 3); startp = endp = p; while (1) { if (*endp == PATH_SEPARATOR || *endp == 0) { strncpy (nstore, startp, endp-startp); if (endp == startp) { strcpy (nstore, "./"); } else if (endp[-1] != '/') { nstore[endp-startp] = '/'; nstore[endp-startp+1] = 0; } else nstore[endp-startp] = 0; add_prefix (pprefix, nstore); if (*endp == 0) break; endp = startp = endp + 1; } else endp++; }}/* Main program. */intmain (argc, argv) int argc; char *argv[];{ char *ld_suffix = "ld"; char *full_ld_suffix = ld_suffix; char *real_ld_suffix = "real-ld"; char *full_real_ld_suffix = real_ld_suffix; char *collect_ld_suffix = "collect-ld"; char *nm_suffix = "nm"; char *full_nm_suffix = nm_suffix; char *gnm_suffix = "gnm"; char *full_gnm_suffix = gnm_suffix;#ifdef LDD_SUFFIX char *ldd_suffix = LDD_SUFFIX; char *full_ldd_suffix = ldd_suffix;#endif char *strip_suffix = "strip"; char *full_strip_suffix = strip_suffix; char *gstrip_suffix = "gstrip"; char *full_gstrip_suffix = gstrip_suffix; char *arg; FILE *outf, *exportf; char *ld_file_name; char *collect_name; char *collect_names; char *p; char **c_argv; char **c_ptr; char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+3); char **ld1 = ld1_argv; char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+6); char **ld2 = ld2_argv; char **object_lst = (char **) xcalloc (sizeof (char *), argc); char **object = object_lst; int first_file; int num_c_args = argc+7;#ifdef DEBUG debug = 1; vflag = 1;#endif#ifndef DEFAULT_A_OUT_NAME output_file = "a.out";#else output_file = DEFAULT_A_OUT_NAME;#endif obstack_begin (&temporary_obstack, 0); obstack_begin (&permanent_obstack, 0); temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); current_demangling_style = gnu_demangling; /* We must check that we do not call ourselves in an infinite recursion loop. We append the name used for us to the COLLECT_NAMES environment variable. In practice, collect will rarely invoke itself. This can happen now that we are no longer called gld. A perfect example is when running gcc in a build directory that has been installed. When looking for ld's, we'll find our installed version and believe that's the real ld. */ /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the previous version of collect (the one that used COLLECT_NAME and only handled two levels of recursion). If we don't we may mutually recurse forever. This can happen (I think) when bootstrapping the old version and a new one is installed (rare, but we should handle it). ??? Hopefully references to COLLECT_NAME can be removed at some point. */ collect_name = (char *) getenv ("COLLECT_NAME"); collect_names = (char *) getenv ("COLLECT_NAMES"); p = (char *) xmalloc (strlen ("COLLECT_NAMES=") + (collect_name ? strlen (collect_name) + 1 : 0) + (collect_names ? strlen (collect_names) + 1 : 0) + strlen (argv[0]) + 1); strcpy (p, "COLLECT_NAMES="); if (collect_name != 0) sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR); if (collect_names != 0) sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR); strcat (p, argv[0]); putenv (p); prefix_from_env ("COLLECT_NAMES", &our_file_names); /* Set environment variable COLLECT_NAME to our name so the previous version of collect won't find us. If it does we'll mutually recurse forever. This can happen when bootstrapping the new version and an old version is installed. ??? Hopefully this bit of code can be removed at some point. */ p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1); sprintf (p, "COLLECT_NAME=%s", argv[0]); putenv (p); p = (char *) getenv ("COLLECT_GCC_OPTIONS"); while (p && *p) { char *q = extract_string (&p); if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) num_c_args++; } obstack_free (&temporary_obstack, temporary_firstobj); ++num_c_args; c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args); if (argc < 2) fatal ("no arguments");#ifdef SIGQUIT if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) signal (SIGQUIT, handler);#endif if (signal (SIGINT, SIG_IGN) != SIG_IGN) signal (SIGINT, handler);#ifdef SIGALRM if (signal (SIGALRM, SIG_IGN) != SIG_IGN) signal (SIGALRM, handler);#endif#ifdef SIGHUP if (signal (SIGHUP, SIG_IGN) != SIG_IGN) signal (SIGHUP, handler);#endif if (signal (SIGSEGV, SIG_IGN) != SIG_IGN) signal (SIGSEGV, handler);#ifdef SIGBUS if (signal (SIGBUS, SIG_IGN) != SIG_IGN) signal (SIGBUS, handler);#endif /* Extract COMPILER_PATH and PATH into our prefix list. */ prefix_from_env ("COMPILER_PATH", &cpath); prefix_from_env ("PATH", &path);#ifdef CROSS_COMPILE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -