X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcollect2.c;h=a249e4c70b2cab27ee4cb248d4f77824b94c4364;hb=4003683bb19a2811d312ac45926f5dd00234d2a6;hp=1541f7cbf22dce5be9262d9fdc3af1ddab3e5719;hpb=c8b793cf1932b4beeec61310dae8c0d793fd4fd8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/collect2.c b/gcc/collect2.c index 1541f7cbf22..a249e4c70b2 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -1,36 +1,41 @@ /* 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 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 2, 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 COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ /* 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. */ +#ifdef vfork /* Autoconf may define this to fork for us. */ # define VFORK_STRING "fork" #else # define VFORK_STRING "vfork" @@ -54,10 +59,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,7 +69,6 @@ Boston, MA 02111-1307, USA. */ #ifdef CROSS_COMPILE #undef SUNOS4_SHARED_LIBRARIES #undef OBJECT_FORMAT_COFF -#undef OBJECT_FORMAT_ROSE #undef MD_EXEC_PREFIX #undef REAL_LD_FILE_NAME #undef REAL_NM_FILE_NAME @@ -80,7 +80,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 @@ -103,7 +103,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 @@ -112,24 +112,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. */ @@ -141,16 +123,23 @@ 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 +#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 + #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES #define SCAN_LIBRARIES #endif @@ -160,10 +149,18 @@ int do_collecting = 1; #else int do_collecting = 0; #endif + +#ifndef COLLECT_PARSE_FLAG +#define COLLECT_PARSE_FLAG(FLAG) +#endif + +/* Nonzero if we should suppress the automatic demangling of identifiers + in linker error messages. Set from COLLECT_NO_DEMANGLE. */ +int no_demangle; /* Linked lists of constructor and destructor names. */ -struct id +struct id { struct id *next; int sequence; @@ -221,18 +218,10 @@ static struct head exports; /* list of exported symbols */ static struct head frame_tables; /* list of frame unwind info tables */ 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 +/* Holds the return value of pexecute and fork. */ +int pid; /* Structure to hold all the directories in which to search for files to execute. */ @@ -251,62 +240,64 @@ 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 *)); +static const char *const libexts[3] = {"a", "so", NULL}; /* possible library extensions */ +#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 *); +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 (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 void write_aix_file (FILE *, struct id *); +static char *resolve_lib_name (const char *); #endif -static char *extract_string PARAMS ((const char **)); +static char *extract_string (const char **); -#ifdef NO_DUP2 -int -dup2 (oldfd, newfd) - int oldfd; - int newfd; +#ifndef HAVE_DUP2 +static int +dup2 (int oldfd, int newfd) { int fdtmp[256]; int fdx = 0; int fd; - + if (oldfd == newfd) return oldfd; close (newfd); @@ -317,13 +308,12 @@ dup2 (oldfd, newfd) return fd; } -#endif +#endif /* ! HAVE_DUP2 */ /* 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); @@ -351,19 +341,11 @@ collect_exit (status) /* Notify user of a non-error. */ void -notice VPARAMS ((const char *msgid, ...)) +notice (const char *msgid, ...) { -#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, msgid); vfprintf (stderr, _(msgid), ap); va_end (ap); } @@ -371,20 +353,12 @@ notice VPARAMS ((const char *msgid, ...)) /* Die when sys call fails. */ void -fatal_perror VPARAMS ((const char * msgid, ...)) +fatal_perror (const char * msgid, ...) { -#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, msgid); fprintf (stderr, "collect2: "); vfprintf (stderr, _(msgid), ap); fprintf (stderr, ": %s\n", xstrerror (e)); @@ -396,19 +370,11 @@ fatal_perror VPARAMS ((const char * msgid, ...)) /* Just die. */ void -fatal VPARAMS ((const char * msgid, ...)) +fatal (const char * msgid, ...) { -#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, msgid); fprintf (stderr, "collect2: "); vfprintf (stderr, _(msgid), ap); fprintf (stderr, "\n"); @@ -420,19 +386,11 @@ fatal VPARAMS ((const char * msgid, ...)) /* Write error message. */ void -error VPARAMS ((const char * msgid, ...)) +error (const char * msgid, ...) { -#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, msgid); fprintf (stderr, "collect2: "); vfprintf (stderr, _(msgid), ap); fprintf (stderr, "\n"); @@ -443,14 +401,13 @@ error VPARAMS ((const char * msgid, ...)) provide a default entry. */ void -fancy_abort () +fancy_abort (void) { fatal ("internal error"); } static void -handler (signo) - int signo; +handler (int signo) { if (c_file != 0 && c_file[0]) maybe_unlink (c_file); @@ -472,8 +429,7 @@ handler (signo) int -file_exists (name) - const char *name; +file_exists (const char *name) { return access (name, R_OK) == 0; } @@ -481,8 +437,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; @@ -512,11 +467,9 @@ extract_string (pp) } void -dump_file (name) - const char *name; +dump_file (const char *name) { FILE *stream = fopen (name, "r"); - int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); if (stream == 0) return; @@ -524,7 +477,7 @@ 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) { @@ -536,13 +489,13 @@ dump_file (name) if (*word == '.') ++word, putc ('.', stderr); p = word; - if (*p == '_' && prepends_underscore) - ++p; + if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) + p += strlen (USER_LABEL_PREFIX); if (no_demangle) result = 0; else - result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI); + result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); if (result) { @@ -550,7 +503,7 @@ dump_file (name) fputs (result, stderr); diff = strlen (word) - strlen (result); - while (diff > 0) + while (diff > 0 && c == ' ') --diff, putc (' ', stderr); while (diff < 0 && c == ' ') ++diff, c = getc (stream); @@ -576,41 +529,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[] = { -#ifdef NO_DOLLAR_IN_LABEL -#ifdef NO_DOT_IN_LABEL + 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 }, -#else - { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 }, - { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 }, - { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 }, -#endif -#else - { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 }, - { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 }, - { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 }, -#endif { "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 } }; @@ -645,14 +587,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; @@ -660,9 +600,9 @@ find_a_file (pprefix, name) if (debug) fprintf (stderr, "Looking for '%s'\n", name); - -#ifdef EXECUTABLE_SUFFIX - len += strlen (EXECUTABLE_SUFFIX); + +#ifdef HOST_EXECUTABLE_SUFFIX + len += strlen (HOST_EXECUTABLE_SUFFIX); #endif temp = xmalloc (len); @@ -681,16 +621,16 @@ find_a_file (pprefix, name) if (debug) fprintf (stderr, " - found: absolute path\n"); - + return temp; } -#ifdef EXECUTABLE_SUFFIX +#ifdef HOST_EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ strcpy (temp, name); - strcat (temp, EXECUTABLE_SUFFIX); - + strcat (temp, HOST_EXECUTABLE_SUFFIX); + if (access (temp, X_OK) == 0) return temp; #endif @@ -705,17 +645,17 @@ 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) return temp; -#ifdef EXECUTABLE_SUFFIX +#ifdef HOST_EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ - strcat (temp, EXECUTABLE_SUFFIX); - + strcat (temp, HOST_EXECUTABLE_SUFFIX); + if (stat (temp, &st) >= 0 && ! S_ISDIR (st.st_mode) && access (temp, X_OK) == 0) @@ -733,9 +673,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; @@ -749,13 +687,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 = xmalloc (sizeof (struct prefix_list)); pl->prefix = xstrdup (prefix); if (*prev) @@ -769,28 +707,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 = xmalloc (strlen (p) + 3); if (debug) fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); - + startp = endp = p; while (1) { @@ -811,7 +745,7 @@ prefix_from_string (p, pprefix) if (debug) fprintf (stderr, " - add prefix: %s\n", nstore); - + add_prefix (pprefix, nstore); if (*endp == 0) break; @@ -824,28 +758,51 @@ prefix_from_string (p, pprefix) /* 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 - const char *ldd_suffix = LDD_SUFFIX; - const char *full_ldd_suffix = ldd_suffix; + static const char *const 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; + static const char *const strip_suffix = "strip"; + static const char *const gstrip_suffix = "gstrip"; + +#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. */ + + 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 *const full_ldd_suffix = ldd_suffix; +#endif + const char *const full_strip_suffix = strip_suffix; + const char *const full_gstrip_suffix = gstrip_suffix; +#endif /* CROSS_COMPILE */ + const char *arg; FILE *outf; #ifdef COLLECT_EXPORT_LIST @@ -864,30 +821,30 @@ main (argc, argv) int first_file; int num_c_args = argc+9; + no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); + + /* Suppress demangling by the real linker, which may be broken. */ + 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 -/* LC_CTYPE determines the character set used by the terminal so it has be set - to output messages correctly. */ - -#ifdef HAVE_LC_MESSAGES - setlocale (LC_CTYPE, ""); - setlocale (LC_MESSAGES, ""); -#else - setlocale (LC_ALL, ""); +#ifdef SIGCHLD + /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will + receive the signal. A different setting is inheritable */ + signal (SIGCHLD, SIG_DFL); #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+3)); + ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10)); + object = (const char **)(object_lst = xcalloc(sizeof (char *), argc)); #ifdef DEBUG debug = 1; @@ -898,10 +855,13 @@ 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; + COLLECT_PARSE_FLAG (argv[i]); + } vflag = debug; } @@ -912,8 +872,7 @@ 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); current_demangling_style = auto_demangling; p = getenv ("COLLECT_GCC_OPTIONS"); @@ -925,11 +884,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"); @@ -959,31 +918,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). */ @@ -1087,7 +1021,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. */ @@ -1097,22 +1031,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"; @@ -1177,9 +1114,16 @@ 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 +#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES + case 'L': + if (is_in_args (arg, (const char **) ld1_argv, ld1-1)) + --ld1; + break; +#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ #endif case 'o': @@ -1238,8 +1182,8 @@ 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); } @@ -1272,9 +1216,8 @@ main (argc, argv) if (exports.first) { - char *buf = xmalloc (strlen (export_file) + 5); + char *buf = concat ("-bE:", export_file, NULL); - sprintf (buf, "-bE:%s", export_file); *ld1++ = buf; *ld2++ = buf; @@ -1398,15 +1341,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 = xcalloc (sizeof (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; @@ -1421,7 +1364,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); @@ -1438,13 +1381,7 @@ main (argc, argv) /* Tell the linker that we have initializer and finalizer functions. */ #ifdef LD_INIT_SWITCH #ifdef COLLECT_EXPORT_LIST - { - /* option name + functions + colons + NULL */ - char *buf = xmalloc (strlen (LD_INIT_SWITCH) - + strlen(initname) + strlen(fininame) + 3); - sprintf (buf, "%s:%s:%s", LD_INIT_SWITCH, initname, fininame); - *ld2++ = buf; - } + *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL); #else *ld2++ = LD_INIT_SWITCH; *ld2++ = initname; @@ -1459,12 +1396,7 @@ main (argc, argv) /* If we did not add export flag to link arguments before, add it to second link phase now. No new exports should have been added. */ if (! exports.first) - { - char *buf = xmalloc (strlen (export_file) + 5); - - sprintf (buf, "-bE:%s", export_file); - *ld2++ = buf; - } + *ld2++ = concat ("-bE:", export_file, NULL); add_to_list (&exports, initname); add_to_list (&exports, fininame); @@ -1500,16 +1432,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); @@ -1522,15 +1454,14 @@ 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) { int status; - pwait (pexecute_pid, &status, 0); + pwait (pid, &status, 0); if (status) { if (WIFSIGNALED (status)) @@ -1538,7 +1469,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); } @@ -1549,8 +1480,7 @@ collect_wait (prog) } static void -do_wait (prog) - const char *prog; +do_wait (const char *prog) { int ret = collect_wait (prog); if (ret != 0) @@ -1564,10 +1494,7 @@ do_wait (prog) /* Execute a program, and wait for the reply. */ void -collect_execute (prog, argv, redir) - const char *prog; - char **argv; - const char *redir; +collect_execute (const char *prog, char **argv, const char *redir) { char *errmsg_fmt; char *errmsg_arg; @@ -1619,9 +1546,8 @@ collect_execute (prog, argv, redir) dup2 (redir_handle, STDERR_FILENO); } - pexecute_pid = pexecute (argv[0], argv, argv[0], NULL, - &errmsg_fmt, &errmsg_arg, - (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH)); + pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg, + (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH)); if (redir) { @@ -1629,18 +1555,16 @@ collect_execute (prog, argv, redir) dup2 (stdout_save, STDOUT_FILENO); dup2 (stderr_save, STDERR_FILENO); - /* Close reponse file. */ + /* Close response file. */ close (redir_handle); } - if (pexecute_pid == -1) + if (pid == -1) fatal_perror (errmsg_fmt, errmsg_arg); } 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); @@ -1649,8 +1573,7 @@ fork_execute (prog, argv) /* Unlink a file unless we are debugging. */ static void -maybe_unlink (file) - const char *file; +maybe_unlink (const char *file) { if (!debug) unlink (file); @@ -1664,12 +1587,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); @@ -1699,8 +1619,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; @@ -1708,7 +1627,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; } @@ -1717,8 +1636,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 @@ -1759,10 +1677,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) { @@ -1771,12 +1686,27 @@ write_list (stream, prefix, list) } } +#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES +/* Given a STRING, return nonzero if it occurs in the list in range + [ARGS_BEGIN,ARGS_END). */ + +static int +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) + if (strcmp (string, *args_pointer) == 0) + return 1; + return 0; +} +#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ + #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) { @@ -1786,14 +1716,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) { @@ -1805,10 +1733,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) { @@ -1819,10 +1744,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) { @@ -1836,9 +1758,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; @@ -1881,17 +1801,12 @@ write_c_file_stat (stream, name) notice ("\nwrite_c_file - output name is %s, prefix is %s\n", output_file, prefix); -#define INIT_NAME_FORMAT "_GLOBAL__FI_%s" - initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2); - sprintf (initname, INIT_NAME_FORMAT, prefix); - -#define FINI_NAME_FORMAT "_GLOBAL__FD_%s" - fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2); - sprintf (fininame, FINI_NAME_FORMAT, prefix); + initname = concat ("_GLOBAL__FI_", prefix, NULL); + fininame = concat ("_GLOBAL__FD_", prefix, NULL); 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"); @@ -1963,8 +1878,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); } } @@ -1972,16 +1887,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) @@ -2037,9 +1950,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 @@ -2053,9 +1964,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) { @@ -2077,15 +1986,12 @@ 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); + void (*quit_handler) (int); char *real_nm_argv[4]; const char **nm_argv = (const char **) real_nm_argv; - int pid; int argc = 0; int pipe_fd[2]; char *p, buf[1024]; @@ -2127,7 +2033,7 @@ scan_prog_file (prog_name, which_pass) fflush (stdout); fflush (stderr); - /* Spawn child nm on pipe */ + /* Spawn child nm on pipe. */ pid = vfork (); if (pid == -1) fatal_perror (VFORK_STRING); @@ -2145,13 +2051,13 @@ scan_prog_file (prog_name, which_pass) fatal_perror ("close %d", pipe_fd[1]); execv (nm_file_name, real_nm_argv); - fatal_perror ("execvp %s", nm_file_name); + fatal_perror ("execv %s", nm_file_name); } /* 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) @@ -2175,7 +2081,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. */ @@ -2255,8 +2161,8 @@ scan_prog_file (prog_name, which_pass) #include /* pointers to the object file */ -unsigned object; /* address of memory mapped file */ -unsigned objsize; /* size of memory mapped to 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 */ @@ -2266,11 +2172,8 @@ 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; +mapfile (const char *name) { int fp; struct stat s; @@ -2292,11 +2195,8 @@ mapfile (name) static const char *libname; -static int libselect PARAMS ((struct direct *)); - static int -libselect (d) - struct direct *d; +libselect (struct direct *d) { return (strncmp (libname, d->d_name, strlen (libname)) == 0); } @@ -2308,11 +2208,9 @@ libselect (d) 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; +libcompare (struct direct **d1, struct direct **d2) { int i1, i2 = strlen (libname); char *e1 = (*d1)->d_name + i2; @@ -2334,7 +2232,7 @@ libcompare (d1, d2) /* 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. */ + /* It has an invalid numeric extension, must prefer the other one. */ else return -1; } @@ -2343,7 +2241,7 @@ libcompare (d1, d2) /* 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. */ + /* It has an invalid numeric extension, must prefer the other one. */ else return 1; } @@ -2353,11 +2251,9 @@ libcompare (d1, d2) /* 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 *)); static void -locatelib (name) - const char *name; +locatelib (const char *name) { static const char **l; static int cnt; @@ -2370,7 +2266,7 @@ locatelib (name) char *ld_rules; char *ldr = 0; /* counting elements in array, need 1 extra for null */ - cnt = 1; + cnt = 1; ld_rules = (char *) (ld_2->ld_rules + code); if (ld_rules) { @@ -2391,12 +2287,12 @@ locatelib (name) cnt++; q = xstrdup (p); } - l = (const char **) xmalloc ((cnt + 3) * sizeof (char *)); + l = xmalloc ((cnt + 3) * sizeof (char *)); pp = l; if (ldr) { *pp++ = ldr; - for (; *ldr != 0; ldr++) + for (; *ldr != 0; ldr++) if (*ldr == ':') { *ldr++ = 0; @@ -2406,7 +2302,7 @@ locatelib (name) if (q) { *pp++ = q; - for (; *q != 0; q++) + for (; *q != 0; q++) if (*q == ':') { *q++ = 0; @@ -2445,9 +2341,8 @@ locatelib (name) /* Scan the _DYNAMIC structure of the output file to find shared libraries that it depends upon and any constructors or destructors they contain. */ -static void -scan_libraries (prog_name) - const char *prog_name; +static void +scan_libraries (const char *prog_name) { struct exec *header; char *base; @@ -2520,17 +2415,15 @@ scan_libraries (prog_name) the output file depends upon and their initialization/finalization routines, if any. */ -static void -scan_libraries (prog_name) - const char *prog_name; +static void +scan_libraries (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)); + void (*int_handler) (int); + void (*quit_handler) (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]; @@ -2569,7 +2462,7 @@ scan_libraries (prog_name) fflush (stdout); fflush (stderr); - /* Spawn child ldd on pipe */ + /* Spawn child ldd on pipe. */ pid = vfork (); if (pid == -1) fatal_perror (VFORK_STRING); @@ -2591,9 +2484,9 @@ scan_libraries (prog_name) } /* 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) @@ -2618,7 +2511,7 @@ 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; @@ -2663,7 +2556,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 @@ -2676,14 +2569,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 @@ -2700,7 +2605,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. @@ -2712,9 +2653,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; @@ -2824,7 +2763,7 @@ scan_prog_file (prog_name, which_pass) #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 (shared_obj) { if (which_pass == PASS_OBJ && (! export_flag)) add_to_list (&exports, name); @@ -2871,14 +2810,13 @@ 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; @@ -2902,7 +2840,7 @@ resolve_lib_name (name) p = "/"; for (j = 0; libexts[j]; j++) { - sprintf (lib_buf, "%s%slib%s.%s", + sprintf (lib_buf, "%s%slib%s.%s", list->prefix, p, name, libexts[j]); if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); if (file_exists (lib_buf)) @@ -2916,705 +2854,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 */