Shared library support.
authorJason Merrill <merrill@gnu.org>
Sat, 19 Nov 1994 04:09:58 +0000 (04:09 +0000)
committerJason Merrill <merrill@gnu.org>
Sat, 19 Nov 1994 04:09:58 +0000 (04:09 +0000)
From-SVN: r8519

21 files changed:
gcc/Makefile.in
gcc/collect2.c
gcc/config/alpha/alpha.h
gcc/config/i386/sol2.h
gcc/config/i386/t-sol2
gcc/config/i860/sysv4.h
gcc/config/m88k/dgux.h
gcc/config/m88k/sysv4.h
gcc/config/m88k/t-sysv4
gcc/config/mips/iris5.h
gcc/config/pa/pa-hpux.h
gcc/config/pa/pa.h
gcc/config/sparc/sol2.h
gcc/config/sparc/sparc.h
gcc/config/sparc/sysv4.h
gcc/config/sparc/t-sol2
gcc/config/svr4.h
gcc/config/t-svr4
gcc/crtstuff.c
gcc/gcc.c
gcc/libgcc2.c

index 7e9231f7276fd0f9ca79925ba4de7e0166e1628a..eb8794da568fbb6290cc5d4b3689fadade563e92 100644 (file)
@@ -340,6 +340,9 @@ FLOAT_H=float.h-nat
 # Extra symbols for fixproto to define when parsing headers.
 FIXPROTO_DEFINES = 
 
+# Extra flags to use when compiling crt{begin,end}.o.
+CRTSTUFF_T_CFLAGS = 
+
 # End of variables for you to override.
 
 # Definition of `all' is here so that new rules inserted by sed
@@ -943,13 +946,13 @@ sublibobjc.a: cc1obj stmp-int-hdrs libgcc2.ready
 # Compile two additional files that are linked with every program
 # linked using GCC on system V, for the sake of C++ constructors.
 crtbegin.o:    crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
-       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_BEGIN \
-         -finhibit-size-directive -fno-inline-functions \
+       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
+         -DCRT_BEGIN -finhibit-size-directive -fno-inline-functions \
          -g0 -c $(srcdir)/crtstuff.c -o crtbegin.o
 
 crtend.o:      crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
-       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_END \
-         -finhibit-size-directive -fno-inline-functions \
+       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
+         -DCRT_END -finhibit-size-directive -fno-inline-functions \
          -g0 -c $(srcdir)/crtstuff.c -o crtend.o
 \f
 # Compiling object files from source files.
index 356bad03b3ee98392b8238382e10fe33e9b6230f..e46b9fa6c7bc9a3ee5218fa0a01ddc27f48f8c5d 100644 (file)
@@ -107,6 +107,7 @@ extern int sys_nerr;
    cross-versions are in the proper directories.  */
 
 #ifdef CROSS_COMPILE
+#undef SUNOS4_SHARED_LIBRARIES
 #undef OBJECT_FORMAT_COFF
 #undef OBJECT_FORMAT_ROSE
 #undef MD_EXEC_PREFIX
@@ -188,6 +189,9 @@ extern int sys_nerr;
 #define SYMBOL__MAIN __main
 #endif
 
+#if defined (LDD_SUFFIX) || defined (SUNOS4_SHARED_LIBRARIES)
+#define SCAN_LIBRARIES
+#endif
 \f
 /* Linked lists of constructor and destructor names. */
 
@@ -209,6 +213,7 @@ struct head
 
 enum pass {
   PASS_FIRST,                          /* without constructors */
+  PASS_LIB,                            /* looking for shared libraries */
   PASS_SECOND                          /* with constructors linked in */
 };
 
@@ -225,12 +230,15 @@ static int strip_flag;                    /* true if -s */
 
 static int debug;                      /* true if -debug */
 
+static int shared_obj;                 /* true if -shared */
+
 static int   temp_filename_length;     /* Length of temp_filename */
 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 *output_file;              /* Output file for ld.  */
 static char *nm_file_name;             /* pathname of nm */
+static char *ldd_file_name;            /* pathname of ldd (or equivalent) */
 static char *strip_file_name;          /* pathname of strip */
 
 static struct head constructors;       /* list of constructors found */
@@ -272,6 +280,7 @@ static void write_list              PROTO((FILE *, char *, struct id *));
 static void write_list_with_asm PROTO((FILE *, char *, struct id *));
 static void write_c_file       PROTO((FILE *, char *));
 static void scan_prog_file     PROTO((char *, enum pass));
+static void scan_libraries     PROTO((char *));
 
 generic *xcalloc ();
 generic *xmalloc ();
@@ -467,6 +476,8 @@ is_ctor_dtor (s)
     { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
     { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
 #endif
+    { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
+    { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
 #ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
                         cfront has its own linker procedure to collect them;
                         if collect2 gets them too, they get collected twice
@@ -792,6 +803,10 @@ main (argc, argv)
   char *full_nm_suffix = nm_suffix;
   char *gnm_suffix     = "gnm";
   char *full_gnm_suffix        = gnm_suffix;
+#ifdef LDD_SUFFIX
+  char *ldd_suffix     = LDD_SUFFIX;
+  char *full_ldd_suffix        = ldd_suffix;
+#endif
   char *strip_suffix   = "strip";
   char *full_strip_suffix = strip_suffix;
   char *gstrip_suffix  = "gstrip";
@@ -943,6 +958,14 @@ main (argc, argv)
   strcat (full_gnm_suffix, "-");
   strcat (full_gnm_suffix, gnm_suffix);
 
+#ifdef LDD_SUFFIX
+  full_ldd_suffix
+    = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1);
+  strcpy (full_ldd_suffix, target_machine);
+  strcat (full_ldd_suffix, "-");
+  strcat (full_ldd_suffix, ldd_suffix);
+#endif
+
   full_strip_suffix
     = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
   strcpy (full_strip_suffix, target_machine);
@@ -1011,6 +1034,12 @@ main (argc, argv)
   if (nm_file_name == 0)
     nm_file_name = find_a_file (&path, full_nm_suffix);
 
+#ifdef LDD_SUFFIX
+  ldd_file_name = find_a_file (&cpath, ldd_suffix);
+  if (ldd_file_name == 0)
+    ldd_file_name = find_a_file (&path, full_ldd_suffix);
+#endif
+
 #ifdef REAL_STRIP_FILE_NAME
   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
   if (strip_file_name == 0)
@@ -1088,6 +1117,17 @@ main (argc, argv)
                }
              break;
 
+           case 'l':
+             if (first_file)
+               {
+                 /* place o_file BEFORE this argument! */
+                 first_file = 0;
+                 ld2--;
+                 *ld2++ = o_file;
+                 *ld2++ = arg;
+               }
+             break;
+
            case 'o':
              output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
              break;
@@ -1116,10 +1156,13 @@ main (argc, argv)
        }
       else if (first_file
               && (p = rindex (arg, '.')) != (char *)0
-              && strcmp (p, ".o") == 0)
+              && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0))
        {
          first_file = 0;
+         /* place o_file BEFORE this argument! */
+         ld2--;
          *ld2++ = o_file;
+         *ld2++ = arg;
        }
     }
 
@@ -1132,11 +1175,24 @@ main (argc, argv)
        while (*q && *q != ' ') q++;
        if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
          *c_ptr++ = savestring (p, q - p);
+       if (strncmp (p, "-shared", sizeof ("shared") - 1) == 0)
+         shared_obj = 1;
 
        if (*q) q++;
        p = q;
       }
 
+#ifdef LD_INIT_SWITCH
+  /* Tell the linker that we have initializer and finalizer functions.  */
+  if (shared_obj)
+    {
+      *ld2++ = LD_INIT_SWITCH;
+      *ld2++ = "_GLOBAL__DI";
+      *ld2++ = LD_FINI_SWITCH;
+      *ld2++ = "_GLOBAL__DD";
+    }
+#endif
+
   *c_ptr++ = c_file;
   *c_ptr = *ld1 = *ld2 = (char *)0;
 
@@ -1158,6 +1214,10 @@ main (argc, argv)
               (c_file_name ? c_file_name : "not found"));
       fprintf (stderr, "nm_file_name        = %s\n",
               (nm_file_name ? nm_file_name : "not found"));
