/* 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, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@cygnus.com),
# define SIGCHLD SIGCLD
#endif
+/* TARGET_64BIT may be defined to use driver specific functionality. */
+#undef TARGET_64BIT
+#define TARGET_64BIT TARGET_64BIT_DEFAULT
+
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
int number;
};
-int vflag; /* true if -v */
+bool vflag; /* true if -v or --version */
static int rflag; /* true if -r */
static int strip_flag; /* true if -s */
static const char *demangle_flag;
/* Current LTO mode. */
static enum lto_mode_d lto_mode = LTO_MODE_NONE;
-int debug; /* true if -debug */
+bool debug; /* true if -debug */
+bool helpflag; /* true if --help */
static int shared_obj; /* true if -shared */
enum scanfilter_masks {
SCAN_NOTHING = 0,
- SCAN_CTOR = 1 << SYM_CTOR,
+ SCAN_CTOR = 1 << SYM_CTOR,
SCAN_DTOR = 1 << SYM_DTOR,
SCAN_INIT = 1 << SYM_INIT,
SCAN_FINI = 1 << SYM_FINI,
va_end (ap);
}
+/* Notify user of a non-error, without translating the format string. */
+void
+notice_translated (const char *cmsgid, ...)
+{
+ va_list ap;
+
+ va_start (ap, cmsgid);
+ vfprintf (stderr, cmsgid, ap);
+ va_end (ap);
+}
+
/* Die when sys call fails. */
void
char **ld1_argv;
const char **ld1;
bool use_plugin = false;
-
+
/* 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
int num_c_args;
char **old_argv;
+ bool use_verbose = false;
+
old_argv = argv;
expandargv (&argc, &argv);
if (argv != old_argv)
for (i = 1; argv[i] != NULL; i ++)
{
if (! strcmp (argv[i], "-debug"))
- debug = 1;
+ debug = true;
else if (! strcmp (argv[i], "-flto") && ! use_plugin)
- lto_mode = LTO_MODE_LTO;
+ {
+ use_verbose = true;
+ lto_mode = LTO_MODE_LTO;
+ }
else if (! strcmp (argv[i], "-fwhopr") && ! use_plugin)
- lto_mode = LTO_MODE_WHOPR;
+ {
+ use_verbose = true;
+ lto_mode = LTO_MODE_WHOPR;
+ }
else if (! strcmp (argv[i], "-plugin"))
{
use_plugin = true;
+ use_verbose = true;
lto_mode = LTO_MODE_NONE;
}
#ifdef COLLECT_EXPORT_LIST
*c_ptr++ = xstrdup (q);
}
}
+ if (use_verbose && *q == '-' && q[1] == 'v' && q[2] == 0)
+ {
+ /* Turn on trace in collect2 if needed. */
+ vflag = true;
+ }
}
obstack_free (&temporary_obstack, temporary_firstobj);
*c_ptr++ = "-fno-profile-arcs";
case 'v':
if (arg[2] == '\0')
- vflag = 1;
+ vflag = true;
break;
case '-':
}
else if (strncmp (arg, "--sysroot=", 10) == 0)
target_system_root = arg + 10;
+ else if (strncmp (arg, "--version", 9) == 0)
+ vflag = true;
+ else if (strncmp (arg, "--help", 9) == 0)
+ helpflag = true;
break;
}
}
would otherwise reference them all, hence drag all the corresponding
objects even if nothing else is referenced. */
{
- const char **export_object_lst
+ 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);
-
+
+ scanfilter this_filter = ld1_filter;
+#if HAVE_AS_REF
+ if (!shared_obj)
+ this_filter &= ~SCAN_DWEH;
+#endif
+
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, this_filter);
-
+
ld1_filter = ld1_filter & ~this_filter;
}
fprintf (stderr, "\n");
}
+ if (helpflag)
+ {
+ fprintf (stderr, "Usage: collect2 [options]\n");
+ fprintf (stderr, " Wrap linker and generate constructor code if needed.\n");
+ fprintf (stderr, " Options:\n");
+ fprintf (stderr, " -debug Enable debug output\n");
+ fprintf (stderr, " --help Display this information\n");
+ fprintf (stderr, " -v, --version Display this program's version number\n");
+ fprintf (stderr, "Overview: http://gcc.gnu.org/onlinedocs/gccint/Collect2.html\n");
+ fprintf (stderr, "Report bugs: %s\n", bug_report_url);
+
+ collect_exit (0);
+ }
+
if (debug)
{
const char *ptr;
/* Load the program, searching all libraries and attempting to provide
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. */
+ constructor or destructor list, just return now. */
{
bool early_exit
= rflag || (! DO_COLLECT_EXPORT_LIST && ! do_collecting);
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);
-
+
if (early_exit)
{
#ifdef COLLECT_EXPORT_LIST
if (debug)
{
- notice ("%d constructor(s) found\n", constructors.number);
- notice ("%d destructor(s) found\n", destructors.number);
- notice ("%d frame table(s) found\n", frame_tables.number);
+ notice_translated (ngettext ("%d constructor found\n",
+ "%d constructors found\n",
+ constructors.number),
+ constructors.number);
+ notice_translated (ngettext ("%d destructor found\n",
+ "%d destructors found\n",
+ destructors.number),
+ destructors.number);
+ notice_translated (ngettext("%d frame table found\n",
+ "%d frame tables found\n",
+ frame_tables.number),
+ frame_tables.number);
}
/* If the scan exposed nothing of special interest, there's no need to
be in ELF format. */
static bool
-is_elf (const char *prog_name)
+is_elf_or_coff (const char *prog_name)
{
FILE *f;
char buf[4];
static char magic[4] = { 0x7f, 'E', 'L', 'F' };
+ static char coffmag[2] = { 0x4c, 0x01 };
- f = fopen (prog_name, "r");
+ f = fopen (prog_name, "rb");
if (f == NULL)
return false;
if (fread (buf, sizeof (buf), 1, f) != 1)
buf[0] = 0;
fclose (f);
- return memcmp (buf, magic, sizeof (magic)) == 0;
+ return memcmp (buf, magic, sizeof (magic)) == 0
+ || memcmp (buf, coffmag, sizeof (coffmag)) == 0;
}
/* Generic version to scan the name list of the loaded program for
if (which_pass == PASS_SECOND)
return;
- /* LTO objects must be in ELF format. This check prevents
+ /* LTO objects must be in a known format. This check prevents
us from accepting an archive containing LTO objects, which
gcc cannnot currently handle. */
- if (which_pass == PASS_LTOINFO && !is_elf (prog_name))
+ if (which_pass == PASS_LTOINFO && !is_elf_or_coff (prog_name))
return;
/* If we do not have an `nm', complain. */
/* Look for the LTO info marker symbol, and add filename to
the LTO objects list if found. */
for (p = buf; (ch = *p) != '\0' && ch != '\n'; p++)
- if (ch == ' '
- && (strncmp (p +1 , "gnu_lto_v1", 10) == 0)
- && ISSPACE( p[11]))
+ if (ch == ' ' && p[1] == '_' && p[2] == '_'
+ && (strncmp (p + (p[3] == '_' ? 2 : 1), "__gnu_lto_v1", 12) == 0)
+ && ISSPACE (p[p[3] == '_' ? 14 : 13]))
{
add_lto_object (<o_objects, prog_name);
/* 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);
+ scan_prog_file (list->name, PASS_LIB, SCAN_ALL);
}
#endif /* LDD_SUFFIX */