]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
memcheck powerpc subfe x, x, x initializes x to 0 or -1 based on CA
authorMark Wielaard <mark@klomp.org>
Thu, 21 Feb 2019 16:21:53 +0000 (17:21 +0100)
committerMark Wielaard <mark@klomp.org>
Thu, 21 Feb 2019 16:21:53 +0000 (17:21 +0100)
GCC might use subfe x, x, x to initialize x to 0 or -1, based on
whether the carry flag is set. This happens in some cases when g++
compiles resetting a unique_ptr. The "trick" used by the compiler is
that it can AND a pointer with the register x (now 0x0 or 0xffffffff)
to set something to NULL or to the given pointer.

subfe is implemented as rD = (log not)rA + rB + XER[CA]
if we instead implement it as rD = rB - rA - (XER[CA] ^ 1)
then memcheck can see that rB and Ra cancel each other out if they
are the same.

https://bugs.kde.org/show_bug.cgi?id=404054

NEWS
VEX/priv/guest_ppc_toIR.c

diff --git a/NEWS b/NEWS
index 4a75a0aa3d6ac4dcce001b795eb526a9f66a68f9..3dfdacf426608fb67a94044ed2f5d13ec77df910 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -102,6 +102,7 @@ where XXXXXX is the bug number as listed below.
 402519  POWER 3.0 addex instruction incorrectly implemented
 402781  Redo the cache used to process indirect branch targets
 403552  s390x: wrong facility bit checked for vector facility
+404054  memcheck powerpc subfe x, x, x initializes x to 0 or -1 based on CA
 
 n-i-bz  add syswrap for PTRACE_GET|SET_THREAD_AREA on amd64.
 n-i-bz  Fix callgrind_annotate non deterministic order for equal total
index e2076426828037eb390ea1c9bd4379b869e73daa..00ae6df2d6010a18ca068b87ea0e8c57aa0098b9 100644 (file)
@@ -5361,11 +5361,15 @@ static Bool dis_int_arith ( UInt theInstr )
              flag_OE ? "o" : "", flag_rC ? ".":"",
              rD_addr, rA_addr, rB_addr);
          // rD = (log not)rA + rB + XER[CA]
+         //    ==>
+         // rD = rB - rA - (XER[CA] ^ 1)
          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
-         assign( rD, binop( mkSzOp(ty, Iop_Add8),
-                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
-                            binop( mkSzOp(ty, Iop_Add8),
-                                   mkexpr(rB), mkexpr(old_xer_ca))) );
+         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
+                            binop( mkSzOp(ty, Iop_Sub8),
+                                   mkexpr(rB), mkexpr(rA)),
+                            binop(mkSzOp(ty, Iop_Xor8),
+                                  mkexpr(old_xer_ca),
+                                  mkSzImm(ty, 1))) );
          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
                           mkexpr(old_xer_ca) );