📄 collect2.c
字号:
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 <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; } else return 0;}/* Given the name NAME of a dynamic dependency, find its pathname and add it to the list of libraries. */static voidlocatelib (name) char *name;{ static char **l; static int cnt; char buf[MAXPATHLEN]; char *p, *q; char **pp; if (l == 0) { char *ld_rules; char *ldr = 0; /* counting elements in array, need 1 extra for null */ cnt = 1; ld_rules = (char *) (ld_2->ld_rules + code); if (ld_rules) { cnt++; for (; *ld_rules != 0; ld_rules++) if (*ld_rules == ':') cnt++; ld_rules = (char *) (ld_2->ld_rules + code); ldr = (char *) malloc (strlen (ld_rules) + 1); strcpy (ldr, ld_rules); } p = getenv ("LD_LIBRARY_PATH"); q = 0; if (p) { cnt++; for (q = p ; *q != 0; q++) if (*q == ':') cnt++; q = (char *) malloc (strlen (p) + 1); strcpy (q, p); } l = (char **) malloc ((cnt + 3) * sizeof (char *)); pp = l; if (ldr) { *pp++ = ldr; for (; *ldr != 0; ldr++) if (*ldr == ':') { *ldr++ = 0; *pp++ = ldr; } } if (q) { *pp++ = q; for (; *q != 0; q++) if (*q == ':') { *q++ = 0; *pp++ = q; } } /* built in directories are /lib, /usr/lib, and /usr/local/lib */ *pp++ = "/lib"; *pp++ = "/usr/lib"; *pp++ = "/usr/local/lib"; *pp = 0; } libname = name; for (pp = l; *pp != 0 ; pp++) { struct direct **namelist; int entries; if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0) { sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name); add_to_list (&libraries, buf); if (debug) fprintf (stderr, "%s\n", buf); break; } } if (*pp == 0) { if (debug) fprintf (stderr, "not found\n"); else fatal ("dynamic dependency %s not found", name); }}/* Scan the _DYNAMIC structure of the output file to find shared libraries that it depends upon and any constructors or destructors they contain. */static void scan_libraries (prog_name) char *prog_name;{ struct exec *header; char *base; struct link_object *lo; char buff[MAXPATHLEN]; struct id *list; mapfile (prog_name); header = (struct exec *)object; if (N_BADMAG (*header)) fatal ("bad magic number in file '%s'", prog_name); if (header->a_dynamic == 0) return; code = (char *) (N_TXTOFF (*header) + (long) header); data = (char *) (N_DATOFF (*header) + (long) header); symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header); if (header->a_magic == ZMAGIC && header->a_entry == 0x20) { /* shared object */ ld = (struct link_dynamic *) (symtab->n_value + code); base = code; } else { /* executable */ ld = (struct link_dynamic *) data; base = code-PAGSIZ; } if (debug) fprintf (stderr, "dynamic dependencies.\n"); ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base); for (lo = (struct link_object *) ld_2->ld_need; lo; lo = (struct link_object *) lo->lo_next) { char *name; lo = (struct link_object *) ((long) lo + code); name = (char *) (code + lo->lo_name); if (lo->lo_library) { if (debug) fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major); sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor); locatelib (buff); } else { if (debug) fprintf (stderr, "\t%s\n", name); add_to_list (&libraries, name); } } if (debug) fprintf (stderr, "\n"); /* now iterate through the library list adding their symbols to the list. */ for (list = libraries.first; list; list = list->next) scan_prog_file (list->name, PASS_LIB);}#else /* SUNOS4_SHARED_LIBRARIES */#ifdef LDD_SUFFIX/* Use the List Dynamic Dependencies program to find shared libraries that the output file depends upon and their initialization/finalization routines, if any. */static void scan_libraries (prog_name) char *prog_name;{ static struct head libraries; /* list of shared libraries found */ struct id *list; void (*int_handler) (); void (*quit_handler) (); char *ldd_argv[4]; int pid; int argc = 0; int pipe_fd[2]; char buf[1024]; FILE *inf; /* If we don't have an `ldd', complain. */ if (ldd_file_name == 0) { error ("cannot find `ldd'"); return; } ldd_argv[argc++] = ldd_file_name; ldd_argv[argc++] = prog_name; ldd_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 = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); } fflush (stdout); fflush (stderr); /* Spawn child ldd 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 (ldd_file_name, ldd_argv); fatal_perror ("executing %s", ldd_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, "\nldd output with constructors/destructors.\n"); /* Read each line of ldd output. */ while (fgets (buf, sizeof buf, inf) != (char *) 0) { int ch, ch2; char *name, *end, *p = buf; /* Extract names of libraries and add to list. */ PARSE_LDD_OUTPUT (p); if (p == 0) continue; name = p; if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) fatal ("dynamic dependency %s not found", buf); /* Find the end of the symbol name. */ for (end = p; (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|'; end++) continue; *end = '\0'; if (access (name, R_OK) == 0) add_to_list (&libraries, name); else fatal ("unable to open dynamic dependency '%s'", buf); if (debug) fprintf (stderr, "\t%s\n", buf); } if (debug) fprintf (stderr, "\n"); if (fclose (inf) != 0) fatal_perror ("fclose of pipe"); do_wait (ldd_file_name); signal (SIGINT, int_handler);#ifdef SIGQUIT signal (SIGQUIT, quit_handler);#endif /* now iterate through the library list adding their symbols to the list. */ for (list = libraries.first; list; list = list->next) scan_prog_file (list->name, PASS_LIB);}#endif /* LDD_SUFFIX */#endif /* SUNOS4_SHARED_LIBRARIES */#endif /* OBJECT_FORMAT_NONE *//* * COFF specific stuff. */#ifdef OBJECT_FORMAT_COFF#if defined(EXTENDED_COFF)# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)# define GCC_SYMENT SYMR# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)# define GCC_SYMINC(X) (1)# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)#else# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)# define GCC_SYMENT SYMENT# define GCC_OK_SYMBOL(X) \ (((X).n_sclass == C_EXT) && \ (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \ ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))# define GCC_SYMINC(X) ((X).n_numaux+1)# define GCC_SYMZERO(X) 0# define GCC_CHECK_HDR(X) (1)#endifextern char *ldgetname ();/* COFF 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;{ LDFILE *ldptr = NULL; int sym_index, sym_count; if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) return; if ((ldptr = ldopen (prog_name, ldptr)) == NULL) fatal ("%s: can't open as COFF file", prog_name); if (!MY_ISCOFF (HEADER (ldptr).f_magic)) fatal ("%s: not a COFF file", prog_name); if (GCC_CHECK_HDR (ldptr)) { sym_count = GCC_SYMBOLS (ldptr); sym_index = GCC_SYMZERO (ldptr); while (sym_index < sym_count) { GCC_SYMENT symbol; if (ldtbread (ldptr, sym_index, &symbol) <= 0) break; sym_index += GCC_SYMINC (symbol); if (GCC_OK_SYMBOL (symbol)) { char *name; if ((name = ldgetname (ldptr, &symbol)) == NULL) continue; /* should never happen */#ifdef XCOFF_DEBUGGING_INFO /* All AIX function names have a duplicate entry beginning with a dot. */ if (*name == '.') ++name;#endif switch (is_ctor_dtor (name)) { case 1: add_to_list (&constructors, name); if (which_pass == PASS_OBJ) add_to_list (&exports, name); break; case 2: add_to_list (&destructors, name); if (which_pass == PASS_OBJ) add_to_list (&exports, name); break; default: /* not a constructor or destructor */ continue; }#if !defined(EXTENDED_COFF) if (debug) fprintf (stderr, "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -