Bug 17455 - [3.4 only] syscall_linkage attribute problem with sibling call optimization
Summary: [3.4 only] syscall_linkage attribute problem with sibling call optimization
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.3.4
: P2 normal
Target Milestone: 3.4.4
Assignee: Jim Wilson
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2004-09-13 11:29 UTC by Stephane Eranian
Modified: 2005-04-23 01:15 UTC (History)
2 users (show)

See Also:
Host: ia64-linux
Target: ia64-linux
Build: ia64-linux
Known to work: 3.3.5 4.0.0 3.4.3
Known to fail: 3.4.0 3.3.3
Last reconfirmed: 2005-04-07 07:54:18


Attachments
Disable sibcalls from syscall_linkage functions. (552 bytes, patch)
2004-09-13 20:01 UTC, Jim Wilson
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stephane Eranian 2004-09-13 11:29:23 UTC
We have found aproblem in the Linux/ia64 kernel related to sibling call
optimization and the syscall_linkage attribute. On this platform, the attribute
indicates that the function paramaters must be treated as read-only
by the compiler. Any modification requires making a copy. 

The following code give an example of the problem we are describing:

void
bar(void)
{
        printf("in syscall_trace\n");
}

void foo(long value) __attribute__((syscall_linkage));
void
foo (long value)
{
        bar();
}

Because foo() is so simple, and bar() is the last call, the compiler
generates a direct branch to bar as opposed to a normal function call.
The bar() function will return directly to the caller of foo().

The generated code at -O2 looks as follows:

0000000000000000 <bar>:
   0:   [MII]       alloc r33=ar.pfs,4,3,0
   6:               mov r32=b0
   c:               addl r35=0,r1
  10:   [MMI]       mov r34=r1;;
  16:               ld8 r35=[r35]
  1c:               nop.i 0x0
  20:   [MIB]       nop.m 0x0
  26:               nop.i 0x0
  2c:               br.call.sptk.many b0=20 <bar+0x20>;;
  30:   [MII]       mov r1=r34
  36:               mov.i ar.pfs=r33
  3c:               mov b0=r32
  40:   [MIB]       nop.m 0x0
  46:               nop.i 0x0
  4c:               br.ret.sptk.many b0;;

0000000000000050 <foo>:
  50:   [MMI]       alloc r16=ar.pfs,8,8,0;;
  56:               alloc r2=ar.pfs,8,0,0
  5c:               nop.i 0x0
  60:   [MIB]       nop.m 0x0
  66:               nop.i 0x0
  6c:               br.many 60 <foo+0x10>;;
  70:   [MFB]       nop.m 0x0
  76:               break.f 0x0
  7c:               nop.b 0x0;;

foo() cannot modify r32 (the first argument) because of the syscall_linkage
attibute. However bar() is allowed to. 

The sibling optimization makes a direct branch (br.many) to bar().
That branch does not actually "protect" r32 because no RSE movement occurs.
The alloc in bar() simply resizes its current frame but the same r32 that
was passed to foo() is also accessible and can be modified at will.

In functions with the syscall_linkage attribute, sibling call optimization
should not be done because it could break the guarantee offered by the
attribute.
Comment 1 Jim Wilson 2004-09-13 20:01:24 UTC
Created attachment 7124 [details]
Disable sibcalls from syscall_linkage functions.

This fixes the bug for me.  I will do the usual testing, and then check it in. 
Since this is a kernel miscompilation problem, I will add the patch to mainline
and gcc-3.4, and also try to get it into gcc-3.3.  The testing will take a few
days.  I will try building a kernel to see what happens, but I won't try
booting it.
Comment 2 Jim Wilson 2004-09-13 20:02:42 UTC
Mine.  IA-64.  Problem confirmed.
Comment 3 GCC Commits 2004-09-15 23:26:57 UTC
Subject: Bug 17455

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	wilson@gcc.gnu.org	2004-09-15 23:26:37

Modified files:
	gcc            : ChangeLog 
	gcc/config/ia64: ia64.c 

Log message:
	Fix linux kernel miscompilation.
	PR target/17455
	* config/ia64/ia64.c (ia64_function_ok_for_sibcall): Return false
	if current_function_decl is a sibcall.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.5471&r2=2.5472
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/ia64/ia64.c.diff?cvsroot=gcc&r1=1.323&r2=1.324

Comment 4 GCC Commits 2004-09-17 17:56:41 UTC
Subject: Bug 17455

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_3-branch
Changes by:	wilson@gcc.gnu.org	2004-09-17 17:56:35

Modified files:
	gcc            : ChangeLog 
	gcc/config/ia64: ia64.c 

Log message:
	Fix linux kernel miscompile.
	PR target/17455
	* config/ia64/ia64.c (ia64_function_ok_for_sibcall): Return false
	if current_function_decl is a sibcall.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.16114.2.1016&r2=1.16114.2.1017
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/ia64/ia64.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.198.2.21&r2=1.198.2.22

Comment 5 Mark Mitchell 2004-11-01 00:46:26 UTC
Postponed until GCC 3.4.4.
Comment 6 Jim Wilson 2005-04-23 01:15:07 UTC
The patch is actually on the gcc-3.4 branch already, I added it Sept 15, 2004. 
I must have forgotten to include the PR line in the cvs log entry, ergo no CVS
commit message in the PR.  And I also forgot to close it.

Fixed on gcc-3.3, gcc-3.4, and mainline (pre gcc-4 branch).