]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/collect2.c
*** empty log message ***
[gcc.git] / gcc / collect2.c
index 814db0b41393484cf3b3e1e77140ce5b1d22d1a1..a3da8bc2b52605470a03dff0a349fb23833e07ac 100644 (file)
@@ -29,31 +29,90 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
-#include <stdlib.h>
 #include <ctype.h>
-#include "gstddef.h"
 #include <errno.h>
 #include <signal.h>
 #include <sys/file.h>
 #include <sys/stat.h>
+#ifdef NO_WAIT_H
 #include <sys/wait.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
 
 #define COLLECT
 
 #include "config.h"
 
 #ifndef __STDC__
-#include "gvarargs.h"
 #define generic char
-#define PROTO(x) ()
 #define const
 
 #else
-#include "stdarg.h"
 #define generic void
-#define PROTO(x) x
 #endif
 
+#ifdef USG
+#define vfork fork
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+/* On MSDOS, write temp files in current dir
+   because there's no place else we can expect to use.  */
+#if __MSDOS__
+#ifndef P_tmpdir
+#define P_tmpdir "./"
+#endif
+#endif
+\f
+/* On certain systems, we have code that works by scanning the object file
+   directly.  But this code uses system-specific header files and library
+   functions, so turn it off in a cross-compiler.  */
+
+#ifdef CROSS_COMPILE
+#undef OBJECT_FORMAT_COFF
+#undef OBJECT_FORMAT_ROSE
+#endif
+
+/* If we can't use a special method, use the ordinary one:
+   run nm to find what symbols are present.
+   In a cross-compiler, this means you need a cross nm,
+   but that isn't quite as unpleasant as special headers.  */
+
+#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
+#define OBJECT_FORMAT_NONE
+#endif
+
+#ifdef OBJECT_FORMAT_COFF
+
+#include <a.out.h>
+#include <ar.h>
+
+#ifdef UMAX
+#include <sgs.h>
+#endif
+
+#ifdef _AIX
+#define ISCOFF(magic) \
+  ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC)
+#endif
+
+#if defined (_AIX) || defined (USG)
+#undef FREAD
+#undef FWRITE
+#endif
+
+#include <ldfcn.h>
+
+#endif /* OBJECT_FORMAT_COFF */
+
 #ifdef OBJECT_FORMAT_ROSE
 
 #ifdef _OSF_SOURCE
@@ -69,25 +128,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <mach_o_header.h>
 #include <mach_o_vals.h>
 #include <mach_o_types.h>
+
 #endif /* OBJECT_FORMAT_ROSE */
 
+#ifdef OBJECT_FORMAT_NONE
+
 /* Default flags to pass to nm.  */
 #ifndef NM_FLAGS
 #define NM_FLAGS "-p"
 #endif
 
-#ifdef USG
-#define vfork fork
-#endif
-
-/* On MSDOS, write temp files in current dir
-   because there's no place else we can expect to use.  */
-#if __MSDOS__
-#ifndef P_tmpdir
-#define P_tmpdir "./"
-#endif
-#endif
-
+#endif /* OBJECT_FORMAT_NONE */
 \f
 /* Linked lists of constructor and destructor names. */
 
@@ -112,11 +163,14 @@ enum pass {
   PASS_SECOND                          /* with constructors linked in */
 };
 
+#ifndef NO_SYS_SIGLIST
 extern char *sys_siglist[];
+#endif
 extern char *version_string;
 
 static int vflag;                      /* true if -v */
 static int rflag;                      /* true if -r */
+static int strip_flag;                 /* true if -s */
 
 static int debug;                      /* true if -debug */
 
@@ -125,31 +179,28 @@ static char *temp_filename;               /* Base of temp filenames */
 static char *c_file;                   /* <xxx>.c for constructor/destructor list. */
 static char *o_file;                   /* <xxx>.o for constructor/destructor list. */
 static char *nm_file_name;             /* pathname of nm */
+static char *strip_file_name;          /* pathname of strip */
 
 static struct head constructors;       /* list of constructors found */
 static struct head destructors;                /* list of destructors found */
 
-extern char *getenv            PROTO(( const char * ));
-extern char *mktemp            PROTO(( char * ));
-extern int   vfork             PROTO(( void ));
-static void  add_to_list       PROTO(( struct head *headp, char *name ));
-static void  scan_prog_file    PROTO(( char *, enum pass ));
-static void  fork_execute      PROTO(( char *, char **argv ));
-static void  do_wait           PROTO(( char * ));
-static void  write_c_file      PROTO(( FILE *, char * ));
-static void  my_exit           PROTO(( int ));
-static void  handler           PROTO(( int ));
-static void  maybe_unlink      PROTO(( char * ));
-static void  choose_temp_base  PROTO(( void ));
-
-generic                *xcalloc        PROTO(( size_t, size_t ));
-generic                *xmalloc        PROTO(( size_t ));
-
+extern char *getenv ();
+extern char *mktemp ();
+static void  add_to_list ();
+static void  scan_prog_file ();
+static void  fork_execute ();
+static void  do_wait ();
+static void  write_c_file ();
+static void  my_exit ();
+static void  handler ();
+static void  maybe_unlink ();
+static void  choose_temp_base ();
+
+generic *xcalloc ();
+generic *xmalloc ();
 \f
