A bug in asm-i386/string.h or egcs/gcc?

H.J. Lu (hjl@lucon.org)
Sun, 5 Apr 1998 10:37:59 -0700 (PDT)


> On Wed, 25 Feb 1998, Jeffrey A Law wrote:
>
> > I think the best way to proceed is for someone to give me a hunk of
> > code that I can feed the compiler that will show a case where a
> > clobber is being used for input addressing. That way I can debug
> > the compiler and see what's really happening.
>
> I can't keep up with the weekly updates, so my GCC currently is:
> gcc version egcs-2.91.06 980122 (gcc-2.8.0 release)
>
> The following code breaks when compiled with -fno-strength-reduce, but
> independantly of -O2/-O3, -fomit-frame-pointer, and -m[345]86:
>
> ===============================================================================
> #include <linux/string.h>
>
> int count_substring_matches(char **haystacks, char **needles)
> {
> int hits=0, i, j;
> for(i=0; haystacks[i]; i++) {
> for(j=0; needles[j]; j++) {
> if (strstr(haystacks[i], needles[j])) hits++;
> }
> }
> return hits;
> }
> ===============================================================================
>
> generates for the strstr function:
>
> ===============================================================================
> #APP
> cld
> movl (%ebx,%edx,4),%edi
> repne
> scasb
> notl %ecx
> decl %ecx
> movl %ecx,%edx
> 1: movl (%ebx,%edx,4),%edi
> movl %esi,%eax
> movl %edx,%ecx
> repe
> cmpsb
> je 2f
> xchgl %eax,%esi
> incl %esi
> cmpb $0,-1(%eax)
> jne 1b
> xorl %eax,%eax
> 2:
> #NO_APP
> ===============================================================================
>
> in this precise case the problem is with %edx. Other compilers/versions
> used %edi in the address computation. Note that it generates correct code
> when I exchange the order of the nested loops !
>
> If I add -fpic the addressing mode is even able to use two
> clobbered registers and becomes (%edx,%edi,4), and only -fstrength-reduce
> -fomit-frame-pointer generates correct pic code. Otherwise the compiler
> sometimes reloads %edi with movl (%edx),%edi.
>
>
>

# gcc -O2 -fno-strength-reduce foo.c
# a.out
zsh: 2924 segmentation fault ./a.out

I am not sure if it is a bug or not. The problem is when an asm
statement marks a register as clobber, how can egcs safely use it
for the asm statement? I think when a register is marked as clobber,
egcs cannot use it inside the asm statement via %0, %1, %2, .... Is
there a fix for that? The bug may be in combine.

Linus, I don't think the current x86 asm statement in linux kernel is
safe, given what I have described in egcs/gcc. However, if we change
it to

:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"m" (ct)

which tells egcs/gcc to put "ct" in memory, it seems to work. Since
there is no register available for it anyway, except for "ebx", "g"
doesn't make much sense. If we limit it to kernerl only, we can change
it to

:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"b" (ct)

In that case, we should protect it with #ifdef/#endif to prevent
it from leaking to the user codes. Either way, it should be fixed.
If necessary, I can go through the current kernel code to check
all those cases.

Thanks.

H.J.
---foo.c--
extern inline char * strstr(const char * cs,const char * ct)
{
register char * __res;
__asm__ __volatile__(
"cld\n\t" \
"movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tmovl %4,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 2f\n\t"
"xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
:"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
:"cx","dx","di","si");
return __res;
}

int count_substring_matches(char **haystacks, char **needles)
{
int hits=0, i, j;
for(i=0; haystacks[i]; i++) {
for(j=0; needles[j]; j++) {
if (strstr(haystacks[i], needles[j])) hits++;
}
}
return hits;
}

main ()
{
char * haystacks [] = {"foobar", 0};
char * needles [] = {"foo", 0};

if (count_substring_matches (haystacks, needles ) != 1)
abort ();

return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu