This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
AIX collect2
- To: gcc-patches at gcc dot gnu dot org
- Subject: AIX collect2
- From: Tom Rix <trix at redhat dot com>
- Date: Wed, 17 Oct 2001 22:38:07 -0500
This patch improves 64 bit linking and static constructors/ destructors
on AIX.
For 64 bit linking the environmental variable LD_EMULATION is set to
aixppc64. This was done instead of mapping -b64 to -maixppc64, because
doing so would break native linking.
On AIX static constuctors/desctructors are handled with a special symbol
__rtinit. This is -binitfini:<init func>:<fini func> on the native
linker. This symbol is now emitted.
The usual testsuite does not explicitly look for the __rtinit symbol.
I have created a test. Since it is device dependent, I placed it in a
new dir. g++.dd/rs6000.
Tom
--
Tom Rix
GCC Engineer
trix@redhat.com
256.704.9201
2001-10-17 Tom Rix <trix@redhat.com>
* collect2.c (main): Set LDEMULATION to aixpp64 for -b64.
(collect_exit): Restore LDEMULATION.
(ld_rtinit_print): New function. Writes out special AIX __rtinit
symbol.
(write_c_file_stat): Call ld_rtinit_print.
* config/rs6000/aix51.h : Define LD_RTINIT.
* config/rs6000/aix43.h : Define LD_RTINIT.
2001-10-17 Tom Rix <trix@redhat.com>
* g++.dd/rs6000/rs6000.exp: New driver for AIX specific g++ tests.
* g++.dd/rs6000/hello.C: New test. Exercises special AIX __rtinit
symbol emitted by collect2.
diff -rc -N -x *~ gcc-old/collect2.c gcc/collect2.c
*** gcc-old/collect2.c Fri Oct 12 21:30:17 2001
--- gcc/collect2.c Wed Oct 17 19:56:57 2001
***************
*** 199,204 ****
--- 199,205 ----
#ifdef COLLECT_EXPORT_LIST
static int export_flag; /* true if -bE */
static int aix64_flag; /* true if -b64 */
+ static char *old_aix_emulation_saved = NULL;
#endif
int debug; /* true if -debug */
***************
*** 344,349 ****
--- 345,357 ----
#ifdef COLLECT_EXPORT_LIST
if (export_file != 0 && export_file[0])
maybe_unlink (export_file);
+
+ /* Reset the LDEMULATION environmental variable. */
+ if (NULL != old_aix_emulation_saved)
+ {
+ setenv ("LDEMULATION", old_aix_emulation_saved, 1);
+ }
+
#endif
if (ldout != 0 && ldout[0])
***************
*** 1120,1127 ****
case 'b':
if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
export_flag = 1;
! else if (arg[2] == '6' && arg[3] == '4')
! aix64_flag = 1;
break;
#endif
--- 1128,1166 ----
case 'b':
if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
export_flag = 1;
! else if (arg[2] == '6' && arg[3] == '4')
! {
! static char *old_aix_emulation;
! char *var = "LDEMULATION=";
! int status = 0;
!
! aix64_flag = 1;
!
! old_aix_emulation = getenv("LDEMULATION");
! if (NULL != old_aix_emulation)
! {
! size_t size = strlen(old_aix_emulation) +
! strlen(var) + 1;
! old_aix_emulation_saved = (char *)malloc(size);
!
! if (NULL != old_aix_emulation_saved)
! {
! sprintf(old_aix_emulation_saved, "%s%s", var,
! old_aix_emulation);
! }
! }
! else
! {
! old_aix_emulation_saved = NULL;
! }
!
! status = putenv("LDEMULATION=aixppc64");
!
! if (status)
! {
! fatal_perror ("Unable to set environment variable LDEMULATION");
! }
! }
break;
#endif
***************
*** 1824,1829 ****
--- 1863,1936 ----
}
}
+ #ifdef LD_RTINIT
+ /* To support the -binitfini option in the gnu linker, the __rtinit symbol
+ must be defined. For more information on __rtinit, see the linker
+ emulation script aix.em. */
+
+ static void
+ ld_rtinit_print(stream, initname, fininame)
+ FILE *stream;
+ char *initname;
+ char *fininame;
+ {
+ unsigned int i;
+ fprintf (stream, "__asm__ (\"\n");
+ fprintf (stream, ".csect .data[RW],3\n");
+ fprintf (stream, " .globl __rtinit\n");
+ fprintf (stream, " .extern %s\n", initname);
+ fprintf (stream, " .extern %s\n", fininame);
+ fprintf (stream, "__rtinit:\n");
+ if (aix64_flag) {
+ fprintf (stream, " .llong 0\n");
+ } else {
+ fprintf (stream, " .long 0\n");
+ }
+ fprintf (stream, " .long f1i - __rtinit\n");
+ fprintf (stream, " .long f1f - __rtinit\n");
+ fprintf (stream, " .long f2i - f1i\n");
+ fprintf (stream, " .align 3\n");
+ if (aix64_flag) {
+ fprintf (stream, "f1i: .llong %s\n", initname);
+ } else {
+ fprintf (stream, "f1i: .long %s\n", initname);
+ }
+ fprintf (stream, " .long s1i - __rtinit\n");
+ fprintf (stream, " .long 0\n");
+ if (aix64_flag) {
+ fprintf (stream, "f2i: .llong 0\n");
+ } else {
+ fprintf (stream, "f2i: .long 0\n");
+ }
+ fprintf (stream, " .long 0\n");
+ fprintf (stream, " .long 0\n");
+ if (aix64_flag) {
+ fprintf (stream, "f1f: .llong %s\n", fininame);
+ } else {
+ fprintf (stream, "f1f: .long %s\n", fininame);
+ }
+ fprintf (stream, " .long s1f - __rtinit\n");
+ fprintf (stream, " .long 0\n");
+ if (aix64_flag) {
+ fprintf (stream, "f2f: .llong 0\n");
+ } else {
+ fprintf (stream, "f2f: .long 0\n");
+ }
+ fprintf (stream, " .long 0\n");
+ fprintf (stream, " .long 0\n");
+ fprintf (stream, " .align 3\n");
+ fprintf (stream, "s1i:\n");
+ for (i = 0; i <= strlen(initname); i++)
+ fprintf (stream, " .byte %u\n", initname[i]);
+ fprintf (stream, " .align 3\n");
+ fprintf (stream, "s1f:\n");
+ for (i = 0; i <= strlen(fininame); i++)
+ fprintf (stream, " .byte %u\n", fininame[i]);
+ fprintf (stream, "\");\n");
+
+ }
+ #endif
+
/* Write out the constructor and destructor tables statically (for a shared
object), along with the functions to execute them. */
***************
*** 1953,1958 ****
--- 2060,2071 ----
fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
}
+
+ #ifdef LD_RTINIT
+ /* AIX gnu linker needs to have the special symbol __rtinit defined. */
+ ld_rtinit_print(stream, initname, fininame);
+ #endif
+
}
/* Write the constructor/destructor tables. */
diff -rc -N -x *~ gcc-old/config/rs6000/aix43.h gcc/config/rs6000/aix43.h
*** gcc-old/config/rs6000/aix43.h Fri Oct 12 21:31:40 2001
--- gcc/config/rs6000/aix43.h Fri Oct 12 21:50:09 2001
***************
*** 221,223 ****
--- 221,227 ----
#undef LD_INIT_SWITCH
#define LD_INIT_SWITCH "-binitfini"
+
+ /* So collect2.c generates the __rtinit symbol. */
+ #undef LD_RTINIT
+ #define LD_RTINIT
diff -rc -N -x *~ gcc-old/config/rs6000/aix51.h gcc/config/rs6000/aix51.h
*** gcc-old/config/rs6000/aix51.h Fri Oct 12 21:31:40 2001
--- gcc/config/rs6000/aix51.h Fri Oct 12 21:50:09 2001
***************
*** 233,235 ****
--- 233,239 ----
#undef LD_INIT_SWITCH
#define LD_INIT_SWITCH "-binitfini"
+
+ /* So collect2.c generates the __rtinit symbol. */
+ #undef LD_RTINIT
+ #define LD_RTINIT
diff -rc -N -x *~ gcc-old/testsuite/g++.dd/rs6000/hello.C gcc/testsuite/g++.dd/rs6000/hello.C
*** gcc-old/testsuite/g++.dd/rs6000/hello.C Wed Dec 31 16:00:00 1969
--- gcc/testsuite/g++.dd/rs6000/hello.C Sun Oct 14 23:26:00 2001
***************
*** 0 ****
--- 1,27 ----
+ #include <stdio.h>
+
+ class foo {
+ public:
+ int i;
+ foo() {
+ i=0;
+ printf("Init %d\n", i);
+ i++;
+ };
+ ~foo() {
+ printf("Fini %d\n", i);
+ i++;
+ };
+ };
+
+ static class foo bar;
+
+ int
+ main()
+ {
+ printf("Hello World %d\n", bar.i);
+ bar.i++;
+ return 0;
+ }
+
+
diff -rc -N -x *~ gcc-old/testsuite/g++.dd/rs6000/rs6000.exp gcc/testsuite/g++.dd/rs6000/rs6000.exp
*** gcc-old/testsuite/g++.dd/rs6000/rs6000.exp Wed Dec 31 16:00:00 1969
--- gcc/testsuite/g++.dd/rs6000/rs6000.exp Sun Oct 14 23:39:46 2001
***************
*** 0 ****
--- 1,72 ----
+ # Copyright (C) 2001 Free Software Foundation, Inc.
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ #
+
+ #
+ # Aix on PowerPC tests
+ #
+
+ if $tracelevel then {
+ strace $tracelevel
+ }
+
+ load_lib g++.exp
+ load_lib c-torture.exp
+
+ proc initfini_test1 {} {
+ global tmpdir srcdir subdir output tool
+
+ set testname "InitFini 1"
+ set filename "$srcdir/$subdir/hello.C"
+ set executable "$tmpdir/hello.x1"
+
+ set output [g++_target_compile $filename $executable executable ""]
+ if { ![file exists $executable] } {
+ fail "$testname compile"
+ untested "$testname execute"
+ untested "$testname symbol check"
+ return
+ } else {
+ pass "$testname compile"
+ }
+
+ set run_output [ exec $executable ]
+ # The last \n is stripped
+ set pass_output "Init 0\nHello World 1\nFini 2"
+
+ if { [ string compare $run_output $pass_output] == 0} {
+ pass "$testname execution"
+ }
+
+ catch { exec objdump -D $executable | grep __rtinit } sym_output
+ if { [ string match *__rtinit* $sym_output ] } {
+ pass "$testname symbol check"
+ } else {
+ fail "$testname symbol check"
+ }
+
+ remote_file build delete $executable
+ }
+
+ proc do_initfini {} {
+ initfini_test1
+ }
+
+ if { [istarget powerpc-*-*] || [istarget rs6000-*-aix*] } then {
+
+ do_initfini
+ }
+
+