https://bugs.winehq.org/show_bug.cgi?id=37272
Bug ID: 37272 Summary: CheatEngine 6.4 fails after remote process 'breakin', reporting 'Debugger Crash:Access violation (Last location:41)' Product: Wine Version: 1.7.26 Hardware: x86 OS: Linux Status: NEW Severity: normal Priority: P2 Component: dbghelp Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net
Hello folks,
as the summary says.
The app works well in general - except when breaking into remote process for debugging (to single step).
The app is pretty verbose about its doings, using 'OutputDebugString' API.
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/Cheat Engine 6.4 ... $ WINEDEBUG=+tid,+seh,+loaddll,+process,+debugstr wine ./Cheat\ Engine.exe
log.txt 2>&1
... 0023:warn:debugstr:OutputDebugStringA "setThreadContext(28, 110, 07E9710C). dr0=0 dr1=0 dr2=0 dr3=0 dr7=400" ... 002b:warn:debugstr:OutputDebugStringA "HandleExceptionDebugEvent:80000004" ... 002b:warn:debugstr:OutputDebugStringA "EXCEPTION_SINGLE_STEP. Dr6=00004000" ... 002b:warn:debugstr:OutputDebugStringA "Handling as a single step event" ... 002b:warn:debugstr:OutputDebugStringA "HandleBreak()" ... 0023:trace:seh:raise_exception code=c0000005 flags=0 addr=0x410464 ip=00410464 tid=0023 0023:trace:seh:raise_exception info[0]=00000001 0023:trace:seh:raise_exception info[1]=d000db06 0023:trace:seh:raise_exception eax=0000000b ebx=044bbc78 ecx=d000dafe edx=001c9071 esi=044bbc74 edi=001c9071 0023:trace:seh:raise_exception ebp=01b8ea5c esp=01b8e9f0 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00210282 0023:trace:seh:call_stack_handlers calling handler at 0x7bc9de17 code=c0000005 flags=0 0023:trace:seh:call_stack_handlers handler at 0x7bc9de17 returned 0 ... --- snip ---
The CheatEngine debugger was attached to 'notepad' process.
--- snip --- Wine-dbg>info process
pid threads executable (all id:s are in hex) 00000027 1 'notepad.exe' 00000022 3 'cheatengine-i386.exe' 00000020 1 'explorer.exe' 0000000e 5 'services.exe' 00000019 3 _ 'plugplay.exe' 00000012 4 _ 'winedevice.exe'
Wine-dbg>info thread
process tid prio (all id:s are in hex) ... 00000022 cheatengine-i386.exe 0000002b 0 00000024 0 00000023 0 00000027 notepad.exe 00000028 0 --- snip ---
Running the debugger under a debugger yields the following:
--- snip --- Unhandled exception: page fault on write access to 0xd000db06 in 32-bit code (0x00410464). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:00410464 ESP:01b8e9f0 EBP:01b8ea5c EFLAGS:00210282( R- -- I S - - - ) EAX:0000000b EBX:040341a8 ECX:d000dafe EDX:001c9071 ESI:040341a4 EDI:001c9071 Stack dump: 0x01b8e9f0: 000000b0 0000000b 040341a4 000000b0 0x01b8ea00: 0423c2e8 0423c2ec 004105ee 0000004c 0x01b8ea10: 0423c2e8 00410bdd 0000001c 0423c2e8 0x01b8ea20: 00000414 0040fa88 006426a9 0423c2e8 0x01b8ea30: 0410a7f8 00000414 006429b7 0423c2e8 0x01b8ea40: 0410a7f8 006427ad 001b2ba8 00000000 000c: sel=0067 base=00000000 limit=00000000 16-bit --x Backtrace: =>0 0x00410464 in cheatengine-i386 (+0x10464) (0x01b8ea5c) 1 0x007011b4 in cheatengine-i386 (+0x3011b3) (0x01b8ea70) 2 0x0050bc97 in cheatengine-i386 (+0x10bc96) (0x01b8f368) 3 0x0050c155 in cheatengine-i386 (+0x10c154) (0x01b8f6a0) 4 0x0044b868 in cheatengine-i386 (+0x4b867) (0x01b8f6b8) 5 0x00452019 in cheatengine-i386 (+0x52018) (0x01b8f728) 6 0x004fd312 in cheatengine-i386 (+0xfd311) (0x01b8f7ac) 7 0x005013c1 in cheatengine-i386 (+0x1013c0) (0x01b8f824) 8 0x0058ef28 in cheatengine-i386 (+0x18ef27) (0x01b8f898) 9 0x006e7668 in cheatengine-i386 (+0x2e7667) (0x01b8faa8) 10 0x7eb8fb5e WINPROC_wrapper+0x19() in user32 (0x01b8fad8) ... 0x00410464: movl $0x0,0x8(%ecx) --- snip ---
The app is open source: https://code.google.com/p/cheat-engine
--- snip --- $ svn checkout http://cheat-engine.googlecode.com/svn/trunk/ cheat-engine-read-only --- snip ---
'Last location:41' part of error message gives a hint:
htps://code.google.com/p/cheat-engine/source/browse/trunk/Cheat%20Engine/debugeventhandler.pas#180
--- snip --- procedure TDebugThreadHandler.VisualizeBreak; begin TDebuggerthread(debuggerthread).execlocation:=41; if processhandler.SystemArchitecture=archx86 then MemoryBrowser.lastdebugcontext:=context^ else MemoryBrowser.lastdebugcontextarm:=armcontext;
WaitingToContinue:=not lua_onBreakpoint(context);
if WaitingToContinue then //no lua script or it returned 0 MemoryBrowser.UpdateDebugContext(self.Handle, self.ThreadId);
end; --- snip ---
The crashes happens during update of stacktrace listview, after a couple of 'dbghelp.StackWalk64' calls.
'TMemoryBrowser.UpdateDebugContext' -> 'TfrmStacktrace.stacktrace'
https://code.google.com/p/cheat-engine/source/browse/trunk/Cheat%20Engine/fr...
The crash address is an indirect reference from ECX = 0xd000dafe (+8) .. a value which corresponds to Wine's 'frame->KdHelp.KiCallUserMode' magic value.
The stack frame data structure passed to 'StackWalk64' is allocated from internal Delphi heap and initialized.
--- snip --- procedure TfrmStacktrace.stacktrace(threadhandle:thandle;context:_context); var stackframe: PStackframe64; cxt:_context; wow64ctx: CONTEXT32; a,b,c,d: dword; sa,sb,sc,sd:string; machinetype: dword;
cp: pointer;
found: boolean; begin
... getmem(stackframe,sizeof(tstackframe)); zeromemory(stackframe,sizeof(tstackframe)); stackframe^.AddrPC.Offset:=context.{$ifdef cpu64}rip{$else}eip{$endif}; stackframe^.AddrPC.mode:=AddrModeFlat;
stackframe^.AddrStack.Offset:=context.{$ifdef cpu64}rsp{$else}esp{$endif}; stackframe^.AddrStack.Mode:=addrmodeflat;
stackframe^.AddrFrame.Offset:=context.{$ifdef cpu64}rbp{$else}ebp{$endif}; stackframe^.AddrFrame.Mode:=addrmodeflat; ... --- snip ---
The corresponding disassembly, annotated:
--- snip --- 0050BBD1 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8] 0050BBD4 BA A4000000 MOV EDX,0A4 ; sizeof(tstackframe) 0050BBD9 E8 323EF0FF CALL cheateng.0040FA10 ; getmem() 0050BBDE 68 A4000000 PUSH 0A4 ; sizeof(tstackframe) 0050BBE3 FF75 F8 PUSH DWORD PTR SS:[EBP-8] 0050BBE6 E8 C5121600 CALL cheateng.0066CEB0 ; zeromemory() 0050BBEB 8B4D F8 MOV ECX,DWORD PTR SS:[EBP-8] 0050BBEE 8B95 38F8FFFF MOV EDX,DWORD PTR SS:[EBP-7C8] 0050BBF4 B8 00000000 MOV EAX,0 0050BBF9 8911 MOV DWORD PTR DS:[ECX],EDX ; stackframe^.AddrPC.. 0050BBFB 8941 04 MOV DWORD PTR DS:[ECX+4],EAX --- snip ---
0xA4 is a bit too small for 'STACKFRAME64' structure.
MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680646%28v=vs.85%2...
My guess is that Delphi/Pascal's definition of 'tstackframe' doesn't include the 'KDHELP64' part which is reserved for kernel debuggers.
The problem is that Wine writes magic values into an area that should be left untouched since we're dealing with usermode debugging. That corrupts the internal heap.
Source: http://source.winehq.org/git/wine.git/blob/61a9eef9a1c0a72e6571742dbb830f7b2...
--- snip --- ... 242 /* we don't handle KdHelp */ 243 frame->KdHelp.Thread = 0xC000FADE; 244 frame->KdHelp.ThCallbackStack = 0x10; 245 frame->KdHelp.ThCallbackBStore = 0; 246 frame->KdHelp.NextCallback = 0; 247 frame->KdHelp.FramePointer = 0; 248 frame->KdHelp.KiCallUserMode = 0xD000DAFE; 249 frame->KdHelp.KeUserCallbackDispatcher = 0xE000F000; 250 frame->KdHelp.SystemRangeStart = 0xC0000000; 251 frame->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000; ... --- snip ---
The code that writes the magic values was added 8 years ago:
http://source.winehq.org/git/wine.git/commitdiff/558130a696a1e6c11a84f3d1f12...
Not sure what the intention was since usermode debuggers can't deal with these things anyway.
With that part fixed, CheatEngine can debug remote processes after attaching.
$ sha1sum CheatEngine64.exe 8cb06bca312ed2bfa02c7f9344f2717d02ecd931 CheatEngine64.exe
$ du -sh CheatEngine64.exe 8.7M CheatEngine64.exe
$ wine --version wine-1.7.26-44-gb10b391
Regards
https://bugs.winehq.org/show_bug.cgi?id=37272
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download URL| |http://mirror3.cheatengine. | |org/download/d1/CheatEngine | |64.exe
https://bugs.winehq.org/show_bug.cgi?id=37272
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |sebastian@fds-team.de
--- Comment #1 from Sebastian Lackner sebastian@fds-team.de --- Should be fixed with http://source.winehq.org/git/wine.git/commit/c6fcb427a2485184e209b91b7b95e37...
https://bugs.winehq.org/show_bug.cgi?id=37272
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |c6fcb427a2485184e209b91b7b9 | |5e37fc891ff88 Status|NEW |RESOLVED Resolution|--- |FIXED
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello folks,
this is fixed by commit http://source.winehq.org/git/wine.git/commitdiff/c6fcb427a2485184e209b91b7b9...
Thanks Sebastian
Break-in and stepping works now (tested notepad).
Regards
https://bugs.winehq.org/show_bug.cgi?id=37272
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #3 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 1.7.36.
https://bugs.winehq.org/show_bug.cgi?id=37272
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|http://mirror3.cheatengine. |https://web.archive.org/web |org/download/d1/CheatEngine |/20140722164425/http://mirr |64.exe |or3.cheatengine.org/downloa | |d/d1/CheatEngine64.exe