ReactOS  0.4.14-dev-556-g4c5b21f
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 
102 extern void putDebugChar(); /* write a single character */
103 extern int getDebugChar(); /* read and return a single char */
104 extern 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 
111 static char initialized; /* boolean flag. != 0 means we've been initialized */
112 
114 /* debug > 0 prints ill-formed commands in valid packets & checksum errors */
115 
116 static 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 
124 enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
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
137 int remcomStack[STACKSIZE/sizeof(int)];
138 static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
139 
140 /*************************** ASSEMBLY CODE MACROS *************************/
141 /* */
142 
143 extern void
144 return_to_prog ();
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. */
149 asm(".text");
150 asm(".globl _return_to_prog");
151 asm("_return_to_prog:");
152 asm(" movw _registers+44, %ss");
153 asm(" movl _registers+16, %esp");
154 asm(" movl _registers+4, %ecx");
155 asm(" movl _registers+8, %edx");
156 asm(" movl _registers+12, %ebx");
157 asm(" movl _registers+20, %ebp");
158 asm(" movl _registers+24, %esi");
159 asm(" movl _registers+28, %edi");
160 asm(" movw _registers+48, %ds");
161 asm(" movw _registers+52, %es");
162 asm(" movw _registers+56, %fs");
163 asm(" movw _registers+60, %gs");
164 asm(" movl _registers+36, %eax");
165 asm(" pushl %eax"); /* saved eflags */
166 asm(" movl _registers+40, %eax");
167 asm(" pushl %eax"); /* saved cs */
168 asm(" movl _registers+32, %eax");
169 asm(" pushl %eax"); /* saved eip */
170 asm(" movl _registers, %eax");
171 
172 asm("ret"); //MF
173 
174 /* use iret to restore pc and flags together so
175  that trace flag works right. */
176 asm(" iret");
177 
178 
179 #ifdef WIN32 //MF
180 asm(".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). */
187 int gdb_i386vector = -1;
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 
229 asm (".text");
230 asm ("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. */
233 asm (" popl %eax");
234 asm (" movl %eax, _gdb_i386errcode");
235 
236 asm (" 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. */
239 asm (" movl _mem_fault_routine, %eax");
240 asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */
241 asm (" 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. */
246 asm (" leave");
247 
248 /* Push the stuff that iret wants. */
249 asm (" pushl %edx"); /* eflags */
250 asm (" pushl %ecx"); /* cs */
251 asm (" pushl %eax"); /* eip */
252 
253 /* Zero mem_fault_routine. */
254 asm (" movl $0, %eax");
255 asm (" movl %eax, _mem_fault_routine");
256 
257 asm ("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  */
272 extern void _catchException3();
273 asm(".text");
274 asm(".globl __catchException3");
275 asm("__catchException3:");
278 asm ("pushl $3");
279 CALL_HOOK();
280 
281 /* Same thing for exception 1. */
282 extern void _catchException1();
283 asm(".text");
284 asm(".globl __catchException1");
285 asm("__catchException1:");
288 asm ("pushl $1");
289 CALL_HOOK();
290 
291 /* Same thing for exception 0. */
292 extern void _catchException0();
293 asm(".text");
294 asm(".globl __catchException0");
295 asm("__catchException0:");
298 asm ("pushl $0");
299 CALL_HOOK();
300 
301 /* Same thing for exception 4. */
302 extern void _catchException4();
303 asm(".text");
304 asm(".globl __catchException4");
305 asm("__catchException4:");
308 asm ("pushl $4");
309 CALL_HOOK();
310 
311 /* Same thing for exception 5. */
312 extern void _catchException5();
313 asm(".text");
314 asm(".globl __catchException5");
315 asm("__catchException5:");
318 asm ("pushl $5");
319 CALL_HOOK();
320 
321 /* Same thing for exception 6. */
322 extern void _catchException6();
323 asm(".text");
324 asm(".globl __catchException6");
325 asm("__catchException6:");
328 asm ("pushl $6");
329 CALL_HOOK();
330 
331 /* Same thing for exception 7. */
332 extern void _catchException7();
333 asm(".text");
334 asm(".globl __catchException7");
335 asm("__catchException7:");
338 asm ("pushl $7");
339 CALL_HOOK();
340 
341 /* Same thing for exception 8. */
342 extern void _catchException8();
343 asm(".text");
344 asm(".globl __catchException8");
345 asm("__catchException8:");
347 SAVE_ERRCODE();
349 asm ("pushl $8");
350 CALL_HOOK();
351 
352 /* Same thing for exception 9. */
353 extern void _catchException9();
354 asm(".text");
355 asm(".globl __catchException9");
356 asm("__catchException9:");
359 asm ("pushl $9");
360 CALL_HOOK();
361 
362 /* Same thing for exception 10. */
363 extern void _catchException10();
364 asm(".text");
365 asm(".globl __catchException10");
366 asm("__catchException10:");
368 SAVE_ERRCODE();
370 asm ("pushl $10");
371 CALL_HOOK();
372 
373 /* Same thing for exception 12. */
374 extern void _catchException12();
375 asm(".text");
376 asm(".globl __catchException12");
377 asm("__catchException12:");
379 SAVE_ERRCODE();
381 asm ("pushl $12");
382 CALL_HOOK();
383 
384 /* Same thing for exception 16. */
385 extern void _catchException16();
386 asm(".text");
387 asm(".globl __catchException16");
388 asm("__catchException16:");
391 asm ("pushl $16");
392 CALL_HOOK();
393 
394 /* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */
395 
396 /* Same thing for exception 13. */
397 extern void _catchException13 ();
398 asm (".text");
399 asm (".globl __catchException13");
400 asm ("__catchException13:");
401 CHECK_FAULT();
403 SAVE_ERRCODE();
405 asm ("pushl $13");
406 CALL_HOOK();
407 
408 /* Same thing for exception 11. */
409 extern void _catchException11 ();
410 asm (".text");
411 asm (".globl __catchException11");
412 asm ("__catchException11:");
413 CHECK_FAULT();
415 SAVE_ERRCODE();
417 asm ("pushl $11");
418 CALL_HOOK();
419 
420 /* Same thing for exception 14. */
421 extern void _catchException14 ();
422 asm (".text");
423 asm (".globl __catchException14");
424 asm ("__catchException14:");
425 CHECK_FAULT();
427 SAVE_ERRCODE();
429 asm ("pushl $14");
430 CALL_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  */
436 asm("_remcomHandler:");
437 asm(" popl %eax"); /* pop off return address */
438 asm(" popl %eax"); /* get the exception number */
439 asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
440 asm(" pushl %eax"); /* push exception onto stack */
441 asm(" call _handle_exception"); /* this never returns */
442 
443 
444 void
446 {
447  return_to_prog ();
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 
465 void handle_exception(int exceptionVector);
466 
467 void 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 
488  handle_exception(exc_info->ExceptionRecord->ExceptionCode & 0xFFFF);
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 
511 int
512 hex (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 
524 static char remcomInBuffer[BUFMAX];
525 static char remcomOutBuffer[BUFMAX];
526 
527 /* scan for the sequence $<data>#<checksum> */
528 
529 char *
530 getpacket (void)
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  {
574  fprintf (stderr,
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 
601 void
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 
630 void 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. */
637 static void (*volatile mem_fault_routine) () = NULL;
638 
639 /* Indicate to caller of mem2hex or hex2mem that there has been an
640  error. */
641 static volatile int mem_err = 0;
642 
643 void
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). */
653 int
654 get_char (char *addr)
655 {
656  return *addr;
657 }
658 
659 void
660 set_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. */
669 char *
670 mem2hex (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 */
704 char *
705 hex2mem (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 */
744 int
745 computeSignal (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 /**********************************************/
805 int
806 hexToInt (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  */
833 void
834 handle_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 */
1011 void
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 
1042 void
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 
1064 int s_initial_breakpoint = 0;
1065 
1066 
1067 #ifdef DEBUG_SERIAL
1068 
1069 FILE* ser_port = NULL;
1070 
1071 int 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 
1080 int getDebugChar()
1081 {
1082  return fgetc(ser_port);
1083 }
1084 
1085 void putDebugChar(int c)
1086 {
1087  fputc(c, ser_port);
1088 }
1089 
1090 
1091 #else // DEBUG_SERIAL
1092 
1093 
1094 static LPTOP_LEVEL_EXCEPTION_FILTER s_prev_exc_handler = 0;
1095 
1096 
1097 #define I386_EXCEPTION_CNT 17
1098 
1099 LONG 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) {
1107  if (mem_fault_routine)
1109  }
1110 
1111  ++exc_info->ContextRecord->Eip;
1112  }
1113 
1115 }
1116 
1117 LONG 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()
1145 void 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 
1152 void 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 
1166 static int s_rem_fd = -1;
1167 
1168 int 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 
1224 int 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 
1246 void 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 
1262 int initialize_gdb_stub()
1263 {
1264  if (!init_gdb_connect())
1265  return 0;
1266 
1267  set_debug_traps();
1268 
1269  s_initial_breakpoint = 1;
1270  breakpoint();
1271 
1272  return 1;
1273 }
1274 
1275 #endif // WIN32
void _catchException14()
int remcomStack[STACKSIZE/sizeof(int)]
_Check_return_opt_ _CRTIMP int __cdecl fputc(_In_ int _Ch, _Inout_ FILE *_File)
#define SAVE_REGISTERS2()
#define CHECK_FAULT()
void exceptionHandler()
ULONG Esp
Definition: nt_native.h:1479
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
u_short sin_port
Definition: winsock.h:511
static void(*volatile mem_fault_routine)()
ULONG Eip
Definition: nt_native.h:1476
#define htonl(x)
Definition: module.h:212
char * hex2mem(char *buf, char *mem, int count, int may_fault)
#define MAKEWORD(a, b)
Definition: typedefs.h:247
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SAVE_ERRCODE()
static int * stackPtr
GLuint GLuint GLsizei count
Definition: gl.h:1545
int hexToInt(char **ptr, int *intValue)
static const char hexchars[]
#define EINTR
Definition: acclib.h:80
ULONG Ecx
Definition: nt_native.h:1467
void _catchException0()
void _catchException7()
int hex(char ch)
#define CALL_HOOK()
void _returnFromException()
#define INADDR_ANY
Definition: StrAddr.c:4
GLuint buffer
Definition: glext.h:5915
ULONG SegGs
Definition: nt_native.h:1453
ULONG SegFs
Definition: nt_native.h:1454
int errno
int initialize_gdb_stub()
ULONG SegDs
Definition: nt_native.h:1456
void _catchException8()
void _catchException6()
#define BUFMAX
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
void set_char(char *addr, int val)
DWORD ExceptionCode
Definition: compat.h:196
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
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
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
long LONG
Definition: pedump.c:60
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:792
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
void _catchException4()
int gdb_i386errcode
#define NUMREGBYTES
ULONG SegEs
Definition: nt_native.h:1455
ULONG Esi
Definition: nt_native.h:1464
static PVOID ptr
Definition: dispmode.c:27
void _catchException11()
void _catchException13()
ULONG SegCs
Definition: nt_native.h:1477
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
smooth NULL
Definition: ftsmooth.c:416
ULONG Edx
Definition: nt_native.h:1466
int gdb_i386vector
ULONG EFlags
Definition: nt_native.h:1478
ULONG Ebx
Definition: nt_native.h:1465
static char initialized
#define PF_INET
Definition: winsock.h:373
int getDebugChar()
void debug_error(char *format)
GLuint GLfloat * val
Definition: glext.h:7180
#define SAVE_REGISTERS1()
PCONTEXT ContextRecord
Definition: rtltypes.h:197
int registers[NUMREGS]
void putpacket(char *buffer)
regnames
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STACKSIZE
int remote_debug
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:144
static volatile int mem_err
void return_to_prog()
void breakpoint(void)
GLenum const GLvoid * addr
Definition: glext.h:9621
static char remcomOutBuffer[BUFMAX]
#define strcpy_s(d, l, s)
Definition: utility.h:200
PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER
Definition: winbase.h:1413
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
ULONG Eax
Definition: nt_native.h:1468
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
void set_mem_err(void)
#define NUMREGS
void _catchException16()
#define LOG(txt)
Definition: utility.h:102
struct in_addr sin_addr
Definition: winsock.h:512
#define TEXT(s)
Definition: k32.h:26
void set_debug_traps(void)
ULONG SegSs
Definition: nt_native.h:1480
char * mem2hex(char *mem, char *buf, int count, int may_fault)
void _catchException3()
#define BREAKPOINT()
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:807
void _catchException9()
void _catchException12()
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
Definition: mem.c:156
#define EOF
Definition: stdio.h:24
FILE * stderr
#define AF_INET
Definition: tcpip.h:117
static char remcomInBuffer[BUFMAX]
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:196
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define SOCK_STREAM
Definition: tcpip.h:118
void exit(int exitcode)
Definition: _exit.c:33
#define htons(x)
Definition: module.h:213
char * getpacket(void)
void _catchException10()
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
short sin_family
Definition: winsock.h:510
void putDebugChar()
ULONG Ebp
Definition: nt_native.h:1475
void handle_exception(int exceptionVector)
void _catchException1()
int get_char(char *addr)
ULONG Edi
Definition: nt_native.h:1463
int computeSignal(int exceptionVector)
#define printf
Definition: config.h:203
_Check_return_opt_ _CRTIMP int __cdecl fgetc(_Inout_ FILE *_File)
void _catchException5()
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:87