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

Reply via email to