These tests demonstrate the use of GoBug's hot key and
traffic light control, which are able to intervene if your program gets
into an infinite loop. It also shows how you can use the log to show
the loop the program has got stuck in. You can get out of the loop
either by closing the debuggee or by changing the registers to allow
a return.
   Infinite Win32 loop
   Infinite ASM loop
   Infinite loop thread (Win32)
   Infinite loop thread (ASM)
   Five infinite loops
Infinite Win32 loop
This test uses DrawFrameControl to draw various shapes
on the screen.
Start GoBug and start Testbug. At "START" press F9 and run the
test "Infinite Win32 loop". You will see the loop working in the
background (you may have to move GoBug's main window a little to see this
if you do not have "auto-activate when running" on). Now press the hot
key (default is Shift-Pause) and since GoBug has no idea where the
code is executing it floods the debuggee's code with INT3s (opcode 0CCh)
to try to cause an exception so that execution goes into GoBug's debug
loop. You will see if this is successful. If so, to get out of the
loop either change ebx to zero and single step your way out or close
the debuggee.
You can also intervene in the same way by using the traffic light
control.
Now restart Testbug using the menu item "file, restart debuggee" but this time press F7 at "START" before starting the infinite loop. Once in the loop open the
log panes and look at the very last instruction pane. You should see
the instructions inside the loop.
Here is the code for this test (GET_CENTRAL_RECT gets in RECT a
central rectangle to draw to):-
INFINITE_LOOP_WIN32:
CALL IL_WIN32
XOR EAX,EAX
RET
;
IL_WIN32:
MOV EBX,20h
MOV EDX,320 ;height
MOV ECX,370 ;width
CALL GET_CENTRAL_RECT ;get in RECT the correct size and position
L390:
MOV EDI,1
MOV D[COUNT],0
L395:
OR EBX,EBX
JZ >L402
PUSH [hWnd]
CALL GetDC
MOV [hDC],EAX
L396:
MOV EDI,[COUNT]
AND EDI,07h ;get uType
CALL GetTickCount
AND EAX,0C91Fh ;get uState (keep only relevant bits)
PUSH EAX,EDI,ADDR RECT,[hDC]
CALL DrawFrameControl ;draw a large button of various types
INC COUNT
OR EAX,EAX ;see if failed
JZ L396 ;yes, so try again
MOV ECX,10 ;success, so delay display
L400:
PUSH ECX
PUSH 10
CALL Sleep
POP ECX
LOOP L400
PUSH hDC,[hWnd]
CALL ReleaseDC
JMP L395
L402:
RET
Infinite ASM loop
This test has a simple asm loop instead of a visual
output, but you can use the same method to intervene.
INFINITE_LOOP_ASM:
CALL IL_ASM
XOR EAX,EAX
RET
;
IL_ASM:
L380:
INC D[COUNT]
MOV EAX,23h
XOR EAX,-1
OR EAX,EAX
MOV EAX,ADDR BUFFER
LEA EAX,BUFFER
LOOP L380
OR ECX,ECX
JZ L380
RET
Infinite loop thread
(Win32)
In this test a new thread is created to run the loop.
This time using the hot key will not be appropriate because this will
may trap the main thread in the message loop rather than the looping
thread. Instead use the traffic light control to try to trap the looping
thread. To do this open the traffic light dialog and change the second
thread to single-step action and click "apply". If successful it will
be the second thread which comes into the debug loop.
INFINITE_LOOP_THREADWIN32:
PUSH ADDR ThreadId,0,0,ADDR THREAD_INFLOOPTESTWIN32,0,0
CALL CreateThread
RET
;
THREAD_INFLOOPTESTWIN32:
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
CALL IL_WIN32
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
RET
Infinite loop thread
(ASM)
This test is a non-visual and purely assembler version
of the last test. Intervene using the traffic light control.
INFINITE_LOOP_THREADASM:
PUSH ADDR ThreadId,0,0,ADDR THREAD_INFLOOPTESTASM,0,0
CALL CreateThread
RET
;
THREAD_INFLOOPTESTASM:
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
CALL IL_ASM
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
XOR EAX,EAX
RET
Five infinite loops
If you and your computer are feeling up to it, you
can make 5 threads with an infinite loop in each thread with this test.
Each thread has a very small loop so you might notice a slowdown in your
machine while Testbug is still running.
You may have to try more than once to trap all the looping threads
with the traffic light control, but eventually they should all get
trapped.
FIVE_INFINITE_LOOPS:
PUSH ADDR ThreadId,0,0,ADDR FIVELOOP1,0,0
CALL CreateThread
PUSH ADDR ThreadId,0,0,ADDR FIVELOOP2,0,0
CALL CreateThread
PUSH ADDR ThreadId,0,0,ADDR FIVELOOP3,0,0
CALL CreateThread
PUSH ADDR ThreadId,0,0,ADDR FIVELOOP4,0,0
CALL CreateThread
PUSH ADDR ThreadId,0,0,ADDR FIVELOOP5,0,0
CALL CreateThread
RET
;
FIVELOOP1:
XOR EAX,EAX ;make z
L31:
NOP
JZ L31
RET
;
FIVELOOP2:
XOR EAX,EAX ;make z
L32:
NOP
JZ L32
RET
;
FIVELOOP3:
XOR EAX,EAX ;make z
L33:
NOP
JZ L33
RET
;
FIVELOOP4:
XOR EAX,EAX ;make z
L34:
NOP
JZ L34
RET
;
FIVELOOP5:
XOR EAX,EAX ;make z
L35:
NOP
JZ L35
RET