This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Problem w/PIC and C++ exceptions in 2.95 on IA-32


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]