Version: (using Devel) OS: Linux Installed from: Compiled sources http://kegel.com/wine/valgrind/logs/2010-01-20-12.46/vg-gdi32_bitmap.txt shows a crash in GetBitmapBits(): Unhandled exception: page fault on read access to 0x7f331000 in 32-bit code (0x0a4c2160). Backtrace: =>0 _vgrZU_libcZdsoZa_memcpy+0x150(dst=0x7f03a058, src=0x7f3300f0, len=16) [memcheck/mc_replace_strmem.c:482] in vgpreload_memcheck-x86-linux.so 1 GetBitmapBits+0x112(hbitmap=0x2d8, count=256, bits=0x7f03a058) [dlls/gdi32/bitmap.c:358] in gdi32 2 test_dib_info+0x419(hbm=0x2d8, bits=0x7f330000, bmih=0x7f21f0b4) [dlls/gdi32/tests/bitmap.c:325] in gdi32_test Wine uses page faulting to keep the local bitmap and the X server's bitmap in sync, and this appears to be confusing valgrind. (We'd like to stop doing this, but it's a lot of work; see http://wiki.winehq.org/DIBEngine )
I don't really see anything in that log that isn't expected, other than wine's reaction, which would seem to be a wine issue not a valgrind issue. As I understand that page you referred to, wine is deliberately protecting this memory and then using the resulting segv's to detect when it has been directly accessed so it can synchronise the two copies of the data. It looks like what has happened here is exactly what you would expect - wine has tried to copy some data into the protected area and has a caught a page fault as a result (originating in memcpy) and the only problem is that for some reason wine has not handled that fault in the expected way but has instead reported it as an unexpected fault. I think if you want to claim that valgrind is at fault here you need to establish what wine was expecting of the fault that we failed to provide - it may be that something in the siginfo we create isn't quite right but we will need more detail before we can do anything about it.
Let me see if I have this right. Running natively, Wine from time to time writes to some page(s) which are write protected. It catches the segv, futzes with with the page protection to make it writable, and lets the signal handler return, thereby restarting the faulting instruction. Is that correct? And (assuming Yes to the above) when you run it on V, it fails in some mysterious way. Yes? Assuming Yes and Yes: can you give --vex-iropt-precise-memory-exns=yes a try?
Yes. And that option makes the problem go away. Huzzah! I'll update Wine's wiki page. (Here's a bit more detail that I wrote before I got your reply: It looks like Wine's fault handler does its thing and then sets the protection on the memory to read-only (from no-access). But under valgrind, the memcpy seems to go too far, and tickles the next page?! To repeat, set up wine and valgrind as described in http://wiki.winehq.org/Wine_and_Valgrind, then do cd dlls/gdi32/tests ~/wine-git/wine winemine & WINEDEBUG=+seh,+bitmap,+virtual /usr/local/valgrind-11036/bin/valgrind --workaround-gcc296-bugs=yes --trace-children=yes ~/wine-git/wine gdi32_test.exe.so bitmap.c > log.bad 2>&1 WINEDEBUG=+seh,+bitmap,+virtual ~/wine-git/wine gdi32_test.exe.so bitmap.c > log.ok 2>&1 )
I guess I should have RTFM, http://valgrind.org/docs/manual/manual-core.html#manual-core.signals
(In reply to comment #3) > Yes. And that option makes the problem go away. > Huzzah! I'll update Wine's wiki page. Ah. So it's the dreaded Precise Exceptions Problem, the scourge of many a fast instruction-set simulator. Valgrind's IR optimiser aggressively removes writes to the simulated registers, when it sees a later write to the same simulated register. This reduces memory traffic (because the simulated registers live in host memory) and increases performance, and generally allows guest register values to be cached in host registers for potentially the entire unit of instrumentation (extended basic blocks). Problem is if a memory instruction takes a fault, it means the in-memory representation of the guest registers is out of date. So when Wine's signal handler returns, Valgrind restarts the faulting (guest) instruction but with out of date guest register values, and it all goes to hell in a handbasket in short order. --vex-iropt-precise-memory-exns=yes disables this optimisation and gives you precise guest register values at all potential memory fault points, thereby solving the problem. Of course this will cost you something in performance. An interesting side comment is that V does in fact by default maintain precise values for the guest stack, frame and instruction pointers, but not for any other registers. This is because if it didn't, then we would be unable to provide sane stack tracebacks in error messages since the unwinder would start with out of date SP/FP/IP values.