/* Collect static initialization info into data structures that can be
traversed by C++ initialization and finalization routines.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@cygnus.com),
Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Build tables of static constructors and destructors and run ld. */
# define SIGCHLD SIGCLD
#endif
-#ifdef vfork /* Autoconf may define this to fork for us. */
-# define VFORK_STRING "fork"
-#else
-# define VFORK_STRING "vfork"
-#endif
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-#ifdef VMS
-#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
- lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
-#endif /* VMS */
-
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
cross-versions are in the proper directories. */
#ifdef CROSS_COMPILE
-#undef SUNOS4_SHARED_LIBRARIES
#undef OBJECT_FORMAT_COFF
#undef MD_EXEC_PREFIX
#undef REAL_LD_FILE_NAME
fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
#endif
-#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
+#ifdef LDD_SUFFIX
#define SCAN_LIBRARIES
#endif
int do_collecting = 0;
#endif
-#ifndef COLLECT_PARSE_FLAG
-#define COLLECT_PARSE_FLAG(FLAG)
-#endif
-
/* Nonzero if we should suppress the automatic demangling of identifiers
in linker error messages. Set from COLLECT_NO_DEMANGLE. */
int no_demangle;
int vflag; /* true if -v */
static int rflag; /* true if -r */
static int strip_flag; /* true if -s */
+static const char *demangle_flag;
#ifdef COLLECT_EXPORT_LIST
static int export_flag; /* true if -bE */
static int aix64_flag; /* true if -b64 */
+static int aixrtl_flag; /* true if -brtl */
#endif
int debug; /* true if -debug */
#ifdef COLLECT_EXPORT_LIST
static const char *export_file; /* <xxx>.x for AIX export list. */
#endif
-const char *ldout; /* File for ld errors. */
+const char *ldout; /* File for ld stdout. */
+const char *lderrout; /* File for ld stderr. */
static const char *output_file; /* Output file for ld. */
static const char *nm_file_name; /* pathname of nm */
#ifdef LDD_SUFFIX
struct obstack temporary_obstack;
char * temporary_firstobj;
-/* Holds the return value of pexecute and fork. */
-int pid;
-
/* Structure to hold all the directories in which to search for files to
execute. */
static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
&libpath_lib_dirs, NULL};
-static const char *const libexts[3] = {"a", "so", NULL}; /* possible library extensions */
#endif
static void handler (int);
static void add_prefix (struct path_prefix *, const char *);
static void prefix_from_env (const char *, struct path_prefix *);
static void prefix_from_string (const char *, struct path_prefix *);
-static void do_wait (const char *);
+static void do_wait (const char *, struct pex_obj *);
static void fork_execute (const char *, char **);
static void maybe_unlink (const char *);
static void add_to_list (struct head *, const char *);
#endif
static char *extract_string (const char **);
\f
-#ifndef HAVE_DUP2
-static int
-dup2 (int oldfd, int newfd)
-{
- int fdtmp[256];
- int fdx = 0;
- int fd;
-
- if (oldfd == newfd)
- return oldfd;
- close (newfd);
- while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
- fdtmp[fdx++] = fd;
- while (fdx > 0)
- close (fdtmp[--fdx]);
-
- return fd;
-}
-#endif /* ! HAVE_DUP2 */
-\f
/* Delete tempfiles and exit function. */
void
if (ldout != 0 && ldout[0])
{
- dump_file (ldout);
+ dump_file (ldout, stdout);
maybe_unlink (ldout);
}
+ if (lderrout != 0 && lderrout[0])
+ {
+ dump_file (lderrout, stderr);
+ maybe_unlink (lderrout);
+ }
+
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
\f
/* Notify user of a non-error. */
void
-notice (const char *msgid, ...)
+notice (const char *cmsgid, ...)
{
va_list ap;
- va_start (ap, msgid);
- vfprintf (stderr, _(msgid), ap);
+ va_start (ap, cmsgid);
+ vfprintf (stderr, _(cmsgid), ap);
va_end (ap);
}
/* Die when sys call fails. */
void
-fatal_perror (const char * msgid, ...)
+fatal_perror (const char * cmsgid, ...)
{
int e = errno;
va_list ap;
- va_start (ap, msgid);
+ va_start (ap, cmsgid);
fprintf (stderr, "collect2: ");
- vfprintf (stderr, _(msgid), ap);
+ vfprintf (stderr, _(cmsgid), ap);
fprintf (stderr, ": %s\n", xstrerror (e));
va_end (ap);
/* Just die. */
void
-fatal (const char * msgid, ...)
+fatal (const char * cmsgid, ...)
{
va_list ap;
- va_start (ap, msgid);
+ va_start (ap, cmsgid);
fprintf (stderr, "collect2: ");
- vfprintf (stderr, _(msgid), ap);
+ vfprintf (stderr, _(cmsgid), ap);
fprintf (stderr, "\n");
va_end (ap);
/* Write error message. */
void
-error (const char * msgid, ...)
+error (const char * gmsgid, ...)
{
va_list ap;
- va_start (ap, msgid);
+ va_start (ap, gmsgid);
fprintf (stderr, "collect2: ");
- vfprintf (stderr, _(msgid), ap);
+ vfprintf (stderr, _(gmsgid), ap);
fprintf (stderr, "\n");
va_end(ap);
}
provide a default entry. */
void
-fancy_abort (void)
+fancy_abort (const char *file, int line, const char *func)
{
- fatal ("internal error");
+ fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
}
\f
static void
if (ldout != 0 && ldout[0])
maybe_unlink (ldout);
+ if (lderrout != 0 && lderrout[0])
+ maybe_unlink (lderrout);
+
#ifdef COLLECT_EXPORT_LIST
if (export_file != 0 && export_file[0])
maybe_unlink (export_file);
#endif
signal (signo, SIG_DFL);
- kill (getpid (), signo);
+ raise (signo);
}
\f
obstack_1grow (&temporary_obstack, '\0');
*pp = p;
- return obstack_finish (&temporary_obstack);
+ return XOBFINISH (&temporary_obstack, char *);
}
\f
void
-dump_file (const char *name)
+dump_file (const char *name, FILE *to)
{
FILE *stream = fopen (name, "r");
const char *word, *p;
char *result;
obstack_1grow (&temporary_obstack, '\0');
- word = obstack_finish (&temporary_obstack);
+ word = XOBFINISH (&temporary_obstack, const char *);
if (*word == '.')
- ++word, putc ('.', stderr);
+ ++word, putc ('.', to);
p = word;
if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
p += strlen (USER_LABEL_PREFIX);
+#ifdef HAVE_LD_DEMANGLE
+ result = 0;
+#else
if (no_demangle)
result = 0;
else
result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
+#endif
if (result)
{
int diff;
- fputs (result, stderr);
+ fputs (result, to);
diff = strlen (word) - strlen (result);
while (diff > 0 && c == ' ')
- --diff, putc (' ', stderr);
+ --diff, putc (' ', to);
while (diff < 0 && c == ' ')
++diff, c = getc (stream);
free (result);
}
else
- fputs (word, stderr);
+ fputs (word, to);
- fflush (stderr);
+ fflush (to);
obstack_free (&temporary_obstack, temporary_firstobj);
}
if (c == EOF)
break;
- putc (c, stderr);
+ putc (c, to);
}
fclose (stream);
}
signal (SIGCHLD, SIG_DFL);
#endif
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
gcc_init_libintl ();
/* Do not invoke xcalloc before this point, since locale needs to be
set first, in case a diagnostic is issued. */
- ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+3));
- ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10));
+ ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+4));
+ ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+11));
object = (const char **)(object_lst = xcalloc(sizeof (char *), argc));
#ifdef DEBUG
{
if (! strcmp (argv[i], "-debug"))
debug = 1;
- COLLECT_PARSE_FLAG (argv[i]);
}
vflag = debug;
}
obstack_begin (&temporary_obstack, 0);
temporary_firstobj = obstack_alloc (&temporary_obstack, 0);
+#ifndef HAVE_LD_DEMANGLE
current_demangling_style = auto_demangling;
+#endif
p = getenv ("COLLECT_GCC_OPTIONS");
while (p && *p)
{
}
obstack_free (&temporary_obstack, temporary_firstobj);
- /* -fno-exceptions -w */
- num_c_args += 2;
+ /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities
+ -fno-exceptions -w */
+ num_c_args += 5;
c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
export_file = make_temp_file (".x");
#endif
ldout = make_temp_file (".ld");
+ lderrout = make_temp_file (".le");
*c_ptr++ = c_file_name;
*c_ptr++ = "-x";
*c_ptr++ = "c";
}
}
obstack_free (&temporary_obstack, temporary_firstobj);
+ *c_ptr++ = "-fno-profile-arcs";
+ *c_ptr++ = "-fno-test-coverage";
+ *c_ptr++ = "-fno-branch-probabilities";
*c_ptr++ = "-fno-exceptions";
*c_ptr++ = "-w";
/* After the first file, put in the c++ rt0. */
first_file = 1;
+#ifdef HAVE_LD_DEMANGLE
+ if (!demangle_flag && !no_demangle)
+ demangle_flag = "--demangle";
+ if (demangle_flag)
+ *ld1++ = *ld2++ = demangle_flag;
+#endif
while ((arg = *++argv) != (char *) 0)
{
*ld1++ = *ld2++ = arg;
export_flag = 1;
else if (arg[2] == '6' && arg[3] == '4')
aix64_flag = 1;
+ else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l')
+ aixrtl_flag = 1;
break;
#endif
ld1--;
ld2--;
}
+ if (!strcmp (arg, "-dynamic-linker") && argv[1])
+ {
+ ++argv;
+ *ld1++ = *ld2++ = *argv;
+ }
break;
case 'l':
if (arg[2] == '\0')
vflag = 1;
break;
+
+ case '-':
+ if (strcmp (arg, "--no-demangle") == 0)
+ {
+ demangle_flag = arg;
+ no_demangle = 1;
+ ld1--;
+ ld2--;
+ }
+ else if (strncmp (arg, "--demangle", 10) == 0)
+ {
+ demangle_flag = arg;
+ no_demangle = 0;
+#ifndef HAVE_LD_DEMANGLE
+ if (arg[10] == '=')
+ {
+ enum demangling_styles style
+ = cplus_demangle_name_to_style (arg+11);
+ if (style == unknown_demangling)
+ error ("unknown demangling style '%s'", arg+11);
+ else
+ current_demangling_style = style;
+ }
+#endif
+ ld1--;
+ ld2--;
+ }
+ break;
}
}
else if ((p = strrchr (arg, '.')) != (char *) 0
if (! exports.first)
*ld2++ = concat ("-bE:", export_file, NULL);
+#ifndef LD_INIT_SWITCH
add_to_list (&exports, initname);
add_to_list (&exports, fininame);
add_to_list (&exports, "_GLOBAL__DI");
add_to_list (&exports, "_GLOBAL__DD");
+#endif
exportf = fopen (export_file, "w");
if (exportf == (FILE *) 0)
fatal_perror ("fopen %s", export_file);
fork_execute ("gcc", c_argv);
#ifdef COLLECT_EXPORT_LIST
- /* On AIX we must call tlink because of possible templates resolution */
+ /* On AIX we must call tlink because of possible templates resolution. */
do_tlink (ld2_argv, object_lst);
#else
- /* Otherwise, simply call ld because tlink is already done */
+ /* Otherwise, simply call ld because tlink is already done. */
fork_execute ("ld", ld2_argv);
/* Let scan_prog_file do any final mods (OSF/rose needs this for
/* Wait for a process to finish, and exit if a nonzero status is found. */
int
-collect_wait (const char *prog)
+collect_wait (const char *prog, struct pex_obj *pex)
{
int status;
- pwait (pid, &status, 0);
+ if (!pex_get_status (pex, 1, &status))
+ fatal_perror ("can't get program status");
+ pex_free (pex);
+
if (status)
{
if (WIFSIGNALED (status))
}
static void
-do_wait (const char *prog)
+do_wait (const char *prog, struct pex_obj *pex)
{
- int ret = collect_wait (prog);
+ int ret = collect_wait (prog, pex);
if (ret != 0)
{
error ("%s returned %d exit status", prog, ret);
\f
/* Execute a program, and wait for the reply. */
-void
-collect_execute (const char *prog, char **argv, const char *redir)
+struct pex_obj *
+collect_execute (const char *prog, char **argv, const char *outname,
+ const char *errname)
{
- char *errmsg_fmt;
- char *errmsg_arg;
- int redir_handle = -1;
- int stdout_save = -1;
- int stderr_save = -1;
+ struct pex_obj *pex;
+ const char *errmsg;
+ int err;
if (vflag || debug)
{
since we might not end up needing something that we could not find. */
if (argv[0] == 0)
- fatal ("cannot find `%s'", prog);
+ fatal ("cannot find '%s'", prog);
- if (redir)
- {
- /* Open response file. */
- redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
-
- /* Duplicate the stdout and stderr file handles
- so they can be restored later. */
- stdout_save = dup (STDOUT_FILENO);
- if (stdout_save == -1)
- fatal_perror ("redirecting stdout: %s", redir);
- stderr_save = dup (STDERR_FILENO);
- if (stderr_save == -1)
- fatal_perror ("redirecting stdout: %s", redir);
-
- /* Redirect stdout & stderr to our response file. */
- dup2 (redir_handle, STDOUT_FILENO);
- dup2 (redir_handle, STDERR_FILENO);
- }
+ pex = pex_init (0, "collect2", NULL);
+ if (pex == NULL)
+ fatal_perror ("pex_init failed");
- pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
- (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
-
- if (redir)
+ errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, outname,
+ errname, &err);
+ if (errmsg != NULL)
{
- /* Restore stdout and stderr to their previous settings. */
- dup2 (stdout_save, STDOUT_FILENO);
- dup2 (stderr_save, STDERR_FILENO);
-
- /* Close response file. */
- close (redir_handle);
+ if (err != 0)
+ {
+ errno = err;
+ fatal_perror (errmsg);
+ }
+ else
+ fatal (errmsg);
}
- if (pid == -1)
- fatal_perror (errmsg_fmt, errmsg_arg);
+ return pex;
}
static void
fork_execute (const char *prog, char **argv)
{
- collect_execute (prog, argv, NULL);
- do_wait (prog);
+ struct pex_obj *pex;
+
+ pex = collect_execute (prog, argv, NULL, NULL);
+ do_wait (prog, pex);
}
\f
/* Unlink a file unless we are debugging. */
maybe_unlink (const char *file)
{
if (!debug)
- unlink (file);
+ unlink_if_ordinary (file);
else
notice ("[Leaving %s]\n", file);
}
scan_prog_file (const char *prog_name, enum pass which_pass)
{
void (*int_handler) (int);
+#ifdef SIGQUIT
void (*quit_handler) (int);
+#endif
char *real_nm_argv[4];
const char **nm_argv = (const char **) real_nm_argv;
int argc = 0;
- int pipe_fd[2];
+ struct pex_obj *pex;
+ const char *errmsg;
+ int err;
char *p, buf[1024];
FILE *inf;
/* If we do not have an `nm', complain. */
if (nm_file_name == 0)
- fatal ("cannot find `nm'");
+ fatal ("cannot find 'nm'");
nm_argv[argc++] = nm_file_name;
if (NM_FLAGS[0] != '\0')
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)
{
fflush (stdout);
fflush (stderr);
- /* Spawn child nm on pipe. */
- pid = vfork ();
- if (pid == -1)
- fatal_perror (VFORK_STRING);
+ pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
+ if (pex == NULL)
+ fatal_perror ("pex_init failed");
- if (pid == 0) /* child context */
+ errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, NULL, &err);
+ if (errmsg != NULL)
{
- /* 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, real_nm_argv);
- fatal_perror ("execv %s", nm_file_name);
+ if (err != 0)
+ {
+ errno = err;
+ fatal_perror (errmsg);
+ }
+ else
+ fatal (errmsg);
}
- /* Parent context from here on. */
int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
#ifdef SIGQUIT
quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
#endif
- if (close (pipe_fd[1]) < 0)
- fatal_perror ("close %d", pipe_fd[1]);
+ inf = pex_read_output (pex, 0);
+ if (inf == NULL)
+ fatal_perror ("can't open nm output");
if (debug)
fprintf (stderr, "\nnm output with constructors/destructors.\n");
if (debug)
fprintf (stderr, "\n");
- if (fclose (inf) != 0)
- fatal_perror ("fclose");
-
- do_wait (nm_file_name);
+ do_wait (nm_file_name, pex);
signal (SIGINT, int_handler);
#ifdef SIGQUIT
#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 void
-mapfile (const 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 == (unsigned)-1)
- fatal ("unable to mmap file '%s'", name);
-
- close (fp);
-}
-
-/* Helpers for locatelib. */
-
-static const char *libname;
-
-static int
-libselect (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 will not be used. */
-
-static int
-libcompare (struct direct **d1, struct direct **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 an 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 an 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 void
-locatelib (const char *name)
-{
- static const char **l;
- static int cnt;
- char buf[MAXPATHLEN];
- char *p, *q;
- const 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 = xstrdup (ld_rules);
- }
- p = getenv ("LD_LIBRARY_PATH");
- q = 0;
- if (p)
- {
- cnt++;
- for (q = p ; *q != 0; q++)
- if (*q == ':')
- cnt++;
- q = xstrdup (p);
- }
- l = xmalloc ((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)
- notice ("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 (const 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)
- notice ("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
static struct head libraries; /* list of shared libraries found */
struct id *list;
void (*int_handler) (int);
+#ifdef SIGQUIT
void (*quit_handler) (int);
+#endif
char *real_ldd_argv[4];
const char **ldd_argv = (const char **) real_ldd_argv;
int argc = 0;
- int pipe_fd[2];
+ struct pex_obj *pex;
+ const char *errmsg;
+ int err;
char buf[1024];
FILE *inf;
/* If we do not have an `ldd', complain. */
if (ldd_file_name == 0)
{
- error ("cannot find `ldd'");
+ error ("cannot find 'ldd'");
return;
}
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)
{
fflush (stdout);
fflush (stderr);
- /* Spawn child ldd on pipe. */
- pid = vfork ();
- if (pid == -1)
- fatal_perror (VFORK_STRING);
+ pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
+ if (pex == NULL)
+ fatal_perror ("pex_init failed");
- if (pid == 0) /* child context */
+ errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
+ if (errmsg != NULL)
{
- /* 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, real_ldd_argv);
- fatal_perror ("execv %s", ldd_file_name);
+ if (err != 0)
+ {
+ errno = err;
+ fatal_perror (errmsg);
+ }
+ else
+ fatal (errmsg);
}
- /* Parent context from here on. */
int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
#ifdef SIGQUIT
quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
#endif
- if (close (pipe_fd[1]) < 0)
- fatal_perror ("close %d", pipe_fd[1]);
+ inf = pex_read_output (pex, 0);
+ if (inf == NULL)
+ fatal_perror ("can't open ldd output");
if (debug)
notice ("\nldd output with constructors/destructors.\n");
if (debug)
fprintf (stderr, "\n");
- if (fclose (inf) != 0)
- fatal_perror ("fclose");
-
- do_wait (ldd_file_name);
+ do_wait (ldd_file_name, pex);
signal (SIGINT, int_handler);
#ifdef SIGQUIT
signal (SIGQUIT, quit_handler);
#endif
- /* now iterate through the library list adding their symbols to
+ /* 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 */
#ifdef OBJECT_FORMAT_COFF
-#if defined(EXTENDED_COFF)
+#if defined (EXTENDED_COFF)
# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
# define GCC_SYMENT SYMR
# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
# define GCC_SYMENT SYMENT
-# define GCC_OK_SYMBOL(X) \
- (((X).n_sclass == C_EXT) && \
- ((X).n_scnum > N_UNDEF) && \
- (aix64_flag \
- || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
- || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
-# define GCC_UNDEF_SYMBOL(X) \
- (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
+# if defined (C_WEAKEXT)
+# define GCC_OK_SYMBOL(X) \
+ (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
+ ((X).n_scnum > N_UNDEF) && \
+ (aix64_flag \
+ || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
+ || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
+# define GCC_UNDEF_SYMBOL(X) \
+ (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
+ ((X).n_scnum == N_UNDEF))
+# else
+# define GCC_OK_SYMBOL(X) \
+ (((X).n_sclass == C_EXT) && \
+ ((X).n_scnum > N_UNDEF) && \
+ (aix64_flag \
+ || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
+ || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
+# define GCC_UNDEF_SYMBOL(X) \
+ (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
+# endif
# define GCC_SYMINC(X) ((X).n_numaux+1)
# define GCC_SYMZERO(X) 0
char *name;
if ((name = ldgetname (ldptr, &symbol)) == NULL)
- continue; /* should never happen */
+ continue; /* Should never happen. */
#ifdef XCOFF_DEBUGGING_INFO
/* All AIX function names have a duplicate entry
case 1:
if (! is_shared)
add_to_list (&constructors, name);
-#ifdef COLLECT_EXPORT_LIST
+#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
if (which_pass == PASS_OBJ)
add_to_list (&exports, name);
#endif
case 2:
if (! is_shared)
add_to_list (&destructors, name);
-#ifdef COLLECT_EXPORT_LIST
+#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
if (which_pass == PASS_OBJ)
add_to_list (&exports, name);
#endif
case 5:
if (! is_shared)
add_to_list (&frame_tables, name);
-#ifdef COLLECT_EXPORT_LIST
+#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
if (which_pass == PASS_OBJ)
add_to_list (&exports, name);
#endif
default: /* not a constructor or destructor */
#ifdef COLLECT_EXPORT_LIST
- /* If we are building a shared object on AIX we need
- to explicitly export all global symbols. */
- if (shared_obj)
- {
- if (which_pass == PASS_OBJ && (! export_flag))
- add_to_list (&exports, name);
- }
+ /* Explicitly export all global symbols when
+ building a shared object on AIX, but do not
+ re-export symbols from another shared object
+ and do not export symbols if the user
+ provides an explicit export list. */
+ if (shared_obj && !is_shared
+ && which_pass == PASS_OBJ && !export_flag)
+ add_to_list (&exports, name);
#endif
continue;
}
{
char *lib_buf;
int i, j, l = 0;
+ /* Library extensions for AIX dynamic linking. */
+ const char * const libexts[2] = {"a", "so"};
for (i = 0; libpaths[i]; i++)
if (libpaths[i]->max_len > l)
const char *p = "";
if (list->prefix[strlen(list->prefix)-1] != '/')
p = "/";
- for (j = 0; libexts[j]; j++)
+ for (j = 0; j < 2; j++)
{
sprintf (lib_buf, "%s%slib%s.%s",
- list->prefix, p, name, libexts[j]);
-if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
+ list->prefix, p, name,
+ libexts[(j + aixrtl_flag) % 2]);
+ if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
if (file_exists (lib_buf))
{
-if (debug) fprintf (stderr, "found: %s\n", lib_buf);
+ if (debug) fprintf (stderr, "found: %s\n", lib_buf);
return (lib_buf);
}
}