📄 collect2.c
字号:
fprintf (stderr, "[cannot find %s]", prog); for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); } fflush (stdout); fflush (stderr); /* If we can't find a program we need, complain error. Do this here since we might not end up needing something that we couldn't find. */ if (argv[0] == 0) fatal ("cannot find `%s'", prog); pid = vfork (); if (pid == -1) {#ifdef vfork 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: %s", redir); if (freopen (redir, "a", stderr) == NULL) fatal_perror ("redirecting stderr: %s", redir); } 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; int frames = (frame_tables.number > 0); /* 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); if (frames) { write_list_with_asm (stream, "extern void *", frame_tables.first); fprintf (stream, "\tstatic void *frame_table[] = {\n"); write_list (stream, "\t\t&", frame_tables.first); fprintf (stream, "\t0\n};\n"); /* This must match what's in frame.h. */ fprintf (stream, "struct object {\n"); fprintf (stream, " void *pc_begin;\n"); fprintf (stream, " void *pc_end;\n"); fprintf (stream, " void *fde_begin;\n"); fprintf (stream, " void *fde_array;\n"); fprintf (stream, " __SIZE_TYPE__ count;\n"); fprintf (stream, " struct object *next;\n"); fprintf (stream, "};\n"); fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); fprintf (stream, "extern void __deregister_frame_info (void *);\n"); fprintf (stream, "static void reg_frame () {\n"); fprintf (stream, "\tstatic struct object ob;\n"); fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); fprintf (stream, "\t}\n"); fprintf (stream, "static void dereg_frame () {\n"); fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); fprintf (stream, "\t}\n"); } fprintf (stream, "void %s() {\n", initname); if (constructors.number > 0 || frames) { fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); write_list (stream, "\t\t", constructors.first); if (frames) fprintf (stream, "\treg_frame,\n"); 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 + frames); 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 || frames) { fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); write_list (stream, "\t\t", destructors.first); if (frames) fprintf (stream, "\tdereg_frame,\n"); 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 + frames); } 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 */ int frames = (frame_tables.number > 0); fprintf (stream, "typedef void entry_pt();\n\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); if (frames) { write_list_with_asm (stream, "extern void *", frame_tables.first); fprintf (stream, "\tstatic void *frame_table[] = {\n"); write_list (stream, "\t\t&", frame_tables.first); fprintf (stream, "\t0\n};\n"); /* This must match what's in frame.h. */ fprintf (stream, "struct object {\n"); fprintf (stream, " void *pc_begin;\n"); fprintf (stream, " void *pc_end;\n"); fprintf (stream, " void *fde_begin;\n"); fprintf (stream, " void *fde_array;\n"); fprintf (stream, " __SIZE_TYPE__ count;\n"); fprintf (stream, " struct object *next;\n"); fprintf (stream, "};\n"); fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); fprintf (stream, "extern void __deregister_frame_info (void *);\n"); fprintf (stream, "static void reg_frame () {\n"); fprintf (stream, "\tstatic struct object ob;\n"); fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); fprintf (stream, "\t}\n"); fprintf (stream, "static void dereg_frame () {\n"); fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); fprintf (stream, "\t}\n"); } fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames); write_list (stream, "\t", constructors.first); if (frames) fprintf (stream, "\treg_frame,\n"); 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 + frames); write_list (stream, "\t", destructors.first); if (frames) fprintf (stream, "\tdereg_frame,\n"); 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;{ fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");#ifndef LD_INIT_SWITCH if (! shared_obj) write_c_file_glob (stream, name); else#endif write_c_file_stat (stream, name); fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");}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; case 5: if (which_pass != PASS_LIB) add_to_list (&frame_tables, name); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -