Skip to contentSkip to conversation

kill IN_STRING_C

PATCH In review Adrian Bunk 8 participants 30 messages Nov 7, 2004 – Nov 10, 2004 2 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 kill IN_STRING_C

Hi Andi,

some months ago, you invented a IN_STRING_C with the following comment:

<-- snip -->

gcc 3.4 optimizes sprintf(foo,"%s",string) into strcpy.

Unfortunately that isn't seen by the inliner and linux/i386 has no out-of-line strcpy so you end up with a linker error.

This patch adds out of line copies for most string functions to avoid this.
...

<-- snip -->

I tried 2.6.10-rc1-mm3 with gcc 3.4.2 and the patch below and didn't observe the problems you described.

Can you still reproduce this problem?
If not, I'll suggest to apply the patch below which saves a few kB in lib/string.o .

include/asm-i386/string.h renamed from include/asm-i386/string.h.old +0 -3
@@ -25,7 +25,6 @@
 
 /* AK: in fact I bet it would be better to move this stuff all out of line.
  */
-#if !defined(IN_STRING_C)
 
 #define __HAVE_ARCH_STRCPY
 static inline char * strcpy(char * dest,const char *src)
@@ -180,8 +179,6 @@
 return __res;
 }
 
-#endif
-
 #define __HAVE_ARCH_STRLEN
 static inline size_t strlen(const char * s)
 {
lib/string.c renamed from lib/string.c.old +0 -2
@@ -19,8 +19,6 @@
  * -  Kissed strtok() goodbye
  */
 
-#define IN_STRING_C 1
- 
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
#1 lore raw
Quoted 3 lines

Can you still reproduce this problem?
If not, I'll suggest to apply the patch below which saves a few kB in lib/string.o .

I would prefer to keep it because there is no guarantee in gcc that it always inlines all string functions unless you pass -minline-all-stringops. And with that the code would be bloated much more than the few out of lined fallback string functions.

Even if it works for you with your configuration it's just by luck.

-Andi

#2 lore raw
Quoted 9 lines · Andi Kleen
Quoted 3 lines

Can you still reproduce this problem?
If not, I'll suggest to apply the patch below which saves a few kB in lib/string.o .

I would prefer to keep it because there is no guarantee in gcc that it always inlines all string functions unless you pass -minline-all-stringops. And with that the code would be bloated much more than the few out of lined fallback string functions.

If I understand your changelog entry correctly, this wasn't the problem (the asm string functions are "static inline").

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Quoted 1 line

Even if it works for you with your configuration it's just by luck.

The two configurations I tried are one configuration with _everything_ except modules enablesd, and the other was _everything_ modular.

That's why I'd like to have an example where it fails to understand the problem.

Quoted 1 line

-Andi

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#3 lore raw
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

-Andi

#4 lore raw
Quoted 5 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

My gcc 3.4.2 didn't show this problem.

Quoted 1 line

-Andi

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#5 lore raw
Quoted 11 lines · you
Quoted 6 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

My gcc 3.4.2 didn't show this problem.

#include <stdio.h>
#include <string.h>
char buf[128];
void test(char *str)

{
    sprintf(buf, "%s", str);
}

gcc -Wall sp.c -S -O2 -fomit-frame-pointer -mregparm=3

        .file   "sp.c"
        .text
        .p2align 4,,15

.globl test
.type test, @function

test:

        movl    %eax, %edx
        movl    $buf, %eax
        jmp     strcpy
        .size   test, .-test
        .comm   buf,128,32
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.3 (PLD Linux)"
Signature · 3 lines
/* Copyright (C) 2003, SCO, Inc. This is valuable Intellectual Property. */

                           #define say(x) lie(x)
#6 lore raw
Quoted 17 lines · Pawe?? Sikora
Quoted 11 lines · you
Quoted 6 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

My gcc 3.4.2 didn't show this problem.

#include <stdio.h>
#include <string.h>
char buf[128];
void test(char *str)

Quoted 6 lines
{
    sprintf(buf, "%s", str);
}

...
jmp strcpy
...

This is the userspace example.

The kernel example is:

#include <linux/string.h>
#include <linux/kernel.h>

char buf[128];
void test(char *str)
{
sprintf(buf, "%s", str);
}

This results with gcc-3.4 (GCC) 3.4.2 (Debian 3.4.2-3) in:

        .file   "test.c"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "%s"
        .text
        .p2align 4,,15
.globl test
        .type   test, @function
test:
        pushl   %eax
        pushl   $.LC0
        pushl   $buf
        call    sprintf
        addl    $12, %esp
        ret
        .size   test, .-test
.globl buf
        .bss
        .align 32
        .type   buf, @object
        .size   buf, 128
buf:
        .zero   128
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.2 (Debian 3.4.2-3)"

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#7 lore raw
Quoted 70 lines · Adrian Bunk
Quoted 17 lines · Pawe?? Sikora
Quoted 11 lines · you
Quoted 6 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

My gcc 3.4.2 didn't show this problem.

#include <stdio.h>
#include <string.h>
char buf[128];
void test(char *str)

Quoted 6 lines
{
    sprintf(buf, "%s", str);
}

...
jmp strcpy
...

This is the userspace example.

The kernel example is:

#include <linux/string.h>
#include <linux/kernel.h>

char buf[128];
void test(char *str)
{
sprintf(buf, "%s", str);
}

This results with gcc-3.4 (GCC) 3.4.2 (Debian 3.4.2-3) in:

       .file   "test.c"
       .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
       .string "%s"
       .text
       .p2align 4,,15
.globl test
       .type   test, @function
test:
       pushl   %eax
       pushl   $.LC0
       pushl   $buf
       call    sprintf
       addl    $12, %esp
       ret
       .size   test, .-test
.globl buf
       .bss
       .align 32
       .type   buf, @object
       .size   buf, 128
buf:
       .zero   128
       .section        .note.GNU-stack,"",@progbits
       .ident  "GCC: (GNU) 3.4.2 (Debian 3.4.2-3)"
Quoted 3 lines

cu
Adrian

On this compiler 3.3.3, -O2 will cause it to use strcpy().

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#8 lore raw
Quoted 2 lines · linux-os

On this compiler 3.3.3, -O2 will cause it to use strcpy().

Not for me:

        .file   "test.c"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "%s"
        .text
        .p2align 4,,15
.globl test
        .type   test, @function
test:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $12, %esp
        movl    %eax, 8(%esp)
        movl    $.LC0, %eax
        movl    %eax, 4(%esp)
        movl    $buf, (%esp)
        call    sprintf
        movl    %ebp, %esp
        popl    %ebp
        ret
        .size   test, .-test
.globl buf
        .bss
        .align 32
        .type   buf, @object
        .size   buf, 128
buf:
        .zero   128
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-2)"

