/* 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, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ 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).
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Build tables of static constructors and destructors and run ld. */
#define COLLECT
#include "collect2.h"
+#include "collect2-aix.h"
#include "demangle.h"
#include "obstack.h"
#include "intl.h"
cross-versions are in the proper directories. */
#ifdef CROSS_DIRECTORY_STRUCTURE
+#ifndef CROSS_AIX_SUPPORT
#undef OBJECT_FORMAT_COFF
+#endif
#undef MD_EXEC_PREFIX
#undef REAL_LD_FILE_NAME
#undef REAL_NM_FILE_NAME
#ifdef OBJECT_FORMAT_COFF
+#ifndef CROSS_DIRECTORY_STRUCTURE
#include <a.out.h>
#include <ar.h>
#endif
#include <ldfcn.h>
+#endif
/* Some systems have an ISCOFF macro, but others do not. In some cases
the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
#define SCAN_LIBRARIES
#endif
+#ifndef SHLIB_SUFFIX
+#define SHLIB_SUFFIX ".so"
+#endif
+
#ifdef USE_COLLECT2
int do_collecting = 1;
#else
int do_collecting = 0;
#endif
+/* Cook up an always defined indication of whether we proceed the
+ "EXPORT_LIST" way. */
+
+#ifdef COLLECT_EXPORT_LIST
+#define DO_COLLECT_EXPORT_LIST 1
+#else
+#define DO_COLLECT_EXPORT_LIST 0
+#endif
+
/* Nonzero if we should suppress the automatic demangling of identifiers
in linker error messages. Set from COLLECT_NO_DEMANGLE. */
int no_demangle;
int number;
};
-/* Enumeration giving which pass this is for scanning the program file. */
-
-enum pass {
- PASS_FIRST, /* without constructors */
- PASS_OBJ, /* individual objects */
- PASS_LIB, /* looking for shared libraries */
- PASS_SECOND /* with constructors linked in */
-};
-
int vflag; /* true if -v */
static int rflag; /* true if -r */
static int strip_flag; /* true if -s */
#endif
static struct head frame_tables; /* list of frame unwind info tables */
+static bool at_file_supplied; /* Whether to use @file arguments */
+static char *response_file; /* Name of any current response file */
+
struct obstack temporary_obstack;
char * temporary_firstobj;
+/* A string that must be prepended to a target OS path in order to find
+ it on the host system. */
+#ifdef TARGET_SYSTEM_ROOT
+static const char *target_system_root = TARGET_SYSTEM_ROOT;
+#else
+static const char *target_system_root = "";
+#endif
+
/* Structure to hold all the directories in which to search for files to
execute. */
&libpath_lib_dirs, NULL};
#endif
+/* Special kinds of symbols that a name may denote. */
+
+typedef enum {
+ SYM_REGULAR = 0, /* nothing special */
+
+ SYM_CTOR = 1, /* constructor */
+ SYM_DTOR = 2, /* destructor */
+ SYM_INIT = 3, /* shared object routine that calls all the ctors */
+ SYM_FINI = 4, /* shared object routine that calls all the dtors */
+ SYM_DWEH = 5 /* DWARF exception handling table */
+} symkind;
+
+static symkind is_ctor_dtor (const char *);
+
static void handler (int);
-static int is_ctor_dtor (const char *);
static char *find_a_file (struct path_prefix *, const char *);
static void add_prefix (struct path_prefix *, const char *);
static void prefix_from_env (const char *, struct path_prefix *);
#ifndef LD_INIT_SWITCH
static void write_c_file_glob (FILE *, const char *);
#endif
-static void scan_prog_file (const char *, enum pass);
#ifdef SCAN_LIBRARIES
static void scan_libraries (const char *);
#endif
static char *resolve_lib_name (const char *);
#endif
static char *extract_string (const char **);
+
+/* Enumerations describing which pass this is for scanning the
+ program file ... */
+
+typedef enum {
+ PASS_FIRST, /* without constructors */
+ PASS_OBJ, /* individual objects */
+ PASS_LIB, /* looking for shared libraries */
+ PASS_SECOND /* with constructors linked in */
+} scanpass;
+
+/* ... and which kinds of symbols are to be considered. */
+
+enum scanfilter_masks {
+ SCAN_NOTHING = 0,
+
+ SCAN_CTOR = 1 << SYM_CTOR,
+ SCAN_DTOR = 1 << SYM_DTOR,
+ SCAN_INIT = 1 << SYM_INIT,
+ SCAN_FINI = 1 << SYM_FINI,
+ SCAN_DWEH = 1 << SYM_DWEH,
+ SCAN_ALL = ~0
+};
+
+/* This type is used for parameters and variables which hold
+ combinations of the flags in enum scanfilter_masks. */
+typedef int scanfilter;
+
+/* Scan the name list of the loaded program for the symbols g++ uses for
+ static constructors and destructors.
+
+ The SCANPASS argument tells which collect processing pass this is for and
+ the SCANFILTER argument tells which kinds of symbols to consider in this
+ pass. Symbols of a special kind not in the filter mask are considered as
+ regular ones.
+
+ 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 void scan_prog_file (const char *, scanpass, scanfilter);
+
\f
/* Delete tempfiles and exit function. */
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
+ if (response_file)
+ maybe_unlink (response_file);
+
exit (status);
}
maybe_unlink (export_file);
#endif
+ if (response_file)
+ maybe_unlink (response_file);
+
signal (signo, SIG_DFL);
raise (signo);
}
diff = strlen (word) - strlen (result);
while (diff > 0 && c == ' ')
--diff, putc (' ', to);
- while (diff < 0 && c == ' ')
- ++diff, c = getc (stream);
+ if (diff < 0 && c == ' ')
+ {
+ while (diff < 0 && c == ' ')
+ ++diff, c = getc (stream);
+ if (!ISSPACE (c))
+ {
+ /* Make sure we output at least one space, or
+ the demangled symbol name will run into
+ whatever text follows. */
+ putc (' ', to);
+ }
+ }
free (result);
}
fclose (stream);
}
\f
-/* Decide whether the given symbol is: a constructor (1), a destructor
- (2), a routine in a shared object that calls all the constructors
- (3) or destructors (4), a DWARF exception-handling table (5), or
- nothing special (0). */
+/* Return the kind of symbol denoted by name S. */
-static int
+static symkind
is_ctor_dtor (const char *s)
{
- struct names { const char *const name; const int len; const int ret;
+ struct names { const char *const name; const int len; symkind ret;
const int two_underscores; };
const struct names *p;
static const struct names special[] = {
#ifndef NO_DOLLAR_IN_LABEL
- { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
- { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
+ { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, SYM_CTOR, 0 },
+ { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, SYM_DTOR, 0 },
#else
#ifndef NO_DOT_IN_LABEL
- { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
- { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
+ { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, SYM_CTOR, 0 },
+ { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, SYM_DTOR, 0 },
#endif /* NO_DOT_IN_LABEL */
#endif /* NO_DOLLAR_IN_LABEL */
- { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
- { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
- { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
- { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
- { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
- { NULL, 0, 0, 0 }
+ { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, SYM_CTOR, 0 },
+ { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, SYM_DTOR, 0 },
+ { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 },
+ { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 },
+ { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 },
+ { NULL, 0, SYM_REGULAR, 0 }
};
while ((ch = *s) == '_')
++s;
if (s == orig_s)
- return 0;
+ return SYM_REGULAR;
for (p = &special[0]; p->len > 0; p++)
{
return p->ret;
}
}
- return 0;
+ return SYM_REGULAR;
}
\f
/* We maintain two prefix lists: one from COMPILER_PATH environment variable
/* Determine the filename to execute (special case for absolute paths). */
- if (*name == '/'
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- || (*name && name[1] == ':')
-#endif
- )
+ if (IS_ABSOLUTE_PATH (name))
{
if (access (name, X_OK) == 0)
{
else
endp++;
}
+ free (nstore);
}
\f
/* Main program. */
const char **c_ptr;
char **ld1_argv;
const char **ld1;
+
+ /* The kinds of symbols we will have to consider when scanning the
+ outcome of a first pass link. This is ALL to start with, then might
+ be adjusted before getting to the first pass link per se, typically on
+ AIX where we perform an early scan of objects and libraries to fetch
+ the list of global ctors/dtors and make sure they are not garbage
+ collected. */
+ scanfilter ld1_filter = SCAN_ALL;
+
char **ld2_argv;
const char **ld2;
char **object_lst;
const char **object;
int first_file;
- int num_c_args = argc+9;
+ int num_c_args;
+ char **old_argv;
+
+ old_argv = argv;
+ expandargv (&argc, &argv);
+ if (argv != old_argv)
+ at_file_supplied = 1;
+
+ num_c_args = argc + 9;
no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
/* 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+4));
- ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+11));
- object = (const char **)(object_lst = xcalloc(sizeof (char *), argc));
+ ld1_argv = XCNEWVEC (char *, argc + 4);
+ ld1 = CONST_CAST2 (const char **, char **, ld1_argv);
+ ld2_argv = XCNEWVEC (char *, argc + 11);
+ ld2 = CONST_CAST2 (const char **, char **, ld2_argv);
+ object_lst = XCNEWVEC (char *, argc);
+ object = CONST_CAST2 (const char **, char **, object_lst);
#ifdef DEBUG
debug = 1;
#endif
obstack_begin (&temporary_obstack, 0);
- temporary_firstobj = obstack_alloc (&temporary_obstack, 0);
+ temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
#ifndef HAVE_LD_DEMANGLE
current_demangling_style = auto_demangling;
-fno-exceptions -w */
num_c_args += 5;
- c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
+ c_argv = XCNEWVEC (char *, num_c_args);
+ c_ptr = CONST_CAST2 (const char **, char **, c_argv);
if (argc < 2)
fatal ("no arguments");
#else
#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
case 'L':
- if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
+ if (is_in_args (arg,
+ CONST_CAST2 (const char **, char **, ld1_argv),
+ ld1 - 1))
--ld1;
break;
#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
ld1--;
ld2--;
}
+ else if (strncmp (arg, "--sysroot=", 10) == 0)
+ target_system_root = arg + 10;
break;
}
}
}
/* The AIX linker will discard static constructors in object files if
- nothing else in the file is referenced, so look at them first. */
- {
- const char **export_object_lst = (const char **)object_lst;
-
- while (export_object_lst < object)
- scan_prog_file (*export_object_lst++, PASS_OBJ);
- }
+ nothing else in the file is referenced, so look at them first. Unless
+ we are building a shared object, ignore the eh frame tables, as we
+ would otherwise reference them all, hence drag all the corresponding
+ objects even if nothing else is referenced. */
{
+ const char **export_object_lst
+ = CONST_CAST2 (const char **, char **, object_lst);
+
struct id *list = libs.first;
+ /* Compute the filter to use from the current one, do scan, then adjust
+ the "current" filter to remove what we just included here. This will
+ control whether we need a first pass link later on or not, and what
+ will remain to be scanned there. */
+
+ scanfilter this_filter
+ = shared_obj ? ld1_filter : (ld1_filter & ~SCAN_DWEH);
+
+ while (export_object_lst < object)
+ scan_prog_file (*export_object_lst++, PASS_OBJ, this_filter);
+
for (; list; list = list->next)
- scan_prog_file (list->name, PASS_FIRST);
+ scan_prog_file (list->name, PASS_FIRST, this_filter);
+
+ ld1_filter = ld1_filter & ~this_filter;
}
if (exports.first)
}
/* Load the program, searching all libraries and attempting to provide
- undefined symbols from repository information. */
-
- /* On AIX we do this later. */
-#ifndef COLLECT_EXPORT_LIST
- do_tlink (ld1_argv, object_lst);
-#endif
-
- /* If -r or they will be run via some other method, do not build the
- constructor or destructor list, just return now. */
- if (rflag
-#ifndef COLLECT_EXPORT_LIST
- || ! do_collecting
-#endif
- )
- {
-#ifdef COLLECT_EXPORT_LIST
- /* Do the link we avoided above if we are exiting. */
+ undefined symbols from repository information.
+
+ If -r or they will be run via some other method, do not build the
+ constructor or destructor list, just return now. */
+ {
+ bool early_exit
+ = rflag || (! DO_COLLECT_EXPORT_LIST && ! do_collecting);
+
+ /* Perform the first pass link now, if we're about to exit or if we need
+ to scan for things we haven't collected yet before pursuing further.
+
+ On AIX, the latter typically includes nothing for shared objects or
+ frame tables for an executable, out of what the required early scan on
+ objects and libraries has performed above. In the !shared_obj case, we
+ expect the relevant tables to be dragged together with their associated
+ functions from precise cross reference insertions by the compiler. */
+
+ if (early_exit || ld1_filter != SCAN_NOTHING)
do_tlink (ld1_argv, object_lst);
-
- /* But make sure we delete the export file we may have created. */
- if (export_file != 0 && export_file[0])
- maybe_unlink (export_file);
+
+ if (early_exit)
+ {
+#ifdef COLLECT_EXPORT_LIST
+ /* Make sure we delete the export file we may have created. */
+ if (export_file != 0 && export_file[0])
+ maybe_unlink (export_file);
#endif
- maybe_unlink (c_file);
- maybe_unlink (o_file);
- return 0;
- }
+ maybe_unlink (c_file);
+ maybe_unlink (o_file);
+ return 0;
+ }
+ }
- /* Examine the namelist with nm and search it for static constructors
- and destructors to call.
- Write the constructor and destructor tables to a .s file and reload. */
+ /* Unless we have done it all already, examine the namelist and search for
+ static constructors and destructors to call. Write the constructor and
+ destructor tables to a .s file and reload. */
- /* On AIX we already scanned for global constructors/destructors. */
-#ifndef COLLECT_EXPORT_LIST
- scan_prog_file (output_file, PASS_FIRST);
-#endif
+ if (ld1_filter != SCAN_NOTHING)
+ scan_prog_file (output_file, PASS_FIRST, ld1_filter);
#ifdef SCAN_LIBRARIES
scan_libraries (output_file);
notice ("%d frame table(s) found\n", frame_tables.number);
}
+ /* If the scan exposed nothing of special interest, there's no need to
+ generate the glue code and relink so return now. */
+
if (constructors.number == 0 && destructors.number == 0
&& frame_tables.number == 0
#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
#endif
)
{
-#ifdef COLLECT_EXPORT_LIST
- /* Do tlink without additional code generation. */
- do_tlink (ld1_argv, object_lst);
-#endif
+ /* Do tlink without additional code generation now if we didn't
+ do it earlier for scanning purposes. */
+ if (ld1_filter == SCAN_NOTHING)
+ do_tlink (ld1_argv, object_lst);
+
/* Strip now if it was requested on the command line. */
if (strip_flag)
{
char **real_strip_argv = XCNEWVEC (char *, 3);
- const char ** strip_argv = (const char **) real_strip_argv;
+ const char ** strip_argv = CONST_CAST2 (const char **, char **,
+ real_strip_argv);
strip_argv[0] = strip_file_name;
strip_argv[1] = output_file;
/* Let scan_prog_file do any final mods (OSF/rose needs this for
constructors/destructors in shared libraries. */
- scan_prog_file (output_file, PASS_SECOND);
+ scan_prog_file (output_file, PASS_SECOND, SCAN_ALL);
#endif
maybe_unlink (c_file);
error ("%s returned %d exit status", prog, ret);
collect_exit (ret);
}
+
+ if (response_file)
+ {
+ unlink (response_file);
+ response_file = NULL;
+ }
}
\f
struct pex_obj *pex;
const char *errmsg;
int err;
+ char *response_arg = NULL;
+ char *response_argv[3] ATTRIBUTE_UNUSED;
+
+ if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL)
+ {
+ /* If using @file arguments, create a temporary file and put the
+ contents of argv into it. Then change argv to an array corresponding
+ to a single argument @FILE, where FILE is the temporary filename. */
+
+ char **current_argv = argv + 1;
+ char *argv0 = argv[0];
+ int status;
+ FILE *f;
+
+ /* Note: we assume argv contains at least one element; this is
+ checked above. */
+
+ response_file = make_temp_file ("");
+
+ f = fopen (response_file, "w");
+
+ if (f == NULL)
+ fatal ("could not open response file %s", response_file);
+
+ status = writeargv (current_argv, f);
+
+ if (status)
+ fatal ("could not write to response file %s", response_file);
+
+ status = fclose (f);
+
+ if (EOF == status)
+ fatal ("could not close response file %s", response_file);
+
+ response_arg = concat ("@", response_file, NULL);
+ response_argv[0] = argv0;
+ response_argv[1] = response_arg;
+ response_argv[2] = NULL;
+
+ argv = response_argv;
+ }
if (vflag || debug)
{
fatal (errmsg);
}
+ if (response_arg)
+ free (response_arg);
+
return pex;
}
static void
add_to_list (struct head *head_ptr, const char *name)
{
- struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1);
+ struct id *newid
+ = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
struct id *p;
strcpy (newid->name, name);
}
else
{
- if (strncmp (q, ".so", 3) == 0)
+ if (strncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0)
{
- q += 3;
+ q += strlen (SHLIB_SUFFIX);
break;
}
else
static void
write_c_file (FILE *stream, const 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");
}
#ifdef COLLECT_EXPORT_LIST
#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__. */
+ the symbols g++ uses for static constructors and destructors. */
static void
-scan_prog_file (const char *prog_name, enum pass which_pass)
+scan_prog_file (const char *prog_name, scanpass which_pass,
+ scanfilter filter)
{
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;
+ const char **nm_argv = CONST_CAST2 (const char **, char**, real_nm_argv);
int argc = 0;
struct pex_obj *pex;
const char *errmsg;
char *name, *end;
/* If it contains a constructor or destructor name, add the name
- to the appropriate list. */
+ to the appropriate list unless this is a kind of symbol we're
+ not supposed to even consider. */
for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
*end = '\0';
switch (is_ctor_dtor (name))
{
- case 1:
+ case SYM_CTOR:
+ if (! (filter & SCAN_CTOR))
+ break;
if (which_pass != PASS_LIB)
add_to_list (&constructors, name);
break;
- case 2:
+ case SYM_DTOR:
+ if (! (filter & SCAN_DTOR))
+ break;
if (which_pass != PASS_LIB)
add_to_list (&destructors, name);
break;
- case 3:
+ case SYM_INIT:
+ if (! (filter & SCAN_INIT))
+ break;
if (which_pass != PASS_LIB)
fatal ("init function found in object %s", prog_name);
#ifndef LD_INIT_SWITCH
#endif
break;
- case 4:
+ case SYM_FINI:
+ if (! (filter & SCAN_FINI))
+ break;
if (which_pass != PASS_LIB)
fatal ("fini function found in object %s", prog_name);
#ifndef LD_FINI_SWITCH
#endif
break;
- case 5:
+ case SYM_DWEH:
+ if (! (filter & SCAN_DWEH))
+ break;
if (which_pass != PASS_LIB)
add_to_list (&frame_tables, name);
break;
void (*quit_handler) (int);
#endif
char *real_ldd_argv[4];
- const char **ldd_argv = (const char **) real_ldd_argv;
+ const char **ldd_argv = CONST_CAST2 (const char **, char **, real_ldd_argv);
int argc = 0;
struct pex_obj *pex;
const char *errmsg;
# define GCC_SYMZERO(X) 0
/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
-#ifdef _AIX51
+#if TARGET_AIX_VERSION >= 51
# define GCC_CHECK_HDR(X) \
((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
|| (HEADER (X).f_magic == 0767 && aix64_flag))
static int
ignore_library (const char *name)
{
- const char *const *p = &aix_std_libs[0];
- while (*p++ != NULL)
- if (! strcmp (name, *p)) return 1;
+ const char *const *p;
+ size_t length;
+
+ if (target_system_root[0] != '\0')
+ {
+ length = strlen (target_system_root);
+ if (strncmp (name, target_system_root, length) != 0)
+ return 0;
+ name += length;
+ }
+ for (p = &aix_std_libs[0]; *p != NULL; ++p)
+ if (strcmp (name, *p) == 0)
+ return 1;
return 0;
}
#endif /* COLLECT_EXPORT_LIST */
#endif
/* 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__. */
+ the symbols g++ uses for static constructors and destructors. */
static void
-scan_prog_file (const char *prog_name, enum pass which_pass)
+scan_prog_file (const char *prog_name, scanpass which_pass,
+ scanfilter filter)
{
LDFILE *ldptr = NULL;
int sym_index, sym_count;
/* Some platforms (e.g. OSF4) declare ldopen as taking a
non-const char * filename parameter, even though it will not
modify that string. So we must cast away const-ness here,
- which will cause -Wcast-qual to burp. */
- if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
+ using CONST_CAST to prevent complaints from -Wcast-qual. */
+ if ((ldptr = ldopen (CONST_CAST (char *, prog_name), ldptr)) != NULL)
{
if (! MY_ISCOFF (HEADER (ldptr).f_magic))
fatal ("%s: not a COFF file", prog_name);
switch (is_ctor_dtor (name))
{
- case 1:
+ case SYM_CTOR:
+ if (! (filter & SCAN_CTOR))
+ break;
if (! is_shared)
add_to_list (&constructors, name);
#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
#endif
break;
- case 2:
+ case SYM_DTOR:
+ if (! (filter & SCAN_DTOR))
+ break;
if (! is_shared)
add_to_list (&destructors, name);
#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
break;
#ifdef COLLECT_EXPORT_LIST
- case 3:
+ case SYM_INIT:
+ if (! (filter & SCAN_INIT))
+ break;
#ifndef LD_INIT_SWITCH
if (is_shared)
add_to_list (&constructors, name);
#endif
break;
- case 4:
+ case SYM_FINI:
+ if (! (filter & SCAN_FINI))
+ break;
#ifndef LD_INIT_SWITCH
if (is_shared)
add_to_list (&destructors, name);
break;
#endif
- case 5:
+ case SYM_DWEH:
+ if (! (filter & SCAN_DWEH))
+ break;
if (! is_shared)
add_to_list (&frame_tables, name);
#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
if (libpaths[i]->max_len > l)
l = libpaths[i]->max_len;
- lib_buf = xmalloc (l + strlen(name) + 10);
+ lib_buf = XNEWVEC (char, l + strlen(name) + 10);
for (i = 0; libpaths[i]; i++)
{