- Tree cleanups proposed on the mailing list. Move all non-Core OS modules to rosapps...
[reactos.git] / rosapps / sysutils / utils / pice / module / shell.c
1 /*++
2
3 Copyright (c) 1998-2001 Klaus P. Gerlicher
4
5 Module Name:
6
7 shell.c
8
9 Abstract:
10
11 user interface for debugger
12
13 Environment:
14
15 Kernel mode only
16
17 Author:
18
19 Klaus P. Gerlicher
20
21 Revision History:
22
23 16-Jul-1998: created
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
27
28 Copyright notice:
29
30 This file may be distributed under the terms of the GNU Public License.
31
32 --*/
33
34 ////////////////////////////////////////////////////
35 // INCLUDES
36 ////
37 #include "remods.h"
38 #include "precomp.h"
39
40
41 ////////////////////////////////////////////////////
42 // DEFINES
43 ////
44 #define LINES_IN_COMMAND_BUFFER (64)
45
46 ////////////////////////////////////////////////////
47 // PROTOTYPES
48 ////
49
50 ////////////////////////////////////////////////////
51 // GLOBALS
52 ////
53
54 ULONG bPreviousCommandWasGo = FALSE;
55
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;
61
62 ULONG g_ulLineNumberStart=0;
63 ULONG ulWindowOffset = 0;
64 BOOLEAN bStepThroughSource=FALSE;
65 BOOLEAN bStepInto = FALSE;
66
67 // key handling
68 UCHAR ucConverted; // key converted from scancode to ANSI
69
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;
81
82 ULONG ulRealStackPtr;
83 static ULONG PCR_SEL = PCR_SELECTOR;
84 static ULONG OLD_PCR;
85
86 char tempShell[256]; // temporary string container
87
88 // old address of display memory
89 USHORT OldSelector=0;
90 ULONG OldOffset=0;
91
92 ULONG ulLastLineDisplayedOffset = 0;
93
94 // functions of function keys
95 char *szFunctionKeys[10]={
96 "mod", // F1
97 "proc", // F2
98 "src", // F3
99 "code", // F4
100 "x", // F5
101 "vma", // F6
102 "", // F7
103 "t", // F8
104 "", // F9
105 "p" // F10
106 };
107
108 // new stack for "deep parsing"
109 ULONG aulNewStack[0x20000];
110 ULONG ulOldStack;
111
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;
119 // previous context
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;
124
125 ULONG CurrentProcess;
126
127 UCHAR ucCommandBuffer[256];
128 USHORT usCurrentPosInInputBuffer=0;
129 volatile BOOLEAN bSingleStep=FALSE;
130
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;
135
136
137 extern ULONG KeyboardIRQL;
138
139 //*************************************************************************
140 // GetLinesInCommandHistory()
141 //
142 //*************************************************************************
143 ULONG GetLinesInCommandHistory(void)
144 {
145 ULONG ulResult = (ulCommandInPos-ulCommandLastPos)%LINES_IN_COMMAND_BUFFER;
146
147 ENTER_FUNC();
148
149 DPRINT((0,"GetLinesInCommandHistory() returns %u (ulIn %u ulLast %u)\n",ulResult,ulCommandInPos,ulCommandLastPos));
150
151 LEAVE_FUNC();
152
153 return ulResult;
154 }
155
156 //*************************************************************************
157 // AddToCommandLineHistory()
158 //
159 //*************************************************************************
160 void AddToCommandLineHistory(LPSTR s)
161 {
162 ULONG i;
163
164 ENTER_FUNC();
165 DPRINT((0,"AddToCommandLineHistory(%s)\n",s));
166
167 if(PICE_strlen(s))
168 {
169 for(i=0;i<LINES_IN_COMMAND_BUFFER;i++)
170 {
171 if(PICE_strcmpi(&aszCommandLines[i][1],s) == 0)
172 {
173 DPRINT((0,"AddToCommandLineHistory(): command line already exists\n"));
174 LEAVE_FUNC();
175 return;
176 }
177 }
178 aszCommandLines[ulCommandInPos][0]=':';
179 PICE_strcpy(&aszCommandLines[ulCommandInPos][1],s);
180 ulCommandCurrentPos = ulCommandInPos = (ulCommandInPos +1)%LINES_IN_COMMAND_BUFFER;
181 if(ulCommandInPos == ulCommandLastPos)
182 {
183 ulCommandLastPos = (ulCommandLastPos+1)%LINES_IN_COMMAND_BUFFER;
184 }
185 }
186
187 LEAVE_FUNC();
188 }
189
190 //*************************************************************************
191 // GetFromCommandLineHistory()
192 //
193 //*************************************************************************
194 LPSTR GetFromCommandLineHistory(ULONG ulCurrentCommandPos)
195 {
196 LPSTR pRet;
197
198 ENTER_FUNC();
199
200 DPRINT((0,"GetFromCommandLineHistory(): current = %u\n",ulCurrentCommandPos));
201
202 // skip leading ':'
203 pRet = aszCommandLines[ulCurrentCommandPos] + 1;
204
205 DPRINT((0,"GetFromCommandLineHistory(%s)\n",pRet));
206
207 LEAVE_FUNC();
208
209 return pRet;
210 }
211
212 //*************************************************************************
213 // ShowStatusLine()
214 //
215 //*************************************************************************
216 void ShowStatusLine(void)
217 {
218 PEPROCESS pCurrentProcess = IoGetCurrentProcess();
219 LPSTR pProcessName;
220
221 ENTER_FUNC();
222
223 if(IsAddressValid((ULONG)pCurrentProcess))
224 {
225 SetForegroundColor(COLOR_TEXT);
226 SetBackgroundColor(COLOR_CAPTION);
227
228 ClrLine(wWindow[OUTPUT_WINDOW].y-1);
229
230 pProcessName = pCurrentProcess->ImageFileName;
231 if(IsAddressValid((ULONG)pProcessName) )
232 {
233 PICE_sprintf(tempShell,
234 " PROCESS(%.8X \"%s\") ",
235 (ULONG)pCurrentProcess,pProcessName);
236 }
237 else
238 {
239 PICE_sprintf(tempShell,
240 " PROCESS(%.8X) ",
241 (ULONG)pCurrentProcess);
242 }
243 PutChar(tempShell,1,wWindow[OUTPUT_WINDOW].y-1);
244
245 ResetColor();
246 }
247
248 LEAVE_FUNC();
249 }
250
251 //*************************************************************************
252 // ProcessBootParams()
253 //
254 //*************************************************************************
255 void ProcessBootParams(void)
256 {
257 LPSTR p1,p2;
258
259 ENTER_FUNC();
260 if(*szBootParams)
261 {
262 DPRINT((0,"ProcessBootParams()\n"));
263
264 p1 = szBootParams;
265
266 while(*p1)
267 {
268 p2 = ucCommandBuffer;
269 DPRINT((0,"ProcessBootParams(): boot params = %s\n",p1));
270 while(*p1 && *p1!=';')
271 {
272 *p2++ = *p1++;
273 }
274 *p2=0;
275 DPRINT((0,"ProcessBootParams(): cmd buf = %s\n",ucCommandBuffer));
276 if(*p1 != ';')
277 {
278 DPRINT((0,"ProcessBootParams(): error in cmd buf\n"));
279 break;
280 }
281 p1++;
282 DPRINT((0,"ProcessBootParams(): next cmd buf = %s\n",p1));
283
284 Parse(ucCommandBuffer,TRUE);
285 }
286 PICE_memset(ucCommandBuffer,0,sizeof(ucCommandBuffer));
287 *szBootParams = 0;
288 }
289 LEAVE_FUNC();
290 }
291
292 //*************************************************************************
293 // bNoCtrlKeys()
294 //
295 //*************************************************************************
296 BOOLEAN __inline bNoCtrlKeys(void)
297 {
298 return (!bControl && !bAlt && !bShift);
299 }
300
301
302 //*************************************************************************
303 // DebuggerShell()
304 //
305 // handle user interface when stopped system
306 //*************************************************************************
307 void DebuggerShell(void)
308 {
309 ARGS Args;
310 UCHAR speaker;
311 PEPROCESS pCurrentProcess;
312
313 ENTER_FUNC();
314
315 // save the graphics state
316 SaveGraphicsState();
317
318 // tell USER we are stopped
319 ShowStoppedMsg();
320
321 FlushKeyboardQueue();
322
323 CheckRingBuffer();
324
325 // kill the speakers annoying beep
326 speaker = inb_p((PCHAR)0x61);
327 speaker &= 0xFC;
328 outb_p(speaker,(PCHAR)0x61);
329
330 ProcessBootParams();
331
332 DPRINT((0,"DebuggerShell(): DisplayRegs()\n"));
333 // display register contents
334 DisplayRegs();
335
336 DPRINT((0,"DebuggerShell(): DisplayMemory()\n"));
337 // display data window
338 Args.Value[0]=OldSelector;
339 Args.Value[1]=OldOffset;
340 Args.Count=2;
341 DisplayMemory(&Args);
342
343 DPRINT((0,"DebuggerShell(): Unassemble()\n"));
344
345 // disassembly from current address
346 PICE_memset(&Args,0,sizeof(ARGS));
347 Args.Value[0]=CurrentCS;
348 Args.Value[1]=CurrentEIP;
349 Args.Count=2;
350 Unassemble(&Args);
351
352 // try to find current process's name
353 pCurrentProcess = IoGetCurrentProcess();
354 CurrentProcess = (ULONG)pCurrentProcess;
355
356 // display status line
357 ShowStatusLine();
358
359 // switch on cursor
360 ShowCursor();
361
362 // while we are not told to exit
363 while(bNotifyToExit==FALSE)
364 {
365 // emulate graphics cursor
366 PrintCursor(FALSE);
367
368 // we have a key press
369 if((ucKeyPressedWhileIdle = GetKeyPolled())!=0)
370 {
371 DPRINT((0,"DebuggerShell(): key = %x control = %u shift = %u\n",ucKeyPressedWhileIdle,bControl,bShift));
372
373 // if cursor reversed, normalize it again (only graphics)
374 if(bRev)
375 {
376 PrintCursor(TRUE);
377 }
378
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));
382
383 #if 0
384 PICE_sprintf(tempShell,"%u -> %u",ucKeyPressedWhileIdle, ucConverted);
385 PutChar(tempShell,GLOBAL_SCREEN_WIDTH-32,wWindow[OUTPUT_WINDOW].y-1);
386 #endif
387
388 if(!bControl && !bAlt && ucConverted)
389 {
390 DPRINT((0,"DebuggerShell(): normal key\n"));
391 if(!(usCurrentPosInInputBuffer==0 && ucConverted==' '))
392 {
393 // if we have space in the command buffer
394 // put the character there
395 if(usCurrentPosInInputBuffer<sizeof(ucCommandBuffer)-1)
396 {
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);
402 }
403 // if we have something in command buffer
404 // try to find command help that fits
405 if(usCurrentPosInInputBuffer)
406 {
407 FindCommand(ucCommandBuffer);
408 }
409 else ShowStoppedMsg();
410 }
411 }
412 // normal key while holding down CONTROL
413 else if(bControl && !bAlt && !bShift && ucConverted)
414 {
415 if(ucConverted == 'f')
416 bNotifyToExit = TRUE;
417 }
418 // normal key while holding down ALT
419 else if(!bControl && bAlt && !bShift && ucConverted)
420 {
421 }
422 // normal key while holding down ALT & CONTROL
423 else if(bControl && bAlt && !bShift && ucConverted)
424 {
425 }
426 // we didn't get a converted key
427 // so this must be a control key
428 else
429 {
430 // RETURN
431 if(bNoCtrlKeys() && ucKeyPressedWhileIdle == SCANCODE_ENTER)
432 {
433 DPRINT((0,"DebuggerShell(): RETURN\n"));
434 ucCommandBuffer[usCurrentPosInInputBuffer]=0;
435 if(ucCommandBuffer[0])
436 {
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__("\n\t \
443 movl %2,%%eax\n\t \
444 movl %%esp,%%ebx\n\t \
445 mov %%ebx,%0\n\t \
446 leal _aulNewStack,%%ebx\n\t \
447 addl $0x1FFF0,%%ebx\n\t \
448 movl %%ebx,%%esp\n\t \
449 pushl $0\n\t \
450 pushl %%eax\n\t \
451 call _Parse\n\t \
452 movl %0,%%ebx\n\t \
453 movl %%ebx,%%esp"
454 :"=m" (ulOldStack)
455 :"m" (ulOldStack),"m" (ucCommandBuffer)
456 :"eax","ebx");
457
458 ShowStoppedMsg();
459 }
460 else
461 {
462 if(ulLastLineDisplayedOffset)
463 {
464 ulLastLineDisplayedOffset = 0;
465 PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1);
466 }
467 }
468 usCurrentPosInInputBuffer=0;
469 PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer));
470 }
471 // backspace
472 else if(bNoCtrlKeys() && ucKeyPressedWhileIdle == SCANCODE_BACKSPACE)
473 {
474 DPRINT((0,"DebuggerShell(): BACKSPACE\n"));
475 if(usCurrentPosInInputBuffer)
476 {
477 if(usCurrentPosInInputBuffer)
478 FindCommand(ucCommandBuffer);
479 else
480 ShowStoppedMsg();
481
482 usCurrentPosInInputBuffer--;
483 ucCommandBuffer[usCurrentPosInInputBuffer]=0;
484 Print(OUTPUT_WINDOW,"\b");
485 }
486 }
487 // Tab
488 else if(bNoCtrlKeys() && ucKeyPressedWhileIdle==SCANCODE_TAB)
489 {
490 DPRINT((0,"DebuggerShell(): TAB\n"));
491 if(usCurrentPosInInputBuffer)
492 {
493 LPSTR pCmd;
494
495 if((pCmd=FindCommand(ucCommandBuffer)) )
496 {
497 ULONG i;
498
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);
509 }
510 }
511 }
512 else
513 {
514 // function keys
515 if(bNoCtrlKeys() && ucKeyPressedWhileIdle>=59 && ucKeyPressedWhileIdle<69)
516 {
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])
526 {
527 ulLastLineDisplayedOffset = 0;
528 PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1);
529
530 // setup a safe stack for parsing
531 __asm__ __volatile__("\n\t \
532 movl %2,%%eax\n\t \
533 movl %%esp,%%ebx\n\t \
534 mov %%ebx,%0\n\t \
535 leal _aulNewStack,%%ebx\n\t \
536 addl $0x1FFF0,%%ebx\n\t \
537 movl %%ebx,%%esp\n\t \
538 pushl $1\n\t \
539 pushl %%eax\n\t \
540 call _Parse\n\t \
541 movl %0,%%ebx\n\t \
542 movl %%ebx,%%esp"
543 :"=m" (ulOldStack)
544 :"m" (ulOldStack),"m" (ucCommandBuffer)
545 :"eax","ebx");
546 PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer));
547 usCurrentPosInInputBuffer=0;
548 }
549 }
550 else
551 {
552 switch(ucKeyPressedWhileIdle)
553 {
554 case SCANCODE_ESC:
555 if(usCurrentPosInInputBuffer)
556 {
557 PICE_sprintf(tempShell,":");
558 ReplaceRingBufferCurrent(tempShell);
559 PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer));
560 usCurrentPosInInputBuffer=0;
561 Print(OUTPUT_WINDOW,"");
562 ShowStoppedMsg();
563 }
564 break;
565 case SCANCODE_HOME: // home
566 DPRINT((0,"DebuggerShell(): HOME\n"));
567 // memory window
568 if(bAlt)
569 {
570 DPRINT((0,"DebuggerShell(): data window home\n"));
571 OldOffset=0x0;
572 // display data window
573 Args.Value[0]=OldSelector;
574 Args.Value[1]=OldOffset;
575 Args.Count=2;
576 DisplayMemory(&Args);
577 }
578 // output window
579 else if(bShift)
580 {
581 DPRINT((0,"DebuggerShell(): output window home\n"));
582 if(ulLastLineDisplayedOffset != LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy)
583 {
584 ulLastLineDisplayedOffset = LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy+1;
585 PrintRingBufferHome(wWindow[OUTPUT_WINDOW].cy-1);
586 }
587 }
588 // source window home
589 else if(bControl)
590 {
591 if(ulCurrentlyDisplayedLineNumber>0)
592 {
593 PICE_SYMBOLFILE_SOURCE* pSrc;
594
595 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
596 {
597 ulCurrentlyDisplayedLineNumber = 1;
598
599 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
600 (LPSTR)pSrc+pSrc->ulOffsetToNext,
601 1,-1);
602 }
603 }
604 }
605 else if(!bShift && !bControl && !bAlt)
606 {
607 }
608 break;
609 case SCANCODE_END: // end
610 DPRINT((0,"DebuggerShell(): END\n"));
611 // memory window
612 if(bAlt)
613 {
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;
619 Args.Count=2;
620 DisplayMemory(&Args);
621 }
622 // output window
623 else if(bShift)
624 {
625 DPRINT((0,"DebuggerShell(): output window end\n"));
626 if(ulLastLineDisplayedOffset)
627 {
628 ulLastLineDisplayedOffset = 0;
629
630 PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1);
631 }
632 }
633 else if(!bShift && !bControl && !bAlt)
634 {
635 }
636 break;
637 case SCANCODE_UP: // up
638 DPRINT((0,"DebuggerShell(): UP\n"));
639 // memory window
640 if(bAlt)
641 {
642 DPRINT((0,"DebuggerShell(): data window up\n"));
643 OldOffset-=0x10;
644 // display data window
645 Args.Value[0]=OldSelector;
646 Args.Value[1]=OldOffset;
647 Args.Count=2;
648 DisplayMemory(&Args);
649 }
650 // output window
651 else if(bShift)
652 {
653 DPRINT((0,"DebuggerShell(): output window up ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset));
654
655 if(ulLastLineDisplayedOffset+wWindow[OUTPUT_WINDOW].cy < LinesInRingBuffer())
656 {
657 ulLastLineDisplayedOffset += 1;
658
659 PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset);
660 }
661 }
662 // source window up
663 else if(bControl)
664 {
665 if((ulCurrentlyDisplayedLineNumber-1)>0 && PICE_strlen(szCurrentFile) )
666 {
667 PICE_SYMBOLFILE_SOURCE* pSrc;
668
669 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
670 {
671 ulCurrentlyDisplayedLineNumber--;
672 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
673 (LPSTR)pSrc+pSrc->ulOffsetToNext,
674 ulCurrentlyDisplayedLineNumber,-1);
675 }
676 }
677 else
678 {
679 UnassembleOneLineUp();
680 }
681 }
682 // command line history
683 else if(!bShift && !bControl && !bAlt)
684 {
685 LPSTR pCurrentCmd;
686 ULONG len;
687
688 DPRINT((0,"DebuggerShell(): command line up\n"));
689
690 // only if anything in history
691 if(GetLinesInCommandHistory())
692 {
693 // go to next entry in history
694 if(ulCommandCurrentPos)
695 ulCommandCurrentPos = (ulCommandCurrentPos-1)%GetLinesInCommandHistory();
696 else
697 ulCommandCurrentPos = GetLinesInCommandHistory()-1;
698 DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos));
699 // get this entry
700 pCurrentCmd = GetFromCommandLineHistory(ulCommandCurrentPos);
701 // if it has a string attached
702 if((len = PICE_strlen(pCurrentCmd)))
703 {
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);
711 }
712 }
713 }
714 break;
715 case SCANCODE_DOWN: // down
716 DPRINT((0,"DebuggerShell(): DOWN\n"));
717 // memory window
718 if(bAlt)
719 {
720 DPRINT((0,"DebuggerShell(): data window down\n"));
721 OldOffset+=0x10;
722 // display data window
723 Args.Value[0]=OldSelector;
724 Args.Value[1]=OldOffset;
725 Args.Count=2;
726 DisplayMemory(&Args);
727 }
728 // output window
729 else if(bShift)
730 {
731 DPRINT((0,"DebuggerShell(): output window down ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset));
732 if(ulLastLineDisplayedOffset)
733 {
734 ulLastLineDisplayedOffset -= 1;
735
736 if(!PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset))
737 {
738 ulLastLineDisplayedOffset = 0;
739 PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1);
740 }
741 }
742 }
743 // source window down
744 else if(bControl)
745 {
746 if(ulCurrentlyDisplayedLineNumber>0 && PICE_strlen(szCurrentFile))
747 {
748 PICE_SYMBOLFILE_SOURCE* pSrc;
749
750 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
751 {
752 ulCurrentlyDisplayedLineNumber++;
753 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
754 (LPSTR)pSrc+pSrc->ulOffsetToNext,
755 ulCurrentlyDisplayedLineNumber,-1);
756 }
757 }
758 else
759 {
760 UnassembleOneLineDown();
761 }
762 }
763 // command line history
764 else if(!bShift && !bControl && !bAlt)
765 {
766 LPSTR pCurrentCmd;
767 ULONG len;
768
769 DPRINT((0,"DebuggerShell(): command line down\n"));
770
771 // only if anything in history
772 if(GetLinesInCommandHistory())
773 {
774 // go to next entry in history
775 ulCommandCurrentPos = (ulCommandCurrentPos+1)%(GetLinesInCommandHistory());
776 DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos));
777 // get this entry
778 pCurrentCmd = GetFromCommandLineHistory(ulCommandCurrentPos);
779 // if it has a string attached
780 if((len = PICE_strlen(pCurrentCmd)))
781 {
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);
789 }
790 }
791 }
792 break;
793 case SCANCODE_LEFT: // left
794 DPRINT((0,"DebuggerShell(): LEFT\n"));
795 // memory window
796 if(bAlt)
797 {
798 DPRINT((0,"DebuggerShell(): data window left\n"));
799
800 OldOffset-=0x1;
801 // display data window
802 Args.Value[0]=OldSelector;
803 Args.Value[1]=OldOffset;
804 Args.Count=2;
805 DisplayMemory(&Args);
806 }
807 else if(!bShift && !bControl && !bAlt)
808 {
809 }
810 else if(bControl)
811 {
812 if(ulWindowOffset > 0)
813 ulWindowOffset--;
814 PICE_memset(&Args,0,sizeof(ARGS));
815 Args.Count=0;
816 Unassemble(&Args);
817 }
818 break;
819 case SCANCODE_RIGHT: // right
820 // memory window
821 if(bAlt)
822 {
823 DPRINT((0,"DebuggerShell(): data window right\n"));
824
825 OldOffset+=0x1;
826 // display data window
827 Args.Value[0]=OldSelector;
828 Args.Value[1]=OldOffset;
829 Args.Count=2;
830 DisplayMemory(&Args);
831 }
832 else if(!bShift && !bControl && !bAlt)
833 {
834 }
835 else if(bControl)
836 {
837 if(ulWindowOffset < 80)
838 ulWindowOffset++;
839 PICE_memset(&Args,0,sizeof(ARGS));
840 Args.Count=0;
841 Unassemble(&Args);
842 }
843 break;
844 case SCANCODE_PGUP: // page up
845 DPRINT((0,"DebuggerShell(): PAGEUP\n"));
846 // memory window
847 if(bAlt)
848 {
849 OldOffset-=wWindow[DATA_WINDOW].cy*0x10;
850 // display data window
851 Args.Value[0]=OldSelector;
852 Args.Value[1]=OldOffset;
853 Args.Count=2;
854 DisplayMemory(&Args);
855 }
856 // output window
857 else if(bShift)
858 {
859 if(ulLastLineDisplayedOffset+2*(wWindow[OUTPUT_WINDOW].cy) < LinesInRingBuffer())
860 {
861 ulLastLineDisplayedOffset += (wWindow[OUTPUT_WINDOW].cy);
862
863 PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset);
864 }
865 else
866 {
867 if(ulLastLineDisplayedOffset != LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy)
868 {
869 ulLastLineDisplayedOffset = LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy;
870 PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset);
871 }
872 }
873 }
874 // source window page up
875 else if(bControl)
876 {
877 if(PICE_strlen(szCurrentFile))
878 {
879 if((ulCurrentlyDisplayedLineNumber-wWindow[SOURCE_WINDOW].cy)>0)
880 {
881 PICE_SYMBOLFILE_SOURCE* pSrc;
882
883 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
884 {
885 ulCurrentlyDisplayedLineNumber -= wWindow[SOURCE_WINDOW].cy;
886
887 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
888 (LPSTR)pSrc+pSrc->ulOffsetToNext,
889 ulCurrentlyDisplayedLineNumber ,-1);
890 }
891 }
892 else
893 {
894 PICE_SYMBOLFILE_SOURCE* pSrc;
895
896 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
897 {
898 ulCurrentlyDisplayedLineNumber = 1;
899
900 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
901 (LPSTR)pSrc+pSrc->ulOffsetToNext,
902 ulCurrentlyDisplayedLineNumber ,-1);
903 }
904 }
905 }
906 else
907 {
908 UnassembleOnePageUp(wWindow[SOURCE_WINDOW].cy);
909 }
910
911 }
912 else if(!bShift && !bControl && !bAlt)
913 {
914 }
915 break;
916 case SCANCODE_PGDN: // page down
917 DPRINT((0,"DebuggerShell(): PAGEDOWN\n"));
918 // memory window
919 if(bAlt)
920 {
921 OldOffset+=wWindow[DATA_WINDOW].cy*0x10;
922 // display data window
923 Args.Value[0]=OldSelector;
924 Args.Value[1]=OldOffset;
925 Args.Count=2;
926 DisplayMemory(&Args);
927 }
928 else if(bShift)
929 {
930 if(ulLastLineDisplayedOffset>wWindow[OUTPUT_WINDOW].cy)
931 {
932 ulLastLineDisplayedOffset -= (wWindow[OUTPUT_WINDOW].cy);
933
934 PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset);
935 }
936 else
937 {
938 if(ulLastLineDisplayedOffset)
939 {
940 ulLastLineDisplayedOffset = 0;
941 PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset);
942 }
943 }
944 }
945 else if(bControl)
946 {
947 if(PICE_strlen(szCurrentFile) )
948 {
949 if((ulCurrentlyDisplayedLineNumber+wWindow[SOURCE_WINDOW].cy)>0)
950 {
951 PICE_SYMBOLFILE_SOURCE* pSrc;
952
953 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
954 {
955 ulCurrentlyDisplayedLineNumber += wWindow[SOURCE_WINDOW].cy;
956
957 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
958 (LPSTR)pSrc+pSrc->ulOffsetToNext,
959 ulCurrentlyDisplayedLineNumber ,-1);
960 }
961 }
962 else
963 {
964 PICE_SYMBOLFILE_SOURCE* pSrc;
965
966 if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) )
967 {
968 ulCurrentlyDisplayedLineNumber = 1;
969
970 DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE),
971 (LPSTR)pSrc+pSrc->ulOffsetToNext,
972 ulCurrentlyDisplayedLineNumber ,-1);
973 }
974 }
975 }
976 else
977 {
978 UnassembleOnePageDown(wWindow[SOURCE_WINDOW].cy);
979 }
980 }
981 else if(!bShift && !bControl && !bAlt)
982 {
983 }
984 break;
985 }
986 }
987 }
988 }
989 ucKeyPressedWhileIdle=0;
990 }
991 }
992
993 SaveOldRegs();
994
995 PrintLogo(TRUE);
996
997 ShowRunningMsg();
998
999 if(bRev)
1000 PrintCursor(TRUE);
1001
1002 // hide the cursor
1003 HideCursor();
1004
1005 FlushKeyboardQueue();
1006
1007 RestoreGraphicsState();
1008
1009 LEAVE_FUNC();
1010 }
1011
1012 //*************************************************************************
1013 // RealIsr()
1014 //
1015 //*************************************************************************
1016 void RealIsr(ULONG dwReasonForBreak)
1017 {
1018 BOOLEAN ReinstallPermanentBp = FALSE;
1019
1020 DPRINT((0,"reason: %u#################################################################\n", dwReasonForBreak));
1021 ENTER_FUNC();
1022
1023 // in handler
1024 bInDebuggerShell = TRUE;
1025
1026 bStepping = FALSE;
1027
1028 // don't assume we must call original handlers yet
1029 dwCallOldInt1Handler = dwCallOldInt3Handler = dwCallOldIntEHandler = dwCallOldGPFaultHandler = 0;
1030 bSkipMainLoop = FALSE;
1031 bEnterNow = FALSE;
1032
1033 // reset trace flag (TF) on the stack
1034 CurrentEFL&=(~0x100);
1035
1036 InstallPrintkHook();
1037
1038 // control is not depressed
1039 bControl=FALSE;
1040
1041 bIrqStateAtBreak = ((CurrentEFL&(1<<9))!=0);
1042
1043 DPRINT((0,"\nbInDebuggerShell %x, dwReasonForBreak: %x, bIrqStateAtBreak: %d\n", bInDebuggerShell, dwReasonForBreak, bIrqStateAtBreak));
1044 DPRINT((0,"CurrentEIP: %x, CurrentESP: %x\n", CurrentEIP, CurrentESP));
1045
1046 // came in because TF flag was set
1047 if(dwReasonForBreak == REASON_SINGLESTEP)
1048 {
1049 ULONG ulAddress,ulAddressCurrent;
1050
1051 DPRINT((0,"REASON_SINGLESTEP: bSingleStep: %u\n", bSingleStep));
1052
1053 if(!bSingleStep)
1054 {
1055 dwCallOldInt1Handler = 1;
1056 DPRINT((0,"no single step requested: %u!\n", dwCallOldInt1Handler));
1057 goto common_return_point;
1058 }
1059
1060 ulAddress = GetLinearAddress(OldCS,OldEIP);
1061 ulAddressCurrent = GetLinearAddress(CurrentCS,CurrentEIP);
1062
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) )
1067 {
1068 DPRINT((0,"reinstalling INT3 @ %.4X:%.8X\n",OldCS,OldEIP));
1069
1070 ReInstallSWBreakpoint(ulAddress);
1071
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)
1076 {
1077 bPreviousCommandWasGo = FALSE;
1078 bInDebuggerShell = FALSE;
1079
1080 if(bStepThroughSource)
1081 {
1082 // set TF flag
1083 CurrentEFL |= 0x100;
1084 }
1085
1086 LEAVE_FUNC();
1087 DPRINT((0,"singlestep-----------------------------------------------------------------\n"));
1088 return;
1089 }
1090 bPreviousCommandWasGo = FALSE;
1091 }
1092
1093 if(IsSwBpAtAddressInstalled(ulAddressCurrent))
1094 DeInstallSWBreakpoint(ulAddressCurrent);
1095
1096 // we came here while stepping through source code block
1097 if(bStepThroughSource)
1098 {
1099 ULONG ulLineNumber;
1100 LPSTR pSrc,pFileName;
1101
1102 DPRINT((0,"RealIsr(): stepping through source!\n"));
1103
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
1107 if(bShowSrc)
1108 pSrc = FindSourceLineForAddress(ulAddressCurrent,&ulLineNumber,NULL,NULL,&pFileName);
1109 else pSrc = NULL;
1110
1111 DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u)\n",ulLineNumber,(ULONG)pSrc,g_ulLineNumberStart));
1112
1113 // if we have found a source line there
1114 if(pSrc && ulLineNumber==g_ulLineNumberStart)
1115 {
1116 DPRINT((0,"RealIsr(): stepping through line #%u in file = %s!\n",ulLineNumber,pFileName));
1117
1118 if(bStepInto)
1119 StepInto(NULL);
1120 else
1121 StepOver(NULL);
1122
1123 bInDebuggerShell = FALSE;
1124 LEAVE_FUNC();
1125 DPRINT((0,"singstep-----------------------------------------------------------------\n"));
1126 return;
1127 }
1128 bStepThroughSource = FALSE;
1129 bNotifyToExit = FALSE;
1130 bSkipMainLoop = FALSE;
1131 }
1132 }
1133 // came in because hardware register triggered a breakpoint
1134 else if(dwReasonForBreak == REASON_HARDWARE_BP)
1135 {
1136 ULONG ulReason;
1137
1138 DPRINT((0,"REASON_HARDWARE_BP\n"));
1139
1140 // disable HW breakpoints
1141 __asm__("\n\t \
1142 movl %%dr6,%%eax\n\t \
1143 movl %%eax,%0\n\t \
1144 xorl %%eax,%%eax\n\t \
1145 movl %%eax,%%dr6\n\t \
1146 movl %%eax,%%dr7"
1147 :"=m" (ulReason)
1148 :
1149 :"eax"
1150 );
1151
1152 DPRINT((0,"REASON_HARDWARE_BP: %x\n",(ulReason&0xF)));
1153
1154 // HW breakpoint DR1 (skip: only used in init_module detection)
1155 if(ulReason&0x2)
1156 {
1157 CurrentEFL |=(1<<16); // set resume flag
1158
1159 bSkipMainLoop = TRUE;
1160
1161 TryToInstallVirtualSWBreakpoints();
1162 }
1163 // HW breakpoint DR0
1164 else if(ulReason&0x1)
1165 {
1166 ULONG ulAddressCurrent;
1167
1168 ulAddressCurrent = GetLinearAddress(CurrentCS,CurrentEIP);
1169
1170 // we came here while stepping through source code block
1171 if(bStepThroughSource)
1172 {
1173 ULONG ulLineNumber;
1174 LPSTR pSrc,pFileName;
1175
1176 DPRINT((0,"RealIsr(): stepping through source! [2]\n"));
1177
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
1181 if(bShowSrc)
1182 pSrc = FindSourceLineForAddress(ulAddressCurrent,&ulLineNumber,NULL,NULL,&pFileName);
1183 else
1184 pSrc = NULL;
1185
1186 DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u) [2]\n",ulLineNumber,(ULONG)pSrc,g_ulLineNumberStart));
1187
1188 // if we have found a source line there
1189 if(pSrc && ulLineNumber==g_ulLineNumberStart)
1190 {
1191 DPRINT((0,"RealIsr(): stepping through line #%u in file = %s! [2]\n",ulLineNumber,pFileName));
1192
1193 if(bStepInto)
1194 StepInto(NULL);
1195 else
1196 StepOver(NULL);
1197
1198 bInDebuggerShell = FALSE;
1199 LEAVE_FUNC();
1200 DPRINT((0,"rrr-----------------------------------------------------------------\n"));
1201 return;
1202 }
1203 bNotifyToExit = FALSE;
1204 bSkipMainLoop = FALSE;
1205 bStepThroughSource = FALSE;
1206 }
1207 }
1208 }
1209 else if(dwReasonForBreak==REASON_INT3)
1210 {
1211 ULONG ulAddress;
1212
1213 DPRINT((0,"REASON_INT3\n"));
1214
1215 // must subtract one cause INT3s are generated after instructions execution
1216 CurrentEIP--;
1217
1218 // make a flat address
1219 ulAddress = GetLinearAddress(CurrentCS,CurrentEIP);
1220
1221 DPRINT((0,"INT3 @ %.8X\n",ulAddress));
1222
1223 // if there's a breakpoint installed at current EIP remove it
1224 if(DeInstallSWBreakpoint(ulAddress) )
1225 {
1226 PSW_BP p;
1227
1228 DPRINT((0,"INT3 @ %.8X removed\n",ulAddress));
1229
1230 // if it's permanent (must be Printk() ) skip the DebuggerShell() and
1231 // do a callback
1232 if( (p = IsPermanentSWBreakpoint(ulAddress)) )
1233 {
1234 DPRINT((0,"permanent breakpoint\n"));
1235
1236 ReinstallPermanentBp = TRUE;
1237
1238 OldCS = CurrentCS;
1239 OldEIP = CurrentEIP;
1240
1241 bSkipMainLoop = TRUE;
1242 DPRINT((0,"callback at %x\n",p->Callback));
1243 if(p->Callback)
1244 p->Callback();
1245 }
1246 else
1247 {
1248 LPSTR pFind;
1249 if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP)))
1250 {
1251 PICE_sprintf(tempShell,"pICE: SW Breakpoint at %s (%.4X:%.8X)\n",pFind,CurrentCS,CurrentEIP);
1252 }
1253 else
1254 {
1255 PICE_sprintf(tempShell,"pICE: SW Breakpoint at %.4X:%.8X\n",CurrentCS,CurrentEIP);
1256 }
1257 Print(OUTPUT_WINDOW,tempShell);
1258 }
1259 CurrentEFL &= ~(1<<16); // clear resume flag
1260 }
1261 else
1262 {
1263 LPSTR pFind;
1264 PEPROCESS my_current = IoGetCurrentProcess();
1265
1266 DPRINT((0,"can't deinstall, somebody else's breakpoint\n"));
1267
1268
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
1271 /*
1272 #if REAL_LINUX_VERSION_CODE < 0x020400
1273 if(ulAddress<TASK_SIZE && !(my_current->flags & PF_PTRACED) )
1274 #else
1275 if(ulAddress<TASK_SIZE && !(my_current->ptrace & PT_PTRACED) )
1276 #endif
1277 */
1278 if( ulAddress )
1279 {
1280 if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP)))
1281 {
1282 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at %s (%.4X:%.8X)\n",pFind,CurrentCS,CurrentEIP);
1283 }
1284 else
1285 {
1286 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at user-mode address %.4X:%.8X\n",CurrentCS,CurrentEIP);
1287 }
1288 Print(OUTPUT_WINDOW,tempShell);
1289 CurrentEFL &= ~(1<<16); // clear resume flag
1290 }
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
1293 /*
1294 else
1295 {
1296 if(ulAddress<TASK_SIZE || !bInt3Here)
1297 {
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;
1303 }
1304 else
1305 {
1306 if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP)))
1307 {
1308 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at (%s) %.4X:%.8X\n",
1309 pFind,CurrentCS,CurrentEIP);
1310 }
1311 else
1312 {
1313 PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at kernel-mode address %.4X:%.8X\n",
1314 CurrentCS,CurrentEIP);
1315 }
1316 Print(OUTPUT_WINDOW,tempShell);
1317 CurrentEFL &= ~(1<<16); // clear resume flag
1318 }
1319 }
1320 */
1321 // skip INT3
1322 CurrentEIP++;
1323 }
1324 }
1325 else if(dwReasonForBreak == REASON_PAGEFAULT)
1326 {
1327 LPSTR pSymbolName;
1328
1329 DPRINT((0,"REASON_PAGEFAULT\n"));
1330
1331 if( ScanExportsByAddress(&pSymbolName,GetLinearAddress(CurrentCS,CurrentEIP)) )
1332 {
1333 PICE_sprintf(tempShell,"pICE: Breakpoint due to page fault at %.4X:%.8X (%s)\n",CurrentCS,CurrentEIP,pSymbolName);
1334 }
1335 else
1336 {
1337 PICE_sprintf(tempShell,"pICE: Breakpoint due to page fault at %.4X:%.8X\n",CurrentCS,CurrentEIP);
1338 }
1339 Print(OUTPUT_WINDOW,tempShell);
1340 PICE_sprintf(tempShell,"pICE: memory referenced %x\n",CurrentCR2);
1341 Print(OUTPUT_WINDOW,tempShell);
1342 dwCallOldIntEHandler = 1;
1343 }
1344 else if(dwReasonForBreak == REASON_GP_FAULT)
1345 {
1346 LPSTR pSymbolName;
1347
1348 DPRINT((0,"REASON_GPFAULT\n"));
1349
1350 if( ScanExportsByAddress(&pSymbolName,GetLinearAddress(CurrentCS,CurrentEIP)) )
1351 {
1352 PICE_sprintf(tempShell,"pICE: Breakpoint due to general protection fault at %.4X:%.8X (%s)\n",CurrentCS,CurrentEIP,pSymbolName);
1353 }
1354 else
1355 {
1356 PICE_sprintf(tempShell,"pICE: Breakpoint due to general protection fault at %.4X:%.8X\n",CurrentCS,CurrentEIP);
1357 }
1358 Print(OUTPUT_WINDOW,tempShell);
1359 dwCallOldGPFaultHandler = 1;
1360 }
1361 else if(dwReasonForBreak == REASON_CTRLF)
1362 {
1363 DPRINT((0,"REASON_CTRLF\n"));
1364 // nothing to do
1365 }
1366 else if(dwReasonForBreak == REASON_DOUBLE_FAULT)
1367 {
1368 DPRINT((0,"REASON_DOUBLE_FAULT\n"));
1369
1370 PICE_sprintf(tempShell,"pICE: Breakpoint due to double fault at %.4X:%.8X\n",CurrentCS,CurrentEIP);
1371 Print(OUTPUT_WINDOW,tempShell);
1372 }
1373 else if(dwReasonForBreak == REASON_INTERNAL_ERROR)
1374 {
1375 DPRINT((0,"REASON_INTERNAL_ERROR\n"));
1376
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");
1380 }
1381 else
1382 {
1383 DPRINT((0,"REASON_UNKNOWN\n"));
1384
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");
1390 }
1391
1392 // we don't single-step yet
1393 DPRINT((0,"RealIsr(): not stepping yet\n"));
1394 bSingleStep=FALSE;
1395
1396 // process commands
1397 if(bSkipMainLoop == FALSE)
1398 {
1399 DPRINT((0,"RealIsr(): saving registers\n"));
1400 // save the extended regs
1401 __asm__ __volatile__
1402 ("\n\t \
1403 pushl %eax\n\t \
1404 movw %es,%ax\n\t \
1405 movw %ax,_CurrentES\n\t \
1406 //movw %fs,%ax\n\t \
1407 //movw %ax,_CurrentFS\n\t \
1408 movw %gs,%ax\n\t \
1409 movw %ax,_CurrentGS\n\t \
1410 movl %dr0,%eax\n\t \
1411 movl %eax,_CurrentDR0\n\t \
1412 movl %dr1,%eax\n\t \
1413 movl %eax,_CurrentDR1\n\t \
1414 movl %dr2,%eax\n\t \
1415 movl %eax,_CurrentDR2\n\t \
1416 movl %dr3,%eax\n\t \
1417 movl %eax,_CurrentDR3\n\t \
1418 movl %dr6,%eax\n\t \
1419 movl %eax,_CurrentDR6\n\t \
1420 movl %dr7,%eax\n\t \
1421 movl %eax,_CurrentDR7\n\t \
1422 movl %cr0,%eax\n\t \
1423 movl %eax,_CurrentCR0\n\t \
1424 movl %cr2,%eax\n\t \
1425 movl %eax,_CurrentCR2\n\t \
1426 movl %cr3,%eax\n\t \
1427 movl %eax,_CurrentCR3\n\t \
1428 popl %eax"
1429 );
1430
1431 CurrentFS = OLD_PCR;
1432 DPRINT((0,"RealIsr(): adding colon to output()\n"));
1433 Print(OUTPUT_WINDOW,":");
1434
1435 DPRINT((0,"RealIsr(): calling DebuggerShell()\n"));
1436 DebuggerShell();
1437 }
1438
1439 // if there was a SW breakpoint at CS:EIP
1440 if(NeedToReInstallSWBreakpoints(GetLinearAddress(CurrentCS,CurrentEIP),TRUE) || ReinstallPermanentBp)
1441 {
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)
1448
1449 bSingleStep=TRUE;
1450 bNotifyToExit=TRUE;
1451 }
1452
1453 common_return_point:
1454
1455 // reset the global flags
1456 bNotifyToExit = FALSE;
1457 bSkipMainLoop = FALSE;
1458
1459 // not in handler anymore
1460 bInDebuggerShell = FALSE;
1461
1462 LEAVE_FUNC();
1463 DPRINT((0,"common return-----------------------------------------------------------------\n"));
1464 }
1465
1466
1467 __asm__(".global NewInt31Handler\n\t \
1468 NewInt31Handler:\n\t \
1469 cli\n\t \
1470 cld\n\t \
1471 \n\t \
1472 pushl %eax\n\t \
1473 pushl %ds\n\t \
1474 \n\t \
1475 movw %ss,%ax\n\t \
1476 mov %ax,%ds\n\t \
1477 \n\t \
1478 mov 0x4(%esp),%eax\n\t \
1479 movl %eax,_CurrentEAX\n\t \
1480 movl %ebx,_CurrentEBX\n\t \
1481 movl %ecx,_CurrentECX\n\t \
1482 movl %edx,_CurrentEDX\n\t \
1483 movl %esi,_CurrentESI\n\t \
1484 movl %edi,_CurrentEDI\n\t \
1485 movl %ebp,_CurrentEBP\n\t \
1486 movl (%esp),%eax\n\t \
1487 movw %ax,_CurrentDS\n\t \
1488 \n\t \
1489 // test for V86 mode\n\t \
1490 testl $0x20000,5*4(%esp)\n\t \
1491 jz notV86\n\t \
1492 \n\t \
1493 int $0x03\n\t \
1494 \n\t \
1495 notV86:\n\t \
1496 // test if stack switched (ring3->ring0 transition)\n\t \
1497 // stack is switched if orig. SS is not global kernel code segment\n\t \
1498 movl 4*4(%esp),%eax\n\t \
1499 cmpw $" STR(GLOBAL_CODE_SEGMENT) ",%ax\n\t \
1500 je notswitched\n\t \
1501 \n\t \
1502 // switched stack\n\t \
1503 movl 6*4(%esp),%eax\n\t \
1504 mov %eax,_CurrentESP\n\t \
1505 mov 7*4(%esp),%eax\n\t \
1506 movzwl %ax,%eax\n\t \
1507 mov %ax,_CurrentSS\n\t \
1508 jmp afterswitch\n\t \
1509 \n\t \
1510 notswitched:\n\t \
1511 // didn't switch stack\n\t \
1512 movl %esp,_CurrentESP\n\t \
1513 addl $24,_CurrentESP\n\t \
1514 movw %ss,%ax\n\t \
1515 movzwl %ax,%eax\n\t \
1516 mov %ax,_CurrentSS\n\t \
1517 \n\t \
1518 afterswitch:\n\t \
1519 // save EIP\n\t \
1520 mov 3*4(%esp),%eax\n\t \
1521 mov %eax,_CurrentEIP\n\t \
1522 //save CS\n\t \
1523 mov 4*4(%esp),%eax\n\t \
1524 movzwl %ax,%eax\n\t \
1525 movw %ax,_CurrentCS\n\t \
1526 // save flags\n\t \
1527 movl 5*4(%esp),%eax\n\t \
1528 andl $0xFFFFFEFF,%eax\n\t \
1529 movl %eax,_CurrentEFL\n\t \
1530 \n\t \
1531 pushal\n\t \
1532 \n\t \
1533 // get reason code\n\t \
1534 mov 0x28(%esp),%ebx\n\t \
1535 \n\t \
1536 /*\n\t \
1537 * Load the PCR selector.\n\t \
1538 */\n\t \
1539 \n\t \
1540 movl %fs, %eax\n\t \
1541 movl %eax, _OLD_PCR\n\t \
1542 movl _PCR_SEL, %eax\n\t \
1543 movl %eax, %fs\n\t \
1544 \n\t \
1545 // setup a large work stack\n\t \
1546 movl %esp,%eax\n\t \
1547 movl %eax,_ulRealStackPtr\n\t \
1548 \n\t \
1549 pushl %ebx\n\t \
1550 call _RealIsr\n\t \
1551 addl $4,%esp\n\t \
1552 \n\t \
1553 pushl %eax\n\t \
1554 movl _OLD_PCR, %eax\n\t \
1555 movl %eax, %fs\n\t \
1556 popl %eax\n\t \
1557 \n\t \
1558 // restore all regs\n\t \
1559 popal\n\t \
1560 \n\t \
1561 // do an EOI to IRQ controller (because we definitely pressed some key)\n\t \
1562 // TODO: SMP APIC support\n\t \
1563 movb $0x20,%al\n\t \
1564 outb %al,$0x20\n\t \
1565 \n\t \
1566 popl %ds\n\t \
1567 popl %eax\n\t \
1568 \n\t \
1569 // remove reason code\n\t \
1570 addl $4,%esp\n\t \
1571 \n\t \
1572 // make EAX available\n\t \
1573 pushl %eax\n\t \
1574 \n\t \
1575 // modify or restore EFLAGS\n\t \
1576 .byte 0x2e\n\t \
1577 mov _CurrentEFL,%eax\n\t \
1578 mov %eax,3*4(%esp)\n\t \
1579 .byte 0x2e\n\t \
1580 movzwl _CurrentCS,%eax\n\t \
1581 mov %eax,2*4(%esp)\n\t \
1582 .byte 0x2e\n\t \
1583 mov _CurrentEIP,%eax\n\t \
1584 mov %eax,1*4(%esp)\n\t \
1585 \n\t \
1586 // restore EAX\n\t \
1587 popl %eax\n\t \
1588 \n\t \
1589 // do we need to call old INT1 handler\n\t \
1590 .byte 0x2e\n\t \
1591 cmp $0,_dwCallOldInt1Handler\n\t \
1592 je do_iret2\n\t \
1593 \n\t \
1594 // call INT3 handler\n\t \
1595 .byte 0x2e\n\t \
1596 jmp *_OldInt1Handler\n\t \
1597 \n\t \
1598 do_iret2:\n\t \
1599 // do we need to call old INT3 handler\n\t \
1600 .byte 0x2e\n\t \
1601 cmp $0,_dwCallOldInt3Handler\n\t \
1602 je do_iret1\n\t \
1603 \n\t \
1604 // call INT3 handler\n\t \
1605 .byte 0x2e\n\t \
1606 jmp *_OldInt3Handler\n\t \
1607 \n\t \
1608 do_iret1:\n\t \
1609 // do we need to call old pagefault handler\n\t \
1610 .byte 0x2e\n\t \
1611 cmp $0,_dwCallOldIntEHandler\n\t \
1612 je do_iret3\n\t \
1613 \n\t \
1614 // call old pagefault handler\n\t \
1615 .byte 0x2e\n\t \
1616 pushl _error_code\n\t \
1617 .byte 0x2e\n\t \
1618 jmp *_OldIntEHandler\n\t \
1619 \n\t \
1620 do_iret3:\n\t \
1621 // do we need to call old general protection fault handler\n\t \
1622 .byte 0x2e\n\t \
1623 cmp $0,_dwCallOldGPFaultHandler\n\t \
1624 je do_iret\n\t \
1625 \n\t \
1626 // call old pagefault handler\n\t \
1627 .byte 0x2e\n\t \
1628 pushl _error_code\n\t \
1629 .byte 0x2e\n\t \
1630 jmp *_OldGPFaultHandler\n\t \
1631 \n\t \
1632 do_iret:\n\t \
1633 //ei\n\t \
1634 //int3\n\t \
1635 iretl ");
1636
1637 //
1638 // stub for entering via CTRL-F
1639 //
1640 // IDTs keyboard IRQ points here
1641 //
1642 __asm__ ("\n\t \
1643 NewGlobalInt31Handler:\n\t \
1644 .byte 0x2e\n\t \
1645 cmpb $0,_bEnterNow\n\t \
1646 jne dotheenter\n\t \
1647 \n\t \
1648 // chain to old handler\n\t \
1649 .byte 0x2e\n\t \
1650 jmp *_OldGlobalInt31Handler\n\t \
1651 \n\t \
1652 dotheenter:\n\t \
1653 pushl $" STR(REASON_CTRLF) "\n\t \
1654 jmp NewInt31Handler "
1655 );
1656
1657 void InstallGlobalKeyboardHook(void)
1658 {
1659 ULONG LocalNewGlobalInt31Handler;
1660
1661 ENTER_FUNC();
1662
1663 MaskIrqs();
1664 if(!OldGlobalInt31Handler)
1665 {
1666 __asm__("mov $NewGlobalInt31Handler,%0"
1667 :"=r" (LocalNewGlobalInt31Handler)
1668 :
1669 :"eax");
1670 OldGlobalInt31Handler=SetGlobalInt(KeyboardIRQL,(ULONG)LocalNewGlobalInt31Handler);
1671 }
1672 UnmaskIrqs();
1673
1674 LEAVE_FUNC();
1675 }
1676
1677 void DeInstallGlobalKeyboardHook(void)
1678 {
1679 ENTER_FUNC();
1680
1681 MaskIrqs();
1682 if(OldGlobalInt31Handler)
1683 {
1684 SetGlobalInt(KeyboardIRQL,(ULONG)OldGlobalInt31Handler);
1685 OldGlobalInt31Handler=0;
1686 }
1687 UnmaskIrqs();
1688
1689 LEAVE_FUNC();
1690 }
1691
1692