Are you using exactly my example file?
Are you using the complete gcc command line as shown by "make V=1"? Which gcc 3.3.3 are you using?

Quoted 2 lines

Cheers,
Dick Johnson

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#9 lore raw
Quoted 39 lines · Adrian Bunk
Quoted 2 lines · linux-os

On this compiler 3.3.3, -O2 will cause it to use strcpy().

Not for me:

       .file   "test.c"
       .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
       .string "%s"
       .text
       .p2align 4,,15
.globl test
       .type   test, @function
test:
       pushl   %ebp
       movl    %esp, %ebp
       subl    $12, %esp
       movl    %eax, 8(%esp)
       movl    $.LC0, %eax
       movl    %eax, 4(%esp)
       movl    $buf, (%esp)
       call    sprintf
       movl    %ebp, %esp
       popl    %ebp
       ret
       .size   test, .-test
.globl buf
       .bss
       .align 32
       .type   buf, @object
       .size   buf, 128
buf:
       .zero   128
       .section        .note.GNU-stack,"",@progbits
       .ident  "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-2)"
Quoted 4 lines

Are you using exactly my example file?
Are you using the complete gcc command line as shown by "make V=1"? Which gcc 3.3.3 are you using?

No, I am using (no headers):
-------------------
extern int sprintf(char *, const char *,...);
extern int puts(const char *);
static const char hello[]="Hello";
int xxx(void);
int xxx(){
char buf[0x100];
sprintf(buf, "%s", hello);
puts(buf);
return 0;
}
--------------------

Compiled as:

gcc -O2 -Wall -S -o xxx xxx.c

I get:

	.file	"xxx.c"
	.section	.rodata
	.type	hello, @object
	.size	hello, 6
hello:
	.string	"Hello"
	.text
	.p2align 2,,3
.globl xxx
	.type	xxx, @function
xxx:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ebx
	subl	$268, %esp
	pushl	$hello
	leal	-264(%ebp), %ebx
	pushl	%ebx
	call	strcpy
	movl	%ebx, (%esp)
	call	puts
	xorl	%eax, %eax
	movl	-4(%ebp), %ebx
	leave
	ret
	.size	xxx, .-xxx
	.section	.note.GNU-stack,"",@progbits
	.ident	"GCC: (GNU) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)"

If I don't use -O2, I get the sprintf() call. If I use the constant string "Hello" instead of the allocated string, it just bypasses everything and calls puts() directly.

If I use -fno-builtin, then it doesn't bypass sprintf(). However, there is no ISO C standard of "built-in" so I don't think any compiler should default to something that is undefined and decide to do whatever its current whims are. Certainly, a compiler that has some capabilities, not defined by a standard, should be able to use those capabilities, but it certainly shouldn't decide to do these things on its own.

Reviewing man gcc I see where I should be able to find out what the built-in commands are:

gcc -dumpspecs

However, this man page is wrong because I don't get a listing of any built-in functions, only the linking and compiler defaults.

The compiler is a tool. It should be just like other tools. Any killer options should be something that take a special effort to turn ON. It shouldn't default to firing the bullet out both ends of the barrel!

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#10 lore raw
Quoted 18 lines · linux-os
Quoted 5 lines

...
Are you using exactly my example file?
Are you using the complete gcc command line as shown by "make V=1"? Which gcc 3.3.3 are you using?

No, I am using (no headers):
-------------------
extern int sprintf(char *, const char *,...);
extern int puts(const char *);
static const char hello[]="Hello";
int xxx(void);

int xxx(){
   char buf[0x100];
   sprintf(buf, "%s", hello);
   puts(buf);
   return 0;
}
Quoted 6 lines

--------------------

Compiled as:

gcc -O2 -Wall -S -o xxx xxx.c
...

If you don't compile the code as it would be compiled inside the kernel, that's your fault...

Please reply only if you can reproduce this with
#include <linux/string.h>, #include <linux/kernel.h> _and_ a gcc command line as it would be in the kernel - everything else is useless.

Quoted 2 lines

Cheers,
Dick Johnson

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#11 lore raw
Quoted 7 lines · Adrian Bunk

If you don't compile the code as it would be compiled inside the kernel, that's your fault...

Please reply only if you can reproduce this with
#include <linux/string.h>, #include <linux/kernel.h> _and_ a gcc command line as it would be in the kernel - everything else is useless.

I attached a script that duplicates the gcc command line for the compile and also generates the 'C' code.

Script started on Mon 08 Nov 2004 05:50:54 PM EST

# sh -v xxx.sh
#!/bin/bash

cat >xxx.c <<EOF
KERN=/usr/src/linux-uname -r
uname -r
touch xxx.o.d
gcc -Wp,-MD,xxx.o.d -nostdinc -iwithprefix include -D__KERNEL__ -I${KERN}/include -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -Wdeclaration-after-statement -pipe -msoft-float -mpreferred-stack-boundary=2 -march=pentium4 -I${KERN}/include/asm-i386/mach-generic -I${KERN}/include/asm-i386/mach-default -DKVER6 -DMAJOR_NR=178 -DTRUE=1 -DFALSE=0 -DMODULE -DKBUILD_BASENAME=xxx -DKBUILD_MODNAME=Junk -S -o xxx xxx.c cat xxx

	.file	"xxx.c"
	.section	.rodata
	.type	hello, @object
	.size	hello, 6
hello:
	.string	"Hello"
	.text
.globl xxx
	.type	xxx, @function
xxx:
	subl	$268, %esp
	movl	%ebx, 264(%esp)
	movl	$hello, 4(%esp)
	leal	8(%esp), %ebx
	movl	%ebx, (%esp)
	call	strcpy
	movl	%ebx, (%esp)
	call	printk
	movl	264(%esp), %ebx
	xorl	%eax, %eax
	addl	$268, %esp
	ret
	.size	xxx, .-xxx
	.type	strcpy, @function
