I got around the problem of gdb unprotecting the write protected page by not setting the breakpoint until after the write fault occurs.
When I stepped through the Shrinker exception handler, I got to the point where it calls ReadProcessMemory with a handle of -1 to get the 8 bytes around the EXC_CallHandler's call. ReadProcessMemory fails with an ACCESS_DENIED, and trips a landmine.
0806d9e8:Call kernel32.ReadProcessMemory(ffffffff,4006cd38,404f489c,00000008,404f48a4) ret=0075f1c3 0806d9e8: read_process_memory( handle=-1, addr=0x4006cd38 ) 0806d9e8: read_process_memory() = ACCESS_DENIED { data={} } 0806d9e8:Ret kernel32.ReadProcessMemory() retval=00000000 ret=0075f1c3
However, when I run wine alone, without gdb, that particular landmine is not tripped:
0806d9e8:Call kernel32.ReadProcessMemory(ffffffff,4006cd38,404f489c,00000008,404f48a4) ret=0075f1c3 0806d9e8: read_process_memory( handle=-1, addr=0x4006cd38 ) 0806d9e8: *attached* 0806d9e8: *signal* signal=19 0806d9e8: read_process_memory() = 0 { data={ff,75,08,ff,d1,64,8b,25} } 0806d9e8:Ret kernel32.ReadProcessMemory() retval=00000001 ret=0075f1c3
BTW, the data returned by ReadProcessMemory is correct, and also will not trip the "Have I been called from Microsoft's NTDLL.DLL method" landmine.
I'll have to think about this for a while, how to use gdb without getting ACCESS_DENIED for ReadProcessMemory. That usually means going off and doing something else until an idea hits me.
--Rob