https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120165
Michael Karcher <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |gcc-bugzilla@michael-karche | |r.net --- Comment #7 from Michael Karcher <[email protected]> --- This is due to a miscompilation of libiberty_vprintf_buffer_size if -fomit-frame-pointer is active, which usually is the case in -O2 builds. I used this command to compile vprintf-support.c: $ BUILDROOT=$HOME/gcc/build $ glaubitz@mitchy:~/gcc/libiberty$ $BUILDROOT/prev-gcc/xgcc -B$BUILDROOT/prev-gcc/ -S -O2 -I../include -DHAVE_STRING_H -DHAVE_STDLIB_H vprintf-support.c -o - The issue is in the compilation of line 174 of vprintf-support.v total_width += strlen (va_arg (ap, char *)); specifically, the subexpression va_arg(ap, char*), which is basically supposed to pick a char* from where ap points to, and then advance ap by four bytes (one machine word). The relevant excerpt of the assembly generated is: ; --- somewhere in libiberty_vprintf_buffer_size: move.l 36(%sp),%a0 ; load current "ap" into %a0 move.b (%a6),%d1 cmp.b #46,%d1 ; 85 if (*p == '.') jne .L9 ; --- snip snap --- .L9: clr.l %d0 .L12: addq.l #1,%a6 ; 101/106/110/114 ++p; ; --- nothing involving %a0 --- cmp.b #112,%d1 ; 176 case 'p': jgt .L18 ; --- snip snap --- .L18: cmp.b #115,%d1 ; 173 case 's': jne .L35 move.l %a0,36(%sp) ; store %a0 back into "ap" (for whatever reason) move.l (%a0)+,-(%sp) ; push the current vararg onto the stack for strlen move.l %a0,36(%sp) ; try to update "ap" (but miss due to changed SP) jsr strlen On the other hand, with "-fno-omit-frame-pointer" added, the excerpt changes to move.l 12(%fp),%a4 ; load current "ap" to %a4 move.b (%a2),%d1 cmp.b #46,%d1 jne .L9 ; --- snip snap --- .L9: clr.l %d0 .L12: addq.l #1,%a2 ; --- nothing involving %a4 --- cmp.b #112,%d1 jgt .L18 ; --- snip snap --- .L18: cmp.b #115,%d1 jne .L35 move.l %a4,%a0 ; copy %a4 (current "ap") to %a0 move.l (%a0)+,-(%sp) ; push current arg, advance %a0 move.l %a0,12(%fp) ; store %a0 to the correct location jsr strlen