-
-#if !defined(HAVE_STRERROR) && !defined(_OSF_SOURCE)
-
-char *strerror (e)
+char *
+my_strerror (e)
      int e;
 {
   extern char *sys_errlist[];
@@ -165,9 +216,6 @@ char *strerror (e)
   sprintf (buffer, "Unknown error %d", e);
   return buffer;
 }
-
-#endif
-
 \f
 /* Delete tempfiles and exit function.  */
 
@@ -175,119 +223,53 @@ static void
 my_exit (status)
      int status;
 {
-  if (c_file[0])
+  if (c_file != 0 && c_file[0])
     maybe_unlink (c_file);
 
-  if (o_file[0])
+  if (o_file != 0 && o_file[0])
     maybe_unlink (o_file);
 
   exit (status);
 }
 
 \f
-#ifndef __STDC__
-
 /* Die when sys call fails. */
 
-/*VARARGS*/
-static void
-fatal_perror (va_alist)
-{
-  char *string;
-  va_list vptr;
-  int e = errno;
-
-  va_start (vptr);
-  string = va_arg (vptr, char *);
-  fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
-  fprintf (stderr, ": %s\n", strerror (e));
-  va_end (vptr);
-  my_exit (1);
-}
-
-/* Just die. */
-
-/*VARARGS*/
-static void
-fatal (va_alist)
-{
-  char *string;
-  va_list vptr;
-
-  va_start (vptr);
-  string = va_arg (vptr, char *);
-  fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
-  fprintf (stderr, "\n");
-  va_end (vptr);
-  my_exit (1);
-}
-
-/* Write error message.  */
-
-/*VARARGS*/
 static void
-error (va_alist)
+fatal_perror (string, arg1, arg2, arg3)
+     char *string;
 {
-  char *string;
-  va_list vptr;
-
-  va_start (vptr);
-  string = va_arg (vptr, char *);
-  fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
-  fprintf (stderr, "\n");
-  va_end (vptr);
-}
-
-#else
-
-static void
-fatal_perror (char *string, ...)
-{
-  va_list vptr;
   int e = errno;
 
-  va_start (vptr, string);
   fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
-  fprintf (stderr, ": %s\n", strerror (e));
-  va_end (vptr);
+  fprintf (stderr, string, arg1, arg2, arg3);
+  fprintf (stderr, ": %s\n", my_strerror (e));
   my_exit (1);
 }
 
 /* Just die. */
 
 static void
-fatal (char *string, ...)
+fatal (string, arg1, arg2, arg3)
+     char *string;
 {
-  va_list vptr;
-
-  va_start (vptr, string);
   fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
+  fprintf (stderr, string, arg1, arg2, arg3);
   fprintf (stderr, "\n");
-  va_end (vptr);
   my_exit (1);
 }
 
 /* Write error message.  */
 
 static void
-error (char *string, ...)
+error (string, arg1, arg2, arg3, arg4)
+     char *string;
 {
-  va_list vptr;
-
-  va_start (vptr, string);
   fprintf (stderr, "collect: ");
-  vfprintf (stderr, string, vptr);
+  fprintf (stderr, string, arg1, arg2, arg3, arg4);
   fprintf (stderr, "\n");
-  va_end (vptr);
 }
-#endif
 
-\f
 /* In case obstack is linked in, and abort is defined to fancy_abort,
    provide a default entry.  */
 
@@ -309,42 +291,97 @@ handler (signo)
     maybe_unlink (o_file);
 
   signal (signo, SIG_DFL);
-
-  fatal ("Caught signal %d [%s]", signo, sys_siglist[signo]);
   kill (getpid (), signo);
 }
 
 \f
 generic *
 xcalloc (size1, size2)
-     size_t size1, size2;
+     int size1, size2;
 {
-  generic *ptr = calloc (size1, size2);
+  generic *ptr = (generic *) calloc (size1, size2);
   if (ptr)
     return ptr;
 
-  fatal ("Out of memory.");
+  fatal ("out of memory");
   return (generic *)0;
 }
 
 generic *
 xmalloc (size)
-     size_t size;
+     int size;
 {
-  generic *ptr = malloc (size);
+  generic *ptr = (generic *) malloc (size);
   if (ptr)
     return ptr;
 
-  fatal ("Out of memory.");
+  fatal ("out of memory");
   return (generic *)0;
 }
 
