Bug 225019 - Wine's GetBitmapBits() crashes under Valgrind
Summary: Wine's GetBitmapBits() crashes under Valgrind
Status: RESOLVED NOT A BUG
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR crash
Target Milestone: ---
Assignee: Julian Seward
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-01-31 16:54 UTC by Dan Kegel
Modified: 2010-01-31 18:50 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dan Kegel 2010-01-31 16:54:29 UTC
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 )
Comment 1 Tom Hughes 2010-01-31 17:08:56 UTC
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.
Comment 2 Julian Seward 2010-01-31 18:26:53 UTC
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?
Comment 3 Dan Kegel 2010-01-31 18:31:15 UTC
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
)
Comment 4 Dan Kegel 2010-01-31 18:35:53 UTC
I guess I should have RTFM, 
http://valgrind.org/docs/manual/manual-core.html#manual-core.signals
Comment 5 Julian Seward 2010-01-31 18:50:46 UTC
(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.