This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Possible problem with inline string functions in glibc, sysdeps/i386/i486/bits/string.h
- From: Davin McCall <davmac at ozonline dot com dot au>
- To: libc-alpha at sources dot redhat dot com
- Date: Fri, 3 Jan 2003 00:15:01 +1100
- Subject: Possible problem with inline string functions in glibc, sysdeps/i386/i486/bits/string.h
- Organization: hobo
Hi,
I'm a bit worried that the dummy ouput operands for a couple of the implemented-as-asm functions in sysdeps/i386/i486/bits/string.h aren't really correct.
Specifically the "mem*()" class of functions take "void *" arguments and therefore I assume that in fact any type of pointer (say an "int *" or some sort of struct ptr) could be passed to these functions. However, a character array is used as the dummy output operand for these functions.
Due to aliasing considerations it seems to me that it might then be possible for the compiler to assume that (in the case where the type of the argument is not actually char *) the buffer contents have not changed across the function call. Therefore it might cache values from the buffer in registers and use those same values after the function call when the buffer is accessed, even though the buffer has really been modified.
for instance the __mempcpy_by2 function:
--- begin ---
__STRING_INLINE char *
__mempcpy_by2 (char *__dest, __const char *__src, size_t __srclen)
{
register char *__tmp = __dest;
register unsigned long int __d0, __d1;
__asm__ __volatile__
("shrl $1,%3\n\t"
"jz 2f\n" /* only a word */
"1:\n\t"
"movl (%2),%0\n\t"
"leal 4(%2),%2\n\t"
"movl %0,(%1)\n\t"
"leal 4(%1),%1\n\t"
"decl %3\n\t"
"jnz 1b\n"
"2:\n\t"
"movw (%2),%w0\n\t"
"movw %w0,(%1)"
: "=&q" (__d0), "=r" (__tmp), "=&r" (__src), "=&r" (__d1),
"=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest)
: "1" (__tmp), "2" (__src), "3" (__srclen / 2),
"m" ( *(struct { __extension__ char __x[__srclen]; } *)__src)
: "cc");
return __tmp + 2;
}
--- end ---
See that "memory" is not listed in the clobber list for this function. On the other hand, it *is* listed in __mempcpy_by4 which essentially does the same thing.
Nor is "memory" listed for __mempcpy_byn.
I think all other "mem*" functions do list "memory" in the clobber list.
I've done some tests to see if I can cause a problem with this but I haven't actually managed to do so yet. I'm not sure, however, that the same would always be true, especially with future versions of gcc.
So: I believe that __mempcpy_by2, and probably __mempcpy_byn, should both have "memory" in the clobber list. But I'd like a second opinion... anyone?
regards,
Davin