+/* Make a copy of a string INPUT with size SIZE.  */
+
+char *
+savestring (input, size)
+     char *input;
+     int size;
+{
+  char *output = (char *) xmalloc (size + 1);
+  bcopy (input, output, size);
+  output[size] = 0;
+  return output;
+}
+\f
+/* Decide whether the given symbol is:
+   a constructor (1), a destructor (2), or neither (0).  */
+
+static int
+is_ctor_dtor (s)
+     char *s;
+{
+  struct names { char *name; int len; int ret; int two_underscores; };
+
+  register struct names *p;
+  register int ch;
+  register char *orig_s = s;
+
+  static struct names special[] = {
+#ifdef NO_DOLLAR_IN_LABEL
+    { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
+    { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
+#else
+    { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
+    { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },
+#endif
+    { "sti__", sizeof ("sti__")-1, 1, 1 },
+    { "std__", sizeof ("std__")-1, 2, 1 },
+    { NULL, 0, 0, 0 }
+  };
+
+  while ((ch = *s) == '_')
+    ++s;
+
+  if (s == orig_s)
+    return 0;
+
+  for (p = &special[0]; p->len > 0; p++)
+    {
+      if (ch == p->name[0]
+         && (!p->two_underscores || ((s - orig_s) >= 2))
+         && strncmp(s, p->name, p->len) == 0)
+       {
+         return p->ret;
+       }
+    }
+  return 0;
+}
+
 \f
 /* Compute a string to use as the base of all temporary file names.
    It is substituted for %g.  */
 
 static void
-choose_temp_base PROTO((void))
+choose_temp_base ()
 {
   char *base = getenv ("TMPDIR");
   int len;
@@ -388,16 +425,16 @@ main (argc, argv)
   FILE *outf;
   char *ld_file_name;
   char *c_file_name;
-  char *B_option;
   char *p;
   char *prefix;
-  char **c_argv                = (char **) xcalloc (sizeof (char *), argc+7);
-  char **c_ptr         = c_argv;
+  char **c_argv;
+  char **c_ptr;
   char **ld1_argv      = (char **) xcalloc (sizeof (char *), argc+2);
   char **ld1           = ld1_argv;
   char **ld2_argv      = (char **) xcalloc (sizeof (char *), argc+5);
   char **ld2           = ld2_argv;
   int first_file;
+  int num_c_args       = argc+7;
   int len;
   int clen;
 
@@ -406,6 +443,21 @@ main (argc, argv)
   vflag = 1;
 #endif
 
+  p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+  if (p)
+    while (*p)
+      {
+       char *q = p;
+       while (*q && *q != ' ') q++;
+       if (*p == '-' && p[1] == 'm')
+         num_c_args++;
+
+       if (*q) q++;
+       p = q;
+      }
+
+  c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
+
   if (argc < 2)
     fatal ("no arguments");
 
@@ -416,7 +468,7 @@ main (argc, argv)
   signal (SIGSEGV, handler);
   signal (SIGBUS,  handler);
 
-  /* Try to discover a valid linker/assembler/nm to use.  */
+  /* Try to discover a valid linker/assembler/nm/strip to use.  */
   len = strlen (argv[0]);
   prefix = (char *)0;
   if (len >= sizeof ("ld")-1)
@@ -465,12 +517,18 @@ main (argc, argv)
     clen = sizeof (STANDARD_BIN_PREFIX) - 1;
 #endif
 
+#ifdef STANDARD_EXEC_PREFIX
+  if (clen < sizeof (STANDARD_EXEC_PREFIX) - 1)
+    clen = sizeof (STANDARD_EXEC_PREFIX) - 1;
+#endif
+
+  /* Allocate enough string space for the longest possible pathnames.  */
   ld_file_name = xcalloc (len + sizeof ("real-ld"), 1);
-  c_file_name  = xcalloc (clen + sizeof ("gcc"), 1);
   nm_file_name = xcalloc (len + sizeof ("gnm"), 1);
-  B_option     = xcalloc (len + sizeof ("-B"), 1);
+  strip_file_name = xcalloc (len + sizeof ("gstrip"), 1);
 
-  memcpy (ld_file_name, prefix, len);
+  /* Determine the full path name of the ld program to use.  */
+  bcopy (prefix, ld_file_name, len);
   strcpy (ld_file_name + len, "real-ld");
   if (access (ld_file_name, X_OK) < 0)
     {
@@ -481,33 +539,41 @@ main (argc, argv)
 #ifdef REAL_LD_FILE_NAME
          ld_file_name = REAL_LD_FILE_NAME;
 #else
-         ld_file_name = (access ("/usr/bin/ld", X_OK) == 0) ? "/usr/bin/ld" : "/bin/ld";
+         ld_file_name = (access ("/usr/bin/ld", X_OK) == 0
+                         ? "/usr/bin/ld" : "/bin/ld");
 #endif
        }
     }
 
-  memcpy (c_file_name, prefix, len);
-  strcpy (c_file_name + len, "gcc");
-  if (access (c_file_name, X_OK) < 0)
+  /* Determine the full path name of the C compiler to use.  */
+  c_file_name = getenv ("COLLECT_GCC");
+  if (c_file_name == 0 || c_file_name[0] != '/')
     {
-#ifdef STANDARD_BIN_PREFIX
-      strcpy (c_file_name, STANDARD_BIN_PREFIX);
-      strcat (c_file_name, "gcc");
+      c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
+      bcopy (prefix, c_file_name, len);
+      strcpy (c_file_name + len, "gcc");
       if (access (c_file_name, X_OK) < 0)
-#endif
        {
-#ifdef STANDARD_EXEC_PREFIX
-         strcpy (c_file_name, STANDARD_EXEC_PREFIX);
+#ifdef STANDARD_BIN_PREFIX
+         strcpy (c_file_name, STANDARD_BIN_PREFIX);
          strcat (c_file_name, "gcc");
          if (access (c_file_name, X_OK) < 0)
 #endif
            {
-             strcpy (c_file_name, "gcc");
+#ifdef STANDARD_EXEC_PREFIX
+             strcpy (c_file_name, STANDARD_EXEC_PREFIX);
+             strcat (c_file_name, "gcc");
+             if (access (c_file_name, X_OK) < 0)
+#endif
+               {
+                 strcpy (c_file_name, "gcc");
+               }
            }
        }
     }
 
-  memcpy (nm_file_name, prefix, len);
+  /* Determine the full path name of the nm to use.  */
+  bcopy (prefix, nm_file_name, len);
   strcpy (nm_file_name + len, "nm");
   if (access (nm_file_name, X_OK) < 0)
     {
@@ -518,13 +584,29 @@ main (argc, argv)
 #ifdef REAL_NM_FILE_NAME
          nm_file_name = REAL_NM_FILE_NAME;
 #else
-         nm_file_name = (access ("/usr/bin/nm", X_OK) == 0) ? "/usr/bin/nm" : "/bin/nm";
+         nm_file_name = (access ("/usr/bin/nm", X_OK) == 0
+                         ? "/usr/bin/nm" : "/bin/nm");
 #endif
        }
     }
 
-  strcpy (B_option, "-B");
-  strcpy (B_option + sizeof ("-B") - 1, prefix);
+  /* Determine the full pathname of the strip to use.  */
+  bcopy (prefix, strip_file_name, len);
+  strcpy (strip_file_name + len, "strip");
+  if (access (strip_file_name, X_OK) < 0)
+    {
+      strcpy (strip_file_name + len, "gstrip");
+      if (access (strip_file_name, X_OK) < 0)
+       {
+         free (strip_file_name);
+#ifdef REAL_STRIP_FILE_NAME
+         strip_file_name = REAL_STRIP_FILE_NAME;
+#else
+         strip_file_name = (access ("/usr/bin/strip", X_OK) == 0
+                            ? "/usr/bin/strip" : "/bin/strip");
+#endif
+       }
+    }
 
   *ld1++ = *ld2++ = "ld";
 
@@ -534,13 +616,21 @@ main (argc, argv)
   o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
   sprintf (c_file, "%s.c", temp_filename);
   sprintf (o_file, "%s.o", temp_filename);
-  *c_ptr++ = "gcc";
+  *c_ptr++ = c_file_name;
   *c_ptr++ = "-c";
   *c_ptr++ = "-o";
   *c_ptr++ = o_file;
 
+  /* !!! When GCC calls collect2,
+     it does not know whether it is calling collect2 or ld.
+     So collect2 cannot meaningfully understand any options
+     except those ld understands.
+     If you propose to make GCC pass some other option,
+     just imagine what will happen if ld is really ld!!!  */
+
   /* Parse arguments.  Remember output file spec, pass the rest to ld. */
-  /* After the first file, put in the c++ rt0 */
+  /* After the first file, put in the c++ rt0.  */
+
   first_file = 1;
   while ((arg = *++argv) != (char *)0)
     {
@@ -559,22 +649,6 @@ main (argc, argv)
                }
              break;
 
-             /* pass -f<xxx>, -B<xxx>, -b<xxx>, -V<xxx>, and -m<xxx>
-                options to gcc.  This allows options to be passed
-                that affect search rules, and the size of pointers. */
-           case 'b':
-           case 'B':
-           case 'f':
-           case 'm':
-           case 'V':
-             if (arg[1] != '\0')
-               {
-                 ld1--;
-                 ld2--;
-                 *c_ptr++ = arg;
-               }
-             break;
-
            case 'o':
              outfile = (arg[2] == '\0') ? argv[1] : &arg[2];
              break;
@@ -584,6 +658,17 @@ main (argc, argv)
                rflag = 1;
              break;
 
+           case 's':
+             if (arg[2] == '\0')
+               {
+                 /* We must strip after the nm run, otherwise C++ linking
+                    won't work.  Thus we strip in the second ld run, or
+                    else with strip if there is no second ld run.  */
+                 strip_flag = 1;
+                 ld1--;
+               }
+             break;
+
            case 'v':
              if (arg[2] == '\0')
                vflag = 1;
@@ -599,13 +684,26 @@ main (argc, argv)
        }
     }
 
