First here is my gcc -v output:
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr
--with-local-prefix=/usr/local --infodir=/usr/share/info
--mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64
--enable-languages=c,c++,objc,fortran,obj-c++,java,ada
--enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.2
--enable-ssp --disable-libssp --disable-libgcj --with-slibdir=/lib64
--with-system-zlib --enable-shared --enable-__cxa_atexit
--enable-libstdcxx-allocator=new --program-suffix=-4.1
--enable-version-specific-runtime-libs --without-system-libunwind
--with-cpu=generic --host=x86_64-suse-linux
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)
I have tracked down a problem while compiling a larger program and make a
compilable code snippet which reproduces the problem (SEGFAULT):
/*snippet.c*/
typedef volatile long fastlock_t;
static inline int fastlock_trylock(fastlock_t *l)
{
int lacquired = 0;
/* note: no 'lock' prefix even on SMP since xchg is always atomic */
asm volatile("movl $1,%0 \n\t" \
"xchgl %0,%1 \n\t" \
"xorl $1,%0"
: "=r"(lacquired)
: "m"(*l)
: "memory");
if (lacquired)
return 1;
return 0;
}
int main(void)
{
fastlock_t* test;
fastlock_trylock(test);
return 0;
}
The compilation worked without warnigs.
The precompiled file looked like this:
# 1 "snippet.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "snippet.c"
typedef volatile long fastlock_t;
static inline int fastlock_trylock(fastlock_t *l)
{
int lacquired = 0;
asm volatile("movl $1,%0 \n\t" "xchgl %0,%1 \n\t" "xorl $1,%0"
: "=r"(lacquired)
: "m"(*l)
: "memory");
if (lacquired)
return 1;
return 0;
}
int main(void)
{
fastlock_t* test;
fastlock_trylock(test);
return 0;
}
Here until now everything looks fine,
but when generating the assembly the error happens.
Here is the assembly of fastlock_trylock:
fastlock_trylock:
.LFB2:
pushq %rbp
.LCFI3:
movq %rsp, %rbp
.LCFI4:
movq %rdi, -24(%rbp)
movl $0, -4(%rbp)
movq -24(%rbp), %rax
#APP
movl $1,%eax
xchgl %eax,(%rax)
xorl $1,%eax
#NO_APP
movl %eax, -4(%rbp)
cmpl $0, -4(%rbp)
je .L4
movl $1, -28(%rbp)
jmp .L6
.L4:
movl $0, -28(%rbp)
.L6:
movl -28(%rbp), %eax
leave
ret
In rax is *l and eax is used for the value, so the pointer is overwritten and
the SEGFAULT happens while accessing the pointer with xchgl.
I'm not familiar with gcc inline asm but I belive that the code of snippet.c
should be allright.
Greets Henne
--
Summary: RAX and EAX are used as two different registers
Product: gcc
Version: 4.1.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: inline-asm
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: henne at nachtwindheim dot de
GCC build triplet: gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)
GCC host triplet: x86_64-suse-linux
GCC target triplet: x86_64-suse-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32178