strcpy:
	subl	$8, %esp
	movl	12(%esp), %ecx
	movl	%esi, (%esp)
	movl	%edi, 4(%esp)
	movl	16(%esp), %esi
	movl	%ecx, %edi
#APP
	1:	lodsb
	stosb
	testb %al,%al
	jne 1b
#NO_APP
	movl	%ecx, %eax
	movl	(%esp), %esi
	movl	4(%esp), %edi
	addl	$8, %esp
	ret
	.size	strcpy, .-strcpy
	.section	.note.GNU-stack,"",@progbits
	.ident	"GCC: (GNU) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)"
# exit

Script done on Mon 08 Nov 2004 05:51:03 PM EST

It clearly invents strcpy, having never been referenced in the source.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#12 lore raw
Quoted 8 lines · linux-os

...
call strcpy
...
strcpy:

	subl	$8, %esp

...
It clearly invents strcpy, having never been referenced in the source.

The asm code you sent does _not_ call a global strcpy function. It calls an asm procedure named "strcpy" it ships itself.

BTW: You are the second person in this thread I have to explain this to...

Quoted 2 lines

Cheers,
Dick Johnson

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#13 lore raw
Quoted 13 lines · Adrian Bunk
Quoted 8 lines · linux-os

...
call strcpy
...
strcpy:

	subl	$8, %esp

...
It clearly invents strcpy, having never been referenced in the source.

The asm code you sent does _not_ call a global strcpy function. It calls an asm procedure named "strcpy" it ships itself.

Quoted 7 lines

BTW: You are the second person in this thread I have to explain this to...

Quoted 2 lines

Cheers,
Dick Johnson

cu
Adrian

Explain WHAT? There is NO strcpy in the code. No such procedure should have been called. Period. The generated code is defective.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#14 lore raw
Quoted 17 lines · linux-os
Quoted 15 lines · Adrian Bunk
Quoted 8 lines · linux-os

...
call strcpy
...
strcpy:

	subl	$8, %esp

...
It clearly invents strcpy, having never been referenced in the source.

The asm code you sent does _not_ call a global strcpy function. It calls an asm procedure named "strcpy" it ships itself.

BTW: You are the second person in this thread I have to explain this to...

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

Cheers,
Dick Johnson

cu
Adrian

Explain WHAT? There is NO strcpy in the code. No such procedure should have been called. Period. The generated code is defective.

Here is more information showing the defective code generation.

Output of nm

00000000 r hello
U printk
00000039 t strcpy
00000000 T xxx

Clearly shows a strcpy symbol when strcpy() was never referenced in the 'C' code.

Output of objdump

xxx.o: file format elf32-i386

Disassembly of section .text:

00000000 <xxx>:

   0:	81 ec 0c 01 00 00    	sub    $0x10c,%esp
   6:	89 9c 24 08 01 00 00 	mov    %ebx,0x108(%esp)
   d:	c7 44 24 04 00 00 00 	movl   $0x0,0x4(%esp)
  14:	00
  15:	8d 5c 24 08          	lea    0x8(%esp),%ebx
  19:	89 1c 24             	mov    %ebx,(%esp)
  1c:	e8 18 00 00 00       	call   39 <strcpy>
  21:	89 1c 24             	mov    %ebx,(%esp)
  24:	e8 fc ff ff ff       	call   25 <xxx+0x25>
  29:	8b 9c 24 08 01 00 00 	mov    0x108(%esp),%ebx
  30:	31 c0                	xor    %eax,%eax
  32:	81 c4 0c 01 00 00    	add    $0x10c,%esp

38: c3 ret

00000039 <strcpy>:

  39:	83 ec 08             	sub    $0x8,%esp
  3c:	8b 4c 24 0c          	mov    0xc(%esp),%ecx
  40:	89 34 24             	mov    %esi,(%esp)
  43:	89 7c 24 04          	mov    %edi,0x4(%esp)
  47:	8b 74 24 10          	mov    0x10(%esp),%esi
  4b:	89 cf                	mov    %ecx,%edi
  4d:	ac                   	lods   %ds:(%esi),%al
  4e:	aa                   	stos   %al,%es:(%edi)
  4f:	84 c0                	test   %al,%al
  51:	75 fa                	jne    4d <strcpy+0x14>
  53:	89 c8                	mov    %ecx,%eax
  55:	8b 34 24             	mov    (%esp),%esi
  58:	8b 7c 24 04          	mov    0x4(%esp),%edi
  5c:	83 c4 08             	add    $0x8,%esp
  5f:	c3                   	ret