-  *c_ptr++ = B_option;
+  /* Get any options that the upper GCC wants to pass to the sub-GCC.  */
+  p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+  if (p)
+    while (*p)
+      {
+       char *q = p;
+       while (*q && *q != ' ') q++;
+       if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
+         *c_ptr++ = savestring (p, q - p);
+
+       if (*q) q++;
+       p = q;
+      }
+
   *c_ptr++ = c_file;
   *c_ptr = *ld1 = *ld2 = (char *)0;
 
   if (vflag)
     {
-      fprintf (stderr, "GNU COLLECT2 version %s", version_string);
+      fprintf (stderr, "collect2 version %s", version_string);
 #ifdef TARGET_VERSION
       TARGET_VERSION;
 #endif
@@ -614,13 +712,31 @@ main (argc, argv)
 
   if (debug)
     {
-      fprintf (stderr, "prefix       = %s\n", prefix);
-      fprintf (stderr, "ld_file_name = %s\n", ld_file_name);
-      fprintf (stderr, "c_file_name  = %s\n", c_file_name);
-      fprintf (stderr, "nm_file_name = %s\n", nm_file_name);
-      fprintf (stderr, "B_option     = %s\n", B_option);
-      fprintf (stderr, "c_file       = %s\n", c_file);
-      fprintf (stderr, "o_file       = %s\n", o_file);
+      char *ptr;
+      fprintf (stderr, "prefix              = %s\n", prefix);
+      fprintf (stderr, "ld_file_name        = %s\n", ld_file_name);
+      fprintf (stderr, "c_file_name         = %s\n", c_file_name);
+      fprintf (stderr, "nm_file_name        = %s\n", nm_file_name);
+      fprintf (stderr, "c_file              = %s\n", c_file);
+      fprintf (stderr, "o_file              = %s\n", o_file);
+
+      ptr = getenv ("COLLECT_GCC_OPTIONS");
+      if (ptr)
+       fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
+
+      ptr = getenv ("COLLECT_GCC");
+      if (ptr)
+       fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
+
+      ptr = getenv ("COMPILER_PATH");
+      if (ptr)
+       fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
+
+      ptr = getenv ("LIBRARY_PATH");
+      if (ptr)
+       fprintf (stderr, "LIBRARY_PATH        = %s\n", ptr);
+
+      fprintf (stderr, "\n");
     }
 
   /* Load the program, searching all libraries.
@@ -643,16 +759,27 @@ main (argc, argv)
     }
 
   if (constructors.number == 0 && destructors.number == 0)
-    return 0;
+    {
+      /* Strip now if it was requested on the command line.  */
+      if (strip_flag)
+       {
+         char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
+         strip_argv[0] = "strip";
+         strip_argv[1] = outfile;
+         strip_argv[2] = (char *) 0;
+         fork_execute (strip_file_name, strip_argv);
+       }
+      return 0;
+    }
 
   outf = fopen (c_file, "w");
   if (outf == (FILE *)0)
