3 Copyright (c) 1998-2001 Klaus P. Gerlicher
11 user interface for debugger
24 22-Sep-1998: rewrite of keyboard hooking through patching the original keyboard driver
25 29-Sep-1998: started documentation on project
26 15-Nov-2000: general cleanup of source files
30 This file may be distributed under the terms of the GNU Public License.
34 ////////////////////////////////////////////////////
41 ////////////////////////////////////////////////////
44 #define LINES_IN_COMMAND_BUFFER (64)
46 ////////////////////////////////////////////////////
50 ////////////////////////////////////////////////////
54 ULONG bPreviousCommandWasGo
= FALSE
;
56 // flags to set when we need to pass things to the old INT handlers
57 ULONG dwCallOldInt1Handler
= 0;
58 ULONG dwCallOldInt3Handler
= 0;
59 ULONG dwCallOldIntEHandler
= 0;
60 ULONG dwCallOldGPFaultHandler
= 0;
62 ULONG g_ulLineNumberStart
=0;
63 ULONG ulWindowOffset
= 0;
64 BOOLEAN bStepThroughSource
=FALSE
;
65 BOOLEAN bStepInto
= FALSE
;
68 UCHAR ucConverted
; // key converted from scancode to ANSI
70 volatile BOOLEAN bControl
=FALSE
; // TRUE when CTRL key was pressed
71 volatile BOOLEAN bShift
=FALSE
; // TRUE when SHIFT key was pressed
72 volatile BOOLEAN bAlt
=FALSE
; // TRUE when ALT key was pressed
73 volatile ULONG OldInt31Handler
; // address of old keyboard ISR
74 volatile ULONG OldGlobalInt31Handler
; // address of old global keyboard ISR
75 volatile BOOLEAN bEnterNow
=FALSE
; // TRUE if already stopped
76 volatile BOOLEAN bNotifyToExit
=FALSE
; // TRUE when debugger should leave
77 volatile BOOLEAN bSkipMainLoop
=FALSE
; // TRUE when debugger should skip main loop
78 volatile UCHAR ucKeyPressedWhileIdle
=0; // key pressed when system was stopped
79 volatile BOOLEAN bInDebuggerShell
=FALSE
; // TRUE while in DebuggerShell()
80 BOOLEAN bIrqStateAtBreak
;
83 static ULONG PCR_SEL
= PCR_SELECTOR
;
86 char tempShell
[256]; // temporary string container
88 // old address of display memory
92 ULONG ulLastLineDisplayedOffset
= 0;
94 // functions of function keys
95 char *szFunctionKeys
[10]={
108 // new stack for "deep parsing"
109 ULONG aulNewStack
[0x20000];
112 // registers save area (context)
113 ULONG CurrentEIP
,CurrentEFL
;
114 ULONG CurrentEAX
,CurrentEBX
,CurrentECX
,CurrentEDX
;
115 ULONG CurrentESP
,CurrentEBP
,CurrentESI
,CurrentEDI
;
116 USHORT CurrentCS
,CurrentDS
=0,CurrentES
,CurrentFS
,CurrentGS
,CurrentSS
;
117 ULONG CurrentDR0
,CurrentDR1
,CurrentDR2
,CurrentDR3
,CurrentDR6
,CurrentDR7
;
118 ULONG CurrentCR0
,CurrentCR2
,CurrentCR3
;
120 ULONG OldEIP
=0,OldEFL
;
121 ULONG OldEAX
,OldEBX
,OldECX
,OldEDX
;
122 ULONG OldESP
,OldEBP
,OldESI
,OldEDI
;
123 USHORT OldCS
=0,OldDS
,OldES
,OldFS
,OldGS
,OldSS
;
125 ULONG CurrentProcess
;
127 UCHAR ucCommandBuffer
[256];
128 USHORT usCurrentPosInInputBuffer
=0;
129 volatile BOOLEAN bSingleStep
=FALSE
;
131 // the last command lines
132 char aszCommandLines
[LINES_IN_COMMAND_BUFFER
][sizeof(ucCommandBuffer
)+2];
133 ULONG ulCommandInPos
=0,ulCommandLastPos
=0;
134 ULONG ulCommandCurrentPos
=0;
137 extern ULONG KeyboardIRQL
;
139 //*************************************************************************
140 // GetLinesInCommandHistory()
142 //*************************************************************************
143 ULONG
GetLinesInCommandHistory(void)
145 ULONG ulResult
= (ulCommandInPos
-ulCommandLastPos
)%LINES_IN_COMMAND_BUFFER
;
149 DPRINT((0,"GetLinesInCommandHistory() returns %u (ulIn %u ulLast %u)\n",ulResult
,ulCommandInPos
,ulCommandLastPos
));
156 //*************************************************************************
157 // AddToCommandLineHistory()
159 //*************************************************************************
160 void AddToCommandLineHistory(LPSTR s
)
165 DPRINT((0,"AddToCommandLineHistory(%s)\n",s
));
169 for(i
=0;i
<LINES_IN_COMMAND_BUFFER
;i
++)
171 if(PICE_strcmpi(&aszCommandLines
[i
][1],s
) == 0)
173 DPRINT((0,"AddToCommandLineHistory(): command line already exists\n"));
178 aszCommandLines
[ulCommandInPos
][0]=':';
179 PICE_strcpy(&aszCommandLines
[ulCommandInPos
][1],s
);
180 ulCommandCurrentPos
= ulCommandInPos
= (ulCommandInPos
+1)%LINES_IN_COMMAND_BUFFER
;
181 if(ulCommandInPos
== ulCommandLastPos
)
183 ulCommandLastPos
= (ulCommandLastPos
+1)%LINES_IN_COMMAND_BUFFER
;
190 //*************************************************************************
191 // GetFromCommandLineHistory()
193 //*************************************************************************
194 LPSTR
GetFromCommandLineHistory(ULONG ulCurrentCommandPos
)
200 DPRINT((0,"GetFromCommandLineHistory(): current = %u\n",ulCurrentCommandPos
));
203 pRet
= aszCommandLines
[ulCurrentCommandPos
] + 1;
205 DPRINT((0,"GetFromCommandLineHistory(%s)\n",pRet
));
212 //*************************************************************************
215 //*************************************************************************
216 void ShowStatusLine(void)
218 PEPROCESS pCurrentProcess
= IoGetCurrentProcess();
223 if(IsAddressValid((ULONG
)pCurrentProcess
))
225 SetForegroundColor(COLOR_TEXT
);
226 SetBackgroundColor(COLOR_CAPTION
);
228 ClrLine(wWindow
[OUTPUT_WINDOW
].y
-1);
230 pProcessName
= pCurrentProcess
->ImageFileName
;
231 if(IsAddressValid((ULONG
)pProcessName
) )
233 PICE_sprintf(tempShell
,
234 " PROCESS(%.8X \"%s\") ",
235 (ULONG
)pCurrentProcess
,pProcessName
);
239 PICE_sprintf(tempShell
,
241 (ULONG
)pCurrentProcess
);
243 PutChar(tempShell
,1,wWindow
[OUTPUT_WINDOW
].y
-1);
251 //*************************************************************************
252 // ProcessBootParams()
254 //*************************************************************************
255 void ProcessBootParams(void)
262 DPRINT((0,"ProcessBootParams()\n"));
268 p2
= ucCommandBuffer
;
269 DPRINT((0,"ProcessBootParams(): boot params = %s\n",p1
));
270 while(*p1
&& *p1
!=';')
275 DPRINT((0,"ProcessBootParams(): cmd buf = %s\n",ucCommandBuffer
));
278 DPRINT((0,"ProcessBootParams(): error in cmd buf\n"));
282 DPRINT((0,"ProcessBootParams(): next cmd buf = %s\n",p1
));
284 Parse(ucCommandBuffer
,TRUE
);
286 PICE_memset(ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
292 //*************************************************************************
295 //*************************************************************************
296 BOOLEAN
inline bNoCtrlKeys(void)
298 return (!bControl
&& !bAlt
&& !bShift
);
302 //*************************************************************************
305 // handle user interface when stopped system
306 //*************************************************************************
307 void DebuggerShell(void)
311 PEPROCESS pCurrentProcess
;
315 // save the graphics state
318 // tell USER we are stopped
321 FlushKeyboardQueue();
325 // kill the speakers annoying beep
326 speaker
= inb_p((PCHAR
)0x61);
328 outb_p(speaker
,(PCHAR
)0x61);
332 DPRINT((0,"DebuggerShell(): DisplayRegs()\n"));
333 // display register contents
336 DPRINT((0,"DebuggerShell(): DisplayMemory()\n"));
337 // display data window
338 Args
.Value
[0]=OldSelector
;
339 Args
.Value
[1]=OldOffset
;
341 DisplayMemory(&Args
);
343 DPRINT((0,"DebuggerShell(): Unassemble()\n"));
345 // disassembly from current address
346 PICE_memset(&Args
,0,sizeof(ARGS
));
347 Args
.Value
[0]=CurrentCS
;
348 Args
.Value
[1]=CurrentEIP
;
352 // try to find current process's name
353 pCurrentProcess
= IoGetCurrentProcess();
354 CurrentProcess
= (ULONG
)pCurrentProcess
;
356 // display status line
362 // while we are not told to exit
363 while(bNotifyToExit
==FALSE
)
365 // emulate graphics cursor
368 // we have a key press
369 if((ucKeyPressedWhileIdle
= GetKeyPolled())!=0)
371 DPRINT((0,"DebuggerShell(): key = %x control = %u shift = %u\n",ucKeyPressedWhileIdle
,bControl
,bShift
));
373 // if cursor reversed, normalize it again (only graphics)
379 // convert key to ANSI, if success add to command buffer and try to
380 // find a command that fits the already entered letters
381 ucConverted
= AsciiFromScan((UCHAR
)(ucKeyPressedWhileIdle
&0x7f));
384 PICE_sprintf(tempShell
,"%u -> %u",ucKeyPressedWhileIdle
, ucConverted
);
385 PutChar(tempShell
,GLOBAL_SCREEN_WIDTH
-32,wWindow
[OUTPUT_WINDOW
].y
-1);
388 if(!bControl
&& !bAlt
&& ucConverted
)
390 DPRINT((0,"DebuggerShell(): normal key\n"));
391 if(!(usCurrentPosInInputBuffer
==0 && ucConverted
==' '))
393 // if we have space in the command buffer
394 // put the character there
395 if(usCurrentPosInInputBuffer
<sizeof(ucCommandBuffer
)-1)
397 ucCommandBuffer
[usCurrentPosInInputBuffer
++]=ucConverted
;
398 // output the character
399 PICE_sprintf(tempShell
,"%c",ucConverted
);
400 wWindow
[OUTPUT_WINDOW
].usCurX
= 1;
401 Print(OUTPUT_WINDOW
,tempShell
);
403 // if we have something in command buffer
404 // try to find command help that fits
405 if(usCurrentPosInInputBuffer
)
407 FindCommand(ucCommandBuffer
);
409 else ShowStoppedMsg();
412 // normal key while holding down CONTROL
413 else if(bControl
&& !bAlt
&& !bShift
&& ucConverted
)
415 if(ucConverted
== 'f')
416 bNotifyToExit
= TRUE
;
418 // normal key while holding down ALT
419 else if(!bControl
&& bAlt
&& !bShift
&& ucConverted
)
422 // normal key while holding down ALT & CONTROL
423 else if(bControl
&& bAlt
&& !bShift
&& ucConverted
)
426 // we didn't get a converted key
427 // so this must be a control key
431 if(bNoCtrlKeys() && ucKeyPressedWhileIdle
== SCANCODE_ENTER
)
433 DPRINT((0,"DebuggerShell(): RETURN\n"));
434 ucCommandBuffer
[usCurrentPosInInputBuffer
]=0;
435 if(ucCommandBuffer
[0])
437 AddToCommandLineHistory(ucCommandBuffer
);
438 ClrLine(wWindow
[OUTPUT_WINDOW
].y
+wWindow
[OUTPUT_WINDOW
].usCurY
);
439 ulLastLineDisplayedOffset
= 0;
440 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
441 // setup a safe stack for parsing
442 __asm__
__volatile__("
446 leal _aulNewStack,%%ebx
455 :"m" (ulOldStack
),"m" (ucCommandBuffer
)
462 if(ulLastLineDisplayedOffset
)
464 ulLastLineDisplayedOffset
= 0;
465 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
468 usCurrentPosInInputBuffer
=0;
469 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
472 else if(bNoCtrlKeys() && ucKeyPressedWhileIdle
== SCANCODE_BACKSPACE
)
474 DPRINT((0,"DebuggerShell(): BACKSPACE\n"));
475 if(usCurrentPosInInputBuffer
)
477 if(usCurrentPosInInputBuffer
)
478 FindCommand(ucCommandBuffer
);
482 usCurrentPosInInputBuffer
--;
483 ucCommandBuffer
[usCurrentPosInInputBuffer
]=0;
484 Print(OUTPUT_WINDOW
,"\b");
488 else if(bNoCtrlKeys() && ucKeyPressedWhileIdle
==SCANCODE_TAB
)
490 DPRINT((0,"DebuggerShell(): TAB\n"));
491 if(usCurrentPosInInputBuffer
)
495 if((pCmd
=FindCommand(ucCommandBuffer
)) )
499 // clear the displayed command line
500 for(i
=0;i
<usCurrentPosInInputBuffer
;i
++)
501 Print(OUTPUT_WINDOW
,"\b");
502 // clear command buffer
503 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
504 // copy the found command into command buffer
505 PICE_strcpy(ucCommandBuffer
,pCmd
);
506 PICE_strcat(ucCommandBuffer
," ");
507 usCurrentPosInInputBuffer
= PICE_strlen(ucCommandBuffer
);
508 Print(OUTPUT_WINDOW
,ucCommandBuffer
);
515 if(bNoCtrlKeys() && ucKeyPressedWhileIdle
>=59 && ucKeyPressedWhileIdle
<69)
517 DPRINT((0,"DebuggerShell(): FUNCTION %u\n",ucKeyPressedWhileIdle
-59));
518 PICE_sprintf(tempShell
,":");
519 ReplaceRingBufferCurrent(tempShell
);
520 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
521 usCurrentPosInInputBuffer
=0;
522 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
523 PICE_strcpy(ucCommandBuffer
,szFunctionKeys
[ucKeyPressedWhileIdle
-59]);
524 usCurrentPosInInputBuffer
=PICE_strlen(ucCommandBuffer
);
525 if(ucCommandBuffer
[0])
527 ulLastLineDisplayedOffset
= 0;
528 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
530 // setup a safe stack for parsing
531 __asm__
__volatile__("
535 leal _aulNewStack,%%ebx
544 :"m" (ulOldStack
),"m" (ucCommandBuffer
)
546 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
547 usCurrentPosInInputBuffer
=0;
552 switch(ucKeyPressedWhileIdle
)
555 if(usCurrentPosInInputBuffer
)
557 PICE_sprintf(tempShell
,":");
558 ReplaceRingBufferCurrent(tempShell
);
559 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
560 usCurrentPosInInputBuffer
=0;
561 Print(OUTPUT_WINDOW
,"");
565 case SCANCODE_HOME
: // home
566 DPRINT((0,"DebuggerShell(): HOME\n"));
570 DPRINT((0,"DebuggerShell(): data window home\n"));
572 // display data window
573 Args
.Value
[0]=OldSelector
;
574 Args
.Value
[1]=OldOffset
;
576 DisplayMemory(&Args
);
581 DPRINT((0,"DebuggerShell(): output window home\n"));
582 if(ulLastLineDisplayedOffset
!= LinesInRingBuffer()-wWindow
[OUTPUT_WINDOW
].cy
)
584 ulLastLineDisplayedOffset
= LinesInRingBuffer()-wWindow
[OUTPUT_WINDOW
].cy
+1;
585 PrintRingBufferHome(wWindow
[OUTPUT_WINDOW
].cy
-1);
588 // source window home
591 if(ulCurrentlyDisplayedLineNumber
>0)
593 PICE_SYMBOLFILE_SOURCE
* pSrc
;
595 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
597 ulCurrentlyDisplayedLineNumber
= 1;
599 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
600 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
605 else if(!bShift
&& !bControl
&& !bAlt
)
609 case SCANCODE_END
: // end
610 DPRINT((0,"DebuggerShell(): END\n"));
614 DPRINT((0,"DebuggerShell(): data window end\n"));
615 OldOffset
=0xFFFFFFFF-0x10*4;
616 // display data window
617 Args
.Value
[0]=OldSelector
;
618 Args
.Value
[1]=OldOffset
;
620 DisplayMemory(&Args
);
625 DPRINT((0,"DebuggerShell(): output window end\n"));
626 if(ulLastLineDisplayedOffset
)
628 ulLastLineDisplayedOffset
= 0;
630 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
633 else if(!bShift
&& !bControl
&& !bAlt
)
637 case SCANCODE_UP
: // up
638 DPRINT((0,"DebuggerShell(): UP\n"));
642 DPRINT((0,"DebuggerShell(): data window up\n"));
644 // display data window
645 Args
.Value
[0]=OldSelector
;
646 Args
.Value
[1]=OldOffset
;
648 DisplayMemory(&Args
);
653 DPRINT((0,"DebuggerShell(): output window up ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset
));
655 if(ulLastLineDisplayedOffset
+wWindow
[OUTPUT_WINDOW
].cy
< LinesInRingBuffer())
657 ulLastLineDisplayedOffset
+= 1;
659 PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
);
665 if((ulCurrentlyDisplayedLineNumber
-1)>0 && PICE_strlen(szCurrentFile
) )
667 PICE_SYMBOLFILE_SOURCE
* pSrc
;
669 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
671 ulCurrentlyDisplayedLineNumber
--;
672 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
673 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
674 ulCurrentlyDisplayedLineNumber
,-1);
679 UnassembleOneLineUp();
682 // command line history
683 else if(!bShift
&& !bControl
&& !bAlt
)
688 DPRINT((0,"DebuggerShell(): command line up\n"));
690 // only if anything in history
691 if(GetLinesInCommandHistory())
693 // go to next entry in history
694 if(ulCommandCurrentPos
)
695 ulCommandCurrentPos
= (ulCommandCurrentPos
-1)%GetLinesInCommandHistory();
697 ulCommandCurrentPos
= GetLinesInCommandHistory()-1;
698 DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos
));
700 pCurrentCmd
= GetFromCommandLineHistory(ulCommandCurrentPos
);
701 // if it has a string attached
702 if((len
= PICE_strlen(pCurrentCmd
)))
704 // replace the current command line
705 PICE_sprintf(tempShell
,":");
706 ReplaceRingBufferCurrent(tempShell
);
707 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
708 PICE_strcpy(ucCommandBuffer
,pCurrentCmd
);
709 usCurrentPosInInputBuffer
=len
;
710 Print(OUTPUT_WINDOW
,pCurrentCmd
);
715 case SCANCODE_DOWN
: // down
716 DPRINT((0,"DebuggerShell(): DOWN\n"));
720 DPRINT((0,"DebuggerShell(): data window down\n"));
722 // display data window
723 Args
.Value
[0]=OldSelector
;
724 Args
.Value
[1]=OldOffset
;
726 DisplayMemory(&Args
);
731 DPRINT((0,"DebuggerShell(): output window down ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset
));
732 if(ulLastLineDisplayedOffset
)
734 ulLastLineDisplayedOffset
-= 1;
736 if(!PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
))
738 ulLastLineDisplayedOffset
= 0;
739 PrintRingBuffer(wWindow
[OUTPUT_WINDOW
].cy
-1);
743 // source window down
746 if(ulCurrentlyDisplayedLineNumber
>0 && PICE_strlen(szCurrentFile
))
748 PICE_SYMBOLFILE_SOURCE
* pSrc
;
750 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
752 ulCurrentlyDisplayedLineNumber
++;
753 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
754 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
755 ulCurrentlyDisplayedLineNumber
,-1);
760 UnassembleOneLineDown();
763 // command line history
764 else if(!bShift
&& !bControl
&& !bAlt
)
769 DPRINT((0,"DebuggerShell(): command line down\n"));
771 // only if anything in history
772 if(GetLinesInCommandHistory())
774 // go to next entry in history
775 ulCommandCurrentPos
= (ulCommandCurrentPos
+1)%(GetLinesInCommandHistory());
776 DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos
));
778 pCurrentCmd
= GetFromCommandLineHistory(ulCommandCurrentPos
);
779 // if it has a string attached
780 if((len
= PICE_strlen(pCurrentCmd
)))
782 // replace the current command line
783 PICE_sprintf(tempShell
,":");
784 ReplaceRingBufferCurrent(tempShell
);
785 PICE_memset(&ucCommandBuffer
,0,sizeof(ucCommandBuffer
));
786 PICE_strcpy(ucCommandBuffer
,pCurrentCmd
);
787 usCurrentPosInInputBuffer
=len
;
788 Print(OUTPUT_WINDOW
,pCurrentCmd
);
793 case SCANCODE_LEFT
: // left
794 DPRINT((0,"DebuggerShell(): LEFT\n"));
798 DPRINT((0,"DebuggerShell(): data window left\n"));
801 // display data window
802 Args
.Value
[0]=OldSelector
;
803 Args
.Value
[1]=OldOffset
;
805 DisplayMemory(&Args
);
807 else if(!bShift
&& !bControl
&& !bAlt
)
812 if(ulWindowOffset
> 0)
814 PICE_memset(&Args
,0,sizeof(ARGS
));
819 case SCANCODE_RIGHT
: // right
823 DPRINT((0,"DebuggerShell(): data window right\n"));
826 // display data window
827 Args
.Value
[0]=OldSelector
;
828 Args
.Value
[1]=OldOffset
;
830 DisplayMemory(&Args
);
832 else if(!bShift
&& !bControl
&& !bAlt
)
837 if(ulWindowOffset
< 80)
839 PICE_memset(&Args
,0,sizeof(ARGS
));
844 case SCANCODE_PGUP
: // page up
845 DPRINT((0,"DebuggerShell(): PAGEUP\n"));
849 OldOffset
-=wWindow
[DATA_WINDOW
].cy
*0x10;
850 // display data window
851 Args
.Value
[0]=OldSelector
;
852 Args
.Value
[1]=OldOffset
;
854 DisplayMemory(&Args
);
859 if(ulLastLineDisplayedOffset
+2*(wWindow
[OUTPUT_WINDOW
].cy
) < LinesInRingBuffer())
861 ulLastLineDisplayedOffset
+= (wWindow
[OUTPUT_WINDOW
].cy
);
863 PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
);
867 if(ulLastLineDisplayedOffset
!= LinesInRingBuffer()-wWindow
[OUTPUT_WINDOW
].cy
)
869 ulLastLineDisplayedOffset
= LinesInRingBuffer()-wWindow
[OUTPUT_WINDOW
].cy
;
870 PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
);
874 // source window page up
877 if(PICE_strlen(szCurrentFile
))
879 if((ulCurrentlyDisplayedLineNumber
-wWindow
[SOURCE_WINDOW
].cy
)>0)
881 PICE_SYMBOLFILE_SOURCE
* pSrc
;
883 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
885 ulCurrentlyDisplayedLineNumber
-= wWindow
[SOURCE_WINDOW
].cy
;
887 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
888 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
889 ulCurrentlyDisplayedLineNumber
,-1);
894 PICE_SYMBOLFILE_SOURCE
* pSrc
;
896 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
898 ulCurrentlyDisplayedLineNumber
= 1;
900 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
901 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
902 ulCurrentlyDisplayedLineNumber
,-1);
908 UnassembleOnePageUp(wWindow
[SOURCE_WINDOW
].cy
);
912 else if(!bShift
&& !bControl
&& !bAlt
)
916 case SCANCODE_PGDN
: // page down
917 DPRINT((0,"DebuggerShell(): PAGEDOWN\n"));
921 OldOffset
+=wWindow
[DATA_WINDOW
].cy
*0x10;
922 // display data window
923 Args
.Value
[0]=OldSelector
;
924 Args
.Value
[1]=OldOffset
;
926 DisplayMemory(&Args
);
930 if(ulLastLineDisplayedOffset
>wWindow
[OUTPUT_WINDOW
].cy
)
932 ulLastLineDisplayedOffset
-= (wWindow
[OUTPUT_WINDOW
].cy
);
934 PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
);
938 if(ulLastLineDisplayedOffset
)
940 ulLastLineDisplayedOffset
= 0;
941 PrintRingBufferOffset(wWindow
[OUTPUT_WINDOW
].cy
-1,ulLastLineDisplayedOffset
);
947 if(PICE_strlen(szCurrentFile
) )
949 if((ulCurrentlyDisplayedLineNumber
+wWindow
[SOURCE_WINDOW
].cy
)>0)
951 PICE_SYMBOLFILE_SOURCE
* pSrc
;
953 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
955 ulCurrentlyDisplayedLineNumber
+= wWindow
[SOURCE_WINDOW
].cy
;
957 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
958 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
959 ulCurrentlyDisplayedLineNumber
,-1);
964 PICE_SYMBOLFILE_SOURCE
* pSrc
;
966 if(ConvertTokenToSrcFile(szCurrentFile
,(PULONG
)&pSrc
) )
968 ulCurrentlyDisplayedLineNumber
= 1;
970 DisplaySourceFile((LPSTR
)pSrc
+sizeof(PICE_SYMBOLFILE_SOURCE
),
971 (LPSTR
)pSrc
+pSrc
->ulOffsetToNext
,
972 ulCurrentlyDisplayedLineNumber
,-1);
978 UnassembleOnePageDown(wWindow
[SOURCE_WINDOW
].cy
);
981 else if(!bShift
&& !bControl
&& !bAlt
)
989 ucKeyPressedWhileIdle
=0;
1005 FlushKeyboardQueue();
1007 RestoreGraphicsState();
1012 //*************************************************************************
1015 //*************************************************************************
1016 void RealIsr(ULONG dwReasonForBreak
)
1018 BOOLEAN ReinstallPermanentBp
= FALSE
;
1020 DPRINT((0,"reason: %u#################################################################\n", dwReasonForBreak
));
1024 bInDebuggerShell
= TRUE
;
1028 // don't assume we must call original handlers yet
1029 dwCallOldInt1Handler
= dwCallOldInt3Handler
= dwCallOldIntEHandler
= dwCallOldGPFaultHandler
= 0;
1030 bSkipMainLoop
= FALSE
;
1033 // reset trace flag (TF) on the stack
1034 CurrentEFL
&=(~0x100);
1036 InstallPrintkHook();
1038 // control is not depressed
1041 bIrqStateAtBreak
= ((CurrentEFL
&(1<<9))!=0);
1043 DPRINT((0,"\nbInDebuggerShell %x, dwReasonForBreak: %x, bIrqStateAtBreak: %d\n", bInDebuggerShell
, dwReasonForBreak
, bIrqStateAtBreak
));
1044 DPRINT((0,"CurrentEIP: %x, CurrentESP: %x\n", CurrentEIP
, CurrentESP
));
1046 // came in because TF flag was set
1047 if(dwReasonForBreak
== REASON_SINGLESTEP
)
1049 ULONG ulAddress
,ulAddressCurrent
;
1051 DPRINT((0,"REASON_SINGLESTEP: bSingleStep: %u\n", bSingleStep
));
1055 dwCallOldInt1Handler
= 1;
1056 DPRINT((0,"no single step requested: %u!\n", dwCallOldInt1Handler
));
1057 goto common_return_point
;
1060 ulAddress
= GetLinearAddress(OldCS
,OldEIP
);
1061 ulAddressCurrent
= GetLinearAddress(CurrentCS
,CurrentEIP
);
1063 // if we came in because we needed to skip past a permanent
1064 // INT3 hook, we need to put the INT3 back in place and
1065 // simply restart the system.
1066 if(NeedToReInstallSWBreakpoints(ulAddress
,TRUE
) )
1068 DPRINT((0,"reinstalling INT3 @ %.4X:%.8X\n",OldCS
,OldEIP
));
1070 ReInstallSWBreakpoint(ulAddress
);
1072 // previous command was go i.e. we did not single-step over a location
1073 // where a permanent breakpoint was installed (Printk() etc.) we simply restart
1074 // else we must stop the system.
1075 if(bPreviousCommandWasGo
)
1077 bPreviousCommandWasGo
= FALSE
;
1078 bInDebuggerShell
= FALSE
;
1080 if(bStepThroughSource
)
1083 CurrentEFL
|= 0x100;
1087 DPRINT((0,"singlestep-----------------------------------------------------------------\n"));
1090 bPreviousCommandWasGo
= FALSE
;
1093 if(IsSwBpAtAddressInstalled(ulAddressCurrent
))
1094 DeInstallSWBreakpoint(ulAddressCurrent
);
1096 // we came here while stepping through source code block
1097 if(bStepThroughSource
)
1100 LPSTR pSrc
,pFileName
;
1102 DPRINT((0,"RealIsr(): stepping through source!\n"));
1104 // look up the corresponding source line
1105 // if there isn't any or the source line number has changed
1106 // we break back into the debugger
1108 pSrc
= FindSourceLineForAddress(ulAddressCurrent
,&ulLineNumber
,NULL
,NULL
,&pFileName
);
1111 DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u)\n",ulLineNumber
,(ULONG
)pSrc
,g_ulLineNumberStart
));
1113 // if we have found a source line there
1114 if(pSrc
&& ulLineNumber
==g_ulLineNumberStart
)
1116 DPRINT((0,"RealIsr(): stepping through line #%u in file = %s!\n",ulLineNumber
,pFileName
));
1123 bInDebuggerShell
= FALSE
;
1125 DPRINT((0,"singstep-----------------------------------------------------------------\n"));
1128 bStepThroughSource
= FALSE
;
1129 bNotifyToExit
= FALSE
;
1130 bSkipMainLoop
= FALSE
;
1133 // came in because hardware register triggered a breakpoint
1134 else if(dwReasonForBreak
== REASON_HARDWARE_BP
)
1138 DPRINT((0,"REASON_HARDWARE_BP\n"));
1140 // disable HW breakpoints
1152 DPRINT((0,"REASON_HARDWARE_BP: %x\n",(ulReason
&0xF)));
1154 // HW breakpoint DR1 (skip: only used in init_module detection)
1157 CurrentEFL
|=(1<<16); // set resume flag
1159 bSkipMainLoop
= TRUE
;
1161 TryToInstallVirtualSWBreakpoints();
1163 // HW breakpoint DR0
1164 else if(ulReason
&0x1)
1166 ULONG ulAddressCurrent
;
1168 ulAddressCurrent
= GetLinearAddress(CurrentCS
,CurrentEIP
);
1170 // we came here while stepping through source code block
1171 if(bStepThroughSource
)
1174 LPSTR pSrc
,pFileName
;
1176 DPRINT((0,"RealIsr(): stepping through source! [2]\n"));
1178 // look up the corresponding source line
1179 // if there isn't any or the source line number has changed
1180 // we break back into the debugger
1182 pSrc
= FindSourceLineForAddress(ulAddressCurrent
,&ulLineNumber
,NULL
,NULL
,&pFileName
);
1186 DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u) [2]\n",ulLineNumber
,(ULONG
)pSrc
,g_ulLineNumberStart
));
1188 // if we have found a source line there
1189 if(pSrc
&& ulLineNumber
==g_ulLineNumberStart
)
1191 DPRINT((0,"RealIsr(): stepping through line #%u in file = %s! [2]\n",ulLineNumber
,pFileName
));
1198 bInDebuggerShell
= FALSE
;
1200 DPRINT((0,"rrr-----------------------------------------------------------------\n"));
1203 bNotifyToExit
= FALSE
;
1204 bSkipMainLoop
= FALSE
;
1205 bStepThroughSource
= FALSE
;
1209 else if(dwReasonForBreak
==REASON_INT3
)
1213 DPRINT((0,"REASON_INT3\n"));
1215 // must subtract one cause INT3s are generated after instructions execution
1218 // make a flat address
1219 ulAddress
= GetLinearAddress(CurrentCS
,CurrentEIP
);
1221 DPRINT((0,"INT3 @ %.8X\n",ulAddress
));
1223 // if there's a breakpoint installed at current EIP remove it
1224 if(DeInstallSWBreakpoint(ulAddress
) )
1228 DPRINT((0,"INT3 @ %.8X removed\n",ulAddress
));
1230 // if it's permanent (must be Printk() ) skip the DebuggerShell() and
1232 if( (p
= IsPermanentSWBreakpoint(ulAddress
)) )
1234 DPRINT((0,"permanent breakpoint\n"));
1236 ReinstallPermanentBp
= TRUE
;
1239 OldEIP
= CurrentEIP
;
1241 bSkipMainLoop
= TRUE
;
1242 DPRINT((0,"callback at %x\n",p
->Callback
));
1249 if(ScanExportsByAddress(&pFind
,GetLinearAddress(CurrentCS
,CurrentEIP
)))
1251 PICE_sprintf(tempShell
,"pICE: SW Breakpoint at %s (%.4X:%.8X)\n",pFind
,CurrentCS
,CurrentEIP
);
1255 PICE_sprintf(tempShell
,"pICE: SW Breakpoint at %.4X:%.8X\n",CurrentCS
,CurrentEIP
);
1257 Print(OUTPUT_WINDOW
,tempShell
);
1259 CurrentEFL
&= ~(1<<16); // clear resume flag
1264 PEPROCESS my_current
= IoGetCurrentProcess();
1266 DPRINT((0,"can't deinstall, somebody else's breakpoint\n"));
1269 // if no other debugger is running on this process and the address is
1270 // above TASK_SIZE we assume this to be a hard embedded INT3
1272 #if REAL_LINUX_VERSION_CODE < 0x020400
1273 if(ulAddress<TASK_SIZE && !(my_current->flags & PF_PTRACED) )
1275 if(ulAddress<TASK_SIZE && !(my_current->ptrace & PT_PTRACED) )
1280 if(ScanExportsByAddress(&pFind
,GetLinearAddress(CurrentCS
,CurrentEIP
)))
1282 PICE_sprintf(tempShell
,"pICE: break due to embedded INT 3 at %s (%.4X:%.8X)\n",pFind
,CurrentCS
,CurrentEIP
);
1286 PICE_sprintf(tempShell
,"pICE: break due to embedded INT 3 at user-mode address %.4X:%.8X\n",CurrentCS
,CurrentEIP
);
1288 Print(OUTPUT_WINDOW
,tempShell
);
1289 CurrentEFL
&= ~(1<<16); // clear resume flag
1291 // well someone is already debugging this, we must pass the INT3 on to old handler
1292 // but only when it's a user-mode address
1296 if(ulAddress<TASK_SIZE || !bInt3Here)
1298 DPRINT((0,"SW Breakpoint but debugged by other process at %.4X:%.8X\n",CurrentCS,CurrentEIP));
1299 // call the old handler on return from RealIsr()
1300 dwCallOldInt3Handler = 1;
1301 // and skip DebuggerShell()
1302 bSkipMainLoop = TRUE;
1306 if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP)))
1308 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at (%s) %.4X:%.8X\n",
1309 pFind,CurrentCS,CurrentEIP);
1313 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at kernel-mode address %.4X:%.8X\n",
1314 CurrentCS,CurrentEIP);
1316 Print(OUTPUT_WINDOW,tempShell);
1317 CurrentEFL &= ~(1<<16); // clear resume flag
1325 else if(dwReasonForBreak
== REASON_PAGEFAULT
)
1329 DPRINT((0,"REASON_PAGEFAULT\n"));
1331 if( ScanExportsByAddress(&pSymbolName
,GetLinearAddress(CurrentCS
,CurrentEIP
)) )
1333 PICE_sprintf(tempShell
,"pICE: Breakpoint due to page fault at %.4X:%.8X (%s)\n",CurrentCS
,CurrentEIP
,pSymbolName
);
1337 PICE_sprintf(tempShell
,"pICE: Breakpoint due to page fault at %.4X:%.8X\n",CurrentCS
,CurrentEIP
);
1339 Print(OUTPUT_WINDOW
,tempShell
);
1340 PICE_sprintf(tempShell
,"pICE: memory referenced %x\n",CurrentCR2
);
1341 Print(OUTPUT_WINDOW
,tempShell
);
1342 dwCallOldIntEHandler
= 1;
1344 else if(dwReasonForBreak
== REASON_GP_FAULT
)
1348 DPRINT((0,"REASON_GPFAULT\n"));
1350 if( ScanExportsByAddress(&pSymbolName
,GetLinearAddress(CurrentCS
,CurrentEIP
)) )
1352 PICE_sprintf(tempShell
,"pICE: Breakpoint due to general protection fault at %.4X:%.8X (%s)\n",CurrentCS
,CurrentEIP
,pSymbolName
);
1356 PICE_sprintf(tempShell
,"pICE: Breakpoint due to general protection fault at %.4X:%.8X\n",CurrentCS
,CurrentEIP
);
1358 Print(OUTPUT_WINDOW
,tempShell
);
1359 dwCallOldGPFaultHandler
= 1;
1361 else if(dwReasonForBreak
== REASON_CTRLF
)
1363 DPRINT((0,"REASON_CTRLF\n"));
1366 else if(dwReasonForBreak
== REASON_DOUBLE_FAULT
)
1368 DPRINT((0,"REASON_DOUBLE_FAULT\n"));
1370 PICE_sprintf(tempShell
,"pICE: Breakpoint due to double fault at %.4X:%.8X\n",CurrentCS
,CurrentEIP
);
1371 Print(OUTPUT_WINDOW
,tempShell
);
1373 else if(dwReasonForBreak
== REASON_INTERNAL_ERROR
)
1375 DPRINT((0,"REASON_INTERNAL_ERROR\n"));
1377 Print(OUTPUT_WINDOW
,"pICE: Please report this error to klauspg@diamondmm.com!\n");
1378 // Print(OUTPUT_WINDOW,"pICE: !!! SYSTEM HALTED !!!\n");
1379 // __asm__ __volatile__("hlt");
1383 DPRINT((0,"REASON_UNKNOWN\n"));
1385 PICE_sprintf(tempShell
,"pICE: Breakpoint due to unknown reason at %.4X:%.8X (code %x)\n",CurrentCS
,CurrentEIP
,dwReasonForBreak
);
1386 Print(OUTPUT_WINDOW
,tempShell
);
1387 Print(OUTPUT_WINDOW
,"pICE: Please report this error to klauspg@diamondmm.com!\n");
1388 Print(OUTPUT_WINDOW
,"pICE: !!! SYSTEM HALTED !!!\n");
1389 __asm__
__volatile__("hlt");
1392 // we don't single-step yet
1393 DPRINT((0,"RealIsr(): not stepping yet\n"));
1397 if(bSkipMainLoop
== FALSE
)
1399 DPRINT((0,"RealIsr(): saving registers\n"));
1400 // save the extended regs
1401 __asm__ __volatile__
1407 //movw %ax,_CurrentFS
1411 movl %eax,_CurrentDR0
1413 movl %eax,_CurrentDR1
1415 movl %eax,_CurrentDR2
1417 movl %eax,_CurrentDR3
1419 movl %eax,_CurrentDR6
1421 movl %eax,_CurrentDR7
1423 movl %eax,_CurrentCR0
1425 movl %eax,_CurrentCR2
1427 movl %eax,_CurrentCR3
1431 CurrentFS
= OLD_PCR
;
1432 DPRINT((0,"RealIsr(): adding colon to output()\n"));
1433 Print(OUTPUT_WINDOW
,":");
1435 DPRINT((0,"RealIsr(): calling DebuggerShell()\n"));
1439 // if there was a SW breakpoint at CS:EIP
1440 if(NeedToReInstallSWBreakpoints(GetLinearAddress(CurrentCS
,CurrentEIP
),TRUE
) || ReinstallPermanentBp
)
1442 DPRINT((0,"need to reinstall INT3\n"));
1443 // remember how we restarted last time
1444 bPreviousCommandWasGo
= !bSingleStep
;
1445 // do a single step to reinstall breakpoint
1446 // modify trace flag
1447 CurrentEFL
|=0x100; // set trace flag (TF)
1453 common_return_point
:
1455 // reset the global flags
1456 bNotifyToExit
= FALSE
;
1457 bSkipMainLoop
= FALSE
;
1459 // not in handler anymore
1460 bInDebuggerShell
= FALSE
;
1463 DPRINT((0,"common return-----------------------------------------------------------------\n"));
1467 __asm__(".global NewInt31Handler
1479 movl %eax,_CurrentEAX
1480 movl %ebx,_CurrentEBX
1481 movl %ecx,_CurrentECX
1482 movl %edx,_CurrentEDX
1483 movl %esi,_CurrentESI
1484 movl %edi,_CurrentEDI
1485 movl %ebp,_CurrentEBP
1489 // test for V86 mode
1490 testl $0x20000,5*4(%esp)
1496 // test if stack switched (ring3->ring0 transition)
1497 // stack is switched if orig. SS is not global kernel code segment
1499 cmpw $" STR(GLOBAL_CODE_SEGMENT
) ",%ax
1504 mov %eax,_CurrentESP
1511 // didn't switch stack
1512 movl %esp,_CurrentESP
1513 addl $24,_CurrentESP
1521 mov %eax,_CurrentEIP
1528 andl $0xFFFFFEFF,%eax
1529 movl %eax,_CurrentEFL
1537 * Load the PCR selector.
1545 // setup a large work stack
1547 movl %eax,_ulRealStackPtr
1561 // do an EOI to IRQ controller (because we definitely pressed some key)
1562 // TODO: SMP APIC support
1569 // remove reason code
1572 // make EAX available
1575 // modify or restore EFLAGS
1577 mov _CurrentEFL,%eax
1580 movzwl _CurrentCS,%eax
1583 mov _CurrentEIP,%eax
1589 // do we need to call old INT1 handler
1591 cmp $0,_dwCallOldInt1Handler
1594 // call INT3 handler
1596 jmp *_OldInt1Handler
1599 // do we need to call old INT3 handler
1601 cmp $0,_dwCallOldInt3Handler
1604 // call INT3 handler
1606 jmp *_OldInt3Handler
1609 // do we need to call old pagefault handler
1611 cmp $0,_dwCallOldIntEHandler
1614 // call old pagefault handler
1618 jmp *_OldIntEHandler
1621 // do we need to call old general protection fault handler
1623 cmp $0,_dwCallOldGPFaultHandler
1626 // call old pagefault handler
1630 jmp *_OldGPFaultHandler
1638 // stub for entering via CTRL-F
1640 // IDTs keyboard IRQ points here
1643 NewGlobalInt31Handler:
1648 // chain to old handler
1650 jmp *_OldGlobalInt31Handler
1653 pushl $" STR(REASON_CTRLF
) "
1654 jmp NewInt31Handler "
1657 void InstallGlobalKeyboardHook(void)
1659 ULONG LocalNewGlobalInt31Handler
;
1664 if(!OldGlobalInt31Handler
)
1666 __asm__("mov $NewGlobalInt31Handler,%0"
1667 :"=r" (LocalNewGlobalInt31Handler
)
1670 OldGlobalInt31Handler
=SetGlobalInt(KeyboardIRQL
,(ULONG
)LocalNewGlobalInt31Handler
);
1677 void DeInstallGlobalKeyboardHook(void)
1682 if(OldGlobalInt31Handler
)
1684 SetGlobalInt(KeyboardIRQL
,(ULONG
)OldGlobalInt31Handler
);
1685 OldGlobalInt31Handler
=0;