aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1992-03-19 22:07:22 +0000
committerRichard Stallman <rms@gnu.org>1992-03-19 22:07:22 +0000
commited5b94621848199bd322de0756c7b199c5a00488 (patch)
tree120bc653764a48a350a2dcfe16cb4454eae3a103 /gcc
parentfd9c4f832dd093fb716b130f217406c23984bed3 (diff)
downloadgcc-ed5b94621848199bd322de0756c7b199c5a00488.zip
gcc-ed5b94621848199bd322de0756c7b199c5a00488.tar.gz
gcc-ed5b94621848199bd322de0756c7b199c5a00488.tar.bz2
*** empty log message ***
From-SVN: r529
Diffstat (limited to 'gcc')
-rw-r--r--gcc/collect2.c612
1 files changed, 417 insertions, 195 deletions
diff --git a/gcc/collect2.c b/gcc/collect2.c
index 814db0b..320ac7d 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -29,15 +29,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
-#include <stdlib.h>
#include <ctype.h>
-#include "gstddef.h"
#include <errno.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#ifndef errno
+extern int errno;
+#endif
+
#define COLLECT
#include "config.h"
@@ -45,15 +47,72 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __STDC__
#include "gvarargs.h"
#define generic char
-#define PROTO(x) ()
#define const
#else
-#include "stdarg.h"
+#include "gstdarg.h"
#define generic void
-#define PROTO(x) x
#endif
+#ifdef USG
+#define vfork fork
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+/* On MSDOS, write temp files in current dir
+ because there's no place else we can expect to use. */
+#if __MSDOS__
+#ifndef P_tmpdir
+#define P_tmpdir "./"
+#endif
+#endif
+
+/* On certain systems, we have code that works by scanning the object file
+ directly. But this code uses system-specific header files and library
+ functions, so turn it off in a cross-compiler. */
+
+#ifdef CROSS_COMPILE
+#undef OBJECT_FORMAT_COFF
+#undef OBJECT_FORMAT_ROSE
+#endif
+
+/* If we can't use a special method, use the ordinary one:
+ run nm to find what symbols are present.
+ In a cross-compiler, this means you need a cross nm,
+ but that isn't quite as unpleasant as special headers. */
+
+#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
+#define OBJECT_FORMAT_NONE
+#endif
+
+#ifdef OBJECT_FORMAT_COFF
+
+#include <a.out.h>
+#include <ar.h>
+
+#ifdef UMAX
+#include <sgs.h>
+#endif
+
+#ifdef _AIX
+#define ISCOFF(magic) \
+ ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC)
+#endif
+
+#if defined (_AIX) || defined (USG)
+#undef FREAD
+#undef FWRITE
+#endif
+
+#include <ldfcn.h>
+
+#endif /* OBJECT_FORMAT_COFF */
+
#ifdef OBJECT_FORMAT_ROSE
#ifdef _OSF_SOURCE
@@ -69,25 +128,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mach_o_header.h>
#include <mach_o_vals.h>
#include <mach_o_types.h>
+
#endif /* OBJECT_FORMAT_ROSE */
+#ifdef OBJECT_FORMAT_NONE
+
/* Default flags to pass to nm. */
#ifndef NM_FLAGS
#define NM_FLAGS "-p"
#endif
-#ifdef USG
-#define vfork fork
-#endif
-
-/* On MSDOS, write temp files in current dir
- because there's no place else we can expect to use. */
-#if __MSDOS__
-#ifndef P_tmpdir
-#define P_tmpdir "./"
-#endif
-#endif
-
+#endif /* OBJECT_FORMAT_NONE */
/* Linked lists of constructor and destructor names. */
@@ -112,7 +163,9 @@ enum pass {
PASS_SECOND /* with constructors linked in */
};
+#ifndef NO_SYS_SIGLIST
extern char *sys_siglist[];
+#endif
extern char *version_string;
static int vflag; /* true if -v */
@@ -129,27 +182,27 @@ static char *nm_file_name; /* pathname of nm */
static struct head constructors; /* list of constructors found */
static struct head destructors; /* list of destructors found */
-extern char *getenv PROTO(( const char * ));
-extern char *mktemp PROTO(( char * ));
-extern int vfork PROTO(( void ));
-static void add_to_list PROTO(( struct head *headp, char *name ));
-static void scan_prog_file PROTO(( char *, enum pass ));
-static void fork_execute PROTO(( char *, char **argv ));
-static void do_wait PROTO(( char * ));
-static void write_c_file PROTO(( FILE *, char * ));
-static void my_exit PROTO(( int ));
-static void handler PROTO(( int ));
-static void maybe_unlink PROTO(( char * ));
-static void choose_temp_base PROTO(( void ));
-
-generic *xcalloc PROTO(( size_t, size_t ));
-generic *xmalloc PROTO(( size_t ));
-
+extern char *getenv ();
+extern char *mktemp ();
+extern int vfork ();
+static void add_to_list ();
+static void scan_prog_file ();
+static void fork_execute ();
+static void do_wait ();
+static void write_c_file ();
+static void my_exit ();
+static void handler ();
+static void maybe_unlink ();
+static void choose_temp_base ();
+
+generic *xcalloc ();
+generic *xmalloc ();
#if !defined(HAVE_STRERROR) && !defined(_OSF_SOURCE)
-char *strerror (e)
+char *
+strerror (e)
int e;
{
extern char *sys_errlist[];
@@ -175,10 +228,10 @@ static void
my_exit (status)
int status;
{
- if (c_file[0])
+ if (c_file != 0 && c_file[0])
maybe_unlink (c_file);
- if (o_file[0])
+ if (o_file != 0 && o_file[0])
maybe_unlink (o_file);
exit (status);
@@ -309,17 +362,15 @@ handler (signo)
maybe_unlink (o_file);
signal (signo, SIG_DFL);
-
- fatal ("Caught signal %d [%s]", signo, sys_siglist[signo]);
kill (getpid (), signo);
}
generic *
xcalloc (size1, size2)
- size_t size1, size2;
+ int size1, size2;
{
- generic *ptr = calloc (size1, size2);
+ generic *ptr = (generic *) calloc (size1, size2);
if (ptr)
return ptr;
@@ -329,9 +380,9 @@ xcalloc (size1, size2)
generic *
xmalloc (size)
- size_t size;
+ int size;
{
- generic *ptr = malloc (size);
+ generic *ptr = (generic *) malloc (size);
if (ptr)
return ptr;
@@ -339,12 +390,68 @@ xmalloc (size)
return (generic *)0;
}
+/* Make a copy of a string INPUT with size SIZE. */
+
+char *
+savestring (input, size)
+ char *input;
+ int size;
+{
+ char *output = (char *) xmalloc (size + 1);
+ strcpy (output, input);
+ return output;
+}
+
+/* Decide whether the given symbol is:
+ a constructor (1), a destructor (2), or neither (0). */
+
+static int
+is_ctor_dtor (s)
+ char *s;
+{
+ struct names { char *name; int len; int ret; int two_underscores; };
+
+ register struct names *p;
+ register int ch;
+ register char *orig_s = s;
+
+ static struct names special[] = {
+#ifdef NO_DOLLAR_IN_LABEL
+ { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
+ { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
+#else
+ { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
+ { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },
+#endif
+ { "sti__", sizeof ("sti__")-1, 1, 1 },
+ { "std__", sizeof ("std__")-1, 2, 1 },
+ { NULL, 0, 0, 0 }
+ };
+
+ while ((ch = *s) == '_')
+ ++s;
+
+ if (s == orig_s)
+ return 0;
+
+ for (p = &special[0]; p->len > 0; p++)
+ {
+ if (ch == p->name[0]
+ && (!p->two_underscores || ((s - orig_s) >= 2))
+ && strncmp(s, p->name, p->len) == 0)
+ {
+ return p->ret;
+ }
+ }
+ return 0;
+}
+
/* Compute a string to use as the base of all temporary file names.
It is substituted for %g. */
static void
-choose_temp_base PROTO((void))
+choose_temp_base ()
{
char *base = getenv ("TMPDIR");
int len;
@@ -388,16 +495,16 @@ main (argc, argv)
FILE *outf;
char *ld_file_name;
char *c_file_name;
- char *B_option;
char *p;
char *prefix;
- char **c_argv = (char **) xcalloc (sizeof (char *), argc+7);
- char **c_ptr = c_argv;
+ char **c_argv;
+ char **c_ptr;
char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2);
char **ld1 = ld1_argv;
char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+5);
char **ld2 = ld2_argv;
int first_file;
+ int num_c_args = argc+7;
int len;
int clen;
@@ -406,6 +513,21 @@ main (argc, argv)
vflag = 1;
#endif
+ p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+ if (p)
+ while (*p)
+ {
+ char *q = p;
+ while (*q && *q != ' ') q++;
+ if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
+ num_c_args++;
+
+ if (*q) q++;
+ p = q;
+ }
+
+ c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
+
if (argc < 2)
fatal ("no arguments");
@@ -466,9 +588,7 @@ main (argc, argv)
#endif
ld_file_name = xcalloc (len + sizeof ("real-ld"), 1);
- c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
nm_file_name = xcalloc (len + sizeof ("gnm"), 1);
- B_option = xcalloc (len + sizeof ("-B"), 1);
memcpy (ld_file_name, prefix, len);
strcpy (ld_file_name + len, "real-ld");
@@ -486,23 +606,28 @@ main (argc, argv)
}
}
- memcpy (c_file_name, prefix, len);
- strcpy (c_file_name + len, "gcc");
- if (access (c_file_name, X_OK) < 0)
+ c_file_name = getenv ("COLLECT_GCC");
+ if (c_file_name == 0 || c_file_name[0] != '/')
{
-#ifdef STANDARD_BIN_PREFIX
- strcpy (c_file_name, STANDARD_BIN_PREFIX);
- strcat (c_file_name, "gcc");
+ c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
+ memcpy (c_file_name, prefix, len);
+ strcpy (c_file_name + len, "gcc");
if (access (c_file_name, X_OK) < 0)
-#endif
{
-#ifdef STANDARD_EXEC_PREFIX
- strcpy (c_file_name, STANDARD_EXEC_PREFIX);
+#ifdef STANDARD_BIN_PREFIX
+ strcpy (c_file_name, STANDARD_BIN_PREFIX);
strcat (c_file_name, "gcc");
if (access (c_file_name, X_OK) < 0)
#endif
{
- strcpy (c_file_name, "gcc");
+#ifdef STANDARD_EXEC_PREFIX
+ strcpy (c_file_name, STANDARD_EXEC_PREFIX);
+ strcat (c_file_name, "gcc");
+ if (access (c_file_name, X_OK) < 0)
+#endif
+ {
+ strcpy (c_file_name, "gcc");
+ }
}
}
}
@@ -523,9 +648,6 @@ main (argc, argv)
}
}
- strcpy (B_option, "-B");
- strcpy (B_option + sizeof ("-B") - 1, prefix);
-
*ld1++ = *ld2++ = "ld";
/* Make temp file names. */
@@ -534,13 +656,21 @@ main (argc, argv)
o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
sprintf (c_file, "%s.c", temp_filename);
sprintf (o_file, "%s.o", temp_filename);
- *c_ptr++ = "gcc";
+ *c_ptr++ = c_file_name;
*c_ptr++ = "-c";
*c_ptr++ = "-o";
*c_ptr++ = o_file;
+ /* !!! When GCC calls collect2,
+ it does not know whether it is calling collect2 or ld.
+ So collect2 cannot meaningfully understand any options
+ except those ld understands.
+ If you propose to make GCC pass some other option,
+ just imagine what will happen if ld is really ld!!! */
+
/* Parse arguments. Remember output file spec, pass the rest to ld. */
- /* After the first file, put in the c++ rt0 */
+ /* After the first file, put in the c++ rt0. */
+
first_file = 1;
while ((arg = *++argv) != (char *)0)
{
@@ -559,22 +689,6 @@ main (argc, argv)
}
break;
- /* pass -f<xxx>, -B<xxx>, -b<xxx>, -V<xxx>, and -m<xxx>
- options to gcc. This allows options to be passed
- that affect search rules, and the size of pointers. */
- case 'b':
- case 'B':
- case 'f':
- case 'm':
- case 'V':
- if (arg[1] != '\0')
- {
- ld1--;
- ld2--;
- *c_ptr++ = arg;
- }
- break;
-
case 'o':
outfile = (arg[2] == '\0') ? argv[1] : &arg[2];
break;
@@ -599,13 +713,26 @@ main (argc, argv)
}
}
- *c_ptr++ = B_option;
+ /* Get any options that the upper GCC wants to pass to the sub-GCC. */
+ p = (char *) getenv ("COLLECT_GCC_OPTIONS");
+ if (p)
+ while (*p)
+ {
+ char *q = p;
+ while (*q && *q != ' ') q++;
+ if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
+ *c_ptr++ = savestring (p, q - p);
+
+ if (*q) q++;
+ p = q;
+ }
+
*c_ptr++ = c_file;
*c_ptr = *ld1 = *ld2 = (char *)0;
if (vflag)
{
- fprintf (stderr, "GNU COLLECT2 version %s", version_string);
+ fprintf (stderr, "collect2 version %s", version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
@@ -614,13 +741,31 @@ main (argc, argv)
if (debug)
{
- fprintf (stderr, "prefix = %s\n", prefix);
- fprintf (stderr, "ld_file_name = %s\n", ld_file_name);
- fprintf (stderr, "c_file_name = %s\n", c_file_name);
- fprintf (stderr, "nm_file_name = %s\n", nm_file_name);
- fprintf (stderr, "B_option = %s\n", B_option);
- fprintf (stderr, "c_file = %s\n", c_file);
- fprintf (stderr, "o_file = %s\n", o_file);
+ char *ptr;
+ fprintf (stderr, "prefix = %s\n", prefix);
+ fprintf (stderr, "ld_file_name = %s\n", ld_file_name);
+ fprintf (stderr, "c_file_name = %s\n", c_file_name);
+ fprintf (stderr, "nm_file_name = %s\n", nm_file_name);
+ fprintf (stderr, "c_file = %s\n", c_file);
+ fprintf (stderr, "o_file = %s\n", o_file);
+
+ ptr = getenv ("COLLECT_GCC_OPTIONS");
+ if (ptr)
+ fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
+
+ ptr = getenv ("COLLECT_GCC");
+ if (ptr)
+ fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
+
+ ptr = getenv ("COMPILER_PATH");
+ if (ptr)
+ fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
+
+ ptr = getenv ("LIBRARY_PATH");
+ if (ptr)
+ fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
+
+ fprintf (stderr, "\n");
}
/* Load the program, searching all libraries.
@@ -688,21 +833,28 @@ do_wait (prog)
wait (&status);
if (status)
{
- int sig = WTERMSIG (status);
+ int sig = status & 0x7F;
int ret;
if (sig != -1 && sig != 0)
{
+#ifdef NO_SYS_SIGLIST
+ error ("%s terminated with signal %d %s",
+ prog,
+ sig,
+ (status & 0200) ? ", core dumped" : "");
+#else
error ("%s terminated with signal %d [%s]%s",
prog,
sig,
sys_siglist[sig],
(status & 0200) ? ", core dumped" : "");
+#endif
my_exit (127);
}
- ret = WEXITSTATUS (status);
+ ret = ((status & 0xFF00) >> 8);
if (ret != -1 && ret != 0)
{
error ("%s returned %d exit status", prog, ret);
@@ -720,8 +872,8 @@ fork_execute (prog, argv)
char **argv;
{
int pid;
- void (*int_handler) PROTO((int));
- void (*quit_handler) PROTO((int));
+ void (*int_handler) ();
+ void (*quit_handler) ();
if (vflag || debug)
{
@@ -748,8 +900,8 @@ fork_execute (prog, argv)
fatal_perror ("Execute %s", prog);
}
- int_handler = (void (*)PROTO((int)))signal (SIGINT, SIG_IGN);
- quit_handler = (void (*)PROTO((int)))signal (SIGQUIT, SIG_IGN);
+ int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
+ quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
do_wait (prog);
@@ -832,18 +984,18 @@ write_c_file (stream, name)
fprintf (stream, "typedef void entry_pt();\n\n");
- write_list_with_asm (stream, "entry_pt ", constructors);
+ write_list_with_asm (stream, "entry_pt ", constructors.first);
fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
- write_list (stream, "\t", constructors);
+ write_list (stream, "\t", constructors.first);
fprintf (stream, "\t0\n};\n\n");
- write_list_with_asm (stream, "entry_pt ", destructors);
+ write_list_with_asm (stream, "entry_pt ", destructors.first);
fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
- write_list (stream, "\t", destructors);
+ write_list (stream, "\t", destructors.first);
fprintf (stream, "\t0\n};\n\n");
fprintf (stream, "extern entry_pt __main;\n");
@@ -851,11 +1003,10 @@ write_c_file (stream, name)
}
-#ifndef OBJECT_FORMAT_ROSE
+#ifdef OBJECT_FORMAT_NONE
-/* OSF/rose specific version to scan the name list of the loaded
- program for the symbols g++ uses for static constructors and
- destructors.
+/* Generic version to scan the name list of the loaded program for
+ the symbols g++ uses for static constructors and destructors.
The constructor table begins at __CTOR_LIST__ and contains a count
of the number of pointers (or -1 if the constructors are built in a
@@ -868,8 +1019,8 @@ scan_prog_file (prog_name, which_pass)
char *prog_name;
enum pass which_pass;
{
- void (*int_handler) PROTO((int));
- void (*quit_handler) PROTO((int));
+ void (*int_handler) ();
+ void (*quit_handler) ();
char *nm_argv[4];
int pid;
int argc = 0;
@@ -880,12 +1031,12 @@ scan_prog_file (prog_name, which_pass)
if (which_pass != PASS_FIRST)
return;
- nm_argv[ argc++ ] = "nm";
+ nm_argv[argc++] = "nm";
if (NM_FLAGS[0] != '\0')
- nm_argv[ argc++ ] = NM_FLAGS;
+ nm_argv[argc++] = NM_FLAGS;
- nm_argv[ argc++ ] = prog_name;
- nm_argv[ argc++ ] = (char *)0;
+ nm_argv[argc++] = prog_name;
+ nm_argv[argc++] = (char *)0;
if (pipe (pipe_fd) < 0)
fatal_perror ("pipe");
@@ -932,8 +1083,8 @@ scan_prog_file (prog_name, which_pass)
}
/* Parent context from here on. */
- int_handler = (void (*)PROTO((int)))signal (SIGINT, SIG_IGN);
- quit_handler = (void (*)PROTO((int)))signal (SIGQUIT, SIG_IGN);
+ int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
+ quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
if (close (pipe_fd[1]) < 0)
fatal_perror ("Close (%d)", pipe_fd[1]);
@@ -945,8 +1096,7 @@ scan_prog_file (prog_name, which_pass)
while (fgets (buf, sizeof buf, inf) != (char *)0)
{
int ch, ch2;
- char *start;
- char *end;
+ char *name, *end;
/* If it contains a constructor or destructor name, add the name
to the appropriate list. */
@@ -956,42 +1106,29 @@ scan_prog_file (prog_name, which_pass)
if (ch == '\0' || ch == '\n')
continue;
-
- start = p;
- while ((ch = *p) == '_') /* skip any extra '_' inserted */
- p++;
-
- for (end = p; (ch2 = *end) != '\0' && !isspace (ch2); end++)
- ;
+
+ name = p;
+ /* Find the end of the symbol name.
+ Don't include `|', because Encore nm can tack that on the end. */
+ for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
+ end++)
+ continue;
*end = '\0';
- if (ch == 'G')
+ switch (is_ctor_dtor (name))
{
- if (! strncmp (p, "GLOBAL_$I$", 10))
- add_to_list (&constructors, p-1);
+ case 1:
+ add_to_list (&constructors, name);
+ break;
- else if (! strncmp (p, "GLOBAL_$D$", 10))
- add_to_list (&destructors, p-1);
+ case 2:
+ add_to_list (&destructors, name);
+ break;
- else /* not a constructor or destructor */
- continue;
+ default: /* not a constructor or destructor */
+ continue;
}
- else if (ch == 's' && (p - start) >= 2)
- {
- if (! strncmp (p, "sti__", 5))
- add_to_list (&constructors, p-2);
-
- else if (! strncmp (p, "std__", 5))
- add_to_list (&destructors, p-2);
-
- else /* not a constructor or destructor */
- continue;
- }
-
- else
- continue;
-
if (debug)
fprintf (stderr, "\t%s\n", buf);
}
@@ -1008,7 +1145,115 @@ scan_prog_file (prog_name, which_pass)
signal (SIGQUIT, quit_handler);
}
-#endif /* !OBJECT_FORMAT_ROSE */
+#endif /* OBJECT_FORMAT_NONE */
+
+
+/*
+ * COFF specific stuff.
+ */
+
+#ifdef OBJECT_FORMAT_COFF
+
+#if defined(EXTENDED_COFF)
+# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax+SYMHEADER(X).iextMax)
+# define GCC_SYMENT SYMR
+# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
+# define GCC_SYMINC(X) (1)
+# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
+#else
+# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
+# define GCC_SYMENT SYMENT
+# define GCC_OK_SYMBOL(X) \
+ (((X).n_sclass == C_EXT) && \
+ (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
+ ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
+# define GCC_SYMINC(X) ((X).n_numaux+1)
+# define GCC_SYMZERO(X) 0
+#endif
+
+extern char *ldgetname ();
+
+/* COFF version to scan the name list of the loaded program for
+ the symbols g++ uses for static constructors and destructors.
+
+ The constructor table begins at __CTOR_LIST__ and contains a count
+ of the number of pointers (or -1 if the constructors are built in a
+ separate section by the linker), followed by the pointers to the
+ constructor functions, terminated with a null pointer. The
+ destructor table has the same format, and begins at __DTOR_LIST__. */
+
+static void
+scan_prog_file (prog_name, which_pass)
+ char *prog_name;
+ enum pass which_pass;
+{
+ LDFILE *ldptr;
+ int sym_index, sym_count;
+
+ if (which_pass != PASS_FIRST)
+ return;
+
+ if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
+ fatal ("%s: can't open as COFF file", prog_name);
+
+ if (!ISCOFF (HEADER(ldptr).f_magic))
+ fatal ("%s: not a COFF file", prog_name);
+
+ sym_count = GCC_SYMBOLS (ldptr);
+ sym_index = GCC_SYMZERO (ldptr);
+ while (sym_index < sym_count)
+ {
+ GCC_SYMENT symbol;
+
+ if (ldtbread (ldptr, sym_index, &symbol) <= 0)
+ break;
+ sym_index += GCC_SYMINC (symbol);
+
+ if (GCC_OK_SYMBOL (symbol))
+ {
+ char *name;
+
+ if ((name = ldgetname (ldptr, &symbol)) == NULL)
+ continue; /* should never happen */
+
+#ifdef _AIX
+ /* All AIX function names begin with a dot. */
+ if (*name++ != '.')
+ continue;
+#endif
+
+ switch (is_ctor_dtor (name))
+ {
+ case 1:
+ add_to_list (&constructors, name);
+ break;
+
+ case 2:
+ add_to_list (&destructors, name);
+ break;
+
+ default: /* not a constructor or destructor */
+ continue;
+ }
+
+#if !defined(EXTENDED_COFF)
+ if (debug)
+ fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
+ symbol.n_scnum, symbol.n_sclass,
+ (symbol.n_type ? "0" : ""), symbol.n_type,
+ name);
+#else
+ if (debug)
+ fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
+ symbol.iss, symbol.value, symbol.index, name);
+#endif
+ }
+ }
+
+ (void) ldclose(ldptr);
+}
+
+#endif /* OBJECT_FORMAT_COFF */
/*
@@ -1023,7 +1268,7 @@ typedef union load_union
{
ldc_header_t hdr; /* common header */
load_cmd_map_command_t map; /* map indexing other load cmds */
- interpreter_command_t iprtr; /* interpereter pathname */
+ interpreter_command_t iprtr; /* interpreter pathname */
strings_command_t str; /* load commands strings section */
region_command_t region; /* region load command */
reloc_command_t reloc; /* relocation section */
@@ -1055,31 +1300,21 @@ struct file_info
int use_mmap; /* != 0 if mmap'ed */
};
-extern int decode_mach_o_hdr PROTO(( void *in_bufp,
- size_t in_bufsize,
- unsigned long hdr_version,
- mo_header_t *headerp ));
+extern int decode_mach_o_hdr ();
-extern int encode_mach_o_hdr PROTO(( mo_header_t *headerp,
- void *out_bufp,
- size_t out_bufsize ));
+extern int encode_mach_o_hdr ();
-static void bad_header PROTO(( int status ));
+static void bad_header ();
-static void print_header PROTO(( mo_header_t *hdr_ptr ));
+static void print_header ();
-static void print_load_command PROTO(( load_union_t *load_hdr,
- size_t offset,
- int number ));
+static void print_load_command ();
-static void add_func_table PROTO(( mo_header_t *hdr_p,
- load_all_t *load_array,
- symbol_info_t *sym,
- int type ));
+static void add_func_table ();
-static struct file_info *read_file PROTO(( char *, int, int ));
+static struct file_info *read_file ();
-static void end_file PROTO(( struct file_info * ));
+static void end_file ();
/* OSF/rose specific version to scan the name list of the loaded
@@ -1203,7 +1438,7 @@ scan_prog_file (prog_name, which_pass)
if (debug)
{
- char *kind = "uknown";
+ char *kind = "unknown";
switch (load_hdr->sym.symc_kind)
{
@@ -1219,7 +1454,7 @@ scan_prog_file (prog_name, which_pass)
if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
continue;
- str_sect = load_array[ load_hdr->sym.symc_strings_section ].section;
+ str_sect = load_array[load_hdr->sym.symc_strings_section].section;
if (str_sect == (char *)0)
fatal ("string section missing");
@@ -1231,50 +1466,37 @@ scan_prog_file (prog_name, which_pass)
{
symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
char *name = sym->si_name.symbol_name + str_sect;
- char *name_start = name;
if (name[0] != '_')
continue;
- while (*++name == '_') /* skip any extra '_' inserted */
- ;
-
if (rw)
{
- if (*name != 'm' || (name - name_start) < 2
- || strcmp (name, "main"))
+ char *n = name;
+ while (*n == '_')
+ ++n;
+ if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
continue;
main_sym = sym;
}
-
- else if (*name == 'G')
- {
- if (! strncmp (name, "GLOBAL_$I$", 10))
- add_to_list (&constructors, name_start);
-
- else if (! strncmp (name, "GLOBAL_$D$", 10))
- add_to_list (&destructors, name_start);
-
- else /* not a constructor or destructor */
- continue;
- }
-
- else if (*name == 's' && (name - name_start) > 2)
+ else
{
- if (! strncmp (name, "sti__", 5))
- add_to_list (&constructors, name_start);
-
- else if (! strncmp (name, "std__", 5))
- add_to_list (&destructors, name_start);
-
- else /* not a constructor or destructor */
- continue;
+ switch (is_ctor_dtor (name))
+ {
+ case 1:
+ add_to_list (&constructors, name);
+ break;
+
+ case 2:
+ add_to_list (&destructors, name);
+ break;
+
+ default: /* not a constructor or destructor */
+ continue;
+ }
}
- else
- continue;
-
if (debug)
fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
sym->si_type, sym->si_sc_type, sym->si_flags, name);
@@ -1369,7 +1591,7 @@ scan_prog_file (prog_name, which_pass)
/* Add a function table to the load commands to call a function
- on initition or termination of the process. */
+ on initiation or termination of the process. */
static void
add_func_table (hdr_p, load_array, sym, type)