-    fatal_perror ("Can't write %s", c_file);
+    fatal_perror ("%s", c_file);
 
   write_c_file (outf, c_file);
 
   if (fclose (outf))
-    fatal_perror ("Can't close %s", c_file);
+    fatal_perror ("closing %s", c_file);
 
   if (debug)
     {
@@ -688,21 +815,28 @@ do_wait (prog)
   wait (&status);
   if (status)
     {
-      int sig = WTERMSIG (status);
+      int sig = status & 0x7F;
       int ret;
 
       if (sig != -1 && sig != 0)
        {
+#ifdef NO_SYS_SIGLIST
+         error ("%s terminated with signal %d %s",
+                prog,
+                sig,
+                (status & 0200) ? ", core dumped" : "");
+#else
          error ("%s terminated with signal %d [%s]%s",
                 prog,
                 sig,
                 sys_siglist[sig],
                 (status & 0200) ? ", core dumped" : "");
+#endif
 
          my_exit (127);
        }
 
-      ret = WEXITSTATUS (status);
+      ret = ((status & 0xFF00) >> 8);
       if (ret != -1 && ret != 0)
        {
          error ("%s returned %d exit status", prog, ret);
@@ -720,8 +854,8 @@ fork_execute (prog, argv)
      char **argv;
 {
   int pid;
-  void (*int_handler) PROTO((int));
-  void (*quit_handler) PROTO((int));
+  void (*int_handler) ();
+  void (*quit_handler) ();
 
   if (vflag || debug)
     {
@@ -745,11 +879,11 @@ fork_execute (prog, argv)
   if (pid == 0)                        /* child context */
     {
       execvp (prog, argv);
-      fatal_perror ("Execute %s", prog);
+      fatal_perror ("executing %s", prog);
     }
 
-  int_handler  = (void (*)PROTO((int)))signal (SIGINT,  SIG_IGN);
-  quit_handler = (void (*)PROTO((int)))signal (SIGQUIT, SIG_IGN);
+  int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
+  quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
 
   do_wait (prog);
 
@@ -832,18 +966,18 @@ write_c_file (stream, name)
 
   fprintf (stream, "typedef void entry_pt();\n\n");
     
-  write_list_with_asm (stream, "entry_pt ", constructors);
+  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
     
   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
-  write_list (stream, "\t", constructors);
+  write_list (stream, "\t", constructors.first);
   fprintf (stream, "\t0\n};\n\n");
 
-  write_list_with_asm (stream, "entry_pt ", destructors);
+  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
 
   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
-  write_list (stream, "\t", destructors);
+  write_list (stream, "\t", destructors.first);
   fprintf (stream, "\t0\n};\n\n");
 
   fprintf (stream, "extern entry_pt __main;\n");
@@ -851,11 +985,10 @@ write_c_file (stream, name)
 }
 
 \f
-#ifndef OBJECT_FORMAT_ROSE
+#ifdef OBJECT_FORMAT_NONE
 
-/* OSF/rose specific version to scan the name list of the loaded
-   program for the symbols g++ uses for static constructors and
-   destructors.
+/* Generic version to scan the name list of the loaded program for
+   the symbols g++ uses for static constructors and destructors.
 
    The constructor table begins at __CTOR_LIST__ and contains a count
    of the number of pointers (or -1 if the constructors are built in a
@@ -868,8 +1001,8 @@ scan_prog_file (prog_name, which_pass)
      char *prog_name;
      enum pass which_pass;
 {
-  void (*int_handler) PROTO((int));
-  void (*quit_handler) PROTO((int));
+  void (*int_handler) ();
+  void (*quit_handler) ();
   char *nm_argv[4];
   int pid;
   int argc = 0;
@@ -880,12 +1013,12 @@ scan_prog_file (prog_name, which_pass)
   if (which_pass != PASS_FIRST)
     return;
 
-  nm_argv[ argc++ ] = "nm";
+  nm_argv[argc++] = "nm";
   if (NM_FLAGS[0] != '\0')
-    nm_argv[ argc++ ] = NM_FLAGS;
+    nm_argv[argc++] = NM_FLAGS;
 
-  nm_argv[ argc++ ] = prog_name;
-  nm_argv[ argc++ ] = (char *)0;
+  nm_argv[argc++] = prog_name;
+  nm_argv[argc++] = (char *)0;
 
   if (pipe (pipe_fd) < 0)
     fatal_perror ("pipe");
@@ -919,24 +1052,24 @@ scan_prog_file (prog_name, which_pass)
     {
       /* setup stdout */
       if (dup2 (pipe_fd[1], 1) < 0)
-       fatal_perror ("Dup2 (%d, 1)", pipe_fd[1]);
+       fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
 
       if (close (pipe_fd[0]) < 0)
-       fatal_perror ("Close (%d)", pipe_fd[0]);
+       fatal_perror ("close (%d)", pipe_fd[0]);
 
       if (close (pipe_fd[1]) < 0)
-       fatal_perror ("Close (%d)", pipe_fd[1]);
+       fatal_perror ("close (%d)", pipe_fd[1]);
 
       execv (nm_file_name, nm_argv);
-      fatal_perror ("Execute %s", nm_file_name);
+      fatal_perror ("executing %s", nm_file_name);
     }
 
   /* Parent context from here on.  */
-  int_handler  = (void (*)PROTO((int)))signal (SIGINT,  SIG_IGN);
-  quit_handler = (void (*)PROTO((int)))signal (SIGQUIT, SIG_IGN);
+  int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
+  quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
 
   if (close (pipe_fd[1]) < 0)
-    fatal_perror ("Close (%d)", pipe_fd[1]);
+    fatal_perror ("close (%d)", pipe_fd[1]);
 
   if (debug)
     fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -945,8 +1078,7 @@ scan_prog_file (prog_name, which_pass)
   while (fgets (buf, sizeof buf, inf) != (char *)0)
     {
       int ch, ch2;
-      char *start;
-      char *end;
+      char *name, *end;
 
       /* If it contains a constructor or destructor name, add the name
         to the appropriate list. */
@@ -956,42 +1088,29 @@ scan_prog_file (prog_name, which_pass)
 
       if (ch == '\0' || ch == '\n')
        continue;
-
-      start = p;
-      while ((ch = *p) == '_') /* skip any extra '_' inserted */
-       p++;
-
-      for (end = p; (ch2 = *end) != '\0' && !isspace (ch2); end++)
-       ;
+  
+      name = p;
+      /* Find the end of the symbol name.
+        Don't include `|', because Encore nm can tack that on the end.  */
+      for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
+          end++)
+       continue;
 
       *end = '\0';
-      if (ch == 'G')
+      switch (is_ctor_dtor (name))
        {
-         if (! strncmp (p, "GLOBAL_$I$", 10))
-           add_to_list (&constructors, p-1);
+       case 1:
+         add_to_list (&constructors, name);
+         break;
 
-         else if (! strncmp (p, "GLOBAL_$D$", 10))
-           add_to_list (&destructors, p-1);
+       case 2:
+         add_to_list (&destructors, name);
+         break;
 
-         else                          /* not a constructor or destructor */
-           continue;
+       default:                /* not a constructor or destructor */
+         continue;
        }
 
-      else if (ch == 's' && (p - start) >= 2)
-       {
-         if (! strncmp (p, "sti__", 5))
-           add_to_list (&constructors, p-2);
-
-         else if (! strncmp (p, "std__", 5))
-           add_to_list (&destructors, p-2);
-
-         else                          /* not a constructor or destructor */
-           continue;
-       }
-
-      else
-       continue;
-
       if (debug)
        fprintf (stderr, "\t%s\n", buf);
     }
@@ -1008,7 +1127,120 @@ scan_prog_file (prog_name, which_pass)
   signal (SIGQUIT, quit_handler);
 }
 
-#endif /* !OBJECT_FORMAT_ROSE */
+#endif /* OBJECT_FORMAT_NONE */
+
+\f
+/*
+ * COFF specific stuff.
+ */
+
+#ifdef OBJECT_FORMAT_COFF
+
+#if defined(EXTENDED_COFF)
+#   define GCC_SYMBOLS(X)      (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
+#   define GCC_SYMENT          SYMR
+#   define GCC_OK_SYMBOL(X)    ((X).st == stProc && (X).sc == scText)
+#   define GCC_SYMINC(X)       (1)
+#   define GCC_SYMZERO(X)      (SYMHEADER(X).isymMax)
+#   define GCC_CHECK_HDR(X)    (PSYMTAB(X) != 0)
+#else
+#   define GCC_SYMBOLS(X)      (HEADER(ldptr).f_nsyms)
+#   define GCC_SYMENT          SYMENT
+#   define GCC_OK_SYMBOL(X) \
+     (((X).n_sclass == C_EXT) && \
+        (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
+         ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
+#   define GCC_SYMINC(X)       ((X).n_numaux+1)
+#   define GCC_SYMZERO(X)      0
+#   define GCC_CHECK_HDR(X)    (1)
+#endif
+
+extern char *ldgetname ();
+
+/* COFF version to scan the name list of the loaded program for
+   the symbols g++ uses for static constructors and destructors.
+
+   The constructor table begins at __CTOR_LIST__ and contains a count
+   of the number of pointers (or -1 if the constructors are built in a
+   separate section by the linker), followed by the pointers to the
+   constructor functions, terminated with a null pointer.  The
+   destructor table has the same format, and begins at __DTOR_LIST__.  */
+
+static void
+scan_prog_file (prog_name, which_pass)
+     char *prog_name;
+     enum pass which_pass;
+{
+  LDFILE *ldptr;
+  int sym_index, sym_count;
+
+  if (which_pass != PASS_FIRST)
+    return;
+
+  if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
+    fatal ("%s: can't open as COFF file", prog_name);
+      
+  if (!ISCOFF (HEADER(ldptr).f_magic))
+    fatal ("%s: not a COFF file", prog_name);
+
+  if (GCC_CHECK_HDR (ldptr))
+    {
+      sym_count = GCC_SYMBOLS (ldptr);
+      sym_index = GCC_SYMZERO (ldptr);
+      while (sym_index < sym_count)
+       {
+         GCC_SYMENT symbol;
+
+         if (ldtbread (ldptr, sym_index, &symbol) <= 0)
+           break;
+         sym_index += GCC_SYMINC (symbol);
+
+         if (GCC_OK_SYMBOL (symbol))
+           {
+             char *name;
+
+             if ((name = ldgetname (ldptr, &symbol)) == NULL)
+               continue;               /* should never happen */
+
+#ifdef _AIX
+             /* All AIX function names begin with a dot. */
+             if (*name++ != '.')
+               continue;
+#endif
+
+             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 !defined(EXTENDED_COFF)
+             if (debug)
+               fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
+                        symbol.n_scnum, symbol.n_sclass,
+                        (symbol.n_type ? "0" : ""), symbol.n_type,
+                        name);
+#else
+             if (debug)
+               fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
+                        symbol.iss, symbol.value, symbol.index, name);
+#endif
+           }
+       }
+    }
+
+  (void) ldclose(ldptr);
+}
+
+#endif /* OBJECT_FORMAT_COFF */
 
 \f
 /*
@@ -1023,7 +1255,7 @@ 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;  /* interpereter pathname */
+  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 */
@@ -1055,31 +1287,21 @@ struct file_info
   int  use_mmap;                       /* != 0 if mmap'ed */
 };
 