+#ifdef LDD_SUFFIX
+      fprintf (stderr, "ldd_file_name       = %s\n",
+              (ldd_file_name ? ldd_file_name : "not found"));
+#endif
       fprintf (stderr, "strip_file_name     = %s\n",
               (strip_file_name ? strip_file_name : "not found"));
       fprintf (stderr, "c_file              = %s\n",
@@ -1195,19 +1255,30 @@ main (argc, argv)
 
   fork_execute ("ld", ld1_argv);
 
-  /* If -r, don't build the constructor or destructor list, just return now.  */
+  /* If -r, don't build the constructor or destructor list, just return now. */
   if (rflag)
     return 0;
 
   scan_prog_file (output_file, PASS_FIRST);
 
+#ifdef SCAN_LIBRARIES
+  scan_libraries (output_file);
+#endif
+
   if (debug)
     {
       fprintf (stderr, "%d constructor(s) found\n", constructors.number);
       fprintf (stderr, "%d destructor(s)  found\n", destructors.number);
     }
 
-  if (constructors.number == 0 && destructors.number == 0)
+  if (constructors.number == 0 && destructors.number == 0
+#ifdef LDD_SUFFIX
+      /* If we will be running these functions ourselves, we want to emit
+        stubs into the shared library so that we don't have to relink
+        dependent programs when we add static objects.  */
+      && ! shared_obj
+#endif
+      )
     {
       /* Strip now if it was requested on the command line.  */
       if (strip_flag)
@@ -1429,10 +1500,107 @@ write_list_with_asm (stream, prefix, list)
     }
 }
 
+/* Write out the constructor and destructor tables statically (for a shared
+   object), along with the functions to execute them.  */
+
+static void
+write_c_file_stat (stream, name)
+     FILE *stream;
+     char *name;
+{
+  char *prefix, *p, *q;
+  char *initname, *fininame;
+
+  /* Figure out name of output_file, stripping off .so version.  */
+  p = rindex (output_file, '/');
+  if (p == 0)
+    p = (char *) output_file;
+  else
+    p++;
+  q = p;
+  while (q)
+    {
+      q = index (q,'.');
+      if (q == 0)
+       {
+         q = p + strlen (p);
+         break;
+       }
+      else
+       {
+         if (strncmp (q, ".so", 3) == 0)
+           {
+             q += 3;
+             break;
+           }
+         else
+           q++;
+       }
+    }
+  /* q points to null at end of the string (or . of the .so version) */
+  prefix = xmalloc (q - p + 1);
+  strncpy (prefix, p, q - p);
+  prefix[q - p] = 0;
+  for (q = prefix; *q; q++)
+    if (!isalnum (*q))
+      *q = '_';
+  if (debug)
+    fprintf (stderr, "\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);
+
+  free (prefix);
+
+  /* Write the tables as C code  */
+
+  fprintf (stream, "static int count;\n");
+  fprintf (stream, "typedef void entry_pt();\n");
+  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
+  fprintf (stream, "void %s() {\n", initname);
+  if (constructors.number > 0)
+    {
+      fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
+      write_list (stream, "\t\t", constructors.first);
+      fprintf (stream, "\t};\n");
+      fprintf (stream, "\tentry_pt **p;\n");
+      fprintf (stream, "\tif (count++ != 0) return;\n");
+      fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
+      fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
+    }
+  fprintf (stream, "}\n");
+  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
+  fprintf (stream, "void %s() {\n", fininame);
+  if (destructors.number > 0)
+    {
+      fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
+      write_list (stream, "\t\t", destructors.first);
+      fprintf (stream, "\t};\n");
+      fprintf (stream, "\tentry_pt **p;\n");
+      fprintf (stream, "\tif (--count != 0) return;\n");
+      fprintf (stream, "\tp = dtors;\n");
+      fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
+              destructors.number);
+    }
+  fprintf (stream, "}\n");
+
+  fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
+  fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
+
+  free (initname);
+  free (fininame);
+}
+
 /* Write the constructor/destructor tables. */
 
 static void
-write_c_file (stream, name)
+write_c_file_glob (stream, name)
      FILE *stream;
      char *name;
 {
@@ -1458,6 +1626,16 @@ write_c_file (stream, name)
   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
 }
 
+static void
+write_c_file (stream, name)
+     FILE *stream;
+     char *name;
+{
+  if (shared_obj)
+    write_c_file_stat (stream, name);
+  else
+    write_c_file_glob (stream, name);
+}
 \f
 #ifdef OBJECT_FORMAT_NONE
 
@@ -1484,14 +1662,14 @@ scan_prog_file (prog_name, which_pass)
   char *p, buf[1024];
   FILE *inf;
 
-  if (which_pass != PASS_FIRST)
+  if (which_pass == PASS_SECOND)
     return;
 
   /* If we don't have an `nm', complain.  */
   if (nm_file_name == 0)
     fatal ("cannot find `nm'");
 
-  nm_argv[argc++] = "nm";
+  nm_argv[argc++] = nm_file_name;
   if (NM_FLAGS[0] != '\0')
     nm_argv[argc++] = NM_FLAGS;
 
@@ -1511,8 +1689,7 @@ scan_prog_file (prog_name, which_pass)
       char **p_argv;
       char *str;
 
-      fprintf (stderr, "%s", nm_file_name);
-      for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
+      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++)
        fprintf (stderr, " %s", str);
 
       fprintf (stderr, "\n");
@@ -1570,9 +1747,10 @@ scan_prog_file (prog_name, which_pass)
         to the appropriate list. */
 
       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
-       ;
+       if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
+         break;
 
-      if (ch == '\0' || ch == '\n')
+      if (ch != '_')
        continue;
   
       name = p;
@@ -1587,10 +1765,24 @@ scan_prog_file (prog_name, which_pass)
       switch (is_ctor_dtor (name))
        {
        case 1:
-         add_to_list (&constructors, name);
+         if (which_pass != PASS_LIB)
+           add_to_list (&constructors, name);
          break;
 
        case 2:
+         if (which_pass != PASS_LIB)
+           add_to_list (&destructors, name);
+         break;
+
+       case 3:
+         if (which_pass != PASS_LIB)
+           fatal ("init function found in object %s", prog_name);
+         add_to_list (&constructors, name);
+         break;
+
+       case 4:
+         if (which_pass != PASS_LIB)
+           fatal ("init function found in object %s", prog_name);
          add_to_list (&destructors, name);
          break;
 
@@ -1616,6 +1808,357 @@ scan_prog_file (prog_name, which_pass)
 #endif
 }
 
