Summary: | PPC32 Special Instruction sequence clobbers R0 instead of preserving R0 | ||
---|---|---|---|
Product: | [Developer tools] valgrind | Reporter: | Dave Lerner <david.lerner26> |
Component: | general | Assignee: | Julian Seward <jseward> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | desrt, flo2030, mark, maynardj |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Unlisted Binaries | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
Dave Lerner
2011-07-29 19:00:00 UTC
Maynard, can you take a look? Would be good to get this in for 3.7.0 Dave, do you remember what toolchain produced the failure? (In reply to comment #1) > Maynard, can you take a look? Would be good to get this in for 3.7.0 It would be nice if it's possible. However, I'd like for it to be fixed by changing the rlwinms so they really are rotates, so that the combined sequence leaves r0 unchanged, rather than by telling gcc that the sequence clobbers r0. A check that the 64-bit version isn't similarly broken would be good. Dave, are you 110% sure about your diagnosis? I'm sure I checked this pretty damn carefully, and I'm surprised this problem hasn't cropped up before now. (In reply to comment #1) > Maynard, can you take a look? Would be good to get this in for 3.7.0 I don't have a 32-bit ppc platform to test on (my work is wholly with ppc64 servers), but I manually built the memcheck/tests/sh-mem testcase as 32-bit and ran it under valgrind on a SLES 11 SP1 system. Works fine there. > > Dave, do you remember what toolchain produced the failure? (In reply to comment #2) > Dave, are you 110% sure about your diagnosis? I'm sure I checked this > pretty damn carefully, and I'm surprised this problem hasn't cropped up > before now. We've hit this bug in GNOME twice now: https://bugzilla.gnome.org/show_bug.cgi?id=702648 https://bugzilla.gnome.org/show_bug.cgi?id=710983 I independently came to the conclusion that it was because r0 was getting clobbered without being declared as such and tested a fix. I then found this bug based on that analysis. That should count for at least some confirmation. The bug cropped up for us because we started using valgrind.h from GLib. We're pretty widely-used, on many platforms, and with a good testsuite. I think maybe this exact combination of circumstances just never came together before... Fixed, valgrind rev 13797, vex rev 2816. I just did the obvious thing and changed the sequence to rlwinm rA,rS,<n>,0,31 as you pointed out, and changed VEX to recognise that instead. I also checked that the 64-bit version is actually correct, which it is. One bad side effect of this now is that apps compiled against the old version of valgrind.h (even with your clobbers-r0 annotation) will now segfault when running on the fixed version of Valgrind, since the client requests compiled into the app will no longer be recognized and hence honoured by V. I'm not sure what can be done about that, since what this is is a bug in a public interface (effectively). I am pondering to add the following code to help detect old code that might be using the old magic instructions on ppc32: diff --git a/priv/guest_ppc_toIR.c b/priv/guest_ppc_toIR.c index adabf64..8f7e4aa 100644 --- a/priv/guest_ppc_toIR.c +++ b/priv/guest_ppc_toIR.c @@ -18783,10 +18783,26 @@ DisResult disInstr_PPC_WRK ( UInt word2 = mode64 ? 0x78006800 : 0x5400683E; UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; UInt word4 = mode64 ? 0x78009802 : 0x5400983E; + Bool is_special_preamble = False; if (getUIntPPCendianly(code+ 0) == word1 && getUIntPPCendianly(code+ 4) == word2 && getUIntPPCendianly(code+ 8) == word3 && getUIntPPCendianly(code+12) == word4) { + is_special_preamble = True; + } else if (! mode64 && + getUIntPPCendianly(code+ 0) == 0x54001800 && + getUIntPPCendianly(code+ 4) == 0x54006800 && + getUIntPPCendianly(code+ 8) == 0x5400E800 && + getUIntPPCendianly(code+12) == 0x54009800) { + static Bool reported = False; + if (!reported) { + vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n"); + vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n"); + reported = True; + } + is_special_preamble = True; + } + if (is_special_preamble) { /* Got a "Special" instruction preamble. Which one is it? */ if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { /* %R3 = client_request ( %R4 ) */ Unfortunalty there are old binaries out there that might be build against an old valgrind.h. This made worse by various projects embedding a private copy of the valgrind.h source. See e.g. http://codesearch.debian.net/search?q=This+file+is+part+of+Valgrind&path=valgrind.h After discussion on irc I pushed the warning/detection of old ppc32 magic instruction sequences from comment #6 as VEX svn r2990. |