[PATCH 1/3] fix literal error warning

Manuel Zerpies manuel.f.zerpies at ww.stud.uni-erlangen.de
Wed Aug 15 18:16:22 UTC 2012


Hi Laurent, hej guys,

>  Worse: these changes are *harmful*.
> 
>  It's ugly, and we really should not rely on that, and Manuel cannot be
> blamed for not knowing it, but gcc performs a lot of magic around printf().
> In this case, the bit of magic that interests us is that
>   printf(CONSTANT)
> gets automagically replaced with
>   fputs(CONSTANT, stdout)

In my tests, with optimization flags and so on, this optimization is
never performed. Nevertheless printf() is replaced with puts() under
certain conditions. The printf() call must be equivalent to the puts()
call. In busybox the const char variables prevent this optimization
because a '\n' is missing at the end of the string.

> (You can test it by dynamically linking a minimal test program using
> printf to write a constant string, and objdumping the resulting
> binary. You will see a reference to fputs and no reference to printf.)

Did that with the following code:

#include <stdio.h>

int main () {
    const char *s = "hello world\n";
    const char *nonl = "hello world2";
    printf ("%s", s);
    printf ("\n");
    printf (s);
    printf ("no newline");
    printf (nonl);
    return 0;
}

The disassembly looks like that:

   0x00000000004004d0 <+0>:     sub    $0x8,%rsp
   0x00000000004004d4 <+4>:     mov    $0x4006ec,%edi
   0x00000000004004d9 <+9>:     callq  0x4004a0 <puts at plt>
   0x00000000004004de <+14>:    mov    $0xa,%edi
   0x00000000004004e3 <+19>:    callq  0x400490 <putchar at plt>
   0x00000000004004e8 <+24>:    mov    $0x4006ec,%edi
   0x00000000004004ed <+29>:    callq  0x4004a0 <puts at plt>
   0x00000000004004f2 <+34>:    mov    $0x4006f8,%esi
   0x00000000004004f7 <+39>:    mov    $0x1,%edi
   0x00000000004004fc <+44>:    xor    %eax,%eax
   0x00000000004004fe <+46>:    callq  0x4004c0 <__printf_chk at plt>
   0x0000000000400503 <+51>:    mov    $0x400703,%esi
   0x0000000000400508 <+56>:    mov    $0x1,%edi
   0x000000000040050d <+61>:    xor    %eax,%eax
   0x000000000040050f <+63>:    callq  0x4004c0 <__printf_chk at plt>
   0x0000000000400514 <+68>:    xor    %eax,%eax
   0x0000000000400516 <+70>:    add    $0x8,%rsp
   0x000000000040051a <+74>:    retq

Here you see, that the optimization only is performed, when it can be
transformed without loss of information (newline).

>  So, since bb_msg_memory_exhausted is constant, the printf part of
>    bb_error_msg_and_die(bb_msg_memory_exhausted);
> is correctly optimized into
>    fputs(bb_msg_memory_exhausted, stdout);
> whereas
>    bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
> uses the full printf() call - which behaves correctly, but is
> suboptimal.

The vasprintf()-part is not optimized to whatever. I tested that with
the following code:

#include <stdio.h>
#include <stdarg.h>

void myprintf(const char* amount, ...)
{
	va_list pointer;
	va_start(pointer,amount);
	char no[100];
	vasprintf(no, amount, pointer);
	va_end(pointer);
	printf(no);
}

int main() {
	const char *foo = "constant char thing";
	myprintf(foo);
}

This is the disassembly of the myprintf()-function where I tried to
examin the behavior of vasprintf() and whether it is optimized or not:

   0x080486c0 <+0>:     push   %ebp
   0x080486c1 <+1>:     mov    %esp,%ebp
   0x080486c3 <+3>:     push   %ebx
   0x080486c4 <+4>:     sub    $0x84,%esp
   0x080486ca <+10>:    mov    %gs:0x14,%eax
   0x080486d0 <+16>:    mov    %eax,-0xc(%ebp)
   0x080486d3 <+19>:    xor    %eax,%eax
   0x080486d5 <+21>:    lea    0xc(%ebp),%eax
   0x080486d8 <+24>:    mov    %eax,0x8(%esp)
   0x080486dc <+28>:    mov    0x8(%ebp),%eax
   0x080486df <+31>:    lea    -0x70(%ebp),%ebx
   0x080486e2 <+34>:    mov    %ebx,(%esp)
   0x080486e5 <+37>:    mov    %eax,0x4(%esp)
   0x080486e9 <+41>:    call   0x80485e8 <vasprintf at plt>
   0x080486ee <+46>:    mov    %ebx,0x4(%esp)
   0x080486f2 <+50>:    movl   $0x1,(%esp)
   0x080486f9 <+57>:    call   0x80485b8 <__printf_chk at plt>
   0x080486fe <+62>:    mov    -0xc(%ebp),%eax
   0x08048701 <+65>:    xor    %gs:0x14,%eax
   0x08048708 <+72>:    jne    0x8048713 <myprintf+83>
   0x0804870a <+74>:    add    $0x84,%esp
   0x08048710 <+80>:    pop    %ebx
   0x08048711 <+81>:    pop    %ebp
   0x08048712 <+82>:    ret    
   0x08048713 <+83>:    call   0x80485d8 <__stack_chk_fail at plt>


>  They fix the spurious warnings, but prevent fputs() optimizations
> from being performed.

This optimization won't be performed as said before.

If I missed something please let me know.

Greets,
Manuel


More information about the busybox mailing list