+#ifdef SUNOS4_SHARED_LIBRARIES
+
+/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
+   that the output file depends upon and their initialization/finalization
+   routines, if any.  */
+
+#include <a.out.h>
+#include <fcntl.h>
+#include <link.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/unistd.h>
+
+/* pointers to the object file */
+unsigned object;       /* address of memory mapped file */
+unsigned objsize;      /* size of memory mapped to file */
+char * code;           /* pointer to code segment */
+char * data;           /* pointer to data segment */
+struct nlist *symtab;  /* pointer to symbol table */
+struct link_dynamic *ld;
+struct link_dynamic_2 *ld_2;
+struct head libraries;
+
+/* Map the file indicated by NAME into memory and store its address.  */
+
+static void
+mapfile (name)
+     char *name;
+{
+  int fp;
+  struct stat s;
+  if ((fp = open (name, O_RDONLY)) == -1)
+    fatal ("unable to open file '%s'", name);
+  if (fstat (fp, &s) == -1)
+    fatal ("unable to stat file '%s'", name);
+
+  objsize = s.st_size;
+  object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                           fp, 0);
+  if (object == -1)
+    fatal ("unable to mmap file '%s'", name);
+
+  close (fp);
+}
+
+/* Given the name NAME of a dynamic dependency, find its pathname and add
+   it to the list of libraries.  */
+
+static void
+locatelib (name)
+     char *name;
+{
+  static char **l;
+  static int cnt;
+  char buf[MAXPATHLEN];
+  char *p, *q;
+  char **pp;
+
+  if (l == 0)
+    {
+      char *ld_rules;
+      char *ldr = 0;
+      /* counting elements in array, need 1 extra for null */
+      cnt = 1;  
+      ld_rules = (char *) (ld_2->ld_rules + code);
+      if (ld_rules)
+       {
+         cnt++;
+         for (; *ld_rules != 0; ld_rules++)
+           if (*ld_rules == ':')
+             cnt++;
+         ld_rules = (char *) (ld_2->ld_rules + code);
+         ldr = (char *) malloc (strlen (ld_rules) + 1);
+         strcpy (ldr, ld_rules);
+       }
+      p = getenv ("LD_LIBRARY_PATH");
+      q = 0;
+      if (p)
+       {
+         cnt++;
+         for (q = p ; *q != 0; q++)
+           if (*q == ':')
+             cnt++;
+         q = (char *) malloc (strlen (p) + 1);
+         strcpy (q, p);
+       }
+      l = (char **) malloc ((cnt + 3) * sizeof (char *));
+      pp = l;
+      if (ldr)
+       {
+         *pp++ = ldr;
+         for (; *ldr != 0; ldr++) 
+           if (*ldr == ':')
+             {
+               *ldr++ = 0;
+               *pp++ = ldr;
+             }
+       }
+      if (q)
+       {
+         *pp++ = q;
+         for (; *q != 0; q++) 
+           if (*q == ':')
+             {
+               *q++ = 0;
+               *pp++ = p;
+             }
+       }
+      /* built in directories are /lib, /usr/lib, and /usr/local/lib */
+      *pp++ = "/lib";
+      *pp++ = "/usr/lib";
+      *pp++ = "/usr/local/lib";
+      *pp = 0;
+    }
+  for (pp = l; *pp != 0 ; pp++)
+    {
+      sprintf (buf, "%s/%s", *pp, name);
+      if (access (buf, R_OK) == 0)
+       {
+         add_to_list (&libraries, buf);
+         if (debug)
+           fprintf (stderr, "%s\n", buf);
+         break;
+       }
+    }
+  if (*pp == 0)
+    {
+      if (debug)
+       fprintf (stderr, "not found\n");
+      else
+       fatal ("dynamic dependency %s not found", 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)
+     char *prog_name;
+{
+  struct exec *header;
+  char *base;
+  struct link_object *lo;
+  char buff[MAXPATHLEN];
+  struct id *list;
+
+  mapfile (prog_name);
+  header = (struct exec *)object;
+  if (N_BADMAG (*header))
+    fatal ("bad magic number in file '%s'", prog_name);
+  if (header->a_dynamic == 0)
+    return;
+
+  code = (char *) (N_TXTOFF (*header) + (long) header);
+  data = (char *) (N_DATOFF (*header) + (long) header);
+  symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
+
+  if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
+    {
+      /* shared object */
+      ld = (struct link_dynamic *) (symtab->n_value + code);
+      base = code;
+    }
+  else
+    {
+      /* executable */
+      ld = (struct link_dynamic *) data;
+      base = code-PAGSIZ;
+    }
+
+  if (debug)
+    fprintf (stderr, "dynamic dependencies.\n");
+
+  ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
+  for (lo = (struct link_object *) ld_2->ld_need; lo;
+       lo = (struct link_object *) lo->lo_next)
+    {
+      char *name;
+      lo = (struct link_object *) ((long) lo + code);
+      name = (char *) (code + lo->lo_name);
+      if (lo->lo_library)
+       {
+         if (debug)
+           fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
+         sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
+         locatelib (buff);
+       }
+      else
+       {
+         if (debug)
+           fprintf (stderr, "\t%s\n", name);
+         add_to_list (&libraries, name);
+       }
+    }
+
+  if (debug)
+    fprintf (stderr, "\n");
+
+  /* now iterate through the library list adding their symbols to
+     the list.  */
+  for (list = libraries.first; list; list = list->next)
+    scan_prog_file (list->name, PASS_LIB);
+}
+
+#else  /* SUNOS4_SHARED_LIBRARIES */
+#ifdef LDD_SUFFIX
+
+/* Use the List Dynamic Dependencies program to find shared libraries that
+   the output file depends upon and their initialization/finalization
+   routines, if any.  */
+
+static void 
+scan_libraries (prog_name)
+     char *prog_name;
+{
+  static struct head libraries;                /* list of shared libraries found */
+  struct id *list;
+  void (*int_handler) ();
+  void (*quit_handler) ();
+  char *ldd_argv[4];
+  int pid;
+  int argc = 0;
+  int pipe_fd[2];
+  char buf[1024];
+  FILE *inf;
+
+  /* If we don't have an `ldd', complain.  */
+  if (ldd_file_name == 0)
+    {
+      error ("cannot find `ldd'");
+      return;
+    }
+
+  ldd_argv[argc++] = ldd_file_name;
+  ldd_argv[argc++] = prog_name;
+  ldd_argv[argc++] = (char *) 0;
+
+  if (pipe (pipe_fd) < 0)
+    fatal_perror ("pipe");
+
+  inf = fdopen (pipe_fd[0], "r");
+  if (inf == (FILE *) 0)
+    fatal_perror ("fdopen");
+
+  /* Trace if needed.  */
+  if (vflag)
+    {
+      char **p_argv;
+      char *str;
+
+      for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
+       fprintf (stderr, " %s", str);
+
+      fprintf (stderr, "\n");
+    }
+
+  fflush (stdout);
+  fflush (stderr);
+
+  /* Spawn child ldd on pipe */
+  pid = vfork ();
+  if (pid == -1)
+    {
+#ifdef vfork
+      fatal_perror ("fork");
+#else
+      fatal_perror ("vfork");
+#endif
+    }
+
+  if (pid == 0)                        /* child context */
+    {
+      /* setup stdout */
+      if (dup2 (pipe_fd[1], 1) < 0)
+       fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
+
+      if (close (pipe_fd[0]) < 0)
+       fatal_perror ("close (%d)", pipe_fd[0]);
+
+      if (close (pipe_fd[1]) < 0)
+       fatal_perror ("close (%d)", pipe_fd[1]);
+
+      execv (ldd_file_name, ldd_argv);
+      fatal_perror ("executing %s", ldd_file_name);
+    }
+
+  /* Parent context from here on.  */
+  int_handler  = (void (*) ()) signal (SIGINT,  SIG_IGN);
+#ifdef SIGQUIT
+  quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+#endif
+
+  if (close (pipe_fd[1]) < 0)
+    fatal_perror ("close (%d)", pipe_fd[1]);
+
+  if (debug)
+    fprintf (stderr, "\nldd output with constructors/destructors.\n");
+
+  /* Read each line of ldd output.  */
+  while (fgets (buf, sizeof buf, inf) != (char *) 0)
+    {
+      int ch, ch2;
+      char *name, *end, *p = buf;
+
+      /* Extract names of libraries and add to list. */
+      PARSE_LDD_OUTPUT (p);
+      if (p == 0)
+       continue;
+
+      name = p;
+      if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
+       fatal ("dynamic dependency %s not found", buf);
+
+      /* Find the end of the symbol name. */
+      for (end = p; 
+          (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
+          end++)
+       continue;
+      *end = '\0';
+
+      if (access (name, R_OK) == 0)
+        add_to_list (&libraries, name);
+      else
+       fatal ("unable to open dynamic dependency '%s'", buf);
+
+      if (debug)
+       fprintf (stderr, "\t%s\n", buf);
+    }
+  if (debug)
+    fprintf (stderr, "\n");
+
+  if (fclose (inf) != 0)
+    fatal_perror ("fclose of pipe");
+
+  do_wait (ldd_file_name);
+
+  signal (SIGINT,  int_handler);
+#ifdef SIGQUIT
+  signal (SIGQUIT, quit_handler);
+#endif
+
+  /* now iterate through the library list adding their symbols to
+     the list.  */
+  for (list = libraries.first; list; list = list->next)
+    scan_prog_file (list->name, PASS_LIB);
+}
+
+#endif /* LDD_SUFFIX */
+#endif /* SUNOS4_SHARED_LIBRARIES */
+
 #endif /* OBJECT_FORMAT_NONE */
 
 \f
index eb5db36f3d49342aff1f14822dc29c72f4d24687..a7d339b119cfca96762d67073336c9eb073aaf9b 100644 (file)
@@ -2019,5 +2019,8 @@ do {                                                      \
 
 /* The linker will stick __main into the .init section.  */
 #define HAS_INIT_SECTION
-#define INIT_NAME_FORMAT "__init_%s"
-#define FINI_NAME_FORMAT "__fini_%s"
+#define LD_INIT_SWITCH "-init"
+#define LD_FINI_SWITCH "-fini"
+
+/* We do want to link in libgcc when building shared libraries under OSF/1.  */
+#define LIBGCC_SPEC "-lgcc"
index 9f80162875cf533e3ab79a710f9c686acf4a337e..90deb5c2aab587ce54bd3757c9ea58fe49841acf 100644 (file)
@@ -31,6 +31,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    it knows what it is doing. */
 
 #define FORCE_INIT_SECTION_ALIGN do { asm (ALIGN_ASM_OP ## " 16"); } while (0)
+#define FORCE_FINI_SECTION_ALIGN FORCE_INIT_SECTION_ALIGN
 
 /* Add "sun" to the list of symbols defined for SVR4.  */
 #undef CPP_PREDEFINES
@@ -44,10 +45,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #undef LIB_SPEC
 #define LIB_SPEC \
-  "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
-   %{!shared:%{!symbolic:-lc}} \
-   crtend.o%s \
-   %{!shared:%{!symbolic:%{pg:crtn.o%s}%{!pg:crtn.o%s}}}"
+  "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s %{pg:crtn.o%s}%{!pg:crtn.o%s}"
 
 /* This should be the same as in svr4.h, except with -R added.  */
 #undef LINK_SPEC
@@ -55,8 +56,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
   "%{h*} %{V} %{v:%{!V:-V}} \
    %{b} %{Wl,*:%*} \
    %{static:-dn -Bstatic} \
-   %{shared:-G -dy} \
-   %{symbolic:-Bsymbolic -G -dy} \
+   %{shared:-G -dy -z text} \
+   %{symbolic:-Bsymbolic -G -dy -z text} \
    %{G:-G} \
    %{YP,*} \
    %{R*} \
index a669b7c69b02be84a3d38f6b6c353ea776f32533..eddad5d535e4079513a31f1ab4c6842f0685aca3 100644 (file)
@@ -22,3 +22,11 @@ crti.o: $(srcdir)/config/i386/sol2-ci.asm
 crtn.o: $(srcdir)/config/i386/sol2-cn.asm
        sed -e '/^!/d' <$(srcdir)/config/i386/sol2-cn.asm >crtn.s
        $(AS) -o crtn.o crtn.s
+
+# We need to use -fpic when we are using gcc to compile the routines in
+# crtstuff.c.  This is only really needed when we are going to use gcc/g++
+# to produce a shared library, but since we don't know ahead of time when
+# we will be doing that, we just always use -fpic when compiling the
+# routines in crtstuff.c.
+
+CRTSTUFF_T_CFLAGS = -fpic
index 3108a749147b6edf1733f11291cb7480dc0c6d16..189c20b55834fa4ddd150976ede4baf9f0751993 100644 (file)
@@ -148,10 +148,25 @@ extern char *current_function_original_name;
        fprintf (FILE, ":\n");                                          \
   } while (0)
 
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+   Note that we want to give these sections the SHF_WRITE attribute
+   because these sections will actually contain data (i.e. tables of
+   addresses of functions in the current root executable or shared library
+   file) and, in the case of a shared library, the relocatable addresses
+   will have to be properly resolved/relocated (and then written into) by
+   the dynamic linker when it actually attaches the given shared library
+   to the executing process.  (Note that on SVR4, you may wish to use the
+   `-z text' option to the ELF linker, when building a shared library, as
+   an additional check that you are doing everything right.  But if you do
+   use the `-z text' option when building a shared library, you will get
+   errors unless the .ctors and .dtors sections are marked as writable
+   via the SHF_WRITE attribute.)  */
 #undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"a\",\"progbits\""
+#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"aw\""
 #undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"a\",\"progbits\""
+#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"aw\""
 
 /* Add definitions to support the .tdesc section as specified in the svr4
    ABI for the i860.  */
index 9765cbee771abbf534f094deeefbfd51c1a06000..8cc0080bec69413b31f81d0ed3c4e944bd2c9535 100644 (file)
@@ -31,7 +31,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
   (TARGET_SVR4 ? DWARF_DEBUG : SDB_DEBUG)
 
 #ifndef VERSION_INFO2
-#define VERSION_INFO2   "$Revision: 1.14 $"
+#define VERSION_INFO2   "$Revision: 1.15 $"
 #endif
 #ifndef NO_BUGS
 #define AS_BUG_IMMEDIATE_LABEL
@@ -119,8 +119,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #undef LINK_SPEC
 #define LINK_SPEC "%{z*} %{h*} %{V} %{v:%{!V:-V}} \
                   %{static:-dn -Bstatic} \
-                  %{shared:-G -dy} \
-                  %{symbolic:-Bsymbolic -G -dy} \
+                  %{shared:-G -dy -z text} \
+                  %{symbolic:-Bsymbolic -G -dy -z text} \
                   %{pg:-L/usr/lib/libp}%{p:-L/usr/lib/libp}"
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt0.o%s} \
@@ -176,7 +176,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Override svr4.h and m88k.h except when compiling crtstuff.c.  These must
    be constant strings when compiling crtstuff.c.  Otherwise, respect the
    -mversion-STRING option used.  */
-#undef INIT_SECTION_PREAMBLE
 #undef INIT_SECTION_ASM_OP
 #undef FINI_SECTION_ASM_OP
 #undef CTORS_SECTION_ASM_OP
@@ -196,12 +195,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                              ? "section\t .dtors,\"aw\""       \
                              : "section\t .dtors,\"d\"")
 #else
-/* These must be constant strings for crtstuff.c.  
-   An elf and bcs crtbegin.o are needed since bcs does not  
-   increment the stack pointer in the init section as elf does */
-#ifndef BCS
-#define INIT_SECTION_PREAMBLE asm ("\taddu\tr31,r31,0x20")  
-#endif
+/* These must be constant strings for crtstuff.c.  */
 #define INIT_SECTION_ASM_OP    "section\t .init,\"x\""
 #define FINI_SECTION_ASM_OP    "section\t .fini,\"x\""
 #define CTORS_SECTION_ASM_OP   "section\t .ctors,\"d\""
index 428c2cf84a7e71d9d976e6908e073cf651215110..cb774a54cff491d359cfa6c8d878c6f7211cfd87 100644 (file)
@@ -60,7 +60,25 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Override svr4.h and m88k.h.  */
 #undef INIT_SECTION_ASM_OP
 #define INIT_SECTION_ASM_OP "section\t.init,\"xa\",#progbits"
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP "section\t.fini,\"xa\",#progbits"
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+   Note that we want to give these sections the SHF_WRITE attribute
+   because these sections will actually contain data (i.e. tables of
+   addresses of functions in the current root executable or shared library
+   file) and, in the case of a shared library, the relocatable addresses
+   will have to be properly resolved/relocated (and then written into) by
+   the dynamic linker when it actually attaches the given shared library
+   to the executing process.  (Note that on SVR4, you may wish to use the
+   `-z text' option to the ELF linker, when building a shared library, as
+   an additional check that you are doing everything right.  But if you do
+   use the `-z text' option when building a shared library, you will get
+   errors unless the .ctors and .dtors sections are marked as writable
+   via the SHF_WRITE attribute.)  */
 #undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP   "section\t.ctors,\"a\",#progbits"
+#define CTORS_SECTION_ASM_OP   "section\t.ctors,\"aw\""
 #undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP   "section\t.dtors,\"a\",#progbits"
+#define DTORS_SECTION_ASM_OP   "section\t.dtors,\"aw\""
index 419a9dbbac936c8ba7c7e446ba840eebe0b6cbca..6a77edb5669f8df24b26b839bb76abb2bf7a2d1b 100644 (file)
@@ -12,3 +12,11 @@ $(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh
 LIB2FUNCS_EXTRA = $(MOVE_ASM)
 LIBGCC1 = libgcc1.null
 CROSS_LIBGCC1 = libgcc1.null
+
+# We need to use -fpic when we are using gcc to compile the routines in
+# crtstuff.c.  This is only really needed when we are going to use gcc/g++
+# to produce a shared library, but since we don't know ahead of time when
+# we will be doing that, we just always use -fpic when compiling the
+# routines in crtstuff.c.
+
+CRTSTUFF_T_CFLAGS=-fpic
index 5b1987bdcab70c156a46e153da1539a39c5dc2ba..e1c40b1f3bf74a967f6c3df7f4faad2d2c87e4f0 100644 (file)
@@ -34,6 +34,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    options, but using this would require modifying how crtstuff works, and
    I will leave that for another time (or someone else).  */
 #define OBJECT_FORMAT_ELF
+#define HAS_INIT_SECTION
+#define LD_INIT_SWITCH "-init"
+#define LD_FINI_SWITCH "-fini"
 
 /* Specify wchar_t types.  */
 #undef WCHAR_TYPE
@@ -82,12 +85,20 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 %{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
 %{bestGnum} %{shared} %{non_shared} \
 %{call_shared} %{no_archive} %{exact_version} \
-%{!shared: %{!non_shared: \
+%{!shared: -u __main -init __main %{!non_shared: \
           %{!call_shared: -call_shared -no_unresolved}}} \
 -_SYSTYPE_SVR4"
 
+/* We now support shared libraries.  */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+  "%{!shared:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}}"
+
 #undef LIB_SPEC
-#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} -lc crtn.o%s"
+#define LIB_SPEC "%{!shared:%{p:-lprof1} %{pg:-lprof1} -lc}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{!shared:crtn.o%s}"
 
 /* We do not want to run mips-tfile!  */
 #undef ASM_FINAL_SPEC
index 66719e8726dbf4a0b6452bb13d4ca0c3d005b83d..10fa503d6b01b61ae08339487c553f1790723813 100644 (file)
@@ -36,13 +36,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define DEFAULT_GDB_EXTENSIONS 0
 
 /* Like the default, except no -lg.  */
-#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}"
+#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}}"
 
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)"
 
 #undef LINK_SPEC
-#define LINK_SPEC "-u main %{static: -a archive}%{g*: -a archive}"
+#define LINK_SPEC \
+  "%{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
 
 /* hpux8 and later have C++ compatable include files, so do not
    pretend they are `extern "C"'.  */
index ceef67d79e7f3a6f0ea27d2cbcb27caac4768a34..0c9a217a8e8c462de98e99953a1890cca1c1a019 100644 (file)
@@ -196,7 +196,7 @@ extern int target_flags;
 
 #define CC1_SPEC "%{pg:} %{p:}"
 
-#define LINK_SPEC "-u main"
+#define LINK_SPEC "%{!shared:-u main} %{shared:-b}"
 
 /* Allow $ in identifiers.  */
 #define DOLLARS_IN_IDENTIFIERS 2
@@ -214,6 +214,22 @@ extern int target_flags;
 /* Names to predefine in the preprocessor for this target machine.  */
 
 #define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -D_HPUX_SOURCE -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
+
+/* HPUX has a program 'chatr' to list the dependencies of dynamically
+   linked executables and shared libraries.  */
+#define LDD_SUFFIX "chatr"
+/* look for lines like "dynamic   /usr/lib/X11R5/libX11.sl".  */
+#define PARSE_LDD_OUTPUT(PTR)                                  \
+do {                                                           \
+  while (*PTR == ' ') PTR++;                                   \
+  if (strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0)   \
+    {                                                          \
+      PTR += sizeof ("dynamic") - 1;                           \
+      while (*p == ' ') PTR++;                                 \
+    }                                                          \
+  else                                                         \
+    PTR = 0;                                                   \
+} while (0)
 \f
 /* target machine storage layout */
 
index e6856bc284abd65885c80b1a82a9ace13db55fb4..0d05365ae4bd74813ce608a72bbc9e9357a8d72e 100644 (file)
@@ -102,13 +102,13 @@ do {                                                                      \
 #define STARTFILE_SPEC "%{!shared: \
                         %{!symbolic: \
                          %{pg:crt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} \
-                         %{pg:gmon.o%s} \
-                         %{pg:crti.o%s}%{!pg:crti.o%s} \
-                         %{ansi:/usr/ccs/lib/values-Xc.o%s} \
-                         %{!ansi: \
-                          %{traditional:/usr/ccs/lib/values-Xt.o%s} \
-                          %{!traditional:/usr/ccs/lib/values-Xa.o%s}}}} \
-                         crtbegin.o%s"
+                         %{pg:gmon.o%s}}} \
+                       %{pg:crti.o%s}%{!pg:crti.o%s} \
+                       %{ansi:/usr/ccs/lib/values-Xc.o%s} \
+                       %{!ansi: \
+                        %{traditional:/usr/ccs/lib/values-Xt.o%s} \
+                        %{!traditional:/usr/ccs/lib/values-Xa.o%s}} \
+                       crtbegin.o%s"
 
 /* ??? Note: in order for -compat-bsd to work fully,
    we must somehow arrange to fixincludes /usr/ucbinclude
@@ -116,10 +116,10 @@ do {                                                                      \
 
 #undef LIB_SPEC
 #define LIB_SPEC \
-  "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
-   %{!shared:%{!symbolic:-lc}} \
-   crtend.o%s \
-   %{!shared:%{!symbolic:%{pg:crtn.o%s}%{!pg:crtn.o%s}}}"
+  "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s %{pg:crtn.o%s}%{!pg:crtn.o%s}"
 
 /* This should be the same as in svr4.h, except with -R added.  */
 #undef LINK_SPEC
@@ -127,8 +127,8 @@ do {                                                                        \
   "%{h*} %{V} %{v:%{!V:-V}} \
    %{b} %{Wl,*:%*} \
    %{static:-dn -Bstatic} \
-   %{shared:-G -dy} \
-   %{symbolic:-Bsymbolic -G -dy} \
+   %{shared:-G -dy -z text} \
+   %{symbolic:-Bsymbolic -G -dy -z text} \
    %{G:-G} \
    %{YP,*} \
    %{R*} \
index 674bdd2b373c84cdb0ad605e01cde2d751abbab0..80bdec258359c9cdbd13b22d70a9ea7b633308f5 100644 (file)
@@ -60,12 +60,13 @@ extern enum arch_type sparc_arch_type;
    -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)"
 #endif
 
-#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}"
+#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
 
 /* Provide required defaults for linker -e and -d switches.  */
 
 #define LINK_SPEC \
- "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}"
+ "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
+  %{assert*} %{shared:-assert pure-text}"
 
 /* Special flags to the Sun-4 assembler when using pipe for input.  */
 
@@ -445,6 +446,15 @@ extern int target_flags;
    Put them in the data section.  This macro is only used in this file.  */
 #define MAX_TEXT_ALIGN 32
 
+/* This forces all variables and constants to the data section when PIC.
+   This is because the SunOS 4 shared library scheme thinks everything in
+   text is a function, and patches the address to point to a loader stub.  */
+/* This is defined to zero for every system which doesn't use the a.out object
+   file format.  */
+#ifndef SUNOS4_SHARED_LIBRARIES
+#define SUNOS4_SHARED_LIBRARIES 0
+#endif
+
 /* This is defined differently for v9 in a cover file.  */
 #define SELECT_SECTION(T,RELOC)                                                \
 {                                                                      \
@@ -455,20 +465,21 @@ extern int target_flags;
          && (DECL_INITIAL (T) == error_mark_node                       \
              || TREE_CONSTANT (DECL_INITIAL (T)))                      \
          && DECL_ALIGN (T) <= MAX_TEXT_ALIGN                           \
-         && ! (flag_pic && (RELOC)))                                   \
+         && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)))      \
        text_section ();                                                \
       else                                                             \
        data_section ();                                                \
     }                                                                  \
   else if (TREE_CODE (T) == CONSTRUCTOR)                               \
     {                                                                  \
-      if (flag_pic != 0 && (RELOC) != 0)                               \
+      if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))            \
        data_section ();                                                \
     }                                                                  \
   else if (*tree_code_type[(int) TREE_CODE (T)] == 'c')                        \
     {                                                                  \
       if ((TREE_CODE (T) == STRING_CST && flag_writable_strings)       \
-         || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN)               \
+         || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN                \
+         || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)))        \
        data_section ();                                                \
       else                                                             \
        text_section ();                                                \
