Bug 25380 - application segmentation fault when compiled with "-O2", but not with "-O1"
Summary: application segmentation fault when compiled with "-O2", but not with "-O1"
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL: http://sources.redhat.com/ml/binutils...
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2005-12-13 01:36 UTC by Hugh Daschbach
Modified: 2005-12-13 12:25 UTC (History)
2 users (show)

See Also:
Host: powerpc64-unknown-linux-gnu
Target: powerpc64-unknown-linux-gnu
Build: powerpc64-unknown-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hugh Daschbach 2005-12-13 01:36:53 UTC
ppc64 segmentation fault on function return that returns the value of another function.

Segmentation fault occurs when application is compiled with "-O2", but not when compiled with "-O1".  *.i files identical, so included is a small test program, rather than the .i file.  Apply following as a patch.  Test with "make test".


diff -urpN null/libwrapped.c ppc-test/libwrapped.c
--- null/libwrapped.c 1969-12-31 16:00:00.000000000 -0800
+++ ppc-test/libwrapped.c 2005-12-12 10:22:02.000000000 -0800
@@ -0,0 +1,11 @@
+#include "proto.h"
+
+unsigned long fn(void)
+{
+   return 0;
+}
+
+unsigned long wrapped(void)
+{
+ return fn();
+}
diff -urpN null/main.c ppc-test/main.c
--- null/main.c 1969-12-31 16:00:00.000000000 -0800
+++ ppc-test/main.c 2005-12-12 12:11:37.000000000 -0800
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include "proto.h"
+
+int  main(int argc, char **argv)
+{
+ printf("unwrapped: %ld\n", fn());
+ printf("wrapped: %ld\n", wrapped());
+ return 0;
+}
diff -urpN null/Makefile ppc-test/Makefile
--- null/Makefile 1969-12-31 16:00:00.000000000 -0800
+++ ppc-test/Makefile 2005-12-12 12:27:25.000000000 -0800
@@ -0,0 +1,21 @@
+# -*- makefile -*-
+
+CFLAGS = -m64 -Wall -g -O2
+
+main: main.o libwrapped.so
+ $(CC) $(CFLAGS) -o main main.o -L. -lwrapped
+
+libwrapped.o: libwrapped.c proto.h
+ $(CC) $(CFLAGS) -c -o libwrapped.o libwrapped.c
+
+libwrapped.so: libwrapped.o
+ ld -g -m elf64ppc -G -h  libwrapped.so -o libwrapped.so libwrapped.o
+
+main.o: main.c proto.h
+ $(CC) $(CFLAGS) -c -o main.o main.c
+
+clean:
+ rm -f *.o *.so main
+
+test: main
+ LD_LIBRARY_PATH=. ./main
diff -urpN null/proto.h ppc-test/proto.h
--- null/proto.h 1969-12-31 16:00:00.000000000 -0800
+++ ppc-test/proto.h 2005-12-09 13:58:10.000000000 -0800
@@ -0,0 +1,3 @@
+extern unsigned long fn(void);
+extern unsigned long wrapped(void);
+
Comment 1 Hugh Daschbach 2005-12-13 02:25:02 UTC
Forgot version data: First seen on 3.4.4 20050721 (Red Hat 3.4.4-2).
Last tested: svn revision 108426.  Still fails.

Using built-in specs.
Target: powerpc64-unknown-linux-gnu
Configured with: ./configure
Thread model: posix
gcc version 4.2.0 20051212 (experimental)
Comment 2 Alan Modra 2005-12-13 04:28:06 UTC
The testcase is invalid, because you are compiling libwrapped.so without -fPIC.  Now, powerpc64 code is always PIC, so you might think that -fPIC (or -fpic) is unnecessary on powerpc64 shared libraries.  However, -fPIC/pic also tells gcc to compile assuming that the object might be for a shared library.  One thing this affects is whether tail calls can be made to global functions.  At -O2, sibling/tail call optimisation is done, so we get a tail call from "wrapped" to "fn" because -fPIC wasn't specified.  This tail call inside the shared lib destroys r2, the TOC pointer, and an invalid TOC access is the reason for the segfault.

It might possible to do something about this in the linker, but more complicated examples are not possible to fix.  eg. where the function tail-called is overridden by a function of the same name in the main app.