[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Will Schmidt changed: What|Removed |Added CC||willschm at gcc dot gnu.org --- Comment #9 from Will Schmidt --- (In reply to Segher Boessenkool from comment #5) > Have you tried a new valgrind? > > Either this is (or was) a known problem in valgrind, or it is related to > one. Cc:ing Aaron, he might know more (he wrote the GCC optimisations > that expose the problem). I've recreated against new (built out of upstream git) valgrind: with --track-origins=yes ==37507== argv[0]=./a.out ==37507== Use of uninitialised value of size 8 ==37507==at 0x1618: main (pr9862.C:16) ==37507== Uninitialised value was created by a stack allocation ==37507==at 0x17D4: isVariable(char*) (pr9862.C:5)
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #10 from Mark Wielaard --- (In reply to Will Schmidt from comment #9) > (In reply to Segher Boessenkool from comment #5) > > Have you tried a new valgrind? > > > > Either this is (or was) a known problem in valgrind, or it is related to > > one. Cc:ing Aaron, he might know more (he wrote the GCC optimisations > > that expose the problem). > > > I've recreated against new (built out of upstream git) valgrind: > with --track-origins=yes > > > ==37507== > argv[0]=./a.out > ==37507== Use of uninitialised value of size 8 > ==37507==at 0x1618: main (pr9862.C:16) > ==37507== Uninitialised value was created by a stack allocation > ==37507==at 0x17D4: isVariable(char*) (pr9862.C:5) Trying to get hold of a ppc64 setup. But could you try with --vgdb-error=0 and then (in another window) gdb ./a.out and target remote | vgdb and continue till you get the TRAP. Then disassamble so we can see the exact instruction that generates the use of uninitialised value?
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #11 from Will Schmidt --- (In reply to Mark Wielaard from comment #10) > (In reply to Will Schmidt from comment #9) > > (In reply to Segher Boessenkool from comment #5) > > > Have you tried a new valgrind? > > > > > > Either this is (or was) a known problem in valgrind, or it is related to > > > one. Cc:ing Aaron, he might know more (he wrote the GCC optimisations > > > that expose the problem). > > > > > > I've recreated against new (built out of upstream git) valgrind: > > with --track-origins=yes > > > > > > ==37507== > > argv[0]=./a.out > > ==37507== Use of uninitialised value of size 8 > > ==37507==at 0x1618: main (pr9862.C:16) > > ==37507== Uninitialised value was created by a stack allocation > > ==37507==at 0x17D4: isVariable(char*) (pr9862.C:5) > > Trying to get hold of a ppc64 setup. But could you try with --vgdb-error=0 > and then (in another window) gdb ./a.out and target remote | vgdb and > continue till you get the TRAP. Then disassamble so we can see the exact > instruction that generates the use of uninitialised value? Yes. so this traps on a ld instruction upon the return from the isVariable call. As seen below here: Window #1: ==79608== argv[0]=./a.out ==79608== Use of uninitialised value of size 8 ==79608==at 0x1618: main (pr9862.C:16) ==79608== Uninitialised value was created by a stack allocation ==79608==at 0x17D4: isVariable(char*) (pr9862.C:5) ==79608== ==79608== (action on error) vgdb me ... Window #2: (gdb) target remote | vgdb Remote debugging using | vgdb relaying data between gdb and process 79608 warning: remote target does not support file transfer, attempting to access files from local filesystem. Reading symbols from /lib64/ld64.so.2... (No debugging symbols found in /lib64/ld64.so.2) 0x04001720 in ?? () from /lib64/ld64.so.2 (gdb) (gdb) set disassemble-next-line on (gdb) c Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. main (argc=, argv=0x1fff00e8a8) at pr9862.C:16 16len = __builtin_strlen (argv[1]); => 0x1618 : 08 00 7f e8 ld r3,8(r31) 0x161c : a5 ff ff 4b bl 0x15c0 <0037.plt_call.strlen@@GLIBC_2.17> 0x1620 : 18 00 41 e8 ld r2,24(r1) 0x1624 : 00 00 00 60 nop 0x1628 : 70 00 21 38 addi r1,r1,112 0x162c : 50 81 62 90 stw r3,-32432(r2) (gdb) disas Dump of assembler code for function main(int, char**): 0x15e0 <+0>: lis r2,4098 0x15e4 <+4>: addir2,r2,32512 0x15e8 <+8>: mflrr0 0x15ec <+12>:std r31,-8(r1) 0x15f0 <+16>:addis r3,r2,-2 0x15f4 <+20>:mr r31,r4 0x15f8 <+24>:addir3,r3,-29882 0x15fc <+28>:std r0,16(r1) 0x1600 <+32>:stdur1,-112(r1) 0x1604 <+36>:ld r4,0(r4) 0x1608 <+40>:bl 0x1580 <0037.plt_call.printf@@GLIBC_2.17> 0x160c <+44>:ld r2,24(r1) 0x1610 <+48>:ld r3,0(r31) 0x1614 <+52>:bl 0x17c4 => 0x1618 <+56>:ld r3,8(r31) 0x161c <+60>:bl 0x15c0 <0037.plt_call.strlen@@GLIBC_2.17> 0x1620 <+64>:ld r2,24(r1) 0x1624 <+68>:nop 0x1628 <+72>:addir1,r1,112 0x162c <+76>:stw r3,-32432(r2) 0x1630 <+80>:li r3,0 0x1634 <+84>:b 0x198c <_restgpr0_31> 0x1638 <+88>:.long 0x0 0x163c <+92>:.long 0x1000900 0x1640 <+96>:.long 0x180 End of assembler dump. (gdb) WIndow#1:
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #12 from Mark Wielaard --- OK, so according to memcheck the load uses a pointer value that isn't initialized properly. And it thinks that value originated from a stack value in the isVariable call. Unfortunately my powerpc assembly is not strong enough to know how to read this precisely, what the calling conventions are and how the address is setup in isVariable.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #13 from Mark Wielaard --- I could replicate this with gcc 9.1.1 with the following source: #define variables (const char* []){ "PK", "KEK", "db"} int ret, len; void isVariable(char *var) { for (int v = 0; v < 2; v++) if (__builtin_strncmp(var,variables[v], 2) == 0) ret = 0; } int main(int argc, char* argv[]) { // __builtin_printf ("argv[0]=%s\n", argv[0]); isVariable(argv[0]); len = __builtin_strlen (argv[0]); return 0; } compiled with gcc -g -Os and valgrind from git trunk with --vgdb=full --track-origins=yes: ==25741== Command: ./a.out ==25741== ==25741== Use of uninitialised value of size 8 ==25741==at 0x1504: main (pr9862.C:16) ==25741== Uninitialised value was created by a stack allocation ==25741==at 0x16C4: isVariable(char*) (pr9862.C:6) ==25741== Disassambly of main and isVariable Dump of assembler code for function main(int, char**): 0x14e0 <+0>: lis r2,4098 0x14e4 <+4>: addir2,r2,32512 0x14e8 <+8>: mflrr0 0x14ec <+12>:std r31,-8(r1) 0x14f0 <+16>:ld r3,0(r4) 0x14f4 <+20>:mr r31,r4 0x14f8 <+24>:std r0,16(r1) 0x14fc <+28>:stdur1,-48(r1) 0x1500 <+32>:bl 0x16b4 0x1504 <+36>:ld r3,0(r31) 0x1508 <+40>:bl 0x14a0 <0023.plt_call.strlen@@GLIBC_2.17> 0x150c <+44>:ld r2,24(r1) 0x1510 <+48>:nop 0x1514 <+52>:addir1,r1,48 0x1518 <+56>:stw r3,-32452(r2) 0x151c <+60>:li r3,0 0x1520 <+64>:b 0x186c <_restgpr0_31> 0x1524 <+68>:.long 0x0 0x1528 <+72>:.long 0x1000900 0x152c <+76>:.long 0x180 End of assembler dump. Dump of assembler code for function isVariable(char*): 0x16ac <+0>: lis r2,4098 0x16b0 <+4>: addir2,r2,32512 0x16b4 <+8>: mflrr0 0x16b8 <+12>:addis r9,r2,-2 0x16bc <+16>:addir9,r9,-30152 0x16c0 <+20>:bl 0x1820 <_savegpr0_25> 0x16c4 <+24>:stdur1,-128(r1) 0x16c8 <+28>:ld r29,0(r9) 0x16cc <+32>:ld r28,8(r9) 0x16d0 <+36>:nop 0x16d4 <+40>:mr r30,r3 0x16d8 <+44>:ld r27,16(r9) 0x16dc <+48>:li r31,0 0x16e0 <+52>:addir25,r2,-32456 0x16e4 <+56>:addir26,r1,32 0x16e8 <+60>:std r29,32(r1) 0x16ec <+64>:std r28,40(r1) 0x16f0 <+68>:rldicr r9,r31,3,60 0x16f4 <+72>:li r5,2 0x16f8 <+76>:std r27,48(r1) 0x16fc <+80>:mr r3,r30 0x1700 <+84>:ldx r4,r26,r9 0x1704 <+88>:bl 0x14c0 <0023.plt_call.strncmp@@GLIBC_2.17> 0x1708 <+92>:ld r2,24(r1) 0x170c <+96>:mr. r9,r3 0x1710 <+100>: bne 0x1718 0x1714 <+104>: stw r9,0(r25) 0x1718 <+108>: cmpldi r31,1 0x171c <+112>: bne 0x1728 0x1720 <+116>: addir1,r1,128 0x1724 <+120>: b 0x1844 <_restgpr0_25> 0x1728 <+124>: li r31,1 0x172c <+128>: b 0x16e8 0x1730 <+132>: .long 0x0 0x1734 <+136>: .long 0x1000900 0x1738 <+140>: .long 0x780 End of assembler dump.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #14 from Will Schmidt --- Using gdb/vgdb to view the valgrind shadow register values, it looks like the uninitialized values are being loaded in via the _restgpr0_25 call being made at the end of isVariable(). Dump of assembler code for function isVariable(char*): 0x16ac <+0>: lis r2,4098 0x16b0 <+4>: addir2,r2,32512 0x16b4 <+8>: mflrr0 0x16b8 <+12>:addis r9,r2,-2 0x16bc <+16>:addir9,r9,-30152 (here: r1 is 0x1fff00e440 ; shadow registers r24..r31 show zero). 0x16c0 <+20>:bl 0x1820 <_savegpr0_25> savegpr0_25 stores r25 thru r31 into the stack (offset of r1) 0x16c4 <+24>:stdur1,-128(r1) And stack pointer updates itself. r1 is now 0x1fff00e3c0 0x16c8 <+28>:ld r29,0(r9) 0x16cc <+32>:ld r28,8(r9) 0x16d0 <+36>:nop 0x16d4 <+40>:mr r30,r3 0x16d8 <+44>:ld r27,16(r9) 0x16dc <+48>:li r31,0 0x16e0 <+52>:addir25,r2,-32456 0x16e4 <+56>:addir26,r1,32 0x16e8 <+60>:std r29,32(r1) 0x16ec <+64>:std r28,40(r1) 0x16f0 <+68>:rldicr r9,r31,3,60 0x16f4 <+72>:li r5,2 0x16f8 <+76>:std r27,48(r1) 0x16fc <+80>:mr r3,r30 0x1700 <+84>:ldx r4,r26,r9 0x1704 <+88>:bl 0x14c0 <0023.plt_call.strncmp@@GLIBC_2.17> 0x1708 <+92>:ld r2,24(r1) 0x170c <+96>:mr. r9,r3 0x1710 <+100>: bne 0x1718 0x1714 <+104>: stw r9,0(r25) 0x1718 <+108>: cmpldi r31,1 0x171c <+112>: bne 0x1728 r1 still 0x1fff00e3c0 0x1720 <+116>: addir1,r1,128 now r1 is 0x1fff00e440 0x1724 <+120>: b 0x1844 <_restgpr0_25> and as we progress through restoring the regs, the valgrind shadow registers are indicating the values are uninitialized as they are restored off the stack (r1). 0x1964 <_restgpr0_25>: ld r25,-56(r1) (gdb) p/x $r25s1 $29 = 0x (gdb) p/x $r26s1 $31 = 0x0 => 0x1968 <_restgpr0_26>: ld r26,-48(r1) (gdb) p/x $r26s1 $32 = 0x 0x196c <_restgpr0_27>: ld r27,-40(r1) 0x1970 <_restgpr0_28>: ld r28,-32(r1) 0x1974 <_restgpr0_29>: ld r0,16(r1) The _restgpr* and _savegpr* functions are not referenced when the test is built at other optimization levels. (I've looked at disassembly from -O0 .. -O4). I do note that the _restgpr and _savegpr functions are called differently. savegpr is called with bl while the restgpr is called via a direct branch; i can't immediately tell if this is by design or if it is in error. 17d0: 71 01 00 48 bl 1940 <_savegpr0_25> 1834: 30 01 00 48 b 1964 <_restgpr0_25>
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #15 from Segher Boessenkool --- (In reply to Will Schmidt from comment #14) > The _restgpr* and _savegpr* functions are not referenced when the test is > built at other optimization levels. (I've looked at disassembly from -O0 .. > -O4). Right, it is a size optimisation. > I do note that the _restgpr and _savegpr functions are called differently. > savegpr is called with bl while the restgpr is called via a direct branch; i > can't immediately tell if this is by design or if it is in error. It is by design: these are special functions defined by the ABI, specifically to save some code space.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #16 from Segher Boessenkool --- (In reply to Mark Wielaard from comment #13) > ==25741== Use of uninitialised value of size 8 > ==25741==at 0x1504: main (pr9862.C:16) r4 is argv here >0x14f0 <+16>: ld r3,0(r4) r3 = argv[0]; >0x14f4 <+20>: mr r31,r4 r31 = argv; // because we need it after the call, save it in a non-volatile reg >0x14f8 <+24>: std r0,16(r1) >0x14fc <+28>: stdur1,-48(r1) >0x1500 <+32>: bl 0x16b4 The call; after this we have to load argv[0] again, the called function might have changed it. >0x1504 <+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 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?
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #17 from Mark Wielaard --- 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 0x1504: main (pr9862.C:16) > > r4 is argv here > >0x14f0 <+16>:ld r3,0(r4) > r3 = argv[0]; > >0x14f4 <+20>:mr r31,r4 > r31 = argv; // because we need it after the call, save it in a non-volatile > reg > >0x14f8 <+24>:std r0,16(r1) > >0x14fc <+28>:stdur1,-48(r1) > >0x1500 <+32>:bl 0x16b4 > The call; after this we have to load argv[0] again, the called function might > have changed it. > >0x1504 <+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: 0x16c0 <+20>:bl 0x1820 <_savegpr0_25> 0x16c4 <+24>:stdur1,-128(r1) [...] 0x1720 <+116>: addir1,r1,128 0x1724 <+120>: b 0x1844 <_restgpr0_25> It looks like it interprets those stack pointer moves as invalidating the values stored on the stack.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #18 from Mark Wielaard --- The current thinking (Julian did the thinking, I am just repeating) is that this is caused by the way the _savegpr and/or restgpr functions return using blr. PPC has two special "lets zap the red zone" (the 288 bytes below the stack pointer) cases: # define VG_STACK_REDZONE_SZB288 // number of addressable bytes below R1 // from 64-bit PowerPC ELF ABI // Supplement 1.7 guest_ppc_zap_RZ_at_blr guest is ppc64-linux==> True guest is ppc32-linux==> False guest is other ==> inapplicable guest_ppc_zap_RZ_at_bl guest is ppc64-linux==> const True guest is ppc32-linux==> const False guest is other ==> inapplicable guest_stack_redzone_size guest is ppc32-linux==> 0 guest is ppc64-linux==> 288 guest is amd64-linux==> 128 guest is other ==> inapplicable /* PPC and AMD64 GUESTS only: how many bytes below the stack pointer are validly addressible? */ Int guest_stack_redzone_size; /* PPC GUESTS only: should we zap the stack red zone at a 'blr' (function return) ? */ Bool guest_ppc_zap_RZ_at_blr; /* PPC GUESTS only: should we zap the stack red zone at a 'bl' (function call) ? Is supplied with the guest address of the target of the call since that may be significant. If NULL, is assumed equivalent to a fn which always returns False. */ Bool (*guest_ppc_zap_RZ_at_bl)(Addr); # if defined(VGP_ppc32_linux) vex_abiinfo.guest_ppc_zap_RZ_at_blr= False; vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL; # endif # if defined(VGP_ppc64be_linux) vex_abiinfo.guest_ppc_zap_RZ_at_blr= True; vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; vex_abiinfo.host_ppc_calls_use_fndescrs= True; # endif # if defined(VGP_ppc64le_linux) vex_abiinfo.guest_ppc_zap_RZ_at_blr= True; vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; vex_abiinfo.host_ppc_calls_use_fndescrs= False; # endif What happens on a blr function return is that, based on the guest_ppc_zap_RZ_at_blr value, the redzone is marked as containing undefined values. And indeed, with this patch: diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 332202a91..6dd01afac 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -1709,7 +1709,7 @@ Bool VG_(translate) ( ThreadId tid, # endif # if defined(VGP_ppc64le_linux) - vex_abiinfo.guest_ppc_zap_RZ_at_blr= True; + vex_abiinfo.guest_ppc_zap_RZ_at_blr= False; vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; vex_abiinfo.host_ppc_calls_use_fndescrs= False; # endif The warning goes away. But is that the right thing to do always? It seems to mask issues where a function is using the red zone values set by another function.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 jseward at acm dot org changed: What|Removed |Added CC||jseward at acm dot org --- Comment #19 from jseward at acm dot org --- (In reply to Mark Wielaard from comment #18) (expanding marginally on Mark's comment) Currently the Memcheck ppc64be and ppc64le ports assume that the redzone (the 288 bytes below SP) is volatile across both calls and returns, and it enforces this behaviour by painting that area of memory as "undefined" for both calls and returns. But the optimisation discussed here appears to carry live data across a return (that's what a "blr" is, right?) So in effect the problem occurs because this optimisation changes the ABI semantics that Memcheck has thus far assumed. As Mark says, we can "fix" this just by disabling the zap-on-return instrumentation behaviour, but that comes at the cost of completely losing the ability to detect genuinely incorrect uses of the redzone across a return.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #20 from Jakub Jelinek --- Can you disable it just for these magic entrypoints (either by name or by content)?
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #21 from jseward at acm dot org --- (In reply to Jakub Jelinek from comment #20) > Can you disable it just for these magic entrypoints (either by name or by > content)? In principle yes. I prefer by-content rather than by-name, in the case where all symbol names have disappeared or changed, etc. However, this would require having a reliable mechanism for detecting the entry points by inspecting their content. It would also require a certain amount of plumbing work, basically making `VexAbiInfo::guest_ppc_zap_RZ_at_blr` be a function rather than a Bool, in the same way that `VexAbiInfo::guest_ppc_zap_RZ_at_bl` already is. It might be a day or two's work to set up and test, once we had a reliable identify-by-content routine available.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #22 from jseward at acm dot org --- Looking back at the above, it's now clearer what the problem is: # Park potentially live data in the red zone _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) # And ka-zap! Memcheck paints -288(r1) .. -1(r1) as undefined. blr # So now they're all "unusable".
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #23 from Segher Boessenkool --- savegpr/restgpr are special ABI-defined functions that do not have all the same ABI calling conventions as normal functions. They indeed write into the parent's frame (red zone, in this case). Maybe you should allow this always when a function has not established a new frame? That always has to be done with a stdu 1,...(1) insn (in 64-bit; stwu in 32-bit, but the 32-bit Linux ABI has no red zone anyway) so it probably isn't too hard to detect. Only leaf functions will not establish a new frame normally (but that can happen later in the function, esp. with shrink-wrapping). Unstacking a frame is most other things that write to r1, often addi 1,1,... and sometimes ld 1,0(1) (there probably are other cases too that I am forgetting here). Maybe you should invalidate the red zone whenever r1 is changed, instead?
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #24 from Segher Boessenkool --- I do see the problems for savegpr/restgpr with that suggestion, but maybe something in that vein can be done.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #1 from Nick Child --- Created attachment 49971 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49971&action=edit source
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Martin Liška changed: What|Removed |Added CC||marxin at gcc dot gnu.org Ever confirmed|0 |1 Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2021-01-15 Assignee|unassigned at gcc dot gnu.org |marxin at gcc dot gnu.org --- Comment #2 from Martin Liška --- Confirmed, working on that..
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Martin Liška changed: What|Removed |Added CC||segher at gcc dot gnu.org Status|ASSIGNED|NEW Assignee|marxin at gcc dot gnu.org |unassigned at gcc dot gnu.org --- Comment #3 from Martin Liška --- A bit reduced test-case: $ cat pr9862.C #define variables (const char* []){ "PK", "KEK", "db"} int ret, len; void isVariable(char *var) { for (int v = 0; v < 2; v++) if (__builtin_strncmp(var,variables[v], 2) == 0) ret = 0; } int main(int argc, char* argv[]) { __builtin_printf ("argv[0]=%s\n", argv[0]); isVariable(argv[0]); len = __builtin_strlen (argv[0]); return 0; } $ g++ pr9862.C -g -Os && valgrind --expensive-definedness-checks=yes ./a.out ==54436== Memcheck, a memory error detector ==54436== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==54436== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==54436== Command: ./a.out ==54436== argv[0]=./a.out ==54436== Use of uninitialised value of size 8 ==54436==at 0x15F8: main (pr9862.C:16) Can please anybody from Power folks take a look?
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #4 from Segher Boessenkool --- Are you sure that target is correct?!
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Segher Boessenkool changed: What|Removed |Added CC||acsawdey at gcc dot gnu.org --- Comment #5 from Segher Boessenkool --- Have you tried a new valgrind? Either this is (or was) a known problem in valgrind, or it is related to one. Cc:ing Aaron, he might know more (he wrote the GCC optimisations that expose the problem).
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 Martin Liška changed: What|Removed |Added Host|powerpcle-*-linux-gnu* |powerpc64le-linux-gnu Build|powerpcle-*-linux-gnu* |powerpc64le-linux-gnu Target|powerpcle-*-linux-gnu* |powerpc64le-linux-gnu --- Comment #6 from Martin Liška --- Fixed target, it's ppc64le and I can reproduce it on gcc112.fsffrance.org machine. It contains valgrind 3.15 which is pretty new.
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #7 from acsawdey at gcc dot gnu.org --- The inline expansion should be disabled by -Os, the patterns for cmpstr[n]si both have this: if (optimize_insn_for_size_p ()) FAIL;
[Bug rtl-optimization/98692] Unitialized Values reported only with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692 --- Comment #8 from Nick Child --- Hello all, Thanks for taking a look at this. In response to some questions: I am using Valgrind 3.16.1 (latest release). And I have encountered this issue on a Power 8 and Power 9 LE machine with multiple versions of RHEL and on Ubuntu. Thanks again, Nick