-extern int decode_mach_o_hdr           PROTO(( void *in_bufp,
-                                               size_t in_bufsize,
-                                               unsigned long hdr_version,
-                                               mo_header_t *headerp ));
+extern int decode_mach_o_hdr ();
 
-extern int encode_mach_o_hdr           PROTO(( mo_header_t *headerp,
-                                               void *out_bufp,
-                                               size_t out_bufsize ));
+extern int encode_mach_o_hdr ();
 
-static void bad_header                 PROTO(( int status ));
+static void bad_header ();
 
-static void print_header               PROTO(( mo_header_t *hdr_ptr ));
+static void print_header ();
 
-static void print_load_command         PROTO(( load_union_t *load_hdr,
-                                               size_t offset,
-                                               int number ));
+static void print_load_command ();
 
-static void add_func_table             PROTO(( mo_header_t *hdr_p,
-                                               load_all_t *load_array,
-                                               symbol_info_t *sym,
-                                               int type ));
+static void add_func_table ();
 
-static struct file_info        *read_file      PROTO(( char *, int, int ));
+static struct file_info        *read_file ();
 
-static void end_file                   PROTO(( struct file_info * ));
+static void end_file ();
 
 \f
 /* OSF/rose specific version to scan the name list of the loaded
@@ -1116,7 +1338,7 @@ scan_prog_file (prog_name, which_pass)
 
   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
   if (prog_fd < 0)
-    fatal_perror ("Can't read %s", prog_name);
+    fatal_perror ("can't read %s", prog_name);
 
   obj_file = read_file (prog_name, prog_fd, rw);
   obj = obj_file->start;
@@ -1139,7 +1361,7 @@ scan_prog_file (prog_name, which_pass)
       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
     {
-      fatal ("incompatibilities exist between object file & expected values.");
+      fatal ("incompatibilities between object file & expected values");
     }
 #endif
 
@@ -1162,7 +1384,7 @@ scan_prog_file (prog_name, which_pass)
       if (rw)
        {
          load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
-         memcpy (ptr, load_hdr, load_hdr->hdr.ldci_cmd_size);
+         bcopy (load_hdr, ptr, load_hdr->hdr.ldci_cmd_size);
          load_hdr = ptr;
 
          /* null out old command map, because we will rewrite at the end.  */
