/* Collect static initialization info into data structures that can be
traversed by C++ initialization and finalization routines.
- Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ Copyright (C) 1992-2015 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).
/* Special kinds of symbols that a name may denote. */
-typedef enum {
+enum symkind {
SYM_REGULAR = 0, /* nothing special */
SYM_CTOR = 1, /* constructor */
SYM_DWEH = 5, /* DWARF exception handling table */
SYM_AIXI = 6,
SYM_AIXD = 7
-} symkind;
+};
const char tool_name[] = "collect2";
/* Enumerations describing which pass this is for scanning the
program file ... */
-typedef enum {
+enum scanpass {
PASS_FIRST, /* without constructors */
PASS_OBJ, /* individual objects */
PASS_LIB, /* looking for shared libraries */
PASS_SECOND, /* with constructors linked in */
PASS_LTOINFO /* looking for objects with LTO info */
-} scanpass;
+};
/* ... and which kinds of symbols are to be considered. */
size_t num_files;
if (!lto_wrapper)
- fatal_error ("COLLECT_LTO_WRAPPER must be set");
+ fatal_error (input_location, "COLLECT_LTO_WRAPPER must be set");
num_lto_c_args++;
signal (SIGCHLD, SIG_DFL);
#endif
- if (atexit (collect_atexit) != 0)
- fatal_error ("atexit failed");
-
/* Unlock the stdio streams. */
unlock_std_streams ();
diagnostic_initialize (global_dc, 0);
+ if (atexit (collect_atexit) != 0)
+ fatal_error (input_location, "atexit failed");
+
/* Do not invoke xcalloc before this point, since locale needs to be
set first, in case a diagnostic is issued. */
c_ptr = CONST_CAST2 (const char **, char **, c_argv);
if (argc < 2)
- fatal_error ("no arguments");
+ fatal_error (input_location, "no arguments");
#ifdef SIGQUIT
if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
stream = fopen (list_filename, "r");
if (stream == NULL)
- fatal_error ("can't open %s: %m", list_filename);
+ fatal_error (input_location, "can't open %s: %m",
+ list_filename);
while (fgets (buf, sizeof buf, stream) != NULL)
{
exportf = fopen (export_file, "w");
if (exportf == (FILE *) 0)
- fatal_error ("fopen %s: %m", export_file);
+ fatal_error (input_location, "fopen %s: %m", export_file);
write_aix_file (exportf, exports.first);
if (fclose (exportf))
- fatal_error ("fclose %s: %m", export_file);
+ fatal_error (input_location, "fclose %s: %m", export_file);
}
#endif
maybe_unlink (output_file);
outf = fopen (c_file, "w");
if (outf == (FILE *) 0)
- fatal_error ("fopen %s: %m", c_file);
+ fatal_error (input_location, "fopen %s: %m", c_file);
write_c_file (outf, c_file);
if (fclose (outf))
- fatal_error ("fclose %s: %m", c_file);
+ fatal_error (input_location, "fclose %s: %m", c_file);
/* Tell the linker that we have initializer and finalizer functions. */
#ifdef LD_INIT_SWITCH
#endif
exportf = fopen (export_file, "w");
if (exportf == (FILE *) 0)
- fatal_error ("fopen %s: %m", export_file);
+ fatal_error (input_location, "fopen %s: %m", export_file);
write_aix_file (exportf, exports.first);
if (fclose (exportf))
- fatal_error ("fclose %s: %m", export_file);
+ fatal_error (input_location, "fclose %s: %m", export_file);
}
#endif
fprintf (stream, " struct object *next;\n");
fprintf (stream, "};\n");
+ fprintf (stream, "extern void __register_frame_info_table_bases (void *, struct object *, void *tbase, void *dbase);\n");
fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
+#ifdef TARGET_AIX_VERSION
+ fprintf (stream, "extern void *__gcc_unwind_dbase;\n");
+#endif
fprintf (stream, "static void reg_frame () {\n");
fprintf (stream, "\tstatic struct object ob;\n");
+#ifdef TARGET_AIX_VERSION
+ /* Use __gcc_unwind_dbase as the base address for data on AIX.
+ This might not be the start of the segment, signed offsets assumed.
+ */
+ fprintf (stream, "\t__register_frame_info_table_bases (frame_table, &ob, (void *)0, &__gcc_unwind_dbase);\n");
+#else
fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
+#endif
fprintf (stream, "\t}\n");
fprintf (stream, "static void dereg_frame () {\n");
/* If we do not have an `nm', complain. */
if (nm_file_name == 0)
- fatal_error ("cannot find 'nm'");
+ fatal_error (input_location, "cannot find 'nm'");
nm_argv[argc++] = nm_file_name;
if (NM_FLAGS[0] != '\0')
pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
if (pex == NULL)
- fatal_error ("pex_init failed: %m");
+ fatal_error (input_location, "pex_init failed: %m");
errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET,
&err);
if (err != 0)
{
errno = err;
- fatal_error ("%s: %m", _(errmsg));
+ fatal_error (input_location, "%s: %m", _(errmsg));
}
else
- fatal_error (errmsg);
+ fatal_error (input_location, errmsg);
}
int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
inf = pex_read_output (pex, 0);
if (inf == NULL)
- fatal_error ("can't open nm output: %m");
+ fatal_error (input_location, "can't open nm output: %m");
if (debug)
{
if (! (filter & SCAN_INIT))
break;
if (which_pass != PASS_LIB)
- fatal_error ("init function found in object %s", prog_name);
+ fatal_error (input_location, "init function found in object %s",
+ prog_name);
#ifndef LD_INIT_SWITCH
add_to_list (&constructors, name);
#endif
if (! (filter & SCAN_FINI))
break;
if (which_pass != PASS_LIB)
- fatal_error ("fini function found in object %s", prog_name);
+ fatal_error (input_location, "fini function found in object %s",
+ prog_name);
#ifndef LD_FINI_SWITCH
add_to_list (&destructors, name);
#endif
pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
if (pex == NULL)
- fatal_error ("pex_init failed: %m");
+ fatal_error (input_location, "pex_init failed: %m");
errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
if (errmsg != NULL)
if (err != 0)
{
errno = err;
- fatal_error ("%s: %m", _(errmsg));
+ fatal_error (input_location, "%s: %m", _(errmsg));
}
else
- fatal_error (errmsg);
+ fatal_error (input_location, errmsg);
}
int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
inf = pex_read_output (pex, 0);
if (inf == NULL)
- fatal_error ("can't open ldd output: %m");
+ fatal_error (input_location, "can't open ldd output: %m");
if (debug)
notice ("\nldd output with constructors/destructors.\n");
name = p;
if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
- fatal_error ("dynamic dependency %s not found", buf);
+ fatal_error (input_location, "dynamic dependency %s not found", buf);
/* Find the end of the symbol name. */
for (end = p;
if (access (name, R_OK) == 0)
add_to_list (&libraries, name);
else
- fatal_error ("unable to open dynamic dependency '%s'", buf);
+ fatal_error (input_location, "unable to open dynamic dependency '%s'",
+ buf);
if (debug)
fprintf (stderr, "\t%s\n", buf);
if ((ldptr = ldopen (CONST_CAST (char *, prog_name), ldptr)) != NULL)
{
if (! MY_ISCOFF (HEADER (ldptr).f_magic))
- fatal_error ("%s: not a COFF file", prog_name);
+ fatal_error (input_location, "%s: not a COFF file", prog_name);
if (GCC_CHECK_HDR (ldptr))
{
provides an explicit export list. */
if (shared_obj && !is_shared
&& which_pass == PASS_OBJ && !export_flag)
- add_to_list (&exports, name);
+ {
+ /* Do not auto-export __dso_handle or
+ __gcc_unwind_dbase. They are required
+ to be local to each module. */
+ if (strcmp(name, "__dso_handle") != 0
+ && strcmp(name, "__gcc_unwind_dbase") != 0)
+ {
+ add_to_list (&exports, name);
+ }
+ }
#endif
continue;
}
}
else
{
- fatal_error ("%s: cannot open as COFF file", prog_name);
+ fatal_error (input_location, "%s: cannot open as COFF file",
+ prog_name);
}
#ifdef COLLECT_EXPORT_LIST
/* On AIX loop continues while there are more members in archive. */
if (debug)
fprintf (stderr, "not found\n");
else
- fatal_error ("library lib%s not found", name);
+ fatal_error (input_location, "library lib%s not found", name);
return (NULL);
}
#endif /* COLLECT_EXPORT_LIST */