This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
c/5370: gcc 3.0: certain i386 %ebp used before set
- From: Kevin Ryde <user42 at zip dot com dot au>
- To: gcc-gnats at gcc dot gnu dot org
- Date: 14 Jan 2002 00:22:33 +0100
- Subject: c/5370: gcc 3.0: certain i386 %ebp used before set
>Number: 5370
>Category: c
>Synopsis: gcc 3.0: certain i386 %ebp used before set
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Sun Jan 13 15:26:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:
>Release: 3.0 (Debian) (Debian testing/unstable)
>Organization:
>Environment:
System: Linux blah 2.2.15 #1 Tue Apr 25 17:13:48 EST 2000 i586 unknown
Architecture: i586
<machine, os, target, libraries (multiple lines)>
host: i386-pc-linux-gnu
build: i386-pc-linux-gnu
target: i386-pc-linux-gnu
configured with: ../src/configure -v --enable-languages=c,c++,java,f77,proto,objc --prefix=/usr --infodir=/share/info --mandir=/share/man --enable-shared --with-gnu-as --with-gnu-ld --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-checking --enable-threads=posix --enable-java-gc=boehm --with-cpp-install-dir=bin --enable-objc-gc i386-linux
>Description:
i386 assembler code generated for a certain bit of C seems to use %ebp
before a value has been stored to that register.
>How-To-Repeat:
The file foo.c attached below compiled with
gcc-3.0 -fPIC -O2 -fomit-frame-pointer -S foo.c
produces
refmpn_divmod_1c:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $12, %esp
call .L20
.L20:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L20], %ebx
movl 12(%ebp), %edi
pushl %ecx
pushl %edi
pushl 8(%ebp)
pushl 4(%ebp)
call refmpn_overlap_fullonly_p@PLT
...
I believe the load and two pushes using %ebp are being done before a
value has been stored to that register.
In one actual program, a seg fault resulted from the first of those
loads, due to garbage in %ebp.
For interest, this code is a GMP reference function, supposed to be
implemented in a simple and safe fashion. Somewhat ironic that it
should provoke a problem where other hairy stuff doesn't :-).
--=-=-=
Content-Type: text/x-csrc
Content-Disposition: attachment; filename=foo.c
unsigned *refmpn_memdup_limbs ();
unsigned *refmpn_malloc_limbs ();
unsigned
refmpn_divmod_1c (unsigned *rp, const unsigned *sp, long size,
unsigned divisor, unsigned carry)
{
unsigned *sp_orig;
unsigned *prod;
unsigned carry_orig;
long i;
do {
if (!( refmpn_overlap_fullonly_p (rp, sp, size) ))
__gmp_assert_fail ("foo.c", 20,
"refmpn_overlap_fullonly_p (rp, sp, size)");
} while (0);
do {
if (!( size >= 0 ))
__gmp_assert_fail ("foo.c", 21, "size >= 0");
} while (0);
do {
if (!( carry < divisor ))
__gmp_assert_fail ("foo.c", 22, "carry < divisor");
} while (0);
if (size == 0)
return carry;
sp_orig = refmpn_memdup_limbs (sp, size);
prod = refmpn_malloc_limbs (size);
carry_orig = carry;
for (i = size-1; i >= 0; i--)
refmpn_udiv_qrnnd (&rp[i], &carry, carry, sp[i], divisor);
do {
if (!( refmpn_mul_1c (prod, rp, size, divisor, carry) == carry_orig ))
__gmp_assert_fail ("foo.c", 34,
"refmpn_mul_1c (prod, rp, size, divisor, carry) == carry_orig");
} while (0);
do {
if (!( refmpn_cmp (prod, sp_orig, size) == 0 ))
__gmp_assert_fail ("foo.c", 35,
"refmpn_cmp (prod, sp_orig, size) == 0");
} while (0);
free (sp_orig);
free (prod);
return carry;
}
--=-=-=--
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
--=-=-=