@@ -481,7 +492,7 @@ extern int target_flags;
 #define SELECT_RTX_SECTION(MODE, X)            \
 {                                              \
   if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \
-      && ! (flag_pic && symbolic_operand (X)))  \
+      && ! (flag_pic && (symbolic_operand (X) || SUNOS4_SHARED_LIBRARIES)))  \
     text_section ();                           \
   else                                         \
     data_section ();                           \
index f81a4f736cf4582ee41ca4c1c28389cd7090cdfd..5a0f7a42429a5ac1627eebb04a42bca72beb2d86 100644 (file)
@@ -37,9 +37,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    appropriate only for typical svr4 systems, but not for the specific
    case of svr4 running on a Sparc.  */
 
-#undef CTORS_SECTION_ASM_OP
-#undef DTORS_SECTION_ASM_OP
 #undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
 #undef CONST_SECTION_ASM_OP
 #undef TYPE_OPERAND_FMT
 #undef PUSHSECTION_FORMAT
@@ -77,24 +76,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
     const_section ();                          \
 }
 
-/* The specialized code which needs to appear in the .init section prior
-   to the prologue code for `__do_global_ctors' (see crtstuff.c).
-
-   On Sparcs running svr4, the /usr/ccs/lib/crti.o file (with gets linked
-   in prior to the crtbegin.o file) has a single `save' instruction in its
-   .init section.  That `save' instruction tries to setup a stack frame for
-   the sake of any subsequent code in the .init section.  Unfortunately,
-   the size it uses for the stack frame is only a guess, and is not really
-   adequate for our purposes.  More importantly, we independently put our
-   own standard function prologue (for __do_global_ctors) into the .init
-   section and that function prologue includes its own `save' instruction!
-   Thus, unless we do something to correct the situation, we'll get *two*
-   stack frames allocated when crt0.o calls the code in the .init section,
-   and havoc will ensue.  The following macro definition prevents such woes.
-*/
-
-#define INIT_SECTION_PREAMBLE  asm ("restore")
-
 /* This is the string used to begin an assembly language comment for the
    Sparc/svr4 assembler.  */
 
