📄 collect2.c
字号:
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, "\tsec=%d class=%d type=%s%o %s\n", symbol.n_scnum, symbol.n_sclass, (symbol.n_type ? "0" : ""), symbol.n_type, name);#else if (debug) fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n", symbol.iss, symbol.value, symbol.index, name);#endif } } } (void) ldclose(ldptr);}#ifdef XCOFF_SCAN_LIBS/* Scan imported AIX libraries for GCC static ctors and dtors. FIXME: it is possible to link an executable without the actual import library by using an "import file" - a text file listing symbols exported by a library. To support this, we would have to scan import files as well as actual shared binaries to find GCC ctors. TODO: use memory mapping instead of 'ld' routines, files are already memory mapped, but we could eliminate the extra in-memory copies. Is it worth the effort? */static voidscan_libraries (prog_name) char *prog_name;{ LDFILE *ldptr; SCNHDR ldsh; static struct path_prefix libpath; /* we should only do this once */ 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); /* find and read loader section */ if (ldnshread (ldptr, _LOADER, &ldsh)) { LDHDR ldh; char *impbuf; int entry; FSEEK (ldptr, ldsh.s_scnptr, BEGINNING); FREAD (&ldh, sizeof (ldh), 1, ldptr); /* read import library list */ impbuf = alloca (ldh.l_istlen); FSEEK (ldptr, ldh.l_impoff + ldsh.s_scnptr, BEGINNING); FREAD (impbuf, ldh.l_istlen, 1, ldptr); if (debug) fprintf (stderr, "LIBPATH=%s\n", impbuf); prefix_from_string (impbuf, &libpath); /* skip LIBPATH and empty base and member fields */ impbuf += strlen (impbuf) + 3; for (entry = 1; entry < ldh.l_nimpid; ++entry) { char *impath = impbuf; char *implib = impath + strlen (impath) + 1; char *impmem = implib + strlen (implib) + 1; char *soname = NULL; char *trial; int pathlen; LDFILE *libptr = NULL; struct prefix_list *pl; ARCHDR ah; impbuf = impmem + strlen (impmem) + 1; if (debug) fprintf (stderr, "PATH+BASE=%s%s\n", impath, implib); /* Skip AIX kernel exports */ if (*impath == '/' && *(impath+1) == '\0' && strcmp (implib, "unix") == 0) continue; pathlen = strlen (impath); trial = alloca (MAX (pathlen + 1, libpath.max_len) + strlen (implib) + 1); if (*impath) { strcpy (trial, impath); if (impath[pathlen - 1] != '/') trial[pathlen++] = '/'; strcpy (trial + pathlen, implib); if (access (trial, R_OK) == 0) soname = trial; } else for (pl = libpath.plist; pl; pl = pl->next) { strcpy (trial, pl->prefix); strcat (trial, implib); if (access (trial, R_OK) == 0) { soname = trial; break; } } if (! soname) fatal ("%s: library not found", implib); if (debug) if (*impmem) fprintf (stderr, "%s (%s)\n", soname, impmem); else fprintf (stderr, "%s\n", soname); do { /* scan imported shared objects for GCC GLOBAL ctors */ short type; if ((libptr = ldopen (soname, libptr)) == NULL) fatal ("%s: can't open import library", soname)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -