[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