@@ -172,8 +153,27 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3);           \
 #define BSS_SECTION_ASM_OP     ".section\t\".bss\""
 #define CONST_SECTION_ASM_OP   ".section\t\".rodata\""
 #define INIT_SECTION_ASM_OP    ".section\t\".init\""
-#define CTORS_SECTION_ASM_OP    ".section\t\".ctors\",#alloc,#execinstr"
-#define DTORS_SECTION_ASM_OP    ".section\t\".dtors\",#alloc,#execinstr"
+#define FINI_SECTION_ASM_OP    ".section\t\".fini\""
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+   Note that we want to give these sections the SHF_WRITE attribute
+   because these sections will actually contain data (i.e. tables of
+   addresses of functions in the current root executable or shared library
+   file) and, in the case of a shared library, the relocatable addresses
+   will have to be properly resolved/relocated (and then written into) by
+   the dynamic linker when it actually attaches the given shared library
+   to the executing process.  (Note that on SVR4, you may wish to use the
+   `-z text' option to the ELF linker, when building a shared library, as
+   an additional check that you are doing everything right.  But if you do
+   use the `-z text' option when building a shared library, you will get
+   errors unless the .ctors and .dtors sections are marked as writable
+   via the SHF_WRITE attribute.)  */
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP    ".section\t\".ctors\",#alloc,#write"
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP    ".section\t\".dtors\",#alloc,#write"
 
 /* A C statement to output something to the assembler file to switch to section
    NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
index 9f79b1f2ab3fdfb28a160b9880292035514704c7..1160c879f860d6c89226e4e93a52d39055152ce1 100644 (file)
@@ -16,3 +16,11 @@ crti.o: $(srcdir)/config/sparc/sol2-ci.asm
        $(AS) -o crti.o $(srcdir)/config/sparc/sol2-ci.asm
 crtn.o: $(srcdir)/config/sparc/sol2-cn.asm
        $(AS) -o crtn.o $(srcdir)/config/sparc/sol2-cn.asm
+
+# We need to use -fpic when we are using gcc to compile the routines in
+# crtstuff.c.  This is only really needed when we are going to use gcc/g++
+# to produce a shared library, but since we don't know ahead of time when
+# we will be doing that, we just always use -fpic when compiling the
+# routines in crtstuff.c.
+
+CRTSTUFF_T_CFLAGS = -fpic
index 663ff4bcbbb1bc5c746bcf8903e9d5b0fdcf344e..5b4011609d7334127d746b2b538f680c2388c122 100644 (file)
@@ -122,17 +122,25 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 #define MD_STARTFILE_PREFIX "/usr/ccs/lib/"
 
 /* Provide a LIB_SPEC appropriate for svr4.  Here we tack on the default
-   standard C library (unless we are building a shared library) followed by
-   our own magical crtend.o file (see crtstuff.c) which provides part of
-   the support for getting C++ file-scope static object constructed before
+   standard C library (unless we are building a shared library).  */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}"
+
+/* Provide a LIBGCC_SPEC appropriate for svr4.  We also want to exclude
+   libgcc when -symbolic.  */
+
+#undef  LIBGCC_SPEC
+#define LIBGCC_SPEC "%{!shared:%{!symbolic:-lgcc}}"
+
+/* Provide an ENDFILE_SPEC appropriate for svr4.  Here we tack on our own
+   magical crtend.o file (see crtstuff.c) which provides part of the
+   support for getting C++ file-scope static object constructed before
    entering `main', followed by the normal svr3/svr4 "finalizer" file,
    which is either `gcrtn.o' or `crtn.o'.  */
 