@@ -1203,7 +1425,7 @@ scan_prog_file (prog_name, which_pass)
 
          if (debug)
            {
-             char *kind = "uknown";
+             char *kind = "unknown";
 
              switch (load_hdr->sym.symc_kind)
                {
@@ -1219,7 +1441,7 @@ scan_prog_file (prog_name, which_pass)
          if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
            continue;
 
-         str_sect = load_array[ load_hdr->sym.symc_strings_section ].section;
+         str_sect = load_array[load_hdr->sym.symc_strings_section].section;
          if (str_sect == (char *)0)
            fatal ("string section missing");
 
@@ -1231,50 +1453,37 @@ scan_prog_file (prog_name, which_pass)
            {
              symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
              char *name = sym->si_name.symbol_name + str_sect;
-             char *name_start = name;
 
              if (name[0] != '_')
                continue;
 
-             while (*++name == '_')    /* skip any extra '_' inserted */
-               ;
-
              if (rw)
                {
-                 if (*name != 'm' || (name - name_start) < 2
-                     || strcmp (name, "main"))
+                 char *n = name;
+                 while (*n == '_')
+                   ++n;
+                 if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
                    continue;
 
                  main_sym = sym;
                }
-
-             else if (*name == 'G')
+             else
                {
-                 if (! strncmp (name, "GLOBAL_$I$", 10))
-                   add_to_list (&constructors, name_start);
-
-                 else if (! strncmp (name, "GLOBAL_$D$", 10))
-                   add_to_list (&destructors, name_start);
-
-                 else          /* not a constructor or destructor */
-                   continue;
+                 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;
+                   }
                }
 
-             else if (*name == 's' && (name - name_start) > 2)
-               {
-                 if (! strncmp (name, "sti__", 5))
-                   add_to_list (&constructors, name_start);
-
-                 else if (! strncmp (name, "std__", 5))
-                   add_to_list (&destructors, name_start);
-
-                 else          /* not a constructor or destructor */
-                   continue;
-               }
-
-             else
-               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);
@@ -1283,7 +1492,7 @@ scan_prog_file (prog_name, which_pass)
     }
 
   if (symbol_load_cmds == 0)
