X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcollect2.c;h=bba108d27491d895e72f4a23b57e7e726806c789;hp=1239b9837564a7e6b13c9646b123de9ec3970a18;hb=06f2e3c68e4f31e2efca41ecee92c441acfc044d;hpb=402eb8ac5a3255dc923f7737c654911d4a7196b2 diff --git a/gcc/collect2.c b/gcc/collect2.c index 1239b983756..bba108d2749 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -1,51 +1,39 @@ /* 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 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 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). -This file is part of GNU CC. +This file is part of GCC. -GNU CC 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 version. +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 3, or (at your option) any later +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* Build tables of static constructors and destructors and run ld. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include #if ! defined( SIGCHLD ) && defined( SIGCLD ) # 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 -#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 @@ -57,10 +45,6 @@ Boston, MA 02111-1307, USA. */ #include "obstack.h" #include "intl.h" #include "version.h" - -/* Obstack allocation and deallocation routines. */ -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free /* On certain systems, we have code that works by scanning the object file directly. But this code uses system-specific header files and library @@ -68,10 +52,8 @@ Boston, MA 02111-1307, USA. */ the utilities are not correct for a cross-compiler; we have to hope that cross-versions are in the proper directories. */ -#ifdef CROSS_COMPILE -#undef SUNOS4_SHARED_LIBRARIES +#ifdef CROSS_DIRECTORY_STRUCTURE #undef OBJECT_FORMAT_COFF -#undef OBJECT_FORMAT_ROSE #undef MD_EXEC_PREFIX #undef REAL_LD_FILE_NAME #undef REAL_NM_FILE_NAME @@ -83,7 +65,7 @@ Boston, MA 02111-1307, USA. */ In a cross-compiler, this means you need a cross nm, but that is not quite as unpleasant as special headers. */ -#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE) +#if !defined (OBJECT_FORMAT_COFF) #define OBJECT_FORMAT_NONE #endif @@ -106,7 +88,7 @@ Boston, MA 02111-1307, USA. */ /* 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 - that either do not have an ISCOFF macro in /usr/include or for those + that either do not have an ISCOFF macro in /usr/include or for those where it is wrong. */ #ifndef MY_ISCOFF @@ -115,24 +97,6 @@ Boston, MA 02111-1307, USA. */ #endif /* OBJECT_FORMAT_COFF */ -#ifdef OBJECT_FORMAT_ROSE - -#ifdef _OSF_SOURCE -#define USE_MMAP -#endif - -#ifdef USE_MMAP -#include -#endif - -#include -#include -#include -#include -#include - -#endif /* OBJECT_FORMAT_ROSE */ - #ifdef OBJECT_FORMAT_NONE /* Default flags to pass to nm. */ @@ -144,20 +108,31 @@ Boston, MA 02111-1307, USA. */ /* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to - give the same symbol without quotes for an alternative entry point. You - must define both, or neither. */ + give the same symbol without quotes for an alternative entry point. */ #ifndef NAME__MAIN #define NAME__MAIN "__main" -#define SYMBOL__MAIN __main #endif /* This must match tree.h. */ #define DEFAULT_INIT_PRIORITY 65535 -#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES +#ifndef COLLECT_SHARED_INIT_FUNC +#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \ + fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC)) +#endif +#ifndef COLLECT_SHARED_FINI_FUNC +#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \ + fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC)) +#endif + +#ifdef LDD_SUFFIX #define SCAN_LIBRARIES #endif +#ifndef SHLIB_SUFFIX +#define SHLIB_SUFFIX ".so" +#endif + #ifdef USE_COLLECT2 int do_collecting = 1; #else @@ -170,7 +145,7 @@ int no_demangle; /* Linked lists of constructor and destructor names. */ -struct id +struct id { struct id *next; int sequence; @@ -189,35 +164,38 @@ struct head enum pass { PASS_FIRST, /* without constructors */ PASS_OBJ, /* individual objects */ - PASS_LIB, /* looking for shared libraries */ + 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 */ +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 */ -static int shared_obj; /* true if -shared */ +static int shared_obj; /* true if -shared */ static const char *c_file; /* .c for constructor/destructor list. */ static const char *o_file; /* .o for constructor/destructor list. */ #ifdef COLLECT_EXPORT_LIST -static const char *export_file; /* .x for AIX export list. */ +static const char *export_file; /* .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 static const char *ldd_file_name; /* pathname of ldd (or equivalent) */ #endif static const char *strip_file_name; /* pathname of strip */ -const char *c_file_name; /* pathname of gcc */ +const char *c_file_name; /* pathname of gcc */ static char *initname, *fininame; /* names of init and fini funcs */ static struct head constructors; /* list of constructors found */ @@ -227,20 +205,12 @@ static struct head exports; /* list of exported symbols */ #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; -struct obstack permanent_obstack; char * temporary_firstobj; -/* Holds the return value of pexecute. */ -int pexecute_pid; - -/* Defined in the automatically-generated underscore.c. */ -extern int prepends_underscore; - -#ifndef GET_ENV_PATH_LIST -#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0) -#endif - /* Structure to hold all the directories in which to search for files to execute. */ @@ -258,82 +228,59 @@ struct path_prefix }; #ifdef COLLECT_EXPORT_LIST -/* Lists to keep libraries to be scanned for global constructors/destructors. */ +/* Lists to keep libraries to be scanned for global constructors/destructors. */ static struct head libs; /* list of libraries */ static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ 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 *libexts[3] = {"a", "so", NULL}; /* possible library extentions */ -#endif - -static void handler PARAMS ((int)); -static int is_ctor_dtor PARAMS ((const char *)); -static char *find_a_file PARAMS ((struct path_prefix *, const char *)); -static void add_prefix PARAMS ((struct path_prefix *, const char *)); -static void prefix_from_env PARAMS ((const char *, struct path_prefix *)); -static void prefix_from_string PARAMS ((const char *, struct path_prefix *)); -static void do_wait PARAMS ((const char *)); -static void fork_execute PARAMS ((const char *, char **)); -static void maybe_unlink PARAMS ((const char *)); -static void add_to_list PARAMS ((struct head *, const char *)); -static int extract_init_priority PARAMS ((const char *)); -static void sort_ids PARAMS ((struct head *)); -static void write_list PARAMS ((FILE *, const char *, struct id *)); +#endif + +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 *); +static void prefix_from_string (const char *, struct path_prefix *); +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 *); +static int extract_init_priority (const char *); +static void sort_ids (struct head *); +static void write_list (FILE *, const char *, struct id *); #ifdef COLLECT_EXPORT_LIST -static void dump_list PARAMS ((FILE *, const char *, struct id *)); +static void dump_list (FILE *, const char *, struct id *); #endif #if 0 -static void dump_prefix_list PARAMS ((FILE *, const char *, struct prefix_list *)); +static void dump_prefix_list (FILE *, const char *, struct prefix_list *); #endif -static void write_list_with_asm PARAMS ((FILE *, const char *, struct id *)); -static void write_c_file PARAMS ((FILE *, const char *)); -static void write_c_file_stat PARAMS ((FILE *, const char *)); +static void write_list_with_asm (FILE *, const char *, struct id *); +static void write_c_file (FILE *, const char *); +static void write_c_file_stat (FILE *, const char *); #ifndef LD_INIT_SWITCH -static void write_c_file_glob PARAMS ((FILE *, const char *)); +static void write_c_file_glob (FILE *, const char *); #endif -static void scan_prog_file PARAMS ((const char *, enum pass)); +static void scan_prog_file (const char *, enum pass); #ifdef SCAN_LIBRARIES -static void scan_libraries PARAMS ((const char *)); +static void scan_libraries (const char *); #endif #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES -static int is_in_args PARAMS ((const char *, const char **, const char **)); +static int is_in_args (const char *, const char **, const char **); #endif #ifdef COLLECT_EXPORT_LIST -static int is_in_list PARAMS ((const char *, struct id *)); -static void write_aix_file PARAMS ((FILE *, struct id *)); -static char *resolve_lib_name PARAMS ((const char *)); -static int ignore_library PARAMS ((const char *)); +#if 0 +static int is_in_list (const char *, struct id *); #endif -static char *extract_string PARAMS ((const char **)); - -#ifdef NO_DUP2 -int -dup2 (oldfd, newfd) - 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; -} +static void write_aix_file (FILE *, struct id *); +static char *resolve_lib_name (const char *); #endif +static char *extract_string (const char **); /* Delete tempfiles and exit function. */ void -collect_exit (status) - int status; +collect_exit (int status) { if (c_file != 0 && c_file[0]) maybe_unlink (c_file); @@ -348,55 +295,48 @@ collect_exit (status) 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); + if (response_file) + maybe_unlink (response_file); + exit (status); } /* Notify user of a non-error. */ void -notice VPARAMS ((const char *msgid, ...)) +notice (const char *cmsgid, ...) { -#ifndef ANSI_PROTOTYPES - const char *msgid; -#endif va_list ap; - VA_START (ap, msgid); - -#ifndef ANSI_PROTOTYPES - msgid = va_arg (ap, const char *); -#endif - - vfprintf (stderr, _(msgid), ap); + va_start (ap, cmsgid); + vfprintf (stderr, _(cmsgid), ap); va_end (ap); } /* Die when sys call fails. */ void -fatal_perror VPARAMS ((const char * msgid, ...)) +fatal_perror (const char * cmsgid, ...) { -#ifndef ANSI_PROTOTYPES - const char *msgid; -#endif int e = errno; va_list ap; - VA_START (ap, msgid); - -#ifndef ANSI_PROTOTYPES - msgid = va_arg (ap, const char *); -#endif - + va_start (ap, cmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(cmsgid), ap); fprintf (stderr, ": %s\n", xstrerror (e)); va_end (ap); @@ -406,21 +346,13 @@ fatal_perror VPARAMS ((const char * msgid, ...)) /* Just die. */ void -fatal VPARAMS ((const char * msgid, ...)) +fatal (const char * cmsgid, ...) { -#ifndef ANSI_PROTOTYPES - const char *msgid; -#endif va_list ap; - - VA_START (ap, msgid); -#ifndef ANSI_PROTOTYPES - msgid = va_arg (ap, const char *); -#endif - + va_start (ap, cmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(cmsgid), ap); fprintf (stderr, "\n"); va_end (ap); @@ -430,21 +362,13 @@ fatal VPARAMS ((const char * msgid, ...)) /* Write error message. */ void -error VPARAMS ((const char * msgid, ...)) +error (const char * gmsgid, ...) { -#ifndef ANSI_PROTOTYPES - const char * msgid; -#endif va_list ap; - - VA_START (ap, msgid); - -#ifndef ANSI_PROTOTYPES - msgid = va_arg (ap, const char *); -#endif + va_start (ap, gmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(gmsgid), ap); fprintf (stderr, "\n"); va_end(ap); } @@ -453,14 +377,13 @@ error VPARAMS ((const char * msgid, ...)) provide a default entry. */ void -fancy_abort () +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); } static void -handler (signo) - int signo; +handler (int signo) { if (c_file != 0 && c_file[0]) maybe_unlink (c_file); @@ -471,19 +394,24 @@ handler (signo) 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 + if (response_file) + maybe_unlink (response_file); + signal (signo, SIG_DFL); - kill (getpid (), signo); + raise (signo); } int -file_exists (name) - const char *name; +file_exists (const char *name) { return access (name, R_OK) == 0; } @@ -491,8 +419,7 @@ file_exists (name) /* Parse a reasonable subset of shell quoting syntax. */ static char * -extract_string (pp) - const char **pp; +extract_string (const char **pp) { const char *p = *pp; int backquote = 0; @@ -518,12 +445,11 @@ extract_string (pp) obstack_1grow (&temporary_obstack, '\0'); *pp = p; - return obstack_finish (&temporary_obstack); + return XOBFINISH (&temporary_obstack, char *); } void -dump_file (name) - const char *name; +dump_file (const char *name, FILE *to) { FILE *stream = fopen (name, "r"); @@ -533,48 +459,62 @@ dump_file (name) { int c; while (c = getc (stream), - c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.')) + c != EOF && (ISIDNUM (c) || c == '$' || c == '.')) obstack_1grow (&temporary_obstack, c); if (obstack_object_size (&temporary_obstack) > 0) { 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 (*p == '_' && prepends_underscore) - ++p; + 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); + 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); - while (diff < 0 && c == ' ') - ++diff, c = getc (stream); + --diff, putc (' ', to); + 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); } 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); } @@ -585,29 +525,30 @@ dump_file (name) nothing special (0). */ static int -is_ctor_dtor (s) - const char *s; +is_ctor_dtor (const char *s) { - struct names { const char *name; int len; int ret; int two_underscores; }; + struct names { const char *const name; const int len; const int ret; + const int two_underscores; }; - register struct names *p; - register int ch; - register const char *orig_s = s; + const struct names *p; + int ch; + const char *orig_s = s; - static struct names special[] = { + 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 }, +#else +#ifndef NO_DOT_IN_LABEL + { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 }, + { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 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 }, -#ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions. - cfront has its own linker procedure to collect them; - if collect2 gets them too, they get collected twice - when the cfront procedure is run and the compiler used - for linking happens to be GCC. */ - { "sti__", sizeof ("sti__")-1, 1, 1 }, - { "std__", sizeof ("std__")-1, 2, 1 }, -#endif /* CFRONT_LOSSAGE */ { NULL, 0, 0, 0 } }; @@ -634,7 +575,7 @@ is_ctor_dtor (s) static struct path_prefix cpath, path; -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE /* This is the name of the target machine. We use it to form the name of the files to execute. */ @@ -642,14 +583,12 @@ static const char *const target_machine = TARGET_MACHINE; #endif /* Search for NAME using prefix list PPREFIX. We only look for executable - files. + files. Return 0 if not found, otherwise return its name, allocated with malloc. */ static char * -find_a_file (pprefix, name) - struct path_prefix *pprefix; - const char *name; +find_a_file (struct path_prefix *pprefix, const char *name) { char *temp; struct prefix_list *pl; @@ -657,12 +596,12 @@ find_a_file (pprefix, name) if (debug) fprintf (stderr, "Looking for '%s'\n", name); - + #ifdef HOST_EXECUTABLE_SUFFIX len += strlen (HOST_EXECUTABLE_SUFFIX); #endif - temp = xmalloc (len); + temp = XNEWVEC (char, len); /* Determine the filename to execute (special case for absolute paths). */ @@ -678,7 +617,7 @@ find_a_file (pprefix, name) if (debug) fprintf (stderr, " - found: absolute path\n"); - + return temp; } @@ -687,7 +626,7 @@ find_a_file (pprefix, name) So try appending that. */ strcpy (temp, name); strcat (temp, HOST_EXECUTABLE_SUFFIX); - + if (access (temp, X_OK) == 0) return temp; #endif @@ -702,7 +641,7 @@ find_a_file (pprefix, name) strcpy (temp, pl->prefix); strcat (temp, name); - + if (stat (temp, &st) >= 0 && ! S_ISDIR (st.st_mode) && access (temp, X_OK) == 0) @@ -712,7 +651,7 @@ find_a_file (pprefix, name) /* Some systems have a suffix for executable files. So try appending that. */ strcat (temp, HOST_EXECUTABLE_SUFFIX); - + if (stat (temp, &st) >= 0 && ! S_ISDIR (st.st_mode) && access (temp, X_OK) == 0) @@ -730,9 +669,7 @@ find_a_file (pprefix, name) /* Add an entry for PREFIX to prefix list PPREFIX. */ static void -add_prefix (pprefix, prefix) - struct path_prefix *pprefix; - const char *prefix; +add_prefix (struct path_prefix *pprefix, const char *prefix) { struct prefix_list *pl, **prev; int len; @@ -746,13 +683,13 @@ add_prefix (pprefix, prefix) else prev = &pprefix->plist; - /* Keep track of the longest prefix */ + /* Keep track of the longest prefix. */ len = strlen (prefix); if (len > pprefix->max_len) pprefix->max_len = len; - pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); + pl = XNEW (struct prefix_list); pl->prefix = xstrdup (prefix); if (*prev) @@ -766,28 +703,24 @@ add_prefix (pprefix, prefix) add of the entries to PPREFIX. */ static void -prefix_from_env (env, pprefix) - const char *env; - struct path_prefix *pprefix; +prefix_from_env (const char *env, struct path_prefix *pprefix) { const char *p; - GET_ENV_PATH_LIST (p, env); + GET_ENVIRONMENT (p, env); if (p) prefix_from_string (p, pprefix); } static void -prefix_from_string (p, pprefix) - const char *p; - struct path_prefix *pprefix; +prefix_from_string (const char *p, struct path_prefix *pprefix) { const char *startp, *endp; - char *nstore = (char *) xmalloc (strlen (p) + 3); + char *nstore = XNEWVEC (char, strlen (p) + 3); if (debug) fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); - + startp = endp = p; while (1) { @@ -808,7 +741,7 @@ prefix_from_string (p, pprefix) if (debug) fprintf (stderr, " - add prefix: %s\n", nstore); - + add_prefix (pprefix, nstore); if (*endp == 0) break; @@ -817,32 +750,56 @@ prefix_from_string (p, pprefix) else endp++; } + free (nstore); } /* Main program. */ -int main PARAMS ((int, char *[])); int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char **argv) { - const char *ld_suffix = "ld"; - const char *full_ld_suffix = ld_suffix; - const char *real_ld_suffix = "real-ld"; - const char *collect_ld_suffix = "collect-ld"; - const char *nm_suffix = "nm"; - const char *full_nm_suffix = nm_suffix; - const char *gnm_suffix = "gnm"; - const char *full_gnm_suffix = gnm_suffix; + static const char *const ld_suffix = "ld"; + static const char *const real_ld_suffix = "real-ld"; + static const char *const collect_ld_suffix = "collect-ld"; + static const char *const nm_suffix = "nm"; + static const char *const gnm_suffix = "gnm"; +#ifdef LDD_SUFFIX + static const char *const ldd_suffix = LDD_SUFFIX; +#endif + static const char *const strip_suffix = "strip"; + static const char *const gstrip_suffix = "gstrip"; + +#ifdef CROSS_DIRECTORY_STRUCTURE + /* If we look for a program in the compiler directories, we just use + the short name, since these directories are already system-specific. + But it we look for a program in the system directories, we need to + qualify the program name with the target machine. */ + + const char *const full_ld_suffix = + concat(target_machine, "-", ld_suffix, NULL); + const char *const full_nm_suffix = + concat (target_machine, "-", nm_suffix, NULL); + const char *const full_gnm_suffix = + concat (target_machine, "-", gnm_suffix, NULL); +#ifdef LDD_SUFFIX + const char *const full_ldd_suffix = + concat (target_machine, "-", ldd_suffix, NULL); +#endif + const char *const full_strip_suffix = + concat (target_machine, "-", strip_suffix, NULL); + const char *const full_gstrip_suffix = + concat (target_machine, "-", gstrip_suffix, NULL); +#else + const char *const full_ld_suffix = ld_suffix; + const char *const full_nm_suffix = nm_suffix; + const char *const full_gnm_suffix = gnm_suffix; #ifdef LDD_SUFFIX - const char *ldd_suffix = LDD_SUFFIX; - const char *full_ldd_suffix = ldd_suffix; + const char *const full_ldd_suffix = ldd_suffix; #endif - const char *strip_suffix = "strip"; - const char *full_strip_suffix = strip_suffix; - const char *gstrip_suffix = "gstrip"; - const char *full_gstrip_suffix = gstrip_suffix; + const char *const full_strip_suffix = strip_suffix; + const char *const full_gstrip_suffix = gstrip_suffix; +#endif /* CROSS_DIRECTORY_STRUCTURE */ + const char *arg; FILE *outf; #ifdef COLLECT_EXPORT_LIST @@ -859,7 +816,15 @@ main (argc, argv) 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"); @@ -867,7 +832,7 @@ main (argc, argv) putenv (xstrdup ("COLLECT_NO_DEMANGLE=")); #if defined (COLLECT2_HOST_INITIALIZATION) - /* Perform system dependent initialization, if neccessary. */ + /* Perform system dependent initialization, if necessary. */ COLLECT2_HOST_INITIALIZATION; #endif @@ -877,25 +842,17 @@ main (argc, argv) signal (SIGCHLD, SIG_DFL); #endif -/* LC_CTYPE determines the character set used by the terminal so it has be set - to output messages correctly. */ + /* Unlock the stdio streams. */ + unlock_std_streams (); -#ifdef HAVE_LC_MESSAGES - setlocale (LC_CTYPE, ""); - setlocale (LC_MESSAGES, ""); -#else - setlocale (LC_ALL, ""); -#endif - - (void) bindtextdomain (PACKAGE, localedir); - (void) textdomain (PACKAGE); + 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 = (char **) xcalloc(sizeof (char *), argc+3)); - ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10)); - object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc)); + 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 debug = 1; @@ -906,10 +863,12 @@ main (argc, argv) are called. */ { int i; - + for (i = 1; argv[i] != NULL; i ++) - if (! strcmp (argv[i], "-debug")) - debug = 1; + { + if (! strcmp (argv[i], "-debug")) + debug = 1; + } vflag = debug; } @@ -920,10 +879,11 @@ main (argc, argv) #endif obstack_begin (&temporary_obstack, 0); - obstack_begin (&permanent_obstack, 0); - temporary_firstobj = (char *) obstack_alloc (&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) { @@ -933,11 +893,11 @@ main (argc, argv) } 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 = (char **) xcalloc (sizeof (char *), num_c_args)); + c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args)); if (argc < 2) fatal ("no arguments"); @@ -967,31 +927,6 @@ main (argc, argv) prefix_from_env ("COMPILER_PATH", &cpath); prefix_from_env ("PATH", &path); -#ifdef CROSS_COMPILE - /* If we look for a program in the compiler directories, we just use - the short name, since these directories are already system-specific. - But it we look for a program in the system directories, we need to - qualify the program name with the target machine. */ - - full_ld_suffix = concat(target_machine, "-", ld_suffix, NULL); - -#if 0 - full_gld_suffix = concat (target_machine, "-", gld_suffix, NULL); -#endif - - full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL); - - full_gnm_suffix = concat (target_machine, "-", gnm_suffix, NULL); - -#ifdef LDD_SUFFIX - full_ldd_suffix = concat (target_machine, "-", ldd_suffix, NULL); -#endif - - full_strip_suffix = concat (target_machine, "-", strip_suffix, NULL); - - full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL); -#endif /* CROSS_COMPILE */ - /* Try to discover a valid linker/nm/strip to use. */ /* Maybe we know the right file to use (if not cross). */ @@ -1053,7 +988,7 @@ main (argc, argv) c_file_name = getenv ("COLLECT_GCC"); if (c_file_name == 0) { -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE c_file_name = concat (target_machine, "-gcc", NULL); #else c_file_name = "gcc"; @@ -1079,6 +1014,7 @@ main (argc, argv) 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"; @@ -1095,7 +1031,7 @@ main (argc, argv) add_prefix (&libpath_lib_dirs, "/usr/lib"); #endif - /* Get any options that the upper GCC wants to pass to the sub-GCC. + /* Get any options that the upper GCC wants to pass to the sub-GCC. AIX support needs to know if -shared has been specified before parsing commandline arguments. */ @@ -1105,22 +1041,25 @@ main (argc, argv) { const char *q = extract_string (&p); if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) - *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); + *c_ptr++ = xstrdup (q); if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0) - *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); - if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0) + *c_ptr++ = xstrdup (q); + if (strcmp (q, "-shared") == 0) shared_obj = 1; if (*q == '-' && q[1] == 'B') { - *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); + *c_ptr++ = xstrdup (q); if (q[2] == 0) { q = extract_string (&p); - *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); + *c_ptr++ = xstrdup (q); } } } 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"; @@ -1135,6 +1074,12 @@ main (argc, argv) /* 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; @@ -1148,9 +1093,11 @@ main (argc, argv) explicitly puts an export list in command line */ case 'b': if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) - export_flag = 1; + 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 @@ -1161,6 +1108,11 @@ main (argc, argv) ld1--; ld2--; } + if (!strcmp (arg, "-dynamic-linker") && argv[1]) + { + ++argv; + *ld1++ = *ld2++ = *argv; + } break; case 'l': @@ -1174,7 +1126,7 @@ main (argc, argv) } #ifdef COLLECT_EXPORT_LIST { - /* Resolving full library name. */ + /* Resolving full library name. */ const char *s = resolve_lib_name (arg+2); /* Saving a full library name. */ @@ -1185,10 +1137,10 @@ main (argc, argv) #ifdef COLLECT_EXPORT_LIST /* Saving directories where to search for libraries. */ - case 'L': + case 'L': add_prefix (&cmdline_lib_dirs, arg+2); break; -#else +#else #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES case 'L': if (is_in_args (arg, (const char **) ld1_argv, ld1-1)) @@ -1229,6 +1181,34 @@ main (argc, argv) 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 @@ -1253,11 +1233,11 @@ main (argc, argv) *object++ = arg; #ifdef COLLECT_EXPORT_LIST /* libraries can be specified directly, i.e. without -l flag. */ - else - { + else + { /* Saving a full library name. */ - add_to_list (&libs, arg); - } + add_to_list (&libs, arg); + } #endif } } @@ -1288,7 +1268,7 @@ main (argc, argv) if (exports.first) { char *buf = concat ("-bE:", export_file, NULL); - + *ld1++ = buf; *ld2++ = buf; @@ -1412,15 +1392,15 @@ main (argc, argv) ) { #ifdef COLLECT_EXPORT_LIST - /* Do tlink without additional code generation */ + /* Do tlink without additional code generation. */ do_tlink (ld1_argv, object_lst); #endif /* Strip now if it was requested on the command line. */ if (strip_flag) { - char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3); + char **real_strip_argv = XCNEWVEC (char *, 3); const char ** strip_argv = (const char **) real_strip_argv; - + strip_argv[0] = strip_file_name; strip_argv[1] = output_file; strip_argv[2] = (char *) 0; @@ -1435,7 +1415,7 @@ main (argc, argv) return 0; } - /* Sort ctor and dtor lists by priority. */ + /* Sort ctor and dtor lists by priority. */ sort_ids (&constructors); sort_ids (&destructors); @@ -1469,10 +1449,12 @@ main (argc, argv) 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); @@ -1503,16 +1485,16 @@ main (argc, argv) 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 constructors/destructors in shared libraries. */ scan_prog_file (output_file, PASS_SECOND); -#endif +#endif maybe_unlink (c_file); maybe_unlink (o_file); @@ -1525,15 +1507,17 @@ main (argc, argv) } -/* Wait for a process to finish, and exit if a non-zero status is found. */ +/* Wait for a process to finish, and exit if a nonzero status is found. */ int -collect_wait (prog) - const char *prog; +collect_wait (const char *prog, struct pex_obj *pex) { int status; - pwait (pexecute_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)) @@ -1541,7 +1525,7 @@ collect_wait (prog) int sig = WTERMSIG (status); error ("%s terminated with signal %d [%s]%s", prog, sig, strsignal(sig), - status & 0200 ? "" : ", core dumped"); + WCOREDUMP(status) ? ", core dumped" : ""); collect_exit (FATAL_EXIT_CODE); } @@ -1552,31 +1536,73 @@ collect_wait (prog) } static void -do_wait (prog) - 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); collect_exit (ret); } + + if (response_file) + { + unlink (response_file); + response_file = NULL; + } } /* Execute a program, and wait for the reply. */ -void -collect_execute (prog, argv, redir) - 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; + 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) { @@ -1601,62 +1627,47 @@ collect_execute (prog, argv, redir) since we might not end up needing something that we could not find. */ if (argv[0] == 0) - 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); - } + fatal ("cannot find '%s'", prog); - pexecute_pid = pexecute (argv[0], argv, argv[0], NULL, - &errmsg_fmt, &errmsg_arg, - (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH)); + pex = pex_init (0, "collect2", NULL); + if (pex == NULL) + fatal_perror ("pex_init failed"); - 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 reponse file. */ - close (redir_handle); + if (err != 0) + { + errno = err; + fatal_perror (errmsg); + } + else + fatal (errmsg); } - if (pexecute_pid == -1) - fatal_perror (errmsg_fmt, errmsg_arg); + if (response_arg) + free (response_arg); + + return pex; } static void -fork_execute (prog, argv) - const char *prog; - char **argv; +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); } /* Unlink a file unless we are debugging. */ static void -maybe_unlink (file) - const char *file; +maybe_unlink (const char *file) { if (!debug) - unlink (file); + unlink_if_ordinary (file); else notice ("[Leaving %s]\n", file); } @@ -1667,12 +1678,9 @@ static long sequence_number = 0; /* Add a name to a linked list. */ static void -add_to_list (head_ptr, name) - struct head *head_ptr; - const char *name; +add_to_list (struct head *head_ptr, const char *name) { - struct id *newid - = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1); + struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1); struct id *p; strcpy (newid->name, name); @@ -1702,8 +1710,7 @@ add_to_list (head_ptr, name) looks like "_GLOBAL_.I.12345.foo". */ static int -extract_init_priority (name) - const char *name; +extract_init_priority (const char *name) { int pos = 0, pri; @@ -1711,7 +1718,7 @@ extract_init_priority (name) ++pos; pos += 10; /* strlen ("GLOBAL__X_") */ - /* Extract init_p number from ctor/dtor name. */ + /* Extract init_p number from ctor/dtor name. */ pri = atoi (name + pos); return pri ? pri : DEFAULT_INIT_PRIORITY; } @@ -1720,8 +1727,7 @@ extract_init_priority (name) ctors will be run from right to left, dtors from left to right. */ static void -sort_ids (head_ptr) - struct head *head_ptr; +sort_ids (struct head *head_ptr) { /* id holds the current element to insert. id_next holds the next element to insert. id_ptr iterates through the already sorted elements @@ -1745,7 +1751,7 @@ sort_ids (head_ptr) || id->sequence > (*id_ptr)->sequence /* Hack: do lexical compare, too. || (id->sequence == (*id_ptr)->sequence - && strcmp (id->name, (*id_ptr)->name) > 0) */ + && strcmp (id->name, (*id_ptr)->name) > 0) */ ) { id->next = *id_ptr; @@ -1762,10 +1768,7 @@ sort_ids (head_ptr) /* Write: `prefix', the names on list LIST, `suffix'. */ static void -write_list (stream, prefix, list) - FILE *stream; - const char *prefix; - struct id *list; +write_list (FILE *stream, const char *prefix, struct id *list) { while (list) { @@ -1779,10 +1782,8 @@ write_list (stream, prefix, list) [ARGS_BEGIN,ARGS_END). */ static int -is_in_args (string, args_begin, args_end) - const char *string; - const char **args_begin; - const char **args_end; +is_in_args (const char *string, const char **args_begin, + const char **args_end) { const char **args_pointer; for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer) @@ -1794,10 +1795,9 @@ is_in_args (string, args_begin, args_end) #ifdef COLLECT_EXPORT_LIST /* This function is really used only on AIX, but may be useful. */ +#if 0 static int -is_in_list (prefix, list) - const char *prefix; - struct id *list; +is_in_list (const char *prefix, struct id *list) { while (list) { @@ -1807,14 +1807,12 @@ is_in_list (prefix, list) return 0; } #endif +#endif /* COLLECT_EXPORT_LIST */ /* Added for debugging purpose. */ #ifdef COLLECT_EXPORT_LIST static void -dump_list (stream, prefix, list) - FILE *stream; - const char *prefix; - struct id *list; +dump_list (FILE *stream, const char *prefix, struct id *list) { while (list) { @@ -1826,10 +1824,7 @@ dump_list (stream, prefix, list) #if 0 static void -dump_prefix_list (stream, prefix, list) - FILE *stream; - const char *prefix; - struct prefix_list *list; +dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list) { while (list) { @@ -1840,10 +1835,7 @@ dump_prefix_list (stream, prefix, list) #endif static void -write_list_with_asm (stream, prefix, list) - FILE *stream; - const char *prefix; - struct id *list; +write_list_with_asm (FILE *stream, const char *prefix, struct id *list) { while (list) { @@ -1857,9 +1849,7 @@ write_list_with_asm (stream, prefix, list) object), along with the functions to execute them. */ static void -write_c_file_stat (stream, name) - FILE *stream; - const char *name ATTRIBUTE_UNUSED; +write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) { const char *p, *q; char *prefix, *r; @@ -1882,9 +1872,9 @@ write_c_file_stat (stream, 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 @@ -1892,7 +1882,7 @@ write_c_file_stat (stream, name) } } /* q points to null at end of the string (or . of the .so version) */ - prefix = xmalloc (q - p + 1); + prefix = XNEWVEC (char, q - p + 1); strncpy (prefix, p, q - p); prefix[q - p] = 0; for (r = prefix; *r; r++) @@ -1907,7 +1897,7 @@ write_c_file_stat (stream, name) free (prefix); - /* Write the tables as C code */ + /* Write the tables as C code. */ fprintf (stream, "static int count;\n"); fprintf (stream, "typedef void entry_pt();\n"); @@ -1979,8 +1969,8 @@ write_c_file_stat (stream, name) if (shared_obj) { - fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname); - fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame); + COLLECT_SHARED_INIT_FUNC(stream, initname); + COLLECT_SHARED_FINI_FUNC(stream, fininame); } } @@ -1988,16 +1978,14 @@ write_c_file_stat (stream, name) #ifndef LD_INIT_SWITCH static void -write_c_file_glob (stream, name) - FILE *stream; - const char *name ATTRIBUTE_UNUSED; +write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED) { - /* Write the tables as C code */ + /* Write the tables as C code. */ int frames = (frame_tables.number > 0); fprintf (stream, "typedef void entry_pt();\n\n"); - + write_list_with_asm (stream, "extern entry_pt ", constructors.first); if (frames) @@ -2053,9 +2041,7 @@ write_c_file_glob (stream, name) #endif /* ! LD_INIT_SWITCH */ static void -write_c_file (stream, name) - FILE *stream; - const char *name; +write_c_file (FILE *stream, const char *name) { fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); #ifndef LD_INIT_SWITCH @@ -2069,9 +2055,7 @@ write_c_file (stream, name) #ifdef COLLECT_EXPORT_LIST static void -write_aix_file (stream, list) - FILE *stream; - struct id *list; +write_aix_file (FILE *stream, struct id *list) { for (; list; list = list->next) { @@ -2093,17 +2077,18 @@ write_aix_file (stream, list) destructor table has the same format, and begins at __DTOR_LIST__. */ static void -scan_prog_file (prog_name, which_pass) - const char *prog_name; - enum pass which_pass; +scan_prog_file (const char *prog_name, enum pass which_pass) { - void (*int_handler) PARAMS ((int)); - void (*quit_handler) PARAMS ((int)); + 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 pid; int argc = 0; - int pipe_fd[2]; + struct pex_obj *pex; + const char *errmsg; + int err; char *p, buf[1024]; FILE *inf; @@ -2112,7 +2097,7 @@ scan_prog_file (prog_name, which_pass) /* 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') @@ -2121,13 +2106,6 @@ scan_prog_file (prog_name, which_pass) 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) { @@ -2143,35 +2121,30 @@ scan_prog_file (prog_name, which_pass) 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 ("execvp %s", nm_file_name); + if (err != 0) + { + errno = err; + fatal_perror (errmsg); + } + else + fatal (errmsg); } - /* Parent context from here on. */ - int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN); + int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); #ifdef SIGQUIT - quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN); + 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"); @@ -2191,7 +2164,7 @@ scan_prog_file (prog_name, which_pass) if (ch != '_') continue; - + name = p; /* Find the end of the symbol name. Do not include `|', because Encore nm can tack that on the end. */ @@ -2245,10 +2218,7 @@ scan_prog_file (prog_name, which_pass) 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 @@ -2256,370 +2226,86 @@ scan_prog_file (prog_name, which_pass) #endif } -#if SUNOS4_SHARED_LIBRARIES +#ifdef LDD_SUFFIX -/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries - that the output file depends upon and their initialization/finalization +/* Use the List Dynamic Dependencies program to find shared libraries that + the output file depends upon and their initialization/finalization routines, if any. */ -#include -#include -#include -#include -#include -#include -#include - -/* 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 PARAMS ((const char *)); - static void -mapfile (name) - 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 PARAMS ((struct direct *)); - -static int -libselect (d) - 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 PARAMS ((struct direct **, struct direct **)); - -static int -libcompare (d1, d2) - struct direct **d1, **d2; +scan_libraries (const char *prog_name) { - int i1, i2 = strlen (libname); - char *e1 = (*d1)->d_name + i2; - char *e2 = (*d2)->d_name + i2; + 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; + struct pex_obj *pex; + const char *errmsg; + int err; + char buf[1024]; + FILE *inf; - while (*e1 && *e2 && *e1 == '.' && *e2 == '.' - && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1])) + /* If we do not have an `ldd', complain. */ + if (ldd_file_name == 0) { - ++e1; - ++e2; - i1 = strtol (e1, &e1, 10); - i2 = strtol (e2, &e2, 10); - if (i1 != i2) - return i1 - i2; + error ("cannot find 'ldd'"); + return; } - if (*e1) - { - /* It has a valid numeric extension, prefer this one. */ - if (*e1 == '.' && e1[1] && ISDIGIT (e1[1])) - return 1; - /* It has a invalid numeric extension, must prefer the other one. */ - else - return -1; - } - else if (*e2) + ldd_argv[argc++] = ldd_file_name; + ldd_argv[argc++] = prog_name; + ldd_argv[argc++] = (char *) 0; + + /* Trace if needed. */ + if (vflag) { - /* It has a valid numeric extension, prefer this one. */ - if (*e2 == '.' && e2[1] && ISDIGIT (e2[1])) - return -1; - /* It has a invalid numeric extension, must prefer the other one. */ - else - return 1; + const char **p_argv; + const char *str; + + for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) + fprintf (stderr, " %s", str); + + fprintf (stderr, "\n"); } - 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 PARAMS ((const char *)); + fflush (stdout); + fflush (stderr); -static void -locatelib (name) - const char *name; -{ - static const char **l; - static int cnt; - char buf[MAXPATHLEN]; - char *p, *q; - const char **pp; + pex = pex_init (PEX_USE_PIPES, "collect2", NULL); + if (pex == NULL) + fatal_perror ("pex_init failed"); - 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 = (const char **) 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++) + errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err); + if (errmsg != NULL) { - struct direct **namelist; - int entries; - if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0) + if (err != 0) { - sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name); - add_to_list (&libraries, buf); - if (debug) - fprintf (stderr, "%s\n", buf); - break; + errno = err; + fatal_perror (errmsg); } - } - if (*pp == 0) - { - if (debug) - notice ("not found\n"); else - fatal ("dynamic dependency %s not found", name); + fatal (errmsg); } -} - -/* 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) - 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); + int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); +#ifdef SIGQUIT + quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); +#endif - 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; - } + inf = pex_read_output (pex, 0); + if (inf == NULL) + fatal_perror ("can't open ldd output"); if (debug) - notice ("dynamic dependencies.\n"); + notice ("\nldd output with constructors/destructors.\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) - const char *prog_name; -{ - static struct head libraries; /* list of shared libraries found */ - struct id *list; - void (*int_handler) PARAMS ((int)); - void (*quit_handler) PARAMS ((int)); - char *real_ldd_argv[4]; - const char **ldd_argv = (const char **) real_ldd_argv; - int pid; - int argc = 0; - int pipe_fd[2]; - char buf[1024]; - FILE *inf; - - /* If we do not 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) - { - const char **p_argv; - const 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) - fatal_perror (VFORK_STRING); - - 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, real_ldd_argv); - fatal_perror ("execv %s", ldd_file_name); - } - - /* Parent context from here on. */ - int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN); -#ifdef SIGQUIT - quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN); -#endif - - if (close (pipe_fd[1]) < 0) - fatal_perror ("close %d", pipe_fd[1]); - - if (debug) - notice ("\nldd output with constructors/destructors.\n"); - - /* Read each line of ldd output. */ - while (fgets (buf, sizeof buf, inf) != (char *) 0) + /* Read each line of ldd output. */ + while (fgets (buf, sizeof buf, inf) != (char *) 0) { int ch2; char *name, *end, *p = buf; @@ -2634,14 +2320,14 @@ scan_libraries (prog_name) fatal ("dynamic dependency %s not found", buf); /* Find the end of the symbol name. */ - for (end = p; + 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); + add_to_list (&libraries, name); else fatal ("unable to open dynamic dependency '%s'", buf); @@ -2651,24 +2337,20 @@ scan_libraries (prog_name) 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 */ @@ -2679,7 +2361,7 @@ scan_libraries (prog_name) #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 @@ -2692,14 +2374,26 @@ scan_libraries (prog_name) # 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 @@ -2716,7 +2410,43 @@ scan_libraries (prog_name) #endif -extern char *ldgetname (); +#ifdef COLLECT_EXPORT_LIST +/* Array of standard AIX libraries which should not + be scanned for ctors/dtors. */ +static const char *const aix_std_libs[] = { + "/unix", + "/lib/libc.a", + "/lib/libm.a", + "/lib/libc_r.a", + "/lib/libm_r.a", + "/usr/lib/libc.a", + "/usr/lib/libm.a", + "/usr/lib/libc_r.a", + "/usr/lib/libm_r.a", + "/usr/lib/threads/libc.a", + "/usr/ccs/lib/libc.a", + "/usr/ccs/lib/libm.a", + "/usr/ccs/lib/libc_r.a", + "/usr/ccs/lib/libm_r.a", + NULL +}; + +/* This function checks the filename and returns 1 + if this name matches the location of a standard AIX library. */ +static int ignore_library (const char *); +static int +ignore_library (const char *name) +{ + const char *const *p = &aix_std_libs[0]; + while (*p++ != NULL) + if (! strcmp (name, *p)) return 1; + return 0; +} +#endif /* COLLECT_EXPORT_LIST */ + +#if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME +extern char *ldgetname (LDFILE *, GCC_SYMENT *); +#endif /* COFF version to scan the name list of the loaded program for the symbols g++ uses for static constructors and destructors. @@ -2728,9 +2458,7 @@ extern char *ldgetname (); destructor table has the same format, and begins at __DTOR_LIST__. */ static void -scan_prog_file (prog_name, which_pass) - const char *prog_name; - enum pass which_pass; +scan_prog_file (const char *prog_name, enum pass which_pass) { LDFILE *ldptr = NULL; int sym_index, sym_count; @@ -2751,9 +2479,9 @@ scan_prog_file (prog_name, which_pass) { #endif /* 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. */ + 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) { if (! MY_ISCOFF (HEADER (ldptr).f_magic)) @@ -2782,7 +2510,7 @@ scan_prog_file (prog_name, which_pass) 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 @@ -2796,7 +2524,7 @@ scan_prog_file (prog_name, which_pass) 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 @@ -2805,7 +2533,7 @@ scan_prog_file (prog_name, which_pass) 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 @@ -2830,7 +2558,7 @@ scan_prog_file (prog_name, which_pass) 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 @@ -2838,13 +2566,14 @@ scan_prog_file (prog_name, which_pass) 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; } @@ -2887,17 +2616,18 @@ scan_prog_file (prog_name, which_pass) (void) ldclose(ldptr); #endif } - +#endif /* OBJECT_FORMAT_COFF */ #ifdef COLLECT_EXPORT_LIST /* Given a library name without "lib" prefix, this function returns a full library name including a path. */ static char * -resolve_lib_name (name) - const char *name; +resolve_lib_name (const char *name) { 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) @@ -2916,14 +2646,15 @@ resolve_lib_name (name) 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); + sprintf (lib_buf, "%s%slib%s.%s", + 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); } } @@ -2932,705 +2663,7 @@ if (debug) fprintf (stderr, "found: %s\n", lib_buf); if (debug) fprintf (stderr, "not found\n"); else - fatal ("Library lib%s not found", name); + fatal ("library lib%s not found", name); return (NULL); } - -/* Array of standard AIX libraries which should not - be scanned for ctors/dtors. */ -static const char *aix_std_libs[] = { - "/unix", - "/lib/libc.a", - "/lib/libm.a", - "/lib/libc_r.a", - "/lib/libm_r.a", - "/usr/lib/libc.a", - "/usr/lib/libm.a", - "/usr/lib/libc_r.a", - "/usr/lib/libm_r.a", - "/usr/lib/threads/libc.a", - "/usr/ccs/lib/libc.a", - "/usr/ccs/lib/libm.a", - "/usr/ccs/lib/libc_r.a", - "/usr/ccs/lib/libm_r.a", - NULL -}; - -/* This function checks the filename and returns 1 - if this name matches the location of a standard AIX library. */ -static int -ignore_library (name) - const char *name; -{ - const char **p = &aix_std_libs[0]; - while (*p++ != NULL) - if (! strcmp (name, *p)) return 1; - return 0; -} -#endif - -#endif /* OBJECT_FORMAT_COFF */ - - -/* - * OSF/rose specific stuff. - */ - -#ifdef OBJECT_FORMAT_ROSE - -/* Union of the various load commands */ - -typedef union load_union -{ - ldc_header_t hdr; /* common header */ - load_cmd_map_command_t map; /* map indexing other load cmds */ - interpreter_command_t iprtr; /* interpreter pathname */ - strings_command_t str; /* load commands strings section */ - region_command_t region; /* region load command */ - reloc_command_t reloc; /* relocation section */ - package_command_t pkg; /* package load command */ - symbols_command_t sym; /* symbol sections */ - entry_command_t ent; /* program start section */ - gen_info_command_t info; /* object information */ - func_table_command_t func; /* function constructors/destructors */ -} load_union_t; - -/* Structure to point to load command and data section in memory. */ - -typedef struct load_all -{ - load_union_t *load; /* load command */ - char *section; /* pointer to section */ -} load_all_t; - -/* Structure to contain information about a file mapped into memory. */ - -struct file_info -{ - char *start; /* start of map */ - char *name; /* filename */ - long size; /* size of the file */ - long rounded_size; /* size rounded to page boundary */ - int fd; /* file descriptor */ - int rw; /* != 0 if opened read/write */ - int use_mmap; /* != 0 if mmap'ed */ -}; - -extern int decode_mach_o_hdr (); -extern int encode_mach_o_hdr (); - -static void add_func_table PARAMS ((mo_header_t *, load_all_t *, - symbol_info_t *, int)); -static void print_header PARAMS ((mo_header_t *)); -static void print_load_command PARAMS ((load_union_t *, size_t, int)); -static void bad_header PARAMS ((int)); -static struct file_info *read_file PARAMS ((const char *, int, int)); -static void end_file PARAMS ((struct file_info *)); - -/* OSF/rose specific 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 void -scan_prog_file (prog_name, which_pass) - const char *prog_name; - enum pass which_pass; -{ - char *obj; - mo_header_t hdr; - load_all_t *load_array; - load_all_t *load_end; - load_all_t *load_cmd; - int symbol_load_cmds; - off_t offset; - int i; - int num_syms; - int status; - char *str_sect; - struct file_info *obj_file; - int prog_fd; - mo_lcid_t cmd_strings = -1; - symbol_info_t *main_sym = 0; - int rw = (which_pass != PASS_FIRST); - - prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY); - if (prog_fd < 0) - fatal_perror ("open %s", prog_name); - - obj_file = read_file (prog_name, prog_fd, rw); - obj = obj_file->start; - - status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr); - if (status != MO_HDR_CONV_SUCCESS) - bad_header (status); - - - /* Do some basic sanity checks. Note we explicitly use the big endian magic number, - since the hardware will automatically swap bytes for us on loading little endian - integers. */ - -#ifndef CROSS_COMPILE - if (hdr.moh_magic != MOH_MAGIC_MSB - || hdr.moh_header_version != MOH_HEADER_VERSION - || hdr.moh_byte_order != OUR_BYTE_ORDER - || hdr.moh_data_rep_id != OUR_DATA_REP_ID - || hdr.moh_cpu_type != OUR_CPU_TYPE - || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE - || hdr.moh_vendor_type != OUR_VENDOR_TYPE) - { - fatal ("incompatibilities between object file & expected values"); - } -#endif - - if (debug) - print_header (&hdr); - - offset = hdr.moh_first_cmd_off; - load_end = load_array - = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2); - - /* Build array of load commands, calculating the offsets */ - for (i = 0; i < hdr.moh_n_load_cmds; i++) - { - load_union_t *load_hdr; /* load command header */ - - load_cmd = load_end++; - load_hdr = (load_union_t *) (obj + offset); - - /* If modifying the program file, copy the header. */ - if (rw) - { - load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size); - memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size); - load_hdr = ptr; - - /* null out old command map, because we will rewrite at the end. */ - if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP) - { - cmd_strings = ptr->map.lcm_ld_cmd_strings; - ptr->hdr.ldci_cmd_type = LDC_UNDEFINED; - } - } - - load_cmd->load = load_hdr; - if (load_hdr->hdr.ldci_section_off > 0) - load_cmd->section = obj + load_hdr->hdr.ldci_section_off; - - if (debug) - print_load_command (load_hdr, offset, i); - - offset += load_hdr->hdr.ldci_cmd_size; - } - - /* If the last command is the load command map and is not undefined, - decrement the count of load commands. */ - if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED) - { - load_end--; - hdr.moh_n_load_cmds--; - } - - /* Go through and process each symbol table section. */ - symbol_load_cmds = 0; - for (load_cmd = load_array; load_cmd < load_end; load_cmd++) - { - load_union_t *load_hdr = load_cmd->load; - - if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS) - { - symbol_load_cmds++; - - if (debug) - { - const char *kind = "unknown"; - - switch (load_hdr->sym.symc_kind) - { - case SYMC_IMPORTS: kind = "imports"; break; - case SYMC_DEFINED_SYMBOLS: kind = "defined"; break; - case SYMC_STABS: kind = "stabs"; break; - } - - notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n", - symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind); - } - - if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS) - continue; - - str_sect = load_array[load_hdr->sym.symc_strings_section].section; - if (str_sect == (char *) 0) - fatal ("string section missing"); - - if (load_cmd->section == (char *) 0) - fatal ("section pointer missing"); - - num_syms = load_hdr->sym.symc_nentries; - for (i = 0; i < num_syms; i++) - { - symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i; - char *name = sym->si_name.symbol_name + str_sect; - - if (name[0] != '_') - continue; - - if (rw) - { - char *n = name + strlen (name) - strlen (NAME__MAIN); - - if ((n - name) < 0 || strcmp (n, NAME__MAIN)) - continue; - while (n != name) - if (*--n != '_') - continue; - - main_sym = sym; - } - else - { - switch (is_ctor_dtor (name)) - { - case 1: - add_to_list (&constructors, name); - break; - - case 2: - add_to_list (&destructors, name); - break; - - default: /* not a constructor or destructor */ - continue; - } - } - - if (debug) - fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n", - sym->si_type, sym->si_sc_type, sym->si_flags, name); - } - } - } - - if (symbol_load_cmds == 0) - fatal ("no symbol table found"); - - /* Update the program file now, rewrite header and load commands. At present, - we assume that there is enough space after the last load command to insert - one more. Since the first section written out is page aligned, and the - number of load commands is small, this is ok for the present. */ - - if (rw) - { - load_union_t *load_map; - size_t size; - - if (cmd_strings == -1) - fatal ("no cmd_strings found"); - - /* Add __main to initializer list. - If we are building a program instead of a shared library, do not - do anything, since in the current version, you cannot do mallocs - and such in the constructors. */ - - if (main_sym != (symbol_info_t *) 0 - && ((hdr.moh_flags & MOH_EXECABLE_F) == 0)) - add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION); - - if (debug) - notice ("\nUpdating header and load commands.\n\n"); - - hdr.moh_n_load_cmds++; - size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1)); - - /* Create new load command map. */ - if (debug) - notice ("load command map, %d cmds, new size %ld.\n", - (int) hdr.moh_n_load_cmds, (long) size); - - load_map = (load_union_t *) xcalloc (1, size); - load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP; - load_map->map.ldc_header.ldci_cmd_size = size; - load_map->map.lcm_ld_cmd_strings = cmd_strings; - load_map->map.lcm_nentries = hdr.moh_n_load_cmds; - load_array[hdr.moh_n_load_cmds-1].load = load_map; - - offset = hdr.moh_first_cmd_off; - for (i = 0; i < hdr.moh_n_load_cmds; i++) - { - load_map->map.lcm_map[i] = offset; - if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP) - hdr.moh_load_map_cmd_off = offset; - - offset += load_array[i].load->hdr.ldci_cmd_size; - } - - hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR; - - if (debug) - print_header (&hdr); - - /* Write header */ - status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR); - if (status != MO_HDR_CONV_SUCCESS) - bad_header (status); - - if (debug) - notice ("writing load commands.\n\n"); - - /* Write load commands */ - offset = hdr.moh_first_cmd_off; - for (i = 0; i < hdr.moh_n_load_cmds; i++) - { - load_union_t *load_hdr = load_array[i].load; - size_t size = load_hdr->hdr.ldci_cmd_size; - - if (debug) - print_load_command (load_hdr, offset, i); - - bcopy ((char *) load_hdr, (char *) (obj + offset), size); - offset += size; - } - } - - end_file (obj_file); - - if (close (prog_fd)) - fatal_perror ("close %s", prog_name); - - if (debug) - fprintf (stderr, "\n"); -} - - -/* Add a function table to the load commands to call a function - on initiation or termination of the process. */ - -static void -add_func_table (hdr_p, load_array, sym, type) - mo_header_t *hdr_p; /* pointer to global header */ - load_all_t *load_array; /* array of ptrs to load cmds */ - symbol_info_t *sym; /* pointer to symbol entry */ - int type; /* fntc_type value */ -{ - /* Add a new load command. */ - int num_cmds = ++hdr_p->moh_n_load_cmds; - int load_index = num_cmds - 1; - size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t); - load_union_t *ptr = xcalloc (1, size); - load_all_t *load_cmd; - int i; - - /* Set the unresolved address bit in the header to force the loader to be - used, since kernel exec does not call the initialization functions. */ - hdr_p->moh_flags |= MOH_UNRESOLVED_F; - - load_cmd = &load_array[load_index]; - load_cmd->load = ptr; - load_cmd->section = (char *) 0; - - /* Fill in func table load command. */ - ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE; - ptr->func.ldc_header.ldci_cmd_size = size; - ptr->func.ldc_header.ldci_section_off = 0; - ptr->func.ldc_header.ldci_section_len = 0; - ptr->func.fntc_type = type; - ptr->func.fntc_nentries = 1; - - /* copy address, turn it from abs. address to (region,offset) if necessary. */ - /* Is the symbol already expressed as (region, offset)? */ - if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0) - { - ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid; - ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff; - } - - /* If not, figure out which region it's in. */ - else - { - mo_vm_addr_t addr = sym->si_value.abs_val; - int found = 0; - - for (i = 0; i < load_index; i++) - { - if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION) - { - region_command_t *region_ptr = &load_array[i].load->region; - - if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0 - && addr >= region_ptr->regc_addr.vm_addr - && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size) - { - ptr->func.fntc_entry_loc[0].adr_lcid = i; - ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr; - found++; - break; - } - } - } - - if (!found) - fatal ("could not convert 0x%l.8x into a region", addr); - } - - if (debug) - notice ("%s function, region %d, offset = %ld (0x%.8lx)\n", - type == FNTC_INITIALIZATION ? "init" : "term", - (int) ptr->func.fntc_entry_loc[i].adr_lcid, - (long) ptr->func.fntc_entry_loc[i].adr_sctoff, - (long) ptr->func.fntc_entry_loc[i].adr_sctoff); - -} - - -/* Print the global header for an OSF/rose object. */ - -static void -print_header (hdr_ptr) - mo_header_t *hdr_ptr; -{ - fprintf (stderr, "\nglobal header:\n"); - fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic); - fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version); - fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version); - fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version); - fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size); - fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order); - fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id); - fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type); - fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype); - fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type); - fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off); - fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off); - fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds); - fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds); - fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags); - - if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F) - fprintf (stderr, ", relocatable"); - - if (hdr_ptr->moh_flags & MOH_LINKABLE_F) - fprintf (stderr, ", linkable"); - - if (hdr_ptr->moh_flags & MOH_EXECABLE_F) - fprintf (stderr, ", execable"); - - if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F) - fprintf (stderr, ", executable"); - - if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F) - fprintf (stderr, ", unresolved"); - - fprintf (stderr, "\n\n"); - return; -} - - -/* Print a short summary of a load command. */ - -static void -print_load_command (load_hdr, offset, number) - load_union_t *load_hdr; - size_t offset; - int number; -{ - mo_long_t type = load_hdr->hdr.ldci_cmd_type; - const char *type_str = (char *) 0; - - switch (type) - { - case LDC_UNDEFINED: type_str = "UNDEFINED"; break; - case LDC_CMD_MAP: type_str = "CMD_MAP"; break; - case LDC_INTERPRETER: type_str = "INTERPRETER"; break; - case LDC_STRINGS: type_str = "STRINGS"; break; - case LDC_REGION: type_str = "REGION"; break; - case LDC_RELOC: type_str = "RELOC"; break; - case LDC_PACKAGE: type_str = "PACKAGE"; break; - case LDC_SYMBOLS: type_str = "SYMBOLS"; break; - case LDC_ENTRY: type_str = "ENTRY"; break; - case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break; - case LDC_GEN_INFO: type_str = "GEN_INFO"; break; - } - - fprintf (stderr, - "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx", - number, - (long) load_hdr->hdr.ldci_cmd_size, - (long) offset, - (long) load_hdr->hdr.ldci_section_off, - (long) load_hdr->hdr.ldci_section_len); - - if (type_str == (char *) 0) - fprintf (stderr, ", ty: unknown (%ld)\n", (long) type); - - else if (type != LDC_REGION) - fprintf (stderr, ", ty: %s\n", type_str); - - else - { - const char *region = ""; - switch (load_hdr->region.regc_usage_type) - { - case REG_TEXT_T: region = ", .text"; break; - case REG_DATA_T: region = ", .data"; break; - case REG_BSS_T: region = ", .bss"; break; - case REG_GLUE_T: region = ", .glue"; break; -#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/ - case REG_RDATA_T: region = ", .rdata"; break; - case REG_SDATA_T: region = ", .sdata"; break; - case REG_SBSS_T: region = ", .sbss"; break; -#endif - } - - fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n", - type_str, - (long) load_hdr->region.regc_vm_addr, - (long) load_hdr->region.regc_vm_size, - region); - } - - return; -} - - -/* Fatal error when {en,de}code_mach_o_header fails. */ - -static void -bad_header (status) - int status; -{ - switch (status) - { - case MO_ERROR_BAD_MAGIC: fatal ("bad magic number"); - case MO_ERROR_BAD_HDR_VERS: fatal ("bad header version"); - case MO_ERROR_BAD_RAW_HDR_VERS: fatal ("bad raw header version"); - case MO_ERROR_BUF2SML: fatal ("raw header buffer too small"); - case MO_ERROR_OLD_RAW_HDR_FILE: fatal ("old raw header file"); - case MO_ERROR_UNSUPPORTED_VERS: fatal ("unsupported version"); - default: - fatal ("unknown {de,en}code_mach_o_hdr return value %d", status); - } -} - - -/* Read a file into a memory buffer. */ - -static struct file_info * -read_file (name, fd, rw) - const char *name; /* filename */ - int fd; /* file descriptor */ - int rw; /* read/write */ -{ - struct stat stat_pkt; - struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1); -#ifdef USE_MMAP - static int page_size; -#endif - - if (fstat (fd, &stat_pkt) < 0) - fatal_perror ("fstat %s", name); - - p->name = name; - p->size = stat_pkt.st_size; - p->rounded_size = stat_pkt.st_size; - p->fd = fd; - p->rw = rw; - -#ifdef USE_MMAP - if (debug) - fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only"); - - if (page_size == 0) - page_size = sysconf (_SC_PAGE_SIZE); - - p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size; - p->start = mmap ((caddr_t) 0, - (rw) ? p->rounded_size : p->size, - (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ, - MAP_FILE | MAP_VARIABLE | MAP_SHARED, - fd, - 0L); - - if (p->start != (char *) 0 && p->start != (char *) -1) - p->use_mmap = 1; - - else -#endif /* USE_MMAP */ - { - long len; - - if (debug) - fprintf (stderr, "read %s\n", name); - - p->use_mmap = 0; - p->start = xmalloc (p->size); - if (lseek (fd, 0L, SEEK_SET) < 0) - fatal_perror ("lseek %s 0", name); - - len = read (fd, p->start, p->size); - if (len < 0) - fatal_perror ("read %s", name); - - if (len != p->size) - fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name); - } - - return p; -} - -/* Do anything necessary to write a file back from memory. */ - -static void -end_file (ptr) - struct file_info *ptr; /* file information block */ -{ -#ifdef USE_MMAP - if (ptr->use_mmap) - { - if (ptr->rw) - { - if (debug) - fprintf (stderr, "msync %s\n", ptr->name); - - if (msync (ptr->start, ptr->rounded_size, MS_ASYNC)) - fatal_perror ("msync %s", ptr->name); - } - - if (debug) - fprintf (stderr, "munmap %s\n", ptr->name); - - if (munmap (ptr->start, ptr->size)) - fatal_perror ("munmap %s", ptr->name); - } - else -#endif /* USE_MMAP */ - { - if (ptr->rw) - { - long len; - - if (debug) - fprintf (stderr, "write %s\n", ptr->name); - - if (lseek (ptr->fd, 0L, SEEK_SET) < 0) - fatal_perror ("lseek %s 0", ptr->name); - - len = write (ptr->fd, ptr->start, ptr->size); - if (len < 0) - fatal_perror ("write %s", ptr->name); - - if (len != ptr->size) - fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name); - } - - free (ptr->start); - } - - free (ptr); -} - -#endif /* OBJECT_FORMAT_ROSE */ +#endif /* COLLECT_EXPORT_LIST */