ReactOS 0.4.15-dev-7788-g1ad9096
i386-stub-win32.c
Go to the documentation of this file.
1/****************************************************************************
2
3 THIS SOFTWARE IS NOT COPYRIGHTED
4
5 HP offers the following for use in the public domain. HP makes no
6 warranty with regard to the software or it's performance and the
7 user accepts the software "AS IS" with all faults.
8
9 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
13****************************************************************************/
14
15/****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17 *
18 * Module name: remcom.c $
19 * Revision: 1.34 $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
22 *
23 * Description: low level support for gdb debugger. $
24 *
25 * Considerations: only works on target hardware $
26 *
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
29 *
30 * NOTES: See Below $
31 *
32 * Modified for 386 by Jim Kingdon, Cygnus Support.
33 *
34 * To enable debugger support, two things need to happen. One, a
35 * call to set_debug_traps() is necessary in order to allow any breakpoints
36 * or error conditions to be properly intercepted and reported to gdb.
37 * Two, a breakpoint needs to be generated to begin communication. This
38 * is most easily accomplished by a call to breakpoint(). Breakpoint()
39 * simulates a breakpoint by executing a trap #1.
40 *
41 * The external function exceptionHandler() is
42 * used to attach a specific handler to a specific 386 vector number.
43 * It should use the same privilege level it runs at. It should
44 * install it as an interrupt gate so that interrupts are masked
45 * while the handler runs.
46 *
47 * Because gdb will sometimes write to the stack area to execute function
48 * calls, this program cannot rely on using the supervisor stack so it
49 * uses it's own stack area reserved in the int array remcomStack.
50 *
51 *************
52 *
53 * The following gdb commands are supported:
54 *
55 * command function Return value
56 *
57 * g return the value of the CPU registers hex data or ENN
58 * G set the value of the CPU registers OK or ENN
59 *
60 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
61 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
62 *
63 * c Resume at current address SNN ( signal NN)
64 * cAA..AA Continue at address AA..AA SNN
65 *
66 * s Step one instruction SNN
67 * sAA..AA Step one instruction from AA..AA SNN
68 *
69 * k kill
70 *
71 * ? What was the last sigval ? SNN (signal NN)
72 *
73 * All commands and responses are sent with a packet which includes a
74 * checksum. A packet consists of
75 *
76 * $<packet info>#<checksum>.
77 *
78 * where
79 * <packet info> :: <characters representing the command or response>
80 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
81 *
82 * When a packet is received, it is first acknowledged with either '+' or '-'.
83 * '+' indicates a successful transfer. '-' indicates a failed transfer.
84 *
85 * Example:
86 *
87 * Host: Reply:
88 * $m0,10#2a +$00010203040506070809101112131415#42
89 *
90 ****************************************************************************/
91
92#include <stdio.h>
93#include <string.h>
94
95#include "utility/utility.h" // for strcpy_s()
96
97/************************************************************************
98 *
99 * external low-level support routines
100 */
101
102extern void putDebugChar(); /* write a single character */
103extern int getDebugChar(); /* read and return a single char */
104extern void exceptionHandler(); /* assign an exception handler */
105
106/************************************************************************/
107/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
108/* at least NUMREGBYTES*2 are needed for register packets */
109#define BUFMAX 400
110
111static char initialized; /* boolean flag. != 0 means we've been initialized */
112
114/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
115
116static const char hexchars[]="0123456789abcdef";
117
118/* Number of registers. */
119#define NUMREGS 16
120
121/* Number of bytes of registers. */
122#define NUMREGBYTES (NUMREGS * 4)
123
125 PC /* also known as eip */,
126 PS /* also known as eflags */,
127 CS, SS, DS, ES, FS, GS};
128
129/*
130 * these should not be static cuz they can be used outside this module
131 */
133
134#ifndef WIN32 //MF
135
136#define STACKSIZE 10000
138static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
139
140/*************************** ASSEMBLY CODE MACROS *************************/
141/* */
142
143extern void
145
146/* Restore the program's registers (including the stack pointer, which
147 means we get the right stack and don't have to worry about popping our
148 return address and any stack frames and so on) and return. */
149asm(".text");
150asm(".globl _return_to_prog");
151asm("_return_to_prog:");
152asm(" movw _registers+44, %ss");
153asm(" movl _registers+16, %esp");
154asm(" movl _registers+4, %ecx");
155asm(" movl _registers+8, %edx");
156asm(" movl _registers+12, %ebx");
157asm(" movl _registers+20, %ebp");
158asm(" movl _registers+24, %esi");
159asm(" movl _registers+28, %edi");
160asm(" movw _registers+48, %ds");
161asm(" movw _registers+52, %es");
162asm(" movw _registers+56, %fs");
163asm(" movw _registers+60, %gs");
164asm(" movl _registers+36, %eax");
165asm(" pushl %eax"); /* saved eflags */
166asm(" movl _registers+40, %eax");
167asm(" pushl %eax"); /* saved cs */
168asm(" movl _registers+32, %eax");
169asm(" pushl %eax"); /* saved eip */
170asm(" movl _registers, %eax");
171
172asm("ret"); //MF
173
174/* use iret to restore pc and flags together so
175 that trace flag works right. */
176asm(" iret");
177
178
179#ifdef WIN32 //MF
180asm(".data"); //MF
181#endif
182
183/* Put the error code here just in case the user cares. */
185/* Likewise, the vector number here (since GDB only gets the signal
186 number through the usual means, and that's not very specific). */
188
189/* GDB stores segment registers in 32-bit words (that's just the way
190 m-i386v.h is written). So zero the appropriate areas in registers. */
191#define SAVE_REGISTERS1() \
192 asm ("movl %eax, _registers"); \
193 asm ("movl %ecx, _registers+4"); \
194 asm ("movl %edx, _registers+8"); \
195 asm ("movl %ebx, _registers+12"); \
196 asm ("movl %ebp, _registers+20"); \
197 asm ("movl %esi, _registers+24"); \
198 asm ("movl %edi, _registers+28"); \
199 asm ("movw $0, %ax"); \
200 asm ("movw %ds, _registers+48"); \
201 asm ("movw %ax, _registers+50"); \
202 asm ("movw %es, _registers+52"); \
203 asm ("movw %ax, _registers+54"); \
204 asm ("movw %fs, _registers+56"); \
205 asm ("movw %ax, _registers+58"); \
206 asm ("movw %gs, _registers+60"); \
207 asm ("movw %ax, _registers+62");
208#define SAVE_ERRCODE() \
209 asm ("popl %ebx"); \
210 asm ("movl %ebx, _gdb_i386errcode");
211#define SAVE_REGISTERS2() \
212 asm ("popl %ebx"); /* old eip */ \
213 asm ("movl %ebx, _registers+32"); \
214 asm ("popl %ebx"); /* old cs */ \
215 asm ("movl %ebx, _registers+40"); \
216 asm ("movw %ax, _registers+42"); \
217 asm ("popl %ebx"); /* old eflags */ \
218 asm ("movl %ebx, _registers+36"); \
219 /* Now that we've done the pops, we can save the stack pointer."); */ \
220 asm ("movw %ss, _registers+44"); \
221 asm ("movw %ax, _registers+46"); \
222 asm ("movl %esp, _registers+16");
223
224/* See if mem_fault_routine is set, if so just IRET to that address. */
225#define CHECK_FAULT() \
226 asm ("cmpl $0, _mem_fault_routine"); \
227 asm ("jne mem_fault");
228
229asm (".text");
230asm ("mem_fault:");
231/* OK to clobber temp registers; we're just going to end up in set_mem_err. */
232/* Pop error code from the stack and save it. */
233asm (" popl %eax");
234asm (" movl %eax, _gdb_i386errcode");
235
236asm (" popl %eax"); /* eip */
237/* We don't want to return there, we want to return to the function
238 pointed to by mem_fault_routine instead. */
239asm (" movl _mem_fault_routine, %eax");
240asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */
241asm (" popl %edx"); /* eflags */
242
243/* Remove this stack frame; when we do the iret, we will be going to
244 the start of a function, so we want the stack to look just like it
245 would after a "call" instruction. */
246asm (" leave");
247
248/* Push the stuff that iret wants. */
249asm (" pushl %edx"); /* eflags */
250asm (" pushl %ecx"); /* cs */
251asm (" pushl %eax"); /* eip */
252
253/* Zero mem_fault_routine. */
254asm (" movl $0, %eax");
255asm (" movl %eax, _mem_fault_routine");
256
257asm ("iret");
258
259
260#define CALL_HOOK() asm("call _remcomHandler");
261
262/* This function is called when a i386 exception occurs. It saves
263 * all the cpu regs in the _registers array, munges the stack a bit,
264 * and invokes an exception handler (remcom_handler).
265 *
266 * stack on entry: stack on exit:
267 * old eflags vector number
268 * old cs (zero-filled to 32 bits)
269 * old eip
270 *
271 */
272extern void _catchException3();
273asm(".text");
274asm(".globl __catchException3");
275asm("__catchException3:");
278asm ("pushl $3");
279CALL_HOOK();
280
281/* Same thing for exception 1. */
282extern void _catchException1();
283asm(".text");
284asm(".globl __catchException1");
285asm("__catchException1:");
288asm ("pushl $1");
289CALL_HOOK();
290
291/* Same thing for exception 0. */
292extern void _catchException0();
293asm(".text");
294asm(".globl __catchException0");
295asm("__catchException0:");
298asm ("pushl $0");
299CALL_HOOK();
300
301/* Same thing for exception 4. */
302extern void _catchException4();
303asm(".text");
304asm(".globl __catchException4");
305asm("__catchException4:");
308asm ("pushl $4");
309CALL_HOOK();
310
311/* Same thing for exception 5. */
312extern void _catchException5();
313asm(".text");
314asm(".globl __catchException5");
315asm("__catchException5:");
318asm ("pushl $5");
319CALL_HOOK();
320
321/* Same thing for exception 6. */
322extern void _catchException6();
323asm(".text");
324asm(".globl __catchException6");
325asm("__catchException6:");
328asm ("pushl $6");
329CALL_HOOK();
330
331/* Same thing for exception 7. */
332extern void _catchException7();
333asm(".text");
334asm(".globl __catchException7");
335asm("__catchException7:");
338asm ("pushl $7");
339CALL_HOOK();
340
341/* Same thing for exception 8. */
342extern void _catchException8();
343asm(".text");
344asm(".globl __catchException8");
345asm("__catchException8:");
349asm ("pushl $8");
350CALL_HOOK();
351
352/* Same thing for exception 9. */
353extern void _catchException9();
354asm(".text");
355asm(".globl __catchException9");
356asm("__catchException9:");
359asm ("pushl $9");
360CALL_HOOK();
361
362/* Same thing for exception 10. */
363extern void _catchException10();
364asm(".text");
365asm(".globl __catchException10");
366asm("__catchException10:");
370asm ("pushl $10");
371CALL_HOOK();
372
373/* Same thing for exception 12. */
374extern void _catchException12();
375asm(".text");
376asm(".globl __catchException12");
377asm("__catchException12:");
381asm ("pushl $12");
382CALL_HOOK();
383
384/* Same thing for exception 16. */
385extern void _catchException16();
386asm(".text");
387asm(".globl __catchException16");
388asm("__catchException16:");
391asm ("pushl $16");
392CALL_HOOK();
393
394/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */
395
396/* Same thing for exception 13. */
397extern void _catchException13 ();
398asm (".text");
399asm (".globl __catchException13");
400asm ("__catchException13:");
405asm ("pushl $13");
406CALL_HOOK();
407
408/* Same thing for exception 11. */
409extern void _catchException11 ();
410asm (".text");
411asm (".globl __catchException11");
412asm ("__catchException11:");
417asm ("pushl $11");
418CALL_HOOK();
419
420/* Same thing for exception 14. */
421extern void _catchException14 ();
422asm (".text");
423asm (".globl __catchException14");
424asm ("__catchException14:");
429asm ("pushl $14");
430CALL_HOOK();
431
432/*
433 * remcomHandler is a front end for handle_exception. It moves the
434 * stack pointer into an area reserved for debugger use.
435 */
436asm("_remcomHandler:");
437asm(" popl %eax"); /* pop off return address */
438asm(" popl %eax"); /* get the exception number */
439asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
440asm(" pushl %eax"); /* push exception onto stack */
441asm(" call _handle_exception"); /* this never returns */
442
443
444void
446{
448}
449
450#endif // !WIN32
451
452
453#ifdef _MSC_VER //MF
454#define BREAKPOINT() __asm int 3;
455#else
456#define BREAKPOINT() asm(" int $3");
457#endif
458
459
460#ifdef WIN32 //MF
461
462#define WIN32_LEAN_AND_MEAN
463//#include <windows.h>
464
465void handle_exception(int exceptionVector);
466
467void win32_exception_handler(EXCEPTION_POINTERS* exc_info)
468{
469 PCONTEXT ctx = exc_info->ContextRecord;
470
471 registers[EAX] = ctx->Eax;
472 registers[ECX] = ctx->Ecx;
473 registers[EDX] = ctx->Edx;
474 registers[EBX] = ctx->Ebx;
475 registers[ESP] = ctx->Esp;
476 registers[EBP] = ctx->Ebp;
477 registers[ESI] = ctx->Esi;
478 registers[EDI] = ctx->Edi;
479 registers[PC] = ctx->Eip;
480 registers[PS] = ctx->EFlags;
481 registers[CS] = ctx->SegCs;
482 registers[SS] = ctx->SegSs;
483 registers[DS] = ctx->SegDs;
484 registers[ES] = ctx->SegEs;
485 registers[FS] = ctx->SegFs;
486 registers[GS] = ctx->SegGs;
487
489
490 ctx->Eax = registers[EAX];
491 ctx->Ecx = registers[ECX];
492 ctx->Edx = registers[EDX];
493 ctx->Ebx = registers[EBX];
494 ctx->Esp = registers[ESP];
495 ctx->Ebp = registers[EBP];
496 ctx->Esi = registers[ESI];
497 ctx->Edi = registers[EDI];
498 ctx->Eip = registers[PC];
499 ctx->EFlags = registers[PS];
500 ctx->SegCs = registers[CS];
501 ctx->SegSs = registers[SS];
502 ctx->SegDs = registers[DS];
503 ctx->SegEs = registers[ES];
504 ctx->SegFs = registers[FS];
505 ctx->SegGs = registers[GS];
506}
507
508#endif // WIN32
509
510
511int
512hex (ch)
513 char ch;
514{
515 if ((ch >= 'a') && (ch <= 'f'))
516 return (ch - 'a' + 10);
517 if ((ch >= '0') && (ch <= '9'))
518 return (ch - '0');
519 if ((ch >= 'A') && (ch <= 'F'))
520 return (ch - 'A' + 10);
521 return (-1);
522}
523
526
527/* scan for the sequence $<data>#<checksum> */
528
529char *
531{
532 char *buffer = &remcomInBuffer[0];
533 unsigned char checksum;
534 unsigned char xmitcsum;
535 int count;
536 char ch;
537
538 while (1)
539 {
540 /* wait around for the start character, ignore all other characters */
541 while ((ch = getDebugChar ()) != '$')
542 ;
543
544 retry:
545 checksum = 0;
546 xmitcsum = -1;
547 count = 0;
548
549 /* now, read until a # or end of buffer is found */
550 while (count < BUFMAX - 1)
551 {
552 ch = getDebugChar ();
553 if (ch == '$')
554 goto retry;
555 if (ch == '#')
556 break;
557 checksum = checksum + ch;
558 buffer[count] = ch;
559 count = count + 1;
560 }
561 buffer[count] = 0;
562
563 if (ch == '#')
564 {
565 ch = getDebugChar ();
566 xmitcsum = hex (ch) << 4;
567 ch = getDebugChar ();
568 xmitcsum += hex (ch);
569
570 if (checksum != xmitcsum)
571 {
572 if (remote_debug)
573 {
575 "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
576 checksum, xmitcsum, buffer);
577 }
578 putDebugChar ('-'); /* failed checksum */
579 }
580 else
581 {
582 putDebugChar ('+'); /* successful transfer */
583
584 /* if a sequence char is present, reply the sequence ID */
585 if (buffer[2] == ':')
586 {
587 putDebugChar (buffer[0]);
588 putDebugChar (buffer[1]);
589
590 return &buffer[3];
591 }
592
593 return &buffer[0];
594 }
595 }
596 }
597}
598
599/* send the packet in buffer. */
600
601void
603{
604 unsigned char checksum;
605 int count;
606 char ch;
607
608 /* $<packet info>#<checksum>. */
609 do
610 {
611 putDebugChar ('$');
612 checksum = 0;
613 count = 0;
614
615 while ((ch = buffer[count]) != 0)
616 {
617 putDebugChar (ch);
618 checksum += ch;
619 count += 1;
620 }
621
622 putDebugChar ('#');
625
626 }
627 while (getDebugChar () != '+');
628}
629
630void debug_error (char* format/*, char* parm*/)
631{
632 if (remote_debug)
633 fprintf (stderr, format/*, parm*/);
634}
635
636/* Address of a routine to RTE to if we get a memory fault. */
637static void (*volatile mem_fault_routine) () = NULL;
638
639/* Indicate to caller of mem2hex or hex2mem that there has been an
640 error. */
641static volatile int mem_err = 0;
642
643void
645{
646 mem_err = 1;
647}
648
649/* These are separate functions so that they are so short and sweet
650 that the compiler won't save any registers (if there is a fault
651 to mem_fault, they won't get restored, so there better not be any
652 saved). */
653int
655{
656 return *addr;
657}
658
659void
660set_char (char *addr, int val)
661{
662 *addr = val;
663}
664
665/* convert the memory pointed to by mem into hex, placing result in buf */
666/* return a pointer to the last char put in buf (null) */
667/* If MAY_FAULT is non-zero, then we should set mem_err in response to
668 a fault; if zero treat a fault like any other fault in the stub. */
669char *
670mem2hex (mem, buf, count, may_fault)
671 char *mem;
672 char *buf;
673 int count;
674 int may_fault;
675{
676 int i;
677 unsigned char ch;
678
679#ifdef WIN32 //MF
680 if (IsBadReadPtr(mem, count))
681 return mem;
682#else
683 if (may_fault)
685#endif
686 for (i = 0; i < count; i++)
687 {
688 ch = get_char (mem++);
689 if (may_fault && mem_err)
690 return (buf);
691 *buf++ = hexchars[ch >> 4];
692 *buf++ = hexchars[ch % 16];
693 }
694 *buf = 0;
695#ifndef WIN32 //MF
696 if (may_fault)
698#endif
699 return (buf);
700}
701
702/* convert the hex array pointed to by buf into binary to be placed in mem */
703/* return a pointer to the character AFTER the last byte written */
704char *
705hex2mem (buf, mem, count, may_fault)
706 char *buf;
707 char *mem;
708 int count;
709 int may_fault;
710{
711 int i;
712 unsigned char ch;
713
714#ifdef WIN32 //MF
715 // MinGW does not support structured exception handling, so let's
716 // go safe and make memory writable by default
717 DWORD old_protect;
718
720#else
721 if (may_fault)
723#endif
724
725 for (i = 0; i < count; i++)
726 {
727 ch = hex (*buf++) << 4;
728 ch = ch + hex (*buf++);
729 set_char (mem++, ch);
730 if (may_fault && mem_err)
731 return (mem);
732 }
733
734#ifndef WIN32 //MF
735 if (may_fault)
737#endif
738
739 return (mem);
740}
741
742/* this function takes the 386 exception vector and attempts to
743 translate this number into a unix compatible signal value */
744int
745computeSignal (int exceptionVector)
746{
747 int sigval;
748 switch (exceptionVector)
749 {
750 case 0:
751 sigval = 8;
752 break; /* divide by zero */
753 case 1:
754 sigval = 5;
755 break; /* debug exception */
756 case 3:
757 sigval = 5;
758 break; /* breakpoint */
759 case 4:
760 sigval = 16;
761 break; /* into instruction (overflow) */
762 case 5:
763 sigval = 16;
764 break; /* bound instruction */
765 case 6:
766 sigval = 4;
767 break; /* Invalid opcode */
768 case 7:
769 sigval = 8;
770 break; /* coprocessor not available */
771 case 8:
772 sigval = 7;
773 break; /* double fault */
774 case 9:
775 sigval = 11;
776 break; /* coprocessor segment overrun */
777 case 10:
778 sigval = 11;
779 break; /* Invalid TSS */
780 case 11:
781 sigval = 11;
782 break; /* Segment not present */
783 case 12:
784 sigval = 11;
785 break; /* stack exception */
786 case 13:
787 sigval = 11;
788 break; /* general protection */
789 case 14:
790 sigval = 11;
791 break; /* page fault */
792 case 16:
793 sigval = 7;
794 break; /* coprocessor error */
795 default:
796 sigval = 7; /* "software generated" */
797 }
798 return (sigval);
799}
800
801/**********************************************/
802/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
803/* RETURN NUMBER OF CHARS PROCESSED */
804/**********************************************/
805int
806hexToInt (char **ptr, int *intValue)
807{
808 int numChars = 0;
809 int hexValue;
810
811 *intValue = 0;
812
813 while (**ptr)
814 {
815 hexValue = hex (**ptr);
816 if (hexValue >= 0)
817 {
818 *intValue = (*intValue << 4) | hexValue;
819 numChars++;
820 }
821 else
822 break;
823
824 (*ptr)++;
825 }
826
827 return (numChars);
828}
829
830/*
831 * This function does all command procesing for interfacing to gdb.
832 */
833void
834handle_exception (int exceptionVector)
835{
836 int sigval, stepping;
837 int addr, length;
838 char *ptr;
839
840#ifndef WIN32 //MF
841 gdb_i386vector = exceptionVector;
842#endif
843
844 if (remote_debug)
845 {
846 printf ("vector=%d, sr=0x%x, pc=0x%x\n",
847 exceptionVector, registers[PS], registers[PC]);
848 }
849
850 /* reply to host that an exception has occurred */
851 sigval = computeSignal (exceptionVector);
852
854
855 *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
856 *ptr++ = hexchars[sigval >> 4];
857 *ptr++ = hexchars[sigval & 0xf];
858
859 *ptr++ = hexchars[ESP];
860 *ptr++ = ':';
861 ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0); /* SP */
862 *ptr++ = ';';
863
864 *ptr++ = hexchars[EBP];
865 *ptr++ = ':';
866 ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0); /* FP */
867 *ptr++ = ';';
868
869 *ptr++ = hexchars[PC];
870 *ptr++ = ':';
871 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0); /* PC */
872 *ptr++ = ';';
873
874 *ptr = '\0';
875
877
878 stepping = 0;
879
880 while (1 == 1)
881 {
882 remcomOutBuffer[0] = 0;
883 ptr = getpacket ();
884
885 switch (*ptr++)
886 {
887 case '?':
888 remcomOutBuffer[0] = 'S';
889 remcomOutBuffer[1] = hexchars[sigval >> 4];
890 remcomOutBuffer[2] = hexchars[sigval % 16];
891 remcomOutBuffer[3] = 0;
892 break;
893 case 'd':
894 remote_debug = !(remote_debug); /* toggle debug flag */
895 break;
896 case 'g': /* return the value of the CPU registers */
898 break;
899 case 'G': /* set the value of the CPU registers - return OK */
900 hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
902 break;
903 case 'P': /* set the value of a single CPU register - return OK */
904 {
905 int regno;
906
907 if (hexToInt (&ptr, &regno) && *ptr++ == '=')
908 if (regno >= 0 && regno < NUMREGS)
909 {
910 hex2mem (ptr, (char *) &registers[regno], 4, 0);
912 break;
913 }
914
916 break;
917 }
918
919 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
920 case 'm':
921 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
922 if (hexToInt (&ptr, &addr))
923 if (*(ptr++) == ',')
924 if (hexToInt (&ptr, &length))
925 {
926 ptr = 0;
927 mem_err = 0;
928 mem2hex ((char *) addr, remcomOutBuffer, length, 1);
929 if (mem_err)
930 {
932 debug_error ("memory fault");
933 }
934 }
935
936 if (ptr)
937 {
939 }
940 break;
941
942 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
943 case 'M':
944 /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
945 if (hexToInt (&ptr, &addr))
946 if (*(ptr++) == ',')
947 if (hexToInt (&ptr, &length))
948 if (*(ptr++) == ':')
949 {
950 mem_err = 0;
951 hex2mem (ptr, (char *) addr, length, 1);
952
953 if (mem_err)
954 {
956 debug_error ("memory fault");
957 }
958 else
959 {
961 }
962
963 ptr = 0;
964 }
965 if (ptr)
966 {
968 }
969 break;
970
971 /* cAA..AA Continue at address AA..AA(optional) */
972 /* sAA..AA Step one instruction from AA..AA(optional) */
973 case 's':
974 stepping = 1;
975 case 'c':
976 /* try to read optional parameter, pc unchanged if no parm */
977 if (hexToInt (&ptr, &addr))
978 registers[PC] = addr;
979
980 /* clear the trace bit */
981 registers[PS] &= 0xfffffeff;
982
983 /* set the trace bit if we're stepping */
984 if (stepping)
985 registers[PS] |= 0x100;
986
987#ifdef WIN32 //MF
988 return;
989#else
990 _returnFromException (); /* this is a jump */
991#endif
992 break;
993
994 /* kill the program */
995 case 'k': /* do nothing */
996#if 0
997 /* Huh? This doesn't look like "nothing".
998 m68k-stub.c and sparc-stub.c don't have it. */
999 BREAKPOINT ();
1000#endif
1001 break;
1002 } /* switch */
1003
1004 /* reply to the request */
1006 }
1007}
1008
1009/* this function is used to set up exception handlers for tracing and
1010 breakpoints */
1011void
1013{
1014#ifndef WIN32 //MF
1015 stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
1016
1032#endif // WIN32
1033
1034 initialized = 1;
1035}
1036
1037/* This function will generate a breakpoint exception. It is used at the
1038 beginning of a program to sync up with a debugger and can be used
1039 otherwise as a quick means to stop program execution and "break" into
1040 the debugger. */
1041
1042void
1044{
1045 if (initialized)
1046 BREAKPOINT ();
1047}
1048
1049
1050
1051 //
1052 // debugger stub implementation for WIN32 applications
1053 // M. Fuchs, 29.11.2003
1054 //
1055
1056#ifdef WIN32
1057
1058#include <stdlib.h>
1059#include <errno.h>
1060
1061#include "utility/utility.h"
1062
1063
1064int s_initial_breakpoint = 0;
1065
1066
1067#ifdef DEBUG_SERIAL
1068
1069FILE* ser_port = NULL;
1070
1071int init_gdb_connect()
1072{
1073 //TODO: set up connection using serial communication port
1074
1075 ser_port = fopen("COM1:", "rwb");
1076
1077 return 1;
1078}
1079
1080int getDebugChar()
1081{
1082 return fgetc(ser_port);
1083}
1084
1085void putDebugChar(int c)
1086{
1087 fputc(c, ser_port);
1088}
1089
1090
1091#else // DEBUG_SERIAL
1092
1093
1094static LPTOP_LEVEL_EXCEPTION_FILTER s_prev_exc_handler = 0;
1095
1096
1097#define I386_EXCEPTION_CNT 17
1098
1099LONG WINAPI exc_protection_handler(EXCEPTION_POINTERS* exc_info)
1100{
1101 int exc_nr = exc_info->ExceptionRecord->ExceptionCode & 0xFFFF;
1102
1103 if (exc_nr < I386_EXCEPTION_CNT) {
1104 //LOG(FmtString(TEXT("exc_protection_handler: Exception %x"), exc_nr));
1105
1106 if (exc_nr==11 || exc_nr==13 || exc_nr==14) {
1109 }
1110
1111 ++exc_info->ContextRecord->Eip;
1112 }
1113
1115}
1116
1117LONG WINAPI exc_handler(EXCEPTION_POINTERS* exc_info)
1118{
1119 int exc_nr = exc_info->ExceptionRecord->ExceptionCode & 0xFFFF;
1120
1121 if (exc_nr < I386_EXCEPTION_CNT) {
1122 //LOG(FmtString("Exception %x", exc_nr));
1123 //LOG(FmtString("EIP=%08X EFLAGS=%08X", exc_info->ContextRecord->Eip, exc_info->ContextRecord->EFlags));
1124
1125 // step over initial breakpoint
1126 if (s_initial_breakpoint) {
1127 s_initial_breakpoint = 0;
1128 ++exc_info->ContextRecord->Eip;
1129 }
1130
1131 SetUnhandledExceptionFilter(exc_protection_handler);
1132
1133 win32_exception_handler(exc_info);
1134 //LOG(FmtString("EIP=%08X EFLAGS=%08X", exc_info->ContextRecord->Eip, exc_info->ContextRecord->EFlags));
1135
1136 SetUnhandledExceptionFilter(exc_handler);
1137
1139 }
1140
1142}
1143
1144/* not needed because we use win32_exception_handler() instead of catchExceptionX()
1145void exceptionHandler(int exc_nr, void* exc_addr)
1146{
1147 if (exc_nr>=0 && exc_nr<I386_EXCEPTION_CNT)
1148 exc_handlers[exc_nr] = exc_addr;
1149}
1150*/
1151
1152void disable_debugging()
1153{
1154 if (s_prev_exc_handler) {
1155 SetUnhandledExceptionFilter(s_prev_exc_handler);
1156 s_prev_exc_handler = 0;
1157 }
1158}
1159
1160#define _INC_WINDOWS
1161#include <winsock.h>
1162#ifdef _MSC_VER
1163#pragma comment(lib, "wsock32")
1164#endif
1165
1166static int s_rem_fd = -1;
1167
1168int init_gdb_connect()
1169{
1170 SOCKADDR_IN srv_addr = {0};
1171 SOCKADDR_IN rem_addr;
1172 WSADATA wsa_data;
1173 int srv_socket, rem_len;
1174
1175 s_prev_exc_handler = SetUnhandledExceptionFilter(exc_handler);
1176
1177 if (WSAStartup(MAKEWORD(2,2), &wsa_data)) {
1178 fprintf(stderr, "WSAStartup() failed");
1179 return 0;
1180 }
1181
1182 srv_addr.sin_family = AF_INET;
1183 srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1184 srv_addr.sin_port = htons(9999);
1185
1186 srv_socket = socket(PF_INET, SOCK_STREAM, 0);
1187 if (srv_socket == -1) {
1188 perror("socket()");
1189 return 0;
1190 }
1191
1192 if (bind(srv_socket, (struct sockaddr*) &srv_addr, sizeof(srv_addr)) == -1) {
1193 perror("bind()");
1194 return 0;
1195 }
1196
1197 if (listen(srv_socket, 4) == -1) {
1198 perror("listen()");
1199 return 0;
1200 }
1201
1202 rem_len = sizeof(rem_addr);
1203
1204 for(;;) {
1205 s_rem_fd = accept(srv_socket, (struct sockaddr*)&rem_addr, &rem_len);
1206
1207 if (s_rem_fd < 0) {
1208 if (errno == EINTR)
1209 continue;
1210
1211 perror("accept()");
1212 return 0;
1213 }
1214
1215 break;
1216 }
1217
1218 return 1;
1219}
1220
1221#endif // DEBUG_SERIAL
1222
1223
1224int getDebugChar()
1225{
1226 char buffer[1024];
1227 int r;
1228
1229 if (s_rem_fd == -1)
1230 return EOF;
1231
1232 r = recv(s_rem_fd, buffer, 1, 0);
1233 if (r == -1) {
1234 perror("recv()");
1235 LOG(TEXT("debugger connection broken"));
1236 s_rem_fd = -1;
1237 return EOF;
1238 }
1239
1240 if (!r)
1241 return EOF;
1242
1243 return buffer[0];
1244}
1245
1246void putDebugChar(int c)
1247{
1248 if (s_rem_fd != -1) {
1249 const char buffer[] = {c};
1250
1251 if (!send(s_rem_fd, buffer, 1, 0)) {
1252 perror("send()");
1253 LOG(TEXT("debugger connection broken"));
1254 exit(-1);
1255 }
1256 }
1257}
1258
1259
1260 // start up GDB stub interface
1261
1263{
1264 if (!init_gdb_connect())
1265 return 0;
1266
1268
1269 s_initial_breakpoint = 1;
1270 breakpoint();
1271
1272 return 1;
1273}
1274
1275#endif // WIN32
#define EINTR
Definition: acclib.h:80
#define NULL
Definition: types.h:112
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:805
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:790
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
#define SOCK_STREAM
Definition: tcpip.h:118
#define AF_INET
Definition: tcpip.h:117
unsigned long DWORD
Definition: ntddk_ex.h:95
#define printf
Definition: freeldr.h:93
USHORT numChars
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const char hexchars[]
int gdb_i386vector
void putpacket(char *buffer)
char * hex2mem(char *buf, char *mem, int count, int may_fault)
void putDebugChar()
int registers[NUMREGS]
void handle_exception(int exceptionVector)
#define STACKSIZE
void _catchException10()
static volatile int mem_err
void _catchException4()
static int * stackPtr
static char remcomOutBuffer[BUFMAX]
int getDebugChar()
void _catchException12()
void return_to_prog()
#define SAVE_REGISTERS1()
#define BREAKPOINT()
void _catchException6()
void _catchException0()
void _catchException5()
#define NUMREGS
char * getpacket(void)
int gdb_i386errcode
void _catchException3()
#define NUMREGBYTES
#define SAVE_REGISTERS2()
void _catchException11()
int computeSignal(int exceptionVector)
void _catchException13()
void _catchException8()
void _catchException9()
void _catchException7()
int hexToInt(char **ptr, int *intValue)
static void(*volatile mem_fault_routine)()
void _catchException14()
void _catchException1()
int get_char(char *addr)
static char remcomInBuffer[BUFMAX]
#define BUFMAX
int remote_debug
void debug_error(char *format)
static char initialized
void _returnFromException()
char * mem2hex(char *mem, char *buf, int count, int may_fault)
#define CHECK_FAULT()
#define SAVE_ERRCODE()
regnames
@ EDI
@ ESP
@ PS
@ ECX
@ ESI
@ EAX
@ FS
@ ES
@ CS
@ EBX
@ EDX
@ GS
@ PC
@ DS
@ SS
@ EBP
void set_mem_err(void)
void exceptionHandler()
void _catchException16()
void set_char(char *addr, int val)
int hex(char ch)
void set_debug_traps(void)
int remcomStack[STACKSIZE/sizeof(int)]
void breakpoint(void)
#define CALL_HOOK()
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:87
_Check_return_opt_ _CRTIMP int __cdecl fgetc(_Inout_ FILE *_File)
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
#define EOF
Definition: stdio.h:24
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fputc(_In_ int _Ch, _Inout_ FILE *_File)
#define INADDR_ANY
Definition: inet.h:53
#define TEXT(s)
Definition: k32.h:26
#define htons(x)
Definition: module.h:215
#define htonl(x)
Definition: module.h:214
int initialize_gdb_stub()
#define strcpy_s(d, l, s)
Definition: utility.h:200
#define LOG(txt)
Definition: utility.h:102
static PVOID ptr
Definition: dispmode.c:27
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
long LONG
Definition: pedump.c:60
#define errno
Definition: errno.h:18
#define exit(n)
Definition: config.h:202
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
ULONG Eip
Definition: nt_native.h:1476
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
DWORD ExceptionCode
Definition: compat.h:208
Definition: mem.c:156
struct in_addr sin_addr
Definition: winsock.h:512
short sin_family
Definition: winsock.h:510
u_short sin_port
Definition: winsock.h:511
#define MAKEWORD(a, b)
Definition: typedefs.h:248
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:135
PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER
Definition: winbase.h:1453
#define WINAPI
Definition: msvc.h:6
#define PF_INET
Definition: winsock.h:373