Problem w/PIC and C++ exceptions in 2.95 on IA-32
David O'Brien
obrien@FreeBSD.ORG
Wed Jan 19 01:41:00 GMT 2000
A FreeBSD user found a bug in the 2.95.2 compiler using the below
program. When run the program dumps core. Marc Espie has verified that
the problem exists on OpenBSD/i386 2.6 too which uses 2.95.1. Since he
provided me with c++filtered assembler of foo.cc for gcc 2.95.2 and for
a recent snapshot that shows the problem on OpenBSD, I've attached them
below too.
An interested FreeBSD user has analyised the bug as follows and provided
a patch. The patch below also fixed the problem on OpenBSD/i386 as
tested by Marc Espie.
If this patch is deamed Ok, can it be commited to the 2.95 branch? The
BSD's track the relase branch and it is very much easier on the CVS
repository to fix problems as vendor imports rather than local changes.
----- Forwarded message from "Alexander N. Kabaev" <ak03@gte.com> -----
The problem is that default builtin_setjmp implementation does not
restore any registers except for stack pointers when doing nonlocal jump.
This means, that every platform, that needs to store/restore some other
state between jumps, has to provide appropriate definitions for
builtin_setjmp_setup and builtin_setjmp_receiver RTL expansions.
Every plaftorm which needs to do some additional processing at setjmp
receive point, such as restoring additional information previously saved
by builtin_setjmp_setup, can provide definition for
builtin_setjmp_receiver RTL expansion. That is exactly what I do in a
patch. The i386 code compiled with -fpic flag requires the value of PIC
register (EBX) to be restored in order to function properly. I do not
provide expansion for builtin_setjmp_setup because GCC documentation
explicitly states that values should be recalculated if possibe, rather
than stored in setjmp buffer and proper value for EBX can easlity be
determined from the current EIP contents.
Index: config/i386/i386.md
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/config/i386/i386.md,v
retrieving revision 1.5
diff -u -r1.5 i386.md
--- config/i386/i386.md 1999/11/15 04:28:55 1.5
+++ config/i386/i386.md 2000/01/16 04:21:02
@@ -8195,3 +8195,13 @@
load_pic_register (1);
DONE;
}")
+
+(define_expand "builtin_setjmp_receiver"
+ [(label_ref (match_operand 0 "" ""))]
+ "flag_pic"
+ "
+{
+ load_pic_register (1);
+ DONE;
+}")
+
----- End forwarded message -----
===== old.s =====
.file "foo.cc"
gcc2_compiled.:
___gnu_compiled_cplusplus:
.text
LC0:
.ascii "Bax thowing...\0"
LC1:
.ascii "in baz\12\0"
LC2:
.ascii "baz should not be here.\12\0"
.align 2,0x90
.globl Baz(void)
.type Baz(void) , @function
Baz(void):
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
pushl %ebx
call L10
L10:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L10],%ebx
leal LC0@GOTOFF(%ebx),%esi
addl $-12,%esp
leal LC1@GOTOFF(%ebx),%eax
pushl %eax
call _printf@PLT
addl $-4,%esp
pushl $0
call ___tfPc@PLT
pushl %eax
pushl %esi
call ___cp_push_exception@PLT
call ___sjthrow@PLT
.size Baz(void) , . - Baz(void)
LC3:
.ascii "foo caught %s\12\0"
.align 2,0x90
.globl Foo(void)
.type Foo(void) , @function
Foo(void):
pushl %ebp
movl %esp,%ebp
subl $92,%esp
pushl %edi
pushl %esi
pushl %ebx
call L32
L32:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L32],%ebx
call ___get_eh_context@PLT
movl %eax,-80(%ebp)
movl %eax,%edx
addl $4,%edx
movl 4(%eax),%eax
movl %eax,-24(%ebp)
movl $0,-20(%ebp)
leal -16(%ebp),%eax
movl %ebp,-16(%ebp)
leal L15@GOTOFF(%ebx),%ecx
movl %ecx,4(%eax)
movl %esp,8(%eax)
jmp L14
.align 2,0x90
L15:
jmp L29
.align 2,0x90
L14:
leal -24(%ebp),%eax
movl %eax,(%edx)
call Baz(void)@PLT
movl -80(%ebp),%edx
movl 4(%edx),%eax
movl (%eax),%eax
movl %eax,4(%edx)
jmp L27
.align 2,0x90
L29:
L12:
addl $-12,%esp
pushl ___tfPc@GOT(%ebx)
call ___eh_rtime_match@PLT
addl $16,%esp
testl %eax,%eax
je L17
call ___start_cp_handler@PLT
movl %eax,-76(%ebp)
movl -80(%ebp),%edx
addl $4,%edx
movl -80(%ebp),%ecx
movl 4(%ecx),%eax
movl %eax,-48(%ebp)
movl $0,-44(%ebp)
leal -40(%ebp),%eax
movl %ebp,-40(%ebp)
leal L21@GOTOFF(%ebx),%ecx
movl %ecx,4(%eax)
movl %esp,8(%eax)
jmp L20
.align 2,0x90
L21:
jmp L30
.align 2,0x90
L20:
leal -48(%ebp),%eax
movl %eax,(%edx)
addl $-8,%esp
movl -76(%ebp),%edx
pushl 8(%edx)
leal LC3@GOTOFF(%ebx),%eax
pushl %eax
call _printf@PLT
movl -80(%ebp),%ecx
movl 4(%ecx),%eax
movl (%eax),%eax
movl %eax,4(%ecx)
addl $16,%esp
addl $-12,%esp
movl -76(%ebp),%eax
pushl %eax
call ___cp_pop_exception@PLT
jmp L27
.align 2,0x90
L17:
call ___sjthrow@PLT
.align 2,0x90
L30:
L18:
movl -80(%ebp),%edx
addl $4,%edx
movl -80(%ebp),%ecx
movl 4(%ecx),%eax
movl %eax,-72(%ebp)
movl $0,-68(%ebp)
leal -64(%ebp),%eax
movl %ebp,-64(%ebp)
leal L25@GOTOFF(%ebx),%ecx
movl %ecx,4(%eax)
movl %esp,8(%eax)
jmp L24
.align 2,0x90
L25:
jmp L31
.align 2,0x90
L24:
leal -72(%ebp),%eax
movl %eax,(%edx)
addl $-12,%esp
movl -76(%ebp),%edx
pushl %edx
call ___cp_pop_exception@PLT
movl -80(%ebp),%ecx
movl 4(%ecx),%eax
movl (%eax),%eax
movl %eax,4(%ecx)
addl $16,%esp
call ___sjthrow@PLT
.align 2,0x90
L31:
L22:
call ___terminate@PLT
.align 2,0x90
L27:
leal -104(%ebp),%esp
popl %ebx
popl %esi
popl %edi
leave
ret
.size Foo(void) , . - Foo(void)
.comm ___tiPc,12
LC4:
.ascii "Pc\0"
.align 2,0x90
.weak ___tfPc
.type ___tfPc , @function
___tfPc:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
pushl %ebx
call L37
L37:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L37],%ebx
movl ___tiPc@GOT(%ebx),%esi
cmpl $0,(%esi)
jne L34
call char type_info function@PLT
addl $-4,%esp
pushl char type_info node@GOT(%ebx)
leal LC4@GOTOFF(%ebx),%eax
pushl %eax
pushl %esi
call ___rtti_ptr@PLT
L34:
movl %esi,%eax
leal -24(%ebp),%esp
popl %ebx
popl %esi
leave
ret
.size ___tfPc , . - ___tfPc
===== new.s =====
.file "foo.cc"
.version "01.01"
gcc2_compiled.:
___gnu_compiled_cplusplus:
.text
LC0:
.ascii "Bax thowing...\0"
LC1:
.ascii "in baz\12\0"
LC2:
.ascii "baz should not be here.\12\0"
.align 2,0x90
.globl Baz(void)
.type Baz(void) , @function
Baz(void):
pushl %ebp
movl %esp, %ebp
subl $16, %esp
pushl %esi
pushl %ebx
call L9
L9:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L9], %ebx
leal LC1@GOTOFF(%ebx), %eax
subl $12, %esp
leal LC0@GOTOFF(%ebx), %esi
pushl %eax
call _printf@PLT
addl $16, %esp
subl $4, %esp
pushl $0
call ___tfPc@PLT
pushl %eax
pushl %esi
call ___cp_push_exception@PLT
addl $16, %esp
call ___sjthrow@PLT
.size Baz(void) , . - Baz(void)
LC3:
.ascii "foo caught %s\12\0"
.align 2,0x90
.globl Foo(void)
.type Foo(void) , @function
Foo(void):
pushl %ebp
movl %esp, %ebp
subl $92, %esp
pushl %edi
pushl %esi
pushl %ebx
call L27
L27:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L27], %ebx
call ___get_eh_context@PLT
movl %eax, -64(%ebp)
movl %eax, -72(%ebp)
movl %eax, %ecx
movl %eax, %edx
movl 4(%edx), %eax
movl %eax, -20(%ebp)
leal -12(%ebp), %edx
leal L13@GOTOFF(%ebx), %eax
movl $0, -16(%ebp)
movl %ebp, -12(%ebp)
addl $4, %ecx
movl %eax, 4(%edx)
movl %esp, 8(%edx)
jmp L12
.align 2,0x90
L13:
call L14
L14:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L14], %ebx
jmp L11
.align 2,0x90
L12:
leal -20(%ebp), %eax
movl %eax, (%ecx)
call Baz(void)@PLT
movl -72(%ebp), %edx
movl 4(%edx), %eax
movl (%eax), %eax
movl %eax, 4(%edx)
jmp L26
.align 2,0x90
L21:
call ___terminate@PLT
.align 2,0x90
L17:
movl -72(%ebp), %edx
movl 4(%edx), %eax
movl -64(%ebp), %ecx
movl %eax, -60(%ebp)
leal -52(%ebp), %edx
leal L23@GOTOFF(%ebx), %eax
movl $0, -56(%ebp)
movl %ebp, -52(%ebp)
addl $4, %ecx
movl %eax, 4(%edx)
movl %esp, 8(%edx)
jmp L22
.align 2,0x90
L23:
call L24
L24:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L24], %ebx
jmp L21
.align 2,0x90
L22:
leal -60(%ebp), %eax
movl %eax, (%ecx)
subl $12, %esp
pushl -68(%ebp)
call ___cp_pop_exception@PLT
movl -72(%ebp), %edx
movl 4(%edx), %eax
movl (%eax), %eax
movl %eax, 4(%edx)
addl $16, %esp
call ___sjthrow@PLT
.align 2,0x90
L11:
subl $12, %esp
pushl ___tfPc@GOT(%ebx)
call ___eh_rtime_match@PLT
addl $16, %esp
testl %eax, %eax
je L16
call ___start_cp_handler@PLT
movl %eax, -68(%ebp)
movl -64(%ebp), %ecx
movl -72(%ebp), %edx
movl 4(%edx), %eax
movl %eax, -40(%ebp)
leal -32(%ebp), %edx
leal L19@GOTOFF(%ebx), %eax
movl $0, -36(%ebp)
movl %ebp, -32(%ebp)
addl $4, %ecx
movl %eax, 4(%edx)
movl %esp, 8(%edx)
jmp L18
.align 2,0x90
L19:
call L20
L20:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L20], %ebx
jmp L17
.align 2,0x90
L18:
leal -40(%ebp), %eax
movl %eax, (%ecx)
subl $8, %esp
movl -68(%ebp), %eax
pushl 8(%eax)
leal LC3@GOTOFF(%ebx), %eax
pushl %eax
call _printf@PLT
movl -72(%ebp), %edx
movl 4(%edx), %eax
movl (%eax), %eax
addl $16, %esp
movl %eax, 4(%edx)
subl $12, %esp
pushl -68(%ebp)
call ___cp_pop_exception@PLT
jmp L26
.align 2,0x90
L16:
call ___sjthrow@PLT
.align 2,0x90
L26:
leal -104(%ebp), %esp
popl %ebx
popl %esi
popl %edi
leave
ret
.size Foo(void) , . - Foo(void)
.comm ___tiPc,12
LC4:
.ascii "Pc\0"
.align 2,0x90
.weak ___tfPc
.type ___tfPc , @function
___tfPc:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
pushl %esi
pushl %ebx
call L31
L31:
popl %ebx
addl $__GLOBAL_OFFSET_TABLE_+[.-L31], %ebx
movl ___tiPc@GOT(%ebx), %esi
movl (%esi), %eax
testl %eax, %eax
jne L29
call char type_info function@PLT
subl $4, %esp
pushl char type_info node@GOT(%ebx)
leal LC4@GOTOFF(%ebx), %eax
pushl %eax
pushl %esi
call ___rtti_ptr@PLT
L29:
leal -24(%ebp), %esp
popl %ebx
movl %esi, %eax
popl %esi
leave
ret
.size ___tfPc , . - ___tfPc
===== program showing the bug =====
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# Makefile
# foo.cc
# main.cc
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
XCXX=g++
XLD=ld
XCXXFLAGS=-g -fpic -fexceptions
X
Xall: arf
X
Xarf: main.o foo.so
X ${CXX} -o arf main.o foo.so
X
X
Xfoo.so: foo.o
X ${LD} -Bshareable -o foo.so foo.o
X
Xclean:
X rm -f arf *.o *.so
END-of-Makefile
echo x - foo.cc
sed 's/^X//' >foo.cc << 'END-of-foo.cc'
X#include <stdio.h>
X
Xint Foo ();
X
Xint Baz ()
X{
X char *msg = "Bax thowing...";
X printf ("in baz\n");
X throw msg;
X printf ("baz should not be here.\n");
X}
X
X
Xint Foo ()
X{
X try {
X Baz ();
X } catch (char *msg) {
X printf ("foo caught %s\n", msg);
X }
X}
END-of-foo.cc
echo x - main.cc
sed 's/^X//' >main.cc << 'END-of-main.cc'
X#include <stdio.h>
X
Xint Foo ();
X
Xint
Xmain ()
X{
X try {
X printf ("calling foo\n");
X Foo ();
X printf ("returned from foo\n");
X } catch (char *msg) {
X printf ("exception from foo: %s\n", msg);
X } catch (...) {
X printf ("unknown exception\n");
X }
X}
END-of-main.cc
exit
More information about the Gcc-bugs
mailing list