https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692

--- Comment #17 from Mark Wielaard <mark at gcc dot gnu.org> ---
Thanks for the step-by-step explanation of the assembly instructions and
calling conventions.

(In reply to Segher Boessenkool from comment #16)
> (In reply to Mark Wielaard from comment #13)
> > ==25741== Use of uninitialised value of size 8
> > ==25741==    at 0x10000504: main (pr9862.C:16)
> 
> r4 is argv here
> >    0x00000000100004f0 <+16>:        ld      r3,0(r4)
> r3 = argv[0];
> >    0x00000000100004f4 <+20>:        mr      r31,r4
> r31 = argv; // because we need it after the call, save it in a non-volatile
> reg
> >    0x00000000100004f8 <+24>:        std     r0,16(r1)
> >    0x00000000100004fc <+28>:        stdu    r1,-48(r1)
> >    0x0000000010000500 <+32>:        bl      0x100006b4 <isVariable(char*)+8>
> The call; after this we have to load argv[0] again, the called function might
> have changed it.
> >    0x0000000010000504 <+36>:        ld      r3,0(r31)
> r3 = argv[0];
> 
> So it is funny that the exact same insn four insns earlier (in the program
> text)
> worked fine, but this one fails.

The different (according to valgrind) is that r4 has a defined value, while it
believes r31 has an undefined value after the isVariable call.

> The ABI says (taken from the ELFv1 ABI, the ELFv2 doc is not nice for
> copy/paste):
> 
> 
> Here is a sample implementation of _savegpr0_N and _restgpr0_N.
> 
>   _savegpr0_14:  std  r14,-144(r1)
>   _savegpr0_15:  std  r15,-136(r1)
>   _savegpr0_16:  std  r16,-128(r1)
>   _savegpr0_17:  std  r17,-120(r1)
>   _savegpr0_18:  std  r18,-112(r1)
>   _savegpr0_19:  std  r19,-104(r1)
>   _savegpr0_20:  std  r20,-96(r1)
>   _savegpr0_21:  std  r21,-88(r1)
>   _savegpr0_22:  std  r22,-80(r1)
>   _savegpr0_23:  std  r23,-72(r1)
>   _savegpr0_24:  std  r24,-64(r1)
>   _savegpr0_25:  std  r25,-56(r1)
>   _savegpr0_26:  std  r26,-48(r1)
>   _savegpr0_27:  std  r27,-40(r1)
>   _savegpr0_28:  std  r28,-32(r1)
>   _savegpr0_29:  std  r29,-24(r1)
>   _savegpr0_30:  std  r30,-16(r1)
>   _savegpr0_31:  std  r31,-8(r1)
>                  std  r0, 16(r1)
>                  blr
>   _restgpr0_14:  ld   r14,-144(r1)
>   _restgpr0_15:  ld   r15,-136(r1)
>   _restgpr0_16:  ld   r16,-128(r1)
>   _restgpr0_17:  ld   r17,-120(r1)
>   _restgpr0_18:  ld   r18,-112(r1)
>   _restgpr0_19:  ld   r19,-104(r1)
>   _restgpr0_20:  ld   r20,-96(r1)
>   _restgpr0_21:  ld   r21,-88(r1)
>   _restgpr0_22:  ld   r22,-80(r1)
>   _restgpr0_23:  ld   r23,-72(r1)
>   _restgpr0_24:  ld   r24,-64(r1)
>   _restgpr0_25:  ld   r25,-56(r1)
>   _restgpr0_26:  ld   r26,-48(r1)
>   _restgpr0_27:  ld   r27,-40(r1)
>   _restgpr0_28:  ld   r28,-32(r1)
>   _restgpr0_29:  ld   r0, 16(r1)
>                  ld   r29,-24(r1)
>                  mtlr r0
>                  ld   r30,-16(r1)
>                  ld   r31,-8(r1)
>                  blr
>   _restgpr0_30:  ld   r30,-16(r1)
>   _restgpr0_31:  ld   r0, 16(r1)
>                  ld   r31,-8(r1)
>                  mtlr r0
>                  blr
> 
> So this is one function with many entry points you could say.  Maybe that is
> what confused valgrind?

So for some reason valgrind doesn't believe the stack value for -8(r1) is valid
when r31 is restored.

What seems to confuse valgrind is:

   0x00000000100006c0 <+20>:    bl      0x10000820 <_savegpr0_25>
   0x00000000100006c4 <+24>:    stdu    r1,-128(r1)
   [...]
   0x0000000010000720 <+116>:   addi    r1,r1,128
   0x0000000010000724 <+120>:   b       0x10000844 <_restgpr0_25>

It looks like it interprets those stack pointer moves as invalidating the
values stored on the stack.

Reply via email to