From 68d69835acdbeb2a30bb3338013e55afda1aca4d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 19 Nov 1994 04:09:58 +0000 Subject: [PATCH] Shared library support. From-SVN: r8519 --- gcc/Makefile.in | 11 +- gcc/collect2.c | 565 ++++++++++++++++++++++++++++++++++++++- gcc/config/alpha/alpha.h | 7 +- gcc/config/i386/sol2.h | 13 +- gcc/config/i386/t-sol2 | 8 + gcc/config/i860/sysv4.h | 19 +- gcc/config/m88k/dgux.h | 14 +- gcc/config/m88k/sysv4.h | 22 +- gcc/config/m88k/t-sysv4 | 8 + gcc/config/mips/iris5.h | 15 +- gcc/config/pa/pa-hpux.h | 5 +- gcc/config/pa/pa.h | 18 +- gcc/config/sparc/sol2.h | 26 +- gcc/config/sparc/sparc.h | 23 +- gcc/config/sparc/sysv4.h | 44 +-- gcc/config/sparc/t-sol2 | 8 + gcc/config/svr4.h | 75 ++++-- gcc/config/t-svr4 | 8 + gcc/crtstuff.c | 163 +++++++++-- gcc/gcc.c | 48 ++-- gcc/libgcc2.c | 37 +-- 21 files changed, 955 insertions(+), 182 deletions(-) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 7e9231f7276..eb8794da568 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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 # Compiling object files from source files. diff --git a/gcc/collect2.c b/gcc/collect2.c index 356bad03b3e..e46b9fa6c7b 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -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 /* 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; /* .c for constructor/destructor list. */ static char *o_file; /* .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); +} #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 +#include +#include +#include +#include +#include + +/* pointers to the object file */ +unsigned object; /* address of memory mapped file */ +unsigned objsize; /* size of memory mapped to file */ +char * code; /* pointer to code segment */ +char * data; /* pointer to data segment */ +struct nlist *symtab; /* pointer to symbol table */ +struct link_dynamic *ld; +struct link_dynamic_2 *ld_2; +struct head libraries; + +/* Map the file indicated by NAME into memory and store its address. */ + +static void +mapfile (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 */ diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index eb5db36f3d4..a7d339b119c 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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" diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h index 9f80162875c..90deb5c2aab 100644 --- a/gcc/config/i386/sol2.h +++ b/gcc/config/i386/sol2.h @@ -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*} \ diff --git a/gcc/config/i386/t-sol2 b/gcc/config/i386/t-sol2 index a669b7c69b0..eddad5d535e 100644 --- a/gcc/config/i386/t-sol2 +++ b/gcc/config/i386/t-sol2 @@ -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 diff --git a/gcc/config/i860/sysv4.h b/gcc/config/i860/sysv4.h index 3108a749147..189c20b5583 100644 --- a/gcc/config/i860/sysv4.h +++ b/gcc/config/i860/sysv4.h @@ -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. */ diff --git a/gcc/config/m88k/dgux.h b/gcc/config/m88k/dgux.h index 9765cbee771..8cc0080bec6 100644 --- a/gcc/config/m88k/dgux.h +++ b/gcc/config/m88k/dgux.h @@ -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\"" diff --git a/gcc/config/m88k/sysv4.h b/gcc/config/m88k/sysv4.h index 428c2cf84a7..cb774a54cff 100644 --- a/gcc/config/m88k/sysv4.h +++ b/gcc/config/m88k/sysv4.h @@ -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\"" diff --git a/gcc/config/m88k/t-sysv4 b/gcc/config/m88k/t-sysv4 index 419a9dbbac9..6a77edb5669 100644 --- a/gcc/config/m88k/t-sysv4 +++ b/gcc/config/m88k/t-sysv4 @@ -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 diff --git a/gcc/config/mips/iris5.h b/gcc/config/mips/iris5.h index 5b1987bdcab..e1c40b1f3bf 100644 --- a/gcc/config/mips/iris5.h +++ b/gcc/config/mips/iris5.h @@ -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 diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h index 66719e8726d..10fa503d6b0 100644 --- a/gcc/config/pa/pa-hpux.h +++ b/gcc/config/pa/pa-hpux.h @@ -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"'. */ diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index ceef67d79e7..0c9a217a8e8 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -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) /* target machine storage layout */ diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index e6856bc284a..0d05365ae4b 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -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*} \ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 674bdd2b373..80bdec25835 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -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 (); \ diff --git a/gcc/config/sparc/sysv4.h b/gcc/config/sparc/sysv4.h index f81a4f736cf..5a0f7a42429 100644 --- a/gcc/config/sparc/sysv4.h +++ b/gcc/config/sparc/sysv4.h @@ -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 diff --git a/gcc/config/sparc/t-sol2 b/gcc/config/sparc/t-sol2 index 9f79b1f2ab3..1160c879f86 100644 --- a/gcc/config/sparc/t-sol2 +++ b/gcc/config/sparc/t-sol2 @@ -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 diff --git a/gcc/config/svr4.h b/gcc/config/svr4.h index 663ff4bcbbb..5b4011609d7 100644 --- a/gcc/config/svr4.h +++ b/gcc/config/svr4.h @@ -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 diff --git a/gcc/config/t-svr4 b/gcc/config/t-svr4 index 9560d905521..f060a9d2ec5 100644 --- a/gcc/config/t-svr4 +++ b/gcc/config/t-svr4 @@ -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 diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c index dcfd8199b6d..bf1ddb48259 100644 --- a/gcc/crtstuff.c +++ b/gcc/crtstuff.c @@ -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) */ diff --git a/gcc/gcc.c b/gcc/gcc.c index 4f9e2c05bfa..79ea18563d6 100644 --- 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 == '{') diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 247b8350d42..44b4de5982c 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -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 */ -/* 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 - #ifdef L_eh typedef struct { void *start; -- 2.30.2