-#undef LIB_SPEC
-#define LIB_SPEC \
-  "%{!shared:%{!symbolic:-lc}} \
-  crtend.o%s \
-  %{!shared:%{!symbolic:%{pg:gcrtn.o}%{!pg:crtn.o%s}}}"
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}"
 
 /* Provide a LINK_SPEC appropriate for svr4.  Here we provide support
    for the special GCC options -static, -shared, and -symbolic which
@@ -161,8 +169,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 #define LINK_SPEC "%{h*} %{V} %{v:%{!V:-V}} \
                   %{b} %{Wl,*:%*} \
                   %{static:-dn -Bstatic} \
-                  %{shared:-G -dy} \
-                  %{symbolic:-Bsymbolic -G -dy} \
+                  %{shared:-G -dy -z text} \
+                  %{symbolic:-Bsymbolic -G -dy -z text} \
                   %{G:-G} \
                   %{YP,*} \
                   %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
@@ -184,12 +192,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{!shared: \
                         %{!symbolic: \
-                         %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} \
-                         %{pg:gcrti.o%s}%{!pg:crti.o%s} \
-                         %{ansi:values-Xc.o%s} \
-                         %{!ansi: \
-                          %{traditional:values-Xt.o%s} \
-                          %{!traditional:values-Xa.o%s}}}} crtbegin.o%s"
+                         %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\
+                       %{pg:gcrti.o%s}%{!pg:crti.o%s} \
+                       %{ansi:values-Xc.o%s} \
+                       %{!ansi: \
+                        %{traditional:values-Xt.o%s} \
+                        %{!traditional:values-Xa.o%s}} \
+                       crtbegin.o%s"
 
 /* Attach a special .ident directive to the end of the file to identify
    the version of GCC which compiled this code.  The format of the
@@ -468,16 +477,33 @@ do {                                                                      \
 #define USE_CONST_SECTION      1
 
 #define CONST_SECTION_ASM_OP   ".section\t.rodata"
-#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"a\",@progbits"
-#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"a\",@progbits"
 
-/* On svr4, we *do* have support for the .init section, and we can put
-   stuff in there to be executed before `main'.  We let crtstuff.c and
-   other files know this by defining the following symbol.  The definition
-   says how to change sections to the .init section.  This is the same
-   for all know svr4 assemblers.  */
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+
+   Note that we want to give these sections the SHF_WRITE attribute
+   because these sections will actually contain data (i.e. tables of
+   addresses of functions in the current root executable or shared library
+   file) and, in the case of a shared library, the relocatable addresses
+   will have to be properly resolved/relocated (and then written into) by
+   the dynamic linker when it actually attaches the given shared library
+   to the executing process.  (Note that on SVR4, you may wish to use the
+   `-z text' option to the ELF linker, when building a shared library, as
+   an additional check that you are doing everything right.  But if you do
+   use the `-z text' option when building a shared library, you will get
+   errors unless the .ctors and .dtors sections are marked as writable
+   via the SHF_WRITE attribute.)  */
+
+#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"aw\""
+#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"aw\""
+
+/* On svr4, we *do* have support for the .init and .fini sections, and we
+   can put stuff in there to be executed before and after `main'.  We let
+   crtstuff.c and other files know this by defining the following symbols.
+   The definitions say how to change sections to the .init and .fini
+   sections.  This is the same for all known svr4 assemblers.  */
 
 #define INIT_SECTION_ASM_OP    ".section\t.init"