[SNIPPED...]

Clearly shows a GLOBAL procedure called strcpy when no such procedure was ever referenced in the code.

Now I will show that the strcpy() procedure is NOT local. It's global and can screw up anything:

Another program....

char printk; // Just quiet the reference

					// ... just a label, never called.

extern int puts(const char *); // No header funnies
extern char *strcpy(char *, const char *);
int main(){
char buf[0x100];
strcpy(buf, "WTF?"); // Going to call it!
puts(buf);
return 0;
}

Show code generation.

$ gcc -S -o aaa zzz.c
	.file	"zzz.c"
	.section	.rodata
.LC0:
	.string	"WTF?"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$264, %esp
	andl	$-16, %esp
	movl	$0, %eax
	subl	%eax, %esp
	subl	$8, %esp
	pushl	$.LC0
	leal	-264(%ebp), %eax
	pushl	%eax
	call	strcpy			# Clearly calls it.
	addl	$16, %esp
	subl	$12, %esp
	leal	-264(%ebp), %eax
	pushl	%eax
	call	puts
	addl	$16, %esp
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.comm	printk,1,1
	.section	.note.GNU-stack,"",@progbits
	.ident	"GCC: (GNU) 3.3.3 20040412 (Red Hat Linux 3.3.3-7)"

Now compile and link with the file containing ROGUE strcpy().

$ gcc -o zzz zzz.c xxx.o
$ ./zzz
WTF?

Executes, calling a ROGUE function that MUST NOT exist.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#15 lore raw
In reply to Adrian Bunk
Quoted 8 lines · Adrian Bunk
Quoted 5 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

I saw it with 3.3-hammer, which had additional optimizations in this area at some point. Note that 3.3-hammer is widely used. I don't know if 3.4 does it in the same way.

-Andi

#16 lore raw
Quoted 6 lines · Andi Kleen
Quoted 5 lines · Adrian Bunk
Quoted 4 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

I saw it with 3.3-hammer, which had additional optimizations in this area at some point. Note that 3.3-hammer is widely used. I don't know if 3.4 does it in the same way.

Is this a -hammer specific problem?
If yes, does a -no-builtin-sprintf fix it?

Or is the problem a missing #include <linux/kernel.h> at the top of include/linux/string.h?

Quoted 1 line

-Andi

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#17 lore raw
Quoted 9 lines · Adrian Bunk
Quoted 8 lines · Andi Kleen
Quoted 7 lines · Adrian Bunk
Quoted 5 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Which gcc is "Newer"?

I saw it with 3.3-hammer, which had additional optimizations in this area at some point. Note that 3.3-hammer is widely used. I don't know if 3.4 does it in the same way.

Is this a -hammer specific problem?

No, I just checked a 4.0 mainline gcc and it does it too.

Note I saw it on x86-64, don't know if it occurs on i386 too.

-Andi

#18 lore raw

Use -ffreestanding?

Quoted 16 lines · Andi Kleen
Quoted 15 lines · Adrian Bunk
Quoted 13 lines · Andi Kleen
Quoted 8 lines · Adrian Bunk
Quoted 5 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

Which gcc is "Newer"?

I saw it with 3.3-hammer, which had additional optimizations in this area at some point. Note that 3.3-hammer is widely used. I don't know if 3.4 does it in the same way.

Quoted 5 lines
Quoted 1 line

Is this a -hammer specific problem?

No, I just checked a 4.0 mainline gcc and it does it too.

Note I saw it on x86-64, don't know if it occurs on i386 too.

OK, I see the difference:
After removing -fno-unit-at-a-time, I see this problem, too.

Why doesn't the kernel use -ffreestanding which should prevent all such problems?

Quoted 1 line

-Andi

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#19 lore raw

Re: Use -ffreestanding?

Quoted 2 lines

Why doesn't the kernel use -ffreestanding which should prevent all such problems?

Because we want most of these optimizations. Also with -ffreestanding you would need to supply the out of line string functions anyways because gcc wouldn't inline them.

-Andi

#20 lore raw