-    fatal ("no symbol table found.");
+    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
@@ -1296,10 +1505,15 @@ scan_prog_file (prog_name, which_pass)
       size_t size;
 
       if (cmd_strings == -1)
-       fatal ("no cmd_strings found.");
+       fatal ("no cmd_strings found");
+
+      /* Add __main to initializer list.
+        If we are building a program instead of a shared library, don't
+        do anything, since in the current version, you cannot do mallocs
+        and such in the constructors.  */
 
-      /* Add __main to initializer list.  */
-      if (main_sym != (symbol_info_t *)0)
+      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)
@@ -1353,7 +1567,7 @@ scan_prog_file (prog_name, which_pass)
          if (debug)
            print_load_command (load_hdr, offset, i);
 
-         memcpy (obj + offset, load_hdr, size);
+         bcopy (load_hdr, obj + offset, size);
          offset += size;
        }
     }
@@ -1361,7 +1575,7 @@ scan_prog_file (prog_name, which_pass)
   end_file (obj_file);
 
   if (close (prog_fd))
-    fatal_perror ("Can't close %s", prog_name);
+    fatal_perror ("closing %s", prog_name);
 
   if (debug)
     fprintf (stderr, "\n");
@@ -1369,7 +1583,7 @@ scan_prog_file (prog_name, which_pass)
 
 \f
 /* Add a function table to the load commands to call a function
-   on initition or termination of the process.  */
+   on initiation or termination of the process.  */
 
 static void
 add_func_table (hdr_p, load_array, sym, type)
This page took 0.059955 seconds and 5 git commands to generate.