+#define FINI_SECTION_ASM_OP    ".section\t.fini"
 
 /* A default list of other sections which we might be "in" at any given
    time.  For targets that use additional sections (e.g. .tdesc) you
@@ -844,3 +870,6 @@ do {                                                                         \
         fprintf ((FILE), "\"\n");                                      \
     }                                                                  \
   while (0)
+
+/* All SVR4 targets use the ELF object file format.  */
+#define OBJECT_FORMAT_ELF
index 9560d905521130f1d8bb8df4620203ac6e2f817f..f060a9d2ec5808056813d691198675a206bf33ac 100644 (file)
@@ -2,3 +2,11 @@
 # end labels to the .ctors and .dtors section when we link using gcc.
 
 EXTRA_PARTS=crtbegin.o crtend.o
+
+# We need to use -fpic when we are using gcc to compile the routines in
+# crtstuff.c.  This is only really needed when we are going to use gcc/g++
+# to produce a shared library, but since we don't know ahead of time when
+# we will be doing that, we just always use -fpic when compiling the
+# routines in crtstuff.c.
+
+CRTSTUFF_T_CFLAGS = -fpic
index dcfd8199b6d183b95b2444c7ecd83d24f2973015..bf1ddb48259a2b82516951cd9f85f1f628c3e24c 100644 (file)
@@ -54,23 +54,89 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "tm.h"
 
+/* Provide default definitions for the pseudo-ops used to switch to the
+   .ctors and .dtors sections.
+   Note that we want to give these sections the SHF_WRITE attribute
+   because these sections will actually contain data (i.e. tables of
+   addresses of functions in the current root executable or shared library
+   file) and, in the case of a shared library, the relocatable addresses
+   will have to be properly resolved/relocated (and then written into) by
+   the dynamic linker when it actually attaches the given shared library
+   to the executing process.  (Note that on SVR4, you may wish to use the
+   `-z text' option to the ELF linker, when building a shared library, as
+   an additional check that you are doing everything right.  But if you do
+   use the `-z text' option when building a shared library, you will get
+   errors unless the .ctors and .dtors sections are marked as writable
+   via the SHF_WRITE attribute.)  */
+
 #ifndef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"a\",@progbits"
+#define CTORS_SECTION_ASM_OP   ".section\t.ctors,\"aw\""
 #endif
 #ifndef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"a\",@progbits"
+#define DTORS_SECTION_ASM_OP   ".section\t.dtors,\"aw\""
 #endif
 
+#ifdef OBJECT_FORMAT_ELF
+
+/*  Declare a pointer to void function type.  */
+typedef void (*func_ptr) (void);
+#define STATIC static
+
+#else  /* OBJECT_FORMAT_ELF */
+
 #include "gbl-ctors.h"
 
 #ifndef ON_EXIT
 #define ON_EXIT(a, b)
 #endif
+#define STATIC
+
+#endif /* OBJECT_FORMAT_ELF */
 
 #ifdef CRT_BEGIN
 
 #ifdef INIT_SECTION_ASM_OP
 
+#ifdef OBJECT_FORMAT_ELF
+
+/* Run all the global destructors on exit from the program.  */
+/* Some systems place the number of pointers in the first word of the
+   table.  On SVR4 however, that word is -1.  In all cases, the table is
+   null-terminated.  On SVR4, we start from the beginning of the list and
+   invoke each per-compilation-unit destructor routine in order
+   until we find that null.
+
+   Note that this function MUST be static.  There will be one of these
+   functions in each root executable and one in each shared library, but
+   although they all have the same code, each one is unique in that it
+   refers to one particular associated `__DTOR_LIST__' which belongs to the
+   same particular root executable or shared library file.  */
+
+static func_ptr __DTOR_LIST__[];
+static void
+__do_global_dtors_aux ()
+{
+  func_ptr *p;
+  for (p = __DTOR_LIST__ + 1; *p; p++)
+    (*p) ();
+}
+
+/* Stick a call to __do_global_dtors_aux into the .fini section.  */
+static void
+fini_dummy ()
+{
+  asm (FINI_SECTION_ASM_OP);
+  __do_global_dtors_aux ();
+#ifdef FORCE_FINI_SECTION_ALIGN
+  FORCE_FINI_SECTION_ALIGN;
+#endif
+  asm (TEXT_SECTION_ASM_OP);
+}
+
+#else  /* OBJECT_FORMAT_ELF */
+
 /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
    and once in crtend.o).  It must be declared static to avoid a link
    error.  Here, we define __do_global_ctors as an externally callable
@@ -92,16 +158,6 @@ void __do_global_ctors ()
 
 asm (INIT_SECTION_ASM_OP);     /* cc1 doesn't know that we are switching! */
 
-/* On some svr4 systems, the .init section preamble code provided in
-   crti.o may do some evil things which we have to undo before we reach
-   the function prologue code for __do_global_ctors (directly below).
-   For such systems, define the macro INIT_SECTION_PREAMBLE to
-   expand into the code needed to undo the actions of the crti.o file.  */
-   
-#ifdef INIT_SECTION_PREAMBLE
-  INIT_SECTION_PREAMBLE;
-#endif
-
 /* A routine to invoke all of the global constructors upon entry to the
    program.  We put this into the .init section (for systems that have
    such a thing) so that we can properly perform the construction of
@@ -118,25 +174,38 @@ __do_global_ctors_aux ()  /* prologue goes in .init section */
   ON_EXIT (__do_global_dtors, 0);
 }
 
+#endif /* OBJECT_FORMAT_ELF */
 #endif /* defined(INIT_SECTION_ASM_OP) */
 
 /* Force cc1 to switch to .data section.  */
 static func_ptr force_to_data[0] = { };
 
+/* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
+   to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
+   __DTOR_END__ } per root executable and also one set of these symbols
+   per shared library.  So in any given whole process image, we may have
+   multiple definitions of each of these symbols.  In order to prevent
+   these definitions from conflicting with one another, and in order to
+   ensure that the proper lists are used for the initialization/finalization
+   of each individual shared library (respectively), we give these symbols
+   only internal (i.e. `static') linkage, and we also make it a point to
+   refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
+   symbol in crtbegin.o, where they are defined.  */
+
 /* The -1 is a flag to __do_global_[cd]tors
    indicating that this table does not start with a count of elements.  */
 #ifdef CTOR_LIST_BEGIN
 CTOR_LIST_BEGIN;
 #else
 asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
-func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
+STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) };
 #endif
 
 #ifdef DTOR_LIST_BEGIN
 DTOR_LIST_BEGIN;
 #else
 asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
-func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
+STATIC func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
 #endif
 
 #endif /* defined(CRT_BEGIN) */
@@ -145,17 +214,51 @@ func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
 
 #ifdef INIT_SECTION_ASM_OP
 
-/* A routine to invoke all of the global constructors upon entry to the
-   program.  We put this into the .init section (for systems that have
-   such a thing) so that we can properly perform the construction of
-   file-scope static-storage C++ objects within shared libraries.
+#ifdef OBJECT_FORMAT_ELF
 
-   This must be virtually identical to the one above so that we can
-   insure that the function prologue from the one above works correctly
-   with the epilogue from this one.  (They will both go into the .init
-   section as the first and last things (respectively) that the linker
-   will put in that section.)
-*/
+static func_ptr __CTOR_END__[];
+static void
+__do_global_ctors_aux ()
+{
+  func_ptr *p;
+  for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+    (*p) ();
+}
+
+/* Stick a call to __do_global_ctors_aux into the .init section.  */
+static void
+init_dummy ()
+{
+  asm (INIT_SECTION_ASM_OP);
+  __do_global_ctors_aux ();
+#ifdef FORCE_INIT_SECTION_ALIGN
+  FORCE_INIT_SECTION_ALIGN;
+#endif
+  asm (TEXT_SECTION_ASM_OP);
+}
+
+#else  /* OBJECT_FORMAT_ELF */
+
+/* Stick the real initialization code, followed by a normal sort of
+   function epilogue at the very end of the .init section for this
+   entire root executable file or for this entire shared library file.
+
+   Note that we use some tricks here to get *just* the body and just
+   a function epilogue (but no function prologue) into the .init
+   section of the crtend.o file.  Sepcifically, we switch to the .text
+   section, start to define a function, and then we switch to the .init
+   section just before the body code.
+
+   Earlier on, we put the corresponding function prologue into the .init
+   section of the crtbegin.o file (which will be linked in first).
+
+   Note that we want to invoke all constructors for C++ file-scope static-
+   storage objects AFTER any other possible initialization actions which
+   may be performed by the code in the .init section contributions made by
+   other libraries, etc.  That's because those other initializations may
+   include setup operations for very primitive things (e.g. initializing
+   the state of the floating-point coprocessor, etc.) which should be done
+   before we start to execute any of the user's code. */
 
 static void
 __do_global_ctors_aux ()       /* prologue goes in .text section */