PATCH 1/1 Use -ffreestanding?

Quoted 4 lines · Andi Kleen
Quoted 2 lines

Why doesn't the kernel use -ffreestanding which should prevent all such problems?

Because we want most of these optimizations. Also with -ffreestanding

Do we really want the compiler to silently replace in-kernel functions with built-ins?

You can still do an explicit
#define strlen __builtin_strlen
if you want to use a gcc built-in function.

Quoted 2 lines

you would need to supply the out of line string functions anyways because gcc wouldn't inline them.

At least with gcc 3.4.2 on i386 adding -ffreestanding and your (i386-specific) IN_STRING_C hack removed compiles fine.

Quoted 1 line

-Andi

I'm open for examples why this actually doesn't work, but after my (limited) testin I'd suggest the patch below for inclusion in the next -mm.

Makefile renamed from Makefile.old +2 -1
@@ -349,7 +349,8 @@
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
-	  	   -fno-strict-aliasing -fno-common
+	  	   -fno-strict-aliasing -fno-common \
+		   -ffreestanding
 AFLAGS		:= -D__ASSEMBLY__
 
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
#21 lore raw

Re: [2.6 patch] Use -ffreestanding?

Quoted 4 lines · Adrian Bunk

I'm open for examples why this actually doesn't work, but after my (limited) testin I'd suggest the patch below for inclusion in the next -mm.

When was -ffreestanding introduced? Iow, it might not work with all compiler versions.. Apart from that, I think it makes sense.

Linus

#22 lore raw

Re: [2.6 patch] Use -ffreestanding?

Quoted 9 lines · Linus Torvalds
Quoted 4 lines · Adrian Bunk

I'm open for examples why this actually doesn't work, but after my (limited) testin I'd suggest the patch below for inclusion in the next -mm.

When was -ffreestanding introduced? Iow, it might not work with all compiler versions.. Apart from that, I think it makes sense.

It's supported in gcc 2.95 (which is the oldest compiler supported by kernel 2.6).

Quoted 1 line

Linus

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
#23 lore raw

Re: [2.6 patch] Use -ffreestanding?

In reply to Linus Torvalds
Quoted 8 lines · Linus Torvalds
Quoted 2 lines · Adrian Bunk

I'm open for examples why this actually doesn't work, but after my (limited) testin I'd suggest the patch below for inclusion in the next -mm.

When was -ffreestanding introduced? Iow, it might not work with all compiler versions.. Apart from that, I think it makes sense.

From RH 7.3:
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-113)

Signature · 3 lines
   -bill davidsen ([email protected])
"The secret to procrastination is to put things off until the
 last possible moment - but no longer"  -me
#24 lore raw
In reply to Andi Kleen
Quoted 7 lines · Andi Kleen
Quoted 3 lines

Rethinking it, I don't even understand the sprintf example in your changelog entry - shouldn't an inclusion of kernel.h always get it right?

Newer gcc rewrites sprintf(buf,"%s",str) to strcpy(buf,str) transparently.

-Andi

Hmmm, how does it get the correct return-value and type? I don't think that a compiler is allowed to change the function(s) called. If gcc is doing this now, there are many potential problems and it needs to be fixed. For instance, one can't qualify a 'C' runtime library and then have a compiler decide that it's not going to call the pre-qualified function.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

#25 lore raw
Quoted 1 line · linux-os

Hmmm, how does it get the correct return-value and type?

Presumably it does it only for sprintf() calls where the return value is ignored.

Quoted 2 lines

I don't
think that a compiler is allowed to change the function(s) called.

GCC is making the assumption that the functions it's replacing comply with the C standard. I personally don't think that's too insane, especially since it can be turned off (see below).

Quoted 4 lines

If gcc is doing this now, there are many potential problems and it needs to be fixed. For instance, one can't qualify a 'C' runtime library and then have a compiler decide that it's not going to call the pre-qualified function.

-fno-builtin

-Ryan

#26 lore raw
In reply to Adrian Bunk
Quoted 6 lines · Andi Kleen
Quoted 5 lines
Quoted 4 lines

Can you still reproduce this problem?
If not, I'll suggest to apply the patch below which saves a few kB in lib/string.o .

Quoted 8 lines
Quoted 5 lines

