From: CRDGW2::CRDGW2::MRGATE::"SMTP::PREP.AI.MIT.EDU::HELP-GCC-REQUEST" 4-MAR-1992 20:46:37.99 To: ARISIA::EVERHART CC: Subj: Re: Patches for GCC2 collect2 under AIX 3.1 From: help-gcc-request@prep.ai.mit.edu@SMTP@CRDGW2 To: Everhart@Arisia@MRGATE Received: by crdgw1.ge.com (5.57/GE 1.123) id AA23567; Wed, 4 Mar 92 19:30:40 EST Received: by life.ai.mit.edu (4.1/AI-4.10) id AA11856; Wed, 4 Mar 92 16:32:06 EST Return-Path: Received: from myrddin.sybus.com by life.ai.mit.edu (4.1/AI-4.10) id AA11830; Wed, 4 Mar 92 16:31:25 EST Received: by myrddin.sybus.com (/\==/\ Smail3.1.25.1 #25.3) id ; Wed, 4 Mar 92 16:31 EST Received: by tct.com (/\==/\ Smail3.1.25.1 #25.5) id ; Wed, 4 Mar 92 16:32 EST Message-Id: Date: Wed, 4 Mar 92 16:32 EST From: chip@tct.com (Chip Salzenberg) To: help-gcc@prep.ai.mit.edu Subject: Re: Patches for GCC2 collect2 under AIX 3.1 In-Reply-To: References: <1992Mar3.004250.26912@dartvax.dartmouth.edu> Organization: TC Telemanagement, Clearwater, FL Better than using "nm" under AIX is to modify collect2 to scan the XCOFF symbols directly. Patches are below. (I understand that these patches, or something like them, will be in the next release.) Shar and enjoy. Index: Makefile.in *************** *** 163,167 **** # that are used for linking. # The rules for compiling them should be in the t-* file for the machine. ! EXTRA_PARTS = # List of extra object files that should be compiled and linked with --- 162,166 ---- # that are used for linking. # The rules for compiling them should be in the t-* file for the machine. ! EXTRA_PARTS = collect2 # List of extra object files that should be compiled and linked with Index: config/rs6000.h *************** *** 1191,1194 **** --- 1191,1197 ---- #define HAVE_ATEXIT + /* Tell collect that the object format is COFF. */ + #define OBJECT_FORMAT_COFF + /* Compute the cost of computing a constant rtl expression RTX whose rtx-code is CODE. The body of this macro is a portion Index: config/x-rs6000 *************** *** 10,12 **** # For some reason, we need -lm for cc1. ! CLIB=-lm --- 10,13 ---- # For some reason, we need -lm for cc1. ! # We need -lld for collect2. ! CLIB=-lm -lld Index: collect2.c *************** *** 55,58 **** --- 55,86 ---- #endif + #ifdef USG + #define vfork fork + #endif + + #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) + #undef FREAD + #undef FWRITE + #endif + + #include + + #endif /* OBJECT_FORMAT_COFF */ + #ifdef OBJECT_FORMAT_ROSE *************** *** 70,75 **** --- 98,106 ---- #include #include + #endif /* OBJECT_FORMAT_ROSE */ + #ifdef OBJECT_FORMAT_NONE + /* Default flags to pass to nm. */ #ifndef NM_FLAGS *************** *** 77,84 **** #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. */ --- 108,111 ---- *************** *** 89,92 **** --- 116,121 ---- #endif + #endif /* OBJECT_FORMAT_NONE */ + /* Linked lists of constructor and destructor names. */ *************** *** 338,341 **** --- 367,415 ---- + /* 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. */ *************** *** 560,564 **** --- 634,641 ---- options to gcc. This allows options to be passed that affect search rules, and the size of pointers. */ + #ifndef _AIX + /* Exception: the AIX linker needs its -b options. */ case 'b': + #endif case 'B': case 'f': *************** *** 849,857 **** ! #ifndef OBJECT_FORMAT_ROSE ! /* OSF/rose specific 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 --- 926,933 ---- ! #ifdef OBJECT_FORMAT_NONE ! /* 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 *************** *** 943,948 **** { int ch, ch2; ! char *start; ! char *end; /* If it contains a constructor or destructor name, add the name --- 1019,1023 ---- { int ch, ch2; ! char *name, *end; /* If it contains a constructor or destructor name, add the name *************** *** 954,996 **** if (ch == '\0' || ch == '\n') continue; ! ! /* Record where the symbol name starts. */ ! start = p; ! ! while ((ch = *p) == '_') /* Skip any extra '_' inserted. */ ! p++; ! ! /* Find end of symbol name and null-terminate it. */ for (end = p; (ch2 = *end) != '\0' && !isspace (ch2); end++) ! ; ! *end = '\0'; ! ! if (ch == 'G') ! { ! if (! strncmp (p, "GLOBAL_$I$", 10)) ! add_to_list (&constructors, start); ! ! else if (! strncmp (p, "GLOBAL_$D$", 10)) ! add_to_list (&destructors, start); ! ! else /* not a constructor or destructor */ ! continue; ! } ! else if (ch == 's' && (p - start) >= 2) { ! if (! strncmp (p, "sti__", 5)) ! add_to_list (&constructors, start); ! ! else if (! strncmp (p, "std__", 5)) ! add_to_list (&destructors, start); ! else /* not a constructor or destructor */ ! continue; } - else - continue; - if (debug) fprintf (stderr, "\t%s\n", buf); --- 1029,1052 ---- if (ch == '\0' || ch == '\n') continue; ! ! name = p; for (end = p; (ch2 = *end) != '\0' && !isspace (ch2); end++) ! continue; ! *end = '\0'; ! 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, "\t%s\n", buf); *************** *** 1009,1013 **** } ! #endif /* !OBJECT_FORMAT_ROSE */ --- 1065,1177 ---- } ! #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 */ *************** *** 1222,1226 **** 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] != '_') --- 1386,1389 ---- *************** *** 1227,1237 **** continue; - while (*++name == '_') /* skip any extra '_' inserted */ - ; - if (rw) { ! if (*name != 'm' || (name - name_start) < 2 ! || strcmp (name, "main")) continue; --- 1390,1399 ---- continue; if (rw) { ! char *n = name; ! while (*n == '_') ! ++n; ! if (*n != 'm' || (n - name) < 2 || strcmp (n, "main")) continue; *************** *** 1238,1268 **** 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; if (debug) --- 1400,1419 ---- main_sym = sym; } ! else { ! 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) -- Chip Salzenberg at Teltronics/TCT , <73717.366@compuserve.com> "Informix 4GL is not a 4G, and it's barely an L." -- John Tombs