@@ -165,23 +268,31 @@ __do_global_ctors_aux ()  /* prologue goes in .text section */
   ON_EXIT (__do_global_dtors, 0);
 }                              /* epilogue and body go in .init section */
 
+#endif /* OBJECT_FORMAT_ELF */
+
 #endif /* defined(INIT_SECTION_ASM_OP) */
 
 /* Force cc1 to switch to .data section.  */
 static func_ptr force_to_data[0] = { };
 
+/* Put a word containing zero at the end of each of our two lists of function
+   addresses.  Note that the words defined here go into the .ctors and .dtors
+   sections of the crtend.o file, and since that file is always linked in
+   last, these words naturally end up at the very ends of the two lists
+   contained in these two sections.  */
+
 #ifdef CTOR_LIST_END
 CTOR_LIST_END;
 #else
 asm (CTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
-func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
+STATIC func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
 #endif
 
 #ifdef DTOR_LIST_END
 DTOR_LIST_END;
 #else
 asm (DTORS_SECTION_ASM_OP);    /* cc1 doesn't know that we are switching! */
-func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
+STATIC func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
 #endif
 
 #endif /* defined(CRT_END) */
index 4f9e2c05bfa2b7b2c1649f3333a011568aec1ee4..79ea18563d6b298ee8066c249ca1414366b98b39 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -362,6 +362,7 @@ or with constant text in a single argument.
        If multilib_dir is set, extra entries are generated with it affixed.
  %l     process LINK_SPEC as a spec.
  %L     process LIB_SPEC as a spec.
+ %G     process LIBGCC_SPEC as a spec.
  %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
  %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
  %c    process SIGNED_CHAR_SPEC as a spec.
@@ -458,7 +459,18 @@ proper position among the other output files.  */
 
 /* config.h can define LIB_SPEC to override the default libraries.  */
 #ifndef LIB_SPEC
-#define LIB_SPEC "%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+#endif
+
+/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
+   included.  */
+#ifndef LIBGCC_SPEC
+#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
+/* Have gcc do the search for libgcc.a.  */
+#define LIBGCC_SPEC "%{!shared:libgcc.a%s}"
+#else
+#define LIBGCC_SPEC "%{!shared:-lgcc}"
+#endif
 #endif
 
 /* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
@@ -505,6 +517,7 @@ static char *asm_spec = ASM_SPEC;
 static char *asm_final_spec = ASM_FINAL_SPEC;
 static char *link_spec = LINK_SPEC;
 static char *lib_spec = LIB_SPEC;
+static char *libgcc_spec = LIBGCC_SPEC;
 static char *endfile_spec = ENDFILE_SPEC;
 static char *startfile_spec = STARTFILE_SPEC;
 static char *switches_need_spaces = SWITCHES_NEED_SPACES;
@@ -728,32 +741,22 @@ static int n_default_compilers
 /* We want %{T*} after %{L*} and %D so that it can be used to specify linker
    scripts which exist in user specified directories, or in standard
    directories.  */
-#ifdef LINK_LIBGCC_SPECIAL_1
-/* Have gcc do the search for libgcc.a, but generate -L options as usual.  */
-static char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
-                       %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
-                       %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
-                       %{L*} %D %{T*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}}";
-#else
 #ifdef LINK_LIBGCC_SPECIAL
-/* Have gcc do the search for libgcc.a, and don't generate -L options.  */
+/* Don't generate -L options.  */
 static char *link_command_spec = "\
 %{!fsyntax-only: \
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
-                       %{L*} %{T*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}}";
+                       %{L*} %{T*} %o %{!nostdlib:%G %L %G %{!A:%E}}\n }}}}}}";
 #else
-/* Use -L and have the linker do the search for -lgcc.  */
+/* Use -L.  */
 static char *link_command_spec = "\
 %{!fsyntax-only: \
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
-                       %{L*} %D %{T*} %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}}";
-#endif
+                       %{L*} %D %{T*} %o %{!nostdlib:%G %L %G %{!A:%E}}\n }}}}}}";
 #endif
 
 /* A vector of options to give to the linker.
@@ -1229,6 +1232,8 @@ set_spec (name, spec)
     endfile_spec = sl->spec;
   else if (! strcmp (name, "lib"))
     lib_spec = sl->spec;
+  else if (! strcmp (name, "libgcc"))
+    libgcc_spec = sl->spec;
   else if (! strcmp (name, "link"))
     link_spec = sl->spec;
   else if (! strcmp (name, "predefines"))
@@ -2490,6 +2495,7 @@ process_command (argc, argv)
          printf ("*endfile:\n%s\n\n", endfile_spec);
          printf ("*link:\n%s\n\n", link_spec);
          printf ("*lib:\n%s\n\n", lib_spec);
+         printf ("*libgcc:\n%s\n\n", libgcc_spec);
          printf ("*startfile:\n%s\n\n", startfile_spec);
          printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces);
          printf ("*signed_char:\n%s\n\n", signed_char_spec);
@@ -3504,6 +3510,12 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              return value;
            break;
 
+         case 'G':
+           value = do_spec_1 (libgcc_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
+           break;
+
          case 'p':
            {
              char *x = (char *) alloca (strlen (cpp_predefines) + 1);
@@ -4872,6 +4884,12 @@ validate_all_switches ()
       /* We have a switch spec.  */
       validate_switches (p + 1);
 
+  p = libgcc_spec;
+  while (c = *p++)
+    if (c == '%' && *p == '{')
+      /* We have a switch spec.  */
+      validate_switches (p + 1);
+
   p = startfile_spec;
   while (c = *p++)
     if (c == '%' && *p == '{')
index 247b8350d422b4fd44f99da9b24ab5f39c839491..44b4de5982cb43c31e7c5857845d9a0dabf94464 100644 (file)
@@ -1996,6 +1996,7 @@ __enable_execute_stack ()
 #define SYMBOL__MAIN __main
 #endif
 
+#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
 /* Run all the global destructors on exit from the program.  */
 
 void
@@ -2009,6 +2010,7 @@ __do_global_dtors ()
     (*p++) ();
 #endif
 }
+#endif
 
 #ifndef INIT_SECTION_ASM_OP
 /* Run all the global constructors on entry to the program.  */
@@ -2112,41 +2114,6 @@ int _exit_dummy_decl = 0;        /* prevent compiler & linker warnings */
 
 #endif /* L_exit */
 \f
-/* In a.out systems, we need to have these dummy constructor and destructor
-   lists in the library.
-
-   When using `collect', the first link will resolve __CTOR_LIST__
-   and __DTOR_LIST__ to these symbols.  We will then run "nm" on the
-   result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
-   Since we don't do the second link if no constructors existed, these
-   dummies must be fully functional empty lists.
-
-   When using `gnu ld', these symbols will be used if there are no
-   constructors.  If there are constructors, the N_SETV symbol defined
-   by the linker from the N_SETT's in input files will define __CTOR_LIST__
-   and __DTOR_LIST__ rather than its being allocated as common storage
-   by the definitions below.
-
-   When using a linker that supports constructor and destructor segments,
-   these definitions will not be used, since crtbegin.o and crtend.o
-   (from crtstuff.c) will have already defined __CTOR_LIST__ and
-    __DTOR_LIST__.  The crt*.o files are passed directly to the linker
-   on its command line, by gcc.  */
-
-/* The list needs two elements:  one is ignored (the old count); the
-   second is the terminating zero.  Since both values are zero, this
-   declaration is not initialized, and it becomes `common'.  */
-
-#ifdef L_ctor_list
-#include "gbl-ctors.h"
-func_ptr __CTOR_LIST__[2];
-#endif
-
-#ifdef L_dtor_list
-#include "gbl-ctors.h"
-func_ptr __DTOR_LIST__[2];
-#endif
-\f
 #ifdef L_eh
 typedef struct {
   void *start;