Hi,
Is it possible that AddVectoredExceptionHandler doesn't work when running wine under gdb? Or maybe it doesn't work in a 32bit wine running in a 64bit system?
I'm seeing a SEGV crash when running any wine program with wine 1.3.24 in gdb but not when running without the debugger. The crash is happening when writing to memory allocated by CreateDIBSection in the function create_alpha_bitmap(). The code is in user32/cursoricon.c.
Here's where the crash happens, at line 791 in user32/cursoricon.c create_alpha_bitmap():
unsigned int alpha = ptr[3]; ptr[0] = ptr[0] * alpha / 255; <-- SEGV here
With the debugger on, writing to ptr[0] causes the segfault. And, indeed, when I look at /proc/PID/maps for the problem address (0x350000) it is read only. Without the debugger, the memory is read-write and the calls work.
WINEDEBUG=+relay,+cursor,+icon,+resource,+bitmap,+virtual,+seh shows that exceptions are used to unlock the DIB as needed. The X11DRV_DIB_FaultHandler is installed and supposed to get invoked when writing to the memory.
And, without gdb running there are exceptions which leads to X11DRV_DIB_Unlock. Here's the trace:
trace:cursor:create_alpha_bitmap line=790 i 0, ptr 0x350000, alpha ac trace:seh:raise_exception code=c0000005 flags=0 addr=0x7e7ea0d8 ip=7e7ea0d8 tid=0028 trace:seh:raise_exception info[0]=00000001 trace:seh:raise_exception info[1]=00350000 trace:seh:raise_exception eax=9999cccc ebx=7e8a5e2c ecx=00000000 edx=00000067 esi=00350000 edi=000000ac trace:seh:raise_exception ebp=00000000 esp=0032f860 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010a02 trace:seh:call_vectored_handlers calling handler at 0x7e14beb0 code=c0000005 flags=0 trace:bitmap:X11DRV_DIB_Lock Locking 0x330 from thread 0028 trace:bitmap:X11DRV_DIB_Coerce AppMod requested in status InSync trace:virtual:NtProtectVirtualMemory 0xffffffff 0x350000 00000400 00000004 trace:virtual:VIRTUAL_SetProt 0x350000-0x350fff c-rw- trace:virtual:VIRTUAL_DumpView View: 0x350000 - 0x350fff (valloc) trace:virtual:VIRTUAL_DumpView 0x350000 - 0x350fff c-rw- trace:bitmap:X11DRV_DIB_DoProtectDIBSection Changed protection from 2 to 4 trace:bitmap:X11DRV_DIB_Unlock Unlocking in status AppMod trace:bitmap:X11DRV_DIB_Unlock Unlocked 0x330 trace:seh:call_vectored_handlers handler at 0x7e14beb0 returned ffffffff trace:cursor:create_alpha_bitmap 804 i 0, ptr 0x350000
That all works. But under gdb the exception handler is not called. The memory is not unlocked and the SEGV happens.
This is all happening in a 64bit Fedora bit system where we have cross compiled a 32bit version of wine. Could that be an issue?
Hopefully someone out there knows the answer to this readily.
Thanks for your time!
-- Michael Ost
On 12/22/2011 04:45 PM, Michael Ost wrote:
Hi,
I'm seeing a SEGV crash when running any wine program with wine 1.3.24 in gdb but not when running without the debugger. The crash is happening when writing to memory allocated by CreateDIBSection in the function create_alpha_bitmap(). The code is in user32/cursoricon.c.
This is not a crash, this is the way it supposed to work. At least until DIB is finished and this hack isn't needed.
Wine uses this trick to detect when DIB memory needs to be synchronized with the X server.
Vitaliy.
On Dec 22, 2011, at 8:14 PM, Vitaliy Margolen wrote:
On 12/22/2011 04:45 PM, Michael Ost wrote:
I'm seeing a SEGV crash when running any wine program with wine 1.3.24 in gdb but not when running without the debugger. The crash is happening when writing to memory allocated by CreateDIBSection in the function create_alpha_bitmap(). The code is in user32/cursoricon.c.
This is not a crash, this is the way it supposed to work. At least until DIB is finished and this hack isn't needed.
Wine uses this trick to detect when DIB memory needs to be synchronized with the X server.
To elaborate:
With the debugger on, writing to ptr[0] causes the segfault. And, indeed, when I look at /proc/PID/maps for the problem address (0x350000) it is read only. Without the debugger, the memory is read-write and the calls work.
The memory is not read-write, at least not at first. Wine handles the SEGV by reading the image back from the X server and making the memory read-write. If and when the app uses GDI to draw to the DIB, then the memory will be made read-only again and the image will be uploaded to the X server before X graphics operations are performed on it.
But under gdb the exception handler is not called. The memory is not unlocked and the SEGV happens.
You have the order of operations the wrong way around. The memory access is attempted. The SEGV is generated ("happens"), whether or not gdb is attached. Gdb, being a debugger, stops the process when most signals are raised, to give the programmer an opportunity to investigate.
If you were to tell gdb to deliver the signal and let the process proceed, using the command "signal SIGSEGV", Wine's signal handler would be invoked and would do the appropriate thing. This will be extremely tedious, though, since DIB accesses can happen a lot.
You can tell gdb to ignore the SEGV using a command like "handle SIGSEGV nostop noprint pass". Unfortunately, that will prevent you from debugging SEGVs other than DIB access. (It also doesn't extract the debugger entirely from the signal handling, making DIB operations somewhat slower than normal, but that can't really be avoided.) This is where winedbg's "set $BreakOnFirstChance=0" can be very valuable. It doesn't help with gdb, though, and it also doesn't help for those applications which use exception handlers to die "gracefully" rather than crashing.
Regards, Ken
On 12/22/11 8:20 PM, Ken Thomases wrote:
On Dec 22, 2011, at 8:14 PM, Vitaliy Margolen wrote:
On 12/22/2011 04:45 PM, Michael Ost wrote:
I'm seeing a SEGV crash when running any wine program with wine 1.3.24 in gdb but not when running without the debugger. The crash is happening when writing to memory allocated by CreateDIBSection in the function create_alpha_bitmap(). The code is in user32/cursoricon.c.
This is not a crash, this is the way it supposed to work. At least until DIB is finished and this hack isn't needed.
Wine uses this trick to detect when DIB memory needs to be synchronized with the X server.
To elaborate:
With the debugger on, writing to ptr[0] causes the segfault. And, indeed, when I look at /proc/PID/maps for the problem address (0x350000) it is read only. Without the debugger, the memory is read-write and the calls work.
The memory is not read-write, at least not at first. Wine handles the SEGV by reading the image back from the X server and making the memory read-write. If and when the app uses GDI to draw to the DIB, then the memory will be made read-only again and the image will be uploaded to the X server before X graphics operations are performed on it.
But under gdb the exception handler is not called. The memory is not unlocked and the SEGV happens.
You have the order of operations the wrong way around. The memory access is attempted. The SEGV is generated ("happens"), whether or not gdb is attached. Gdb, being a debugger, stops the process when most signals are raised, to give the programmer an opportunity to investigate.
If you were to tell gdb to deliver the signal and let the process proceed, using the command "signal SIGSEGV", Wine's signal handler would be invoked and would do the appropriate thing. This will be extremely tedious, though, since DIB accesses can happen a lot.
You can tell gdb to ignore the SEGV using a command like "handle SIGSEGV nostop noprint pass". Unfortunately, that will prevent you from debugging SEGVs other than DIB access. (It also doesn't extract the debugger entirely from the signal handling, making DIB operations somewhat slower than normal, but that can't really be avoided.) This is where winedbg's "set $BreakOnFirstChance=0" can be very valuable. It doesn't help with gdb, though, and it also doesn't help for those applications which use exception handlers to die "gracefully" rather than crashing.
This all makes sense, and pulls the code together for me. Thanks!
I assume this is a recent development, because I was successfully using gdb with our last wine version - 1.1.7.
But it no longer sounds workable to use gdb for debugging winelib applications, which is a drag. Are you suggesting using winedbg instead? Do you know if it can be used as a drop-in replacement in, say, Qt Creator (which is my IDE of choice)?
-- Michael Ost
On Dec 23, 2011, at 3:10 PM, Michael Ost wrote:
This all makes sense, and pulls the code together for me. Thanks!
You're welcome.
I assume this is a recent development, because I was successfully using gdb with our last wine version - 1.1.7.
Nope. This is how it has worked for a long, long time. Don't know what else has changed. Maybe some of the other work on the DIB engine has changed whether/when the DIB accesses cause access violations that you're seeing.
But it no longer sounds workable to use gdb for debugging winelib applications, which is a drag. Are you suggesting using winedbg instead?
Well, you can use winedbg with $BreakOnFirstChance set to 0, for some apps. (Setting $BreakOnFirstChance to 0 only has to be done once for a given WINEPREFIX. It's saved in the registry.)
You can also try that "handle SIGSEGV nostop noprint pass" command I gave you. You might try starting with that signal-handling setup and then, when you get close to where you expect a true crash to happen, switch it back ("handle SIGSEGV stop print nopass").
Some day, the DIB engine will be complete and this memory protection scheme will not be necessary to coordinate DIB access between memory and the X server.
Do you know if it can be used as a drop-in replacement in, say, Qt Creator (which is my IDE of choice)?
No, it can't. Its interface is not identical to gdb's.
Regards, Ken
On Fri, Dec 23, 2011 at 11:56:35PM -0600, Ken Thomases wrote:
On Dec 23, 2011, at 3:10 PM, Michael Ost wrote:
This all makes sense, and pulls the code together for me. Thanks!
You're welcome.
I assume this is a recent development, because I was successfully using gdb with our last wine version - 1.1.7.
Nope. This is how it has worked for a long, long time. Don't know what else has changed. Maybe some of the other work on the DIB engine has changed whether/when the DIB accesses cause access violations that you're seeing.
Yes, the DIB engine should no longer let this happen with the last 1.3. releases since around September or so.
Otherwise, in gdb you can type "pass" to pass the signal on to the program.
Ciao, Marcus
On 12/23/2011 09:56 PM, Ken Thomases wrote:
On Dec 23, 2011, at 3:10 PM, Michael Ost wrote:
This all makes sense, and pulls the code together for me. Thanks!
You're welcome.
I assume this is a recent development, because I was successfully using gdb with our last wine version - 1.1.7.
Nope. This is how it has worked for a long, long time. Don't know what else has changed. Maybe some of the other work on the DIB engine has changed whether/when the DIB accesses cause access violations that you're seeing.
Interesting. Maybe a resource that is loaded at startup changed so it needs alpha blending now. I'll see if I can hack around that for my local use with gdb.
Thanks again, Michael Ost
But it no longer sounds workable to use gdb for debugging winelib applications, which is a drag. Are you suggesting using winedbg instead?
Well, you can use winedbg with $BreakOnFirstChance set to 0, for some apps. (Setting $BreakOnFirstChance to 0 only has to be done once for a given WINEPREFIX. It's saved in the registry.)
You can also try that "handle SIGSEGV nostop noprint pass" command I gave you. You might try starting with that signal-handling setup and then, when you get close to where you expect a true crash to happen, switch it back ("handle SIGSEGV stop print nopass").
Some day, the DIB engine will be complete and this memory protection scheme will not be necessary to coordinate DIB access between memory and the X server.
Do you know if it can be used as a drop-in replacement in, say, Qt Creator (which is my IDE of choice)?
No, it can't. Its interface is not identical to gdb's.
Regards, Ken