📄 collect2.c
字号:
fatal_perror ("fork");#else fatal_perror ("vfork");#endif } if (pid == 0) /* child context */ { if (redir) { unlink (redir); if (freopen (redir, "a", stdout) == NULL) fatal_perror ("redirecting stdout"); if (freopen (redir, "a", stderr) == NULL) fatal_perror ("redirecting stderr"); } execvp (argv[0], argv); fatal_perror ("executing %s", prog); }}static voidfork_execute (prog, argv) char *prog; char **argv;{ collect_execute (prog, argv, NULL); do_wait (prog);}/* Unlink a file unless we are debugging. */static voidmaybe_unlink (file) char *file;{ if (!debug) unlink (file); else fprintf (stderr, "[Leaving %s]\n", file);}/* Add a name to a linked list. */static voidadd_to_list (head_ptr, name) struct head *head_ptr; char *name;{ struct id *newid = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1); struct id *p; static long sequence_number = 0; strcpy (newid->name, name); if (head_ptr->first) head_ptr->last->next = newid; else head_ptr->first = newid; /* Check for duplicate symbols. */ for (p = head_ptr->first; strcmp (name, p->name) != 0; p = p->next) ; if (p != newid) { head_ptr->last->next = 0; free (newid); return; } newid->sequence = ++sequence_number; head_ptr->last = newid; head_ptr->number++;}/* Write: `prefix', the names on list LIST, `suffix'. */static voidwrite_list (stream, prefix, list) FILE *stream; char *prefix; struct id *list;{ while (list) { fprintf (stream, "%sx%d,\n", prefix, list->sequence); list = list->next; }}static voidwrite_list_with_asm (stream, prefix, list) FILE *stream; char *prefix; struct id *list;{ while (list) { fprintf (stream, "%sx%d __asm__ (\"%s\");\n", prefix, list->sequence, list->name); list = list->next; }}/* Write out the constructor and destructor tables statically (for a shared object), along with the functions to execute them. */static voidwrite_c_file_stat (stream, name) FILE *stream; char *name;{ char *prefix, *p, *q; /* Figure out name of output_file, stripping off .so version. */ p = rindex (output_file, '/'); if (p == 0) p = (char *) output_file; else p++; q = p; while (q) { q = index (q,'.'); if (q == 0) { q = p + strlen (p); break; } else { if (strncmp (q, ".so", 3) == 0) { q += 3; break; } else q++; } } /* q points to null at end of the string (or . of the .so version) */ prefix = xmalloc (q - p + 1); strncpy (prefix, p, q - p); prefix[q - p] = 0; for (q = prefix; *q; q++) if (!isalnum (*q)) *q = '_'; if (debug) fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n", output_file, prefix);#define INIT_NAME_FORMAT "_GLOBAL__FI_%s" initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2); sprintf (initname, INIT_NAME_FORMAT, prefix);#define FINI_NAME_FORMAT "_GLOBAL__FD_%s" fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2); sprintf (fininame, FINI_NAME_FORMAT, prefix); free (prefix); /* Write the tables as C code */ fprintf (stream, "static int count;\n"); fprintf (stream, "typedef void entry_pt();\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); fprintf (stream, "void %s() {\n", initname); if (constructors.number > 0) { fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); write_list (stream, "\t\t", constructors.first); fprintf (stream, "\t};\n"); fprintf (stream, "\tentry_pt **p;\n"); fprintf (stream, "\tif (count++ != 0) return;\n"); fprintf (stream, "\tp = ctors + %d;\n", constructors.number); fprintf (stream, "\twhile (p > ctors) (*--p)();\n"); } else fprintf (stream, "\t++count;\n"); fprintf (stream, "}\n"); write_list_with_asm (stream, "extern entry_pt ", destructors.first); fprintf (stream, "void %s() {\n", fininame); if (destructors.number > 0) { fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); write_list (stream, "\t\t", destructors.first); fprintf (stream, "\t};\n"); fprintf (stream, "\tentry_pt **p;\n"); fprintf (stream, "\tif (--count != 0) return;\n"); fprintf (stream, "\tp = dtors;\n"); fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n", destructors.number); } fprintf (stream, "}\n"); if (shared_obj) { fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname); fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame); }}/* Write the constructor/destructor tables. */static voidwrite_c_file_glob (stream, name) FILE *stream; char *name;{ /* Write the tables as C code */ fprintf (stream, "typedef void entry_pt();\n\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number); write_list (stream, "\t", constructors.first); fprintf (stream, "\t0\n};\n\n"); write_list_with_asm (stream, "extern entry_pt ", destructors.first); fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number); write_list (stream, "\t", destructors.first); fprintf (stream, "\t0\n};\n\n"); fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN); fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);}static voidwrite_c_file (stream, name) FILE *stream; char *name;{#ifndef LD_INIT_SWITCH if (! shared_obj) write_c_file_glob (stream, name); else#endif write_c_file_stat (stream, name);}static voidwrite_export_file (stream) FILE *stream;{ struct id *list = exports.first; for (; list; list = list->next) fprintf (stream, "%s\n", list->name);}#ifdef OBJECT_FORMAT_NONE/* Generic version to scan the name list of the loaded program for the symbols g++ uses for static constructors and destructors. The constructor table begins at __CTOR_LIST__ and contains a count of the number of pointers (or -1 if the constructors are built in a separate section by the linker), followed by the pointers to the constructor functions, terminated with a null pointer. The destructor table has the same format, and begins at __DTOR_LIST__. */static voidscan_prog_file (prog_name, which_pass) char *prog_name; enum pass which_pass;{ void (*int_handler) (); void (*quit_handler) (); char *nm_argv[4]; int pid; int argc = 0; int pipe_fd[2]; char *p, buf[1024]; FILE *inf; if (which_pass == PASS_SECOND) return; /* If we don't have an `nm', complain. */ if (nm_file_name == 0) fatal ("cannot find `nm'"); nm_argv[argc++] = nm_file_name; if (NM_FLAGS[0] != '\0') nm_argv[argc++] = NM_FLAGS; nm_argv[argc++] = prog_name; nm_argv[argc++] = (char *)0; if (pipe (pipe_fd) < 0) fatal_perror ("pipe"); inf = fdopen (pipe_fd[0], "r"); if (inf == (FILE *)0) fatal_perror ("fdopen"); /* Trace if needed. */ if (vflag) { char **p_argv; char *str; for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); } fflush (stdout); fflush (stderr); /* Spawn child nm on pipe */ pid = vfork (); if (pid == -1) {#ifdef vfork fatal_perror ("fork");#else fatal_perror ("vfork");#endif } if (pid == 0) /* child context */ { /* setup stdout */ if (dup2 (pipe_fd[1], 1) < 0) fatal_perror ("dup2 (%d, 1)", pipe_fd[1]); if (close (pipe_fd[0]) < 0) fatal_perror ("close (%d)", pipe_fd[0]); if (close (pipe_fd[1]) < 0) fatal_perror ("close (%d)", pipe_fd[1]); execv (nm_file_name, nm_argv); fatal_perror ("executing %s", nm_file_name); } /* Parent context from here on. */ int_handler = (void (*) ())signal (SIGINT, SIG_IGN);#ifdef SIGQUIT quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);#endif if (close (pipe_fd[1]) < 0) fatal_perror ("close (%d)", pipe_fd[1]); if (debug) fprintf (stderr, "\nnm output with constructors/destructors.\n"); /* Read each line of nm output. */ while (fgets (buf, sizeof buf, inf) != (char *)0) { int ch, ch2; char *name, *end; /* If it contains a constructor or destructor name, add the name to the appropriate list. */ for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) if (ch == ' ' && p[1] == 'U' && p[2] == ' ') break; if (ch != '_') continue; name = p; /* Find the end of the symbol name. Don't include `|', because Encore nm can tack that on the end. */ for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|'; end++) continue; *end = '\0'; switch (is_ctor_dtor (name)) { case 1: if (which_pass != PASS_LIB) add_to_list (&constructors, name); break; case 2: if (which_pass != PASS_LIB) add_to_list (&destructors, name); break; case 3: if (which_pass != PASS_LIB) fatal ("init function found in object %s", prog_name);#ifndef LD_INIT_SWITCH add_to_list (&constructors, name);#endif break; case 4: if (which_pass != PASS_LIB) fatal ("fini function found in object %s", prog_name);#ifndef LD_FINI_SWITCH add_to_list (&destructors, name);#endif break; default: /* not a constructor or destructor */ continue; } if (debug) fprintf (stderr, "\t%s\n", buf); } if (debug) fprintf (stderr, "\n"); if (fclose (inf) != 0) fatal_perror ("fclose of pipe"); do_wait (nm_file_name); signal (SIGINT, int_handler);#ifdef SIGQUIT signal (SIGQUIT, quit_handler);#endif}#if SUNOS4_SHARED_LIBRARIES/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries that the output file depends upon and their initialization/finalization routines, if any. */#include <a.out.h>#include <fcntl.h>#include <link.h>#include <sys/mman.h>#include <sys/param.h>#include <sys/unistd.h>#include <sys/dir.h>/* pointers to the object file */unsigned object; /* address of memory mapped file */unsigned objsize; /* size of memory mapped to file */char * code; /* pointer to code segment */char * data; /* pointer to data segment */struct nlist *symtab; /* pointer to symbol table */struct link_dynamic *ld;struct link_dynamic_2 *ld_2;struct head libraries;/* Map the file indicated by NAME into memory and store its address. */static voidmapfile (name) char *name;{ int fp; struct stat s; if ((fp = open (name, O_RDONLY)) == -1) fatal ("unable to open file '%s'", name); if (fstat (fp, &s) == -1) fatal ("unable to stat file '%s'", name); objsize = s.st_size; object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fp, 0); if (object == -1) fatal ("unable to mmap file '%s'", name); close (fp);}/* Helpers for locatelib. */static char *libname;static intlibselect (d) struct direct *d;{ return (strncmp (libname, d->d_name, strlen (libname)) == 0);}/* If one file has an additional numeric extension past LIBNAME, then put that one first in the sort. If both files have additional numeric extensions, then put the one with the higher number first in the sort. We must verify that the extension is numeric, because Sun saves the original versions of patched libraries with a .FCS extension. Files with invalid extensions must go last in the sort, so that they won't be used. */static intlibcompare (d1, d2) struct direct **d1, **d2;{ int i1, i2 = strlen (libname); char *e1 = (*d1)->d_name + i2; char *e2 = (*d2)->d_name + i2; while (*e1 && *e2 && *e1 == '.' && *e2 == '.' && e1[1] && isdigit (e1[1]) && e2[1] && isdigit (e2[1])) { ++e1; ++e2; i1 = strtol (e1, &e1, 10); i2 = strtol (e2, &e2, 10); if (i1 != i2) return i1 - i2; } if (*e1) { /* It has a valid numeric extension, prefer this one. */ if (*e1 == '.' && e1[1] && isdigit (e1[1])) return 1; /* It has a invalid numeric extension, must prefer the other one. */ else return -1; } else if (*e2) { /* It has a valid numeric extension, prefer this one. */ if (*e2 == '.' && e2[1] && isdigit (e2[1])) return -1; /* It has a invalid numeric extension, must prefer the other one. */ else return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -