From ed5b94621848199bd322de0756c7b199c5a00488 Mon Sep 17 00:00:00 2001 From: Richard Stallman Date: Thu, 19 Mar 1992 22:07:22 +0000 Subject: [PATCH] *** empty log message *** From-SVN: r529 --- gcc/collect2.c | 612 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 417 insertions(+), 195 deletions(-) diff --git a/gcc/collect2.c b/gcc/collect2.c index 814db0b4139..320ac7d47df 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 #include #include -#include #include -#include "gstddef.h" #include #include #include #include #include +#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 +#include + +#ifdef UMAX +#include +#endif + +#ifdef _AIX +#define ISCOFF(magic) \ + ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC) +#endif + +#if defined (_AIX) || defined (USG) +#undef FREAD +#undef FWRITE +#endif + +#include + +#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 #include #include + #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, -B, -b, -V, and -m - 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,49 +1466,36 @@ 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) - { - if (! strncmp (name, "sti__", 5)) - add_to_list (&constructors, name_start); - - else if (! strncmp (name, "std__", 5)) - add_to_list (&destructors, name_start); - - else /* not a constructor or destructor */ - continue; - } - else - continue; + { + switch (is_ctor_dtor (name)) + { + case 1: + add_to_list (&constructors, name); + break; + + case 2: + add_to_list (&destructors, name); + break; + + default: /* not a constructor or destructor */ + continue; + } + } if (debug) fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n", @@ -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)