This is the mail archive of the gcc-bugs@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]
Other format: [Raw text]

volatile is not volatile enough


Hi,

given a statement like
  int a[2];
  func2(func1(a), a[0], a[1]);
where a is modified by func1, func2 receives wrong input on the stack. In
detail, first a[1], then a[0] and then a is pushed onto the stack, then func1
gets called and pops off its a -- which is modified after.
Adding the keyword volatile doesnot help.

I am using gcc 3.3 20030226 (prerelease) SuSE Linux 8.2.

Here is a test script:
#include <stdio.h>
#define volatile

volatile void *func1(volatile int[]);
volatile void *func2(volatile void *, volatile int, volatile int);

int main(void) {
  volatile int a[2] = {13, 101};
  volatile void *result;

  /* IMPACT
     The result on stdout should be x=14 y=102 not x=13 y=101.
  */
  func2(func1(a), a[0], a[1]);


  /* CAUSE
     Unknown, however, when using objdump:

 8048344:       55                      push   %ebp
 8048345:       89 e5                   mov    %esp,%ebp
 8048347:       83 ec 18                sub    $0x18,%esp
 804834a:       83 e4 f0                and    $0xfffffff0,%esp
 804834d:       b8 00 00 00 00          mov    $0x0,%eax
 8048352:       29 c4                   sub    %eax,%esp
 8048354:       c7 45 f8 0d 00 00 00    movl   $0xd,0xfffffff8(%ebp)
 804835b:       c7 45 fc 65 00 00 00    movl   $0x65,0xfffffffc(%ebp)
 8048362:       83 ec 04                sub    $0x4,%esp

 Here it comes, GCC uses a "trick" to save instructions:
 it already pushes a[0] and a[1] onto the stack, and then a itself,
 while func1 only pops its one argument, a -- which gets modified.

 Even if adding the volatile keyword, this behavior does not change.
 Even if adding it everywhere.

 8048365:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
 8048368:       50                      push   %eax
 8048369:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
 804836c:       50                      push   %eax
 804836d:       8d 45 f8                lea    0xfffffff8(%ebp),%eax
 8048370:       50                      push   %eax
 8048371:       e8 3c 00 00 00          call   80483b2 <func1>
 8048376:       83 c4 04                add    $0x4,%esp
 8048379:       50                      push   %eax
 804837a:       e8 59 00 00 00          call   80483d8 <func2>
 804837f:       83 c4 10                add    $0x10,%esp

  */

  // Following works...
  result = func1(a);
  func2(result, a[0], a[1]);
  return 0;
}

volatile void *func1(volatile int a[]) {
  ++a[0];
  ++a[1];
  return NULL;
}

volatile void *func2(volatile void *p, volatile int x, volatile int y) {
  printf("x=%d, y=%d\n", x, y);
  return p;
}

EOF

- Jan Engelhardt


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