I would prefer to keep it because there is no guarantee in gcc that it always inlines all string functions unless you pass -minline-all-stringops. And with that the code would be bloated much more than the few out of lined fallback string functions.

If I understand your changelog entry correctly, this wasn't the problem (the asm string functions are "static inline").

Actually, shouldn't the string functions be "extern inline" then? That would mean we use the copy from lib/string.c instead of generating a new copy for each file in which gcc decides not to inline the function. It would also let you get rid of the IN_STRING_C hack that is needed to avoid the clash of the "static inline" and the "extern" version.

	Arnd <><
#27 lore raw
Quoted 12 lines · Arnd Bergmann
Quoted 12 lines · Andi Kleen
Quoted 10 lines
Quoted 4 lines

Can you still reproduce this problem?
If not, I'll suggest to apply the patch below which saves a few kB in lib/string.o .

I would prefer to keep it because there is no guarantee in gcc that it always inlines all string functions unless you pass -minline-all-stringops. And with that the code would be bloated much more than the few out of lined fallback string functions.

Quoted 7 lines
Quoted 2 lines

If I understand your changelog entry correctly, this wasn't the problem (the asm string functions are "static inline").

Actually, shouldn't the string functions be "extern inline" then? That would mean we use the copy from lib/string.c instead of generating a new copy for each file in which gcc decides not to inline the function.
...

In the kernel, we #define inline to __attribute__((always_inline)) [1] leaving gcc no room for a decision to not inline it.

Quoted 1 line
	Arnd <><

cu
Adrian

[1] only for gcc >= 3.1, but I don't remember problems with older gcc versions

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#30 lore raw
Quoted 25 lines · you
Quoted 24 lines · Pawe?? Sikora

...
[~/rpm/BUILD] # gcc -Wall sp.c -S -O2 -fomit-frame-pointer -mregparm=3
-nostdinc -isystem /usr/src/linux/include

sp.c: In function `test':
sp.c:7: warning: implicit declaration of function `sprintf'

[~/rpm/BUILD] # cat sp.s

        .file   "sp.c"
        .text
        .p2align 4,,15
.globl test
        .type   test, @function
test:
        movl    %eax, %edx
        movl    $buf, %eax
        jmp     strcpy
        .size   test, .-test
        .comm   buf,128,32
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.3 (PLD Linux)"
Quoted 3 lines
Quoted 1 line

What now?

Do a "make V=1" and use the complete gcc call you see there.

[~/rpm/BUILD/linux-2.6.10-rc1] #

gcc -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -Wdeclaration-after-statement -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium3 -Iinclude/asm-i386/mach-default -S sp.c

        .file   "sp.c"
        .text
        .p2align 4,,15
.globl test
        .type   test, @function
test:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        movl    $buf, (%esp)
        movl    8(%ebp), %eax
        movl    %eax, 4(%esp)
        call    strcpy

leave
ret
.size test, .-test
.p2align 4,,15
.type strcpy, @function
strcpy:

        pushl   %ebp
        movl    %esp, %ebp
        subl    $12, %esp
        movl    %esi, -8(%ebp)
        movl    8(%ebp), %edx
        movl    12(%ebp), %esi
        movl    %edi, -4(%ebp)
        movl    %edx, %edi

#APP
1: lodsb
stosb
testb %al,%al
jne 1b
#NO_APP

        movl    -8(%ebp), %esi
        movl    %edx, %eax
        movl    -4(%ebp), %edi
        movl    %ebp, %esp
        popl    %ebp
        ret
        .size   strcpy, .-strcpy
.globl buf
        .bss
        .align 32
        .type   buf, @object
        .size   buf, 128
buf:
        .zero   128
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.3 (PLD Linux)"
Signature · 3 lines
/* Copyright (C) 2003, SCO, Inc. This is valuable Intellectual Property. */

                           #define say(x) lie(x)
#31 lore raw
Quoted 9 lines · Pawe?? Sikora

gcc -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall

(quoted diff) +0 -3
-Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2
-Wdeclaration-after-statement -pipe -msoft-float -mpreferred-stack-boundary=2
-fno-unit-at-a-time -march=pentium3 -Iinclude/asm-i386/mach-default -S sp.c
 
...
        call    strcpy
...
Quoted 3 lines

strcpy:
pushl %ebp
...

That's no function call. :-)

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed