source: rtems/c/src/lib/libbsp/i386/shared/comm/i386-stub.c @ e8d4c360

4.104.114.95
Last change on this file since e8d4c360 was e8d4c360, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/07/08 at 14:30:51

Include stdbool.h.

  • Property mode set to 100644
File size: 25.4 KB
Line 
1/*
2 *  This is the gdb i386 remote debug stub from gdb 4.XX.
3 *
4 *  $Id$
5 */
6
7/****************************************************************************
8
9  THIS SOFTWARE IS NOT COPYRIGHTED
10
11  HP offers the following for use in the public domain.  HP makes no
12  warranty with regard to the software or it's performance and the
13  user accepts the software "AS IS" with all faults.
14
15  HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
16  TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
19  ****************************************************************************/
20
21/****************************************************************************
22 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
23 *
24 *  Module name: remcom.c $
25 *  Revision: 1.34 $
26 *  Date: 91/03/09 12:29:49 $
27 *  Contributor:     Lake Stevens Instrument Division$
28 *
29 *  Description:     low level support for gdb debugger. $
30 *
31 *  Considerations:  only works on target hardware $
32 *
33 *  Written by:      Glenn Engel $
34 *  ModuleState:     Experimental $
35 *
36 *  NOTES:           See Below $
37 *
38 *  Modified for 386 by Jim Kingdon, Cygnus Support.
39 *  Modified for RTEMS by Aleksey Romanov, Quality Quorum, Inc.
40 *
41 *  To enable debugger support, two things need to happen.  One, a
42 *  call to set_debug_traps() is necessary in order to allow any breakpoints
43 *  or error conditions to be properly intercepted and reported to gdb.
44 *  Two, a breakpoint needs to be generated to begin communication.  This
45 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
46 *  simulates a breakpoint by executing a trap #1.
47 *
48 *  The external function exceptionHandler() is
49 *  used to attach a specific handler to a specific 386 vector number.
50 *  It should use the same privilege level it runs at.  It should
51 *  install it as an interrupt gate so that interrupts are masked
52 *  while the handler runs.
53 *  Also, need to assign exceptionHook and oldExceptionHook.
54 *
55 *  Because gdb will sometimes write to the stack area to execute function
56 *  calls, this program cannot rely on using the supervisor stack so it
57 *  uses it's own stack area reserved in the int array remcomStack.
58 *
59 *************
60 *
61 *    The following gdb commands are supported:
62 *
63 * command          function                               Return value
64 *
65 *    g             return the value of the CPU registers  hex data or ENN
66 *    G             set the value of the CPU registers     OK or ENN
67 *
68 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
69 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
70 *
71 *    c             Resume at current address              SNN   ( signal NN)
72 *    cAA..AA       Continue at address AA..AA             SNN
73 *
74 *    s             Step one instruction                   SNN
75 *    sAA..AA       Step one instruction from AA..AA       SNN
76 *
77 *    k             kill
78 *
79 *    ?             What was the last sigval ?             SNN   (signal NN)
80 *
81 * All commands and responses are sent with a packet which includes a
82 * checksum.  A packet consists of
83 *
84 * $<packet info>#<checksum>.
85 *
86 * where
87 * <packet info> :: <characters representing the command or response>
88 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
89 *
90 * When a packet is received, it is first acknowledged with either '+' or '-'.
91 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
92 *
93 * Example:
94 *
95 * Host:                  Reply:
96 * $m0,10#2a               +$00010203040506070809101112131415#42
97 *
98 ****************************************************************************/
99
100#include <stdio.h>
101#include <string.h>
102#include <stdbool.h>
103
104/************************************************************************
105 *
106 * external low-level support routines
107 */
108extern int putDebugChar (int ch);          /* write a single character      */
109extern int getDebugChar (void);            /* read and return a single char */
110
111/* assign an exception handler */
112extern void exceptionHandler (int, void (*handler) (void));
113
114/************************************************************************/
115/* BUFMAX defines the maximum number of characters in inbound/outbound buffers */
116/* at least NUMREGBYTES*2 are needed for register packets */
117#define BUFMAX 400
118
119static bool initialized = false;        /* boolean flag. != 0 means we've been initialized */
120
121extern int remote_debug;
122/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
123
124extern void waitabit (void);
125
126static const char hexchars[] = "0123456789abcdef";
127
128/* Number of registers.  */
129#define NUMREGS 16
130
131/* Number of bytes per register.  */
132#define REGBYTES 4
133
134/* Number of bytes of registers.  */
135#define NUMREGBYTES (NUMREGS * REGBYTES)
136
137enum regnames
138  {
139    EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
140    PC /* also known as eip */ ,
141    PS /* also known as eflags */ ,
142    CS, SS, DS, ES, FS, GS
143  };
144
145/*
146 * these should not be static cuz they can be used outside this module
147 */
148int registers[NUMREGS];
149
150#define STACKSIZE 10000
151int remcomStack[STACKSIZE / sizeof (int)];
152static int *stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
153
154/***************************  ASSEMBLY CODE MACROS *************************/
155/*                                                                         */
156
157extern void
158  return_to_prog (void);
159
160/* Restore the program's registers (including the stack pointer, which
161   means we get the right stack and don't have to worry about popping our
162   return address and any stack frames and so on) and return.  */
163asm (".text");
164asm (".globl return_to_prog");
165asm ("return_to_prog:");
166asm ("        movw registers+44, %ss");
167asm ("        movl registers+16, %esp");
168asm ("        movl registers+4, %ecx");
169asm ("        movl registers+8, %edx");
170asm ("        movl registers+12, %ebx");
171asm ("        movl registers+20, %ebp");
172asm ("        movl registers+24, %esi");
173asm ("        movl registers+28, %edi");
174asm ("        movw registers+48, %ds");
175asm ("        movw registers+52, %es");
176asm ("        movw registers+56, %fs");
177asm ("        movw registers+60, %gs");
178asm ("        movl registers+36, %eax");
179asm ("        pushl %eax");     /* saved eflags */
180asm ("        movl registers+40, %eax");
181asm ("        pushl %eax");     /* saved cs */
182asm ("        movl registers+32, %eax");
183asm ("        pushl %eax");     /* saved eip */
184asm ("        movl registers, %eax");
185/* use iret to restore pc and flags together so
186   that trace flag works right.  */
187asm ("        iret");
188
189#define BREAKPOINT() asm("   int $3");
190
191/* Put the error code here just in case the user cares.  */
192int gdb_i386errcode;
193/* Likewise, the vector number here (since GDB only gets the signal
194   number through the usual means, and that's not very specific).  */
195int gdb_i386vector = -1;
196
197/* GDB stores segment registers in 32-bit words (that's just the way
198   m-i386v.h is written).  So zero the appropriate areas in registers.  */
199#define SAVE_REGISTERS1() \
200  asm ("movl %eax, registers");                                           \
201  asm ("movl %ecx, registers+4");                                            \
202  asm ("movl %edx, registers+8");                                            \
203  asm ("movl %ebx, registers+12");                                           \
204  asm ("movl %ebp, registers+20");                                           \
205  asm ("movl %esi, registers+24");                                           \
206  asm ("movl %edi, registers+28");                                           \
207  asm ("movw $0, %ax");                                                      \
208  asm ("movw %ds, registers+48");                                            \
209  asm ("movw %ax, registers+50");                                            \
210  asm ("movw %es, registers+52");                                            \
211  asm ("movw %ax, registers+54");                                            \
212  asm ("movw %fs, registers+56");                                            \
213  asm ("movw %ax, registers+58");                                            \
214  asm ("movw %gs, registers+60");                                            \
215  asm ("movw %ax, registers+62");
216#define SAVE_ERRCODE() \
217  asm ("popl %ebx");                                  \
218  asm ("movl %ebx, gdb_i386errcode");
219#define SAVE_REGISTERS2() \
220  asm ("popl %ebx"); /* old eip */                                           \
221  asm ("movl %ebx, registers+32");                                           \
222  asm ("popl %ebx");     /* old cs */                                        \
223  asm ("movl %ebx, registers+40");                                           \
224  asm ("movw %ax, registers+42");                                           \
225  asm ("popl %ebx");     /* old eflags */                                    \
226  asm ("movl %ebx, registers+36");                                           \
227  /* Now that we've done the pops, we can save the stack pointer.");  */   \
228  asm ("movw %ss, registers+44");                                            \
229  asm ("movw %ax, registers+46");                                            \
230  asm ("movl %esp, registers+16");
231
232/* See if mem_fault_routine is set, if so just IRET to that address.  */
233#define CHECK_FAULT() \
234  asm ("cmpl $0, mem_fault_routine");                                      \
235  asm ("jne mem_fault");
236
237asm (".text");
238asm ("mem_fault:");
239/* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
240/* Pop error code from the stack and save it.  */
241asm ("     popl %eax");
242asm ("     movl %eax, gdb_i386errcode");
243
244asm ("     popl %eax");         /* eip */
245/* We don't want to return there, we want to return to the function
246   pointed to by mem_fault_routine instead.  */
247asm ("     movl mem_fault_routine, %eax");
248asm ("     popl %ecx");         /* cs (low 16 bits; junk in hi 16 bits).  */
249asm ("     popl %edx");         /* eflags */
250
251/* Remove this stack frame; when we do the iret, we will be going to
252   the start of a function, so we want the stack to look just like it
253   would after a "call" instruction.  */
254asm ("     leave");
255
256/* Push the stuff that iret wants.  */
257asm ("     pushl %edx");        /* eflags */
258asm ("     pushl %ecx");        /* cs */
259asm ("     pushl %eax");        /* eip */
260
261/* Zero mem_fault_routine.  */
262asm ("     movl $0, %eax");
263asm ("     movl %eax, mem_fault_routine");
264
265asm ("iret");
266
267#define CALL_HOOK() asm("call _remcomHandler");
268
269/* This function is called when a i386 exception occurs.  It saves
270 * all the cpu regs in the registers array, munges the stack a bit,
271 * and invokes an exception handler (remcom_handler).
272 *
273 * stack on entry:                       stack on exit:
274 *   old eflags                          vector number
275 *   old cs (zero-filled to 32 bits)
276 *   old eip
277 *
278 */
279extern void _catchException3 (void);
280asm (".text");
281asm (".globl _catchException3");
282asm ("_catchException3:");
283SAVE_REGISTERS1 ();
284SAVE_REGISTERS2 ();
285asm ("pushl $3");
286CALL_HOOK ();
287
288/* Same thing for exception 1.  */
289extern void _catchException1 (void);
290asm (".text");
291asm (".globl _catchException1");
292asm ("_catchException1:");
293SAVE_REGISTERS1 ();
294SAVE_REGISTERS2 ();
295asm ("pushl $1");
296CALL_HOOK ();
297
298/* Same thing for exception 0.  */
299extern void _catchException0 (void);
300asm (".text");
301asm (".globl _catchException0");
302asm ("_catchException0:");
303SAVE_REGISTERS1 ();
304SAVE_REGISTERS2 ();
305asm ("pushl $0");
306CALL_HOOK ();
307
308/* Same thing for exception 4.  */
309extern void _catchException4 (void);
310asm (".text");
311asm (".globl _catchException4");
312asm ("_catchException4:");
313SAVE_REGISTERS1 ();
314SAVE_REGISTERS2 ();
315asm ("pushl $4");
316CALL_HOOK ();
317
318/* Same thing for exception 5.  */
319extern void _catchException5 (void);
320asm (".text");
321asm (".globl _catchException5");
322asm ("_catchException5:");
323SAVE_REGISTERS1 ();
324SAVE_REGISTERS2 ();
325asm ("pushl $5");
326CALL_HOOK ();
327
328/* Same thing for exception 6.  */
329extern void _catchException6 (void);
330asm (".text");
331asm (".globl _catchException6");
332asm ("_catchException6:");
333SAVE_REGISTERS1 ();
334SAVE_REGISTERS2 ();
335asm ("pushl $6");
336CALL_HOOK ();
337
338/* Same thing for exception 7.  */
339extern void _catchException7 (void);
340asm (".text");
341asm (".globl _catchException7");
342asm ("_catchException7:");
343SAVE_REGISTERS1 ();
344SAVE_REGISTERS2 ();
345asm ("pushl $7");
346CALL_HOOK ();
347
348/* Same thing for exception 8.  */
349extern void _catchException8 (void);
350asm (".text");
351asm (".globl _catchException8");
352asm ("_catchException8:");
353SAVE_REGISTERS1 ();
354SAVE_ERRCODE ();
355SAVE_REGISTERS2 ();
356asm ("pushl $8");
357CALL_HOOK ();
358
359/* Same thing for exception 9.  */
360extern void _catchException9 (void);
361asm (".text");
362asm (".globl _catchException9");
363asm ("_catchException9:");
364SAVE_REGISTERS1 ();
365SAVE_REGISTERS2 ();
366asm ("pushl $9");
367CALL_HOOK ();
368
369/* Same thing for exception 10.  */
370extern void _catchException10 (void);
371asm (".text");
372asm (".globl _catchException10");
373asm ("_catchException10:");
374SAVE_REGISTERS1 ();
375SAVE_ERRCODE ();
376SAVE_REGISTERS2 ();
377asm ("pushl $10");
378CALL_HOOK ();
379
380/* Same thing for exception 12.  */
381extern void _catchException12 (void);
382asm (".text");
383asm (".globl _catchException12");
384asm ("_catchException12:");
385SAVE_REGISTERS1 ();
386SAVE_ERRCODE ();
387SAVE_REGISTERS2 ();
388asm ("pushl $12");
389CALL_HOOK ();
390
391/* Same thing for exception 16.  */
392extern void _catchException16 (void);
393asm (".text");
394asm (".globl _catchException16");
395asm ("_catchException16:");
396SAVE_REGISTERS1 ();
397SAVE_REGISTERS2 ();
398asm ("pushl $16");
399CALL_HOOK ();
400
401/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
402
403/* Same thing for exception 13.  */
404extern void _catchException13 (void);
405asm (".text");
406asm (".globl _catchException13");
407asm ("_catchException13:");
408CHECK_FAULT ();
409SAVE_REGISTERS1 ();
410SAVE_ERRCODE ();
411SAVE_REGISTERS2 ();
412asm ("pushl $13");
413CALL_HOOK ();
414
415/* Same thing for exception 11.  */
416extern void _catchException11 (void);
417asm (".text");
418asm (".globl _catchException11");
419asm ("_catchException11:");
420CHECK_FAULT ();
421SAVE_REGISTERS1 ();
422SAVE_ERRCODE ();
423SAVE_REGISTERS2 ();
424asm ("pushl $11");
425CALL_HOOK ();
426
427/* Same thing for exception 14.  */
428extern void _catchException14 (void);
429asm (".text");
430asm (".globl _catchException14");
431asm ("_catchException14:");
432CHECK_FAULT ();
433SAVE_REGISTERS1 ();
434SAVE_ERRCODE ();
435SAVE_REGISTERS2 ();
436asm ("pushl $14");
437CALL_HOOK ();
438
439/*
440 * remcomHandler is a front end for handle_exception.  It moves the
441 * stack pointer into an area reserved for debugger use.
442 */
443extern void remcomHandler (void);
444asm ("_remcomHandler:");
445asm ("           popl %eax");   /* pop off return address     */
446asm ("           popl %eax");   /* get the exception number   */
447asm ("          movl stackPtr, %esp");  /* move to remcom stack area  */
448asm ("          pushl %eax");   /* push exception onto stack  */
449asm ("          call  handle_exception");       /* this never returns */
450
451void
452_returnFromException (void)
453{
454  return_to_prog ();
455}
456
457int
458hex (char ch)
459{
460  if ((ch >= 'a') && (ch <= 'f'))
461    return (ch - 'a' + 10);
462  if ((ch >= '0') && (ch <= '9'))
463    return (ch - '0');
464  if ((ch >= 'A') && (ch <= 'F'))
465    return (ch - 'A' + 10);
466  return (-1);
467}
468
469/* scan for the sequence $<data>#<checksum>     */
470void
471getpacket (char *buffer)
472{
473  unsigned char checksum;
474  unsigned char xmitcsum;
475  int i;
476  int count;
477  char ch;
478
479  do
480    {
481      /* wait around for the start character, ignore all other characters */
482      while ((ch = (getDebugChar () & 0x7f)) != '$');
483      checksum = 0;
484      xmitcsum = -1;
485
486      count = 0;
487
488      /* now, read until a # or end of buffer is found */
489      while (count < BUFMAX)
490        {
491          ch = getDebugChar () & 0x7f;
492          if (ch == '#')
493            break;
494          checksum = checksum + ch;
495          buffer[count] = ch;
496          count = count + 1;
497        }
498      buffer[count] = 0;
499
500      if (ch == '#')
501        {
502          xmitcsum = hex (getDebugChar () & 0x7f) << 4;
503          xmitcsum += hex (getDebugChar () & 0x7f);
504          if ((remote_debug) && (checksum != xmitcsum))
505            {
506              fprintf (stderr, "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
507                       checksum, xmitcsum, buffer);
508            }
509
510          if (checksum != xmitcsum)
511            putDebugChar ('-'); /* failed checksum */
512          else
513            {
514              putDebugChar ('+');       /* successful transfer */
515              /* if a sequence char is present, reply the sequence ID */
516              if (buffer[2] == ':')
517                {
518                  putDebugChar (buffer[0]);
519                  putDebugChar (buffer[1]);
520                  /* remove sequence chars from buffer */
521                  count = strlen (buffer);
522                  for (i = 3; i <= count; i++)
523                    buffer[i - 3] = buffer[i];
524                }
525            }
526        }
527    }
528  while (checksum != xmitcsum);
529
530}
531
532/* send the packet in buffer.  */
533
534void
535putpacket (char *buffer)
536{
537  unsigned char checksum;
538  int count;
539  char ch;
540
541  /*  $<packet info>#<checksum>. */
542  do
543    {
544      putDebugChar ('$');
545      checksum = 0;
546      count = 0;
547
548      while ((ch = buffer[count]))
549        {
550          if (!putDebugChar (ch))
551            return;
552          checksum += ch;
553          count += 1;
554        }
555
556      putDebugChar ('#');
557      putDebugChar (hexchars[checksum >> 4]);
558      putDebugChar (hexchars[checksum % 16]);
559
560    }
561  while ((getDebugChar () & 0x7f) != '+');
562
563}
564
565char remcomInBuffer[BUFMAX];
566char remcomOutBuffer[BUFMAX];
567static short error;
568
569void
570debug_error (
571     char *format,
572     char *parm
573)
574{
575  if (remote_debug)
576    fprintf (stderr, format, parm);
577}
578
579/* Address of a routine to RTE to if we get a memory fault.  */
580static void (*volatile mem_fault_routine) (void) = NULL;
581
582/* Indicate to caller of mem2hex or hex2mem that there has been an
583   error.  */
584static volatile int mem_err = 0;
585
586void
587set_mem_err (void)
588{
589  mem_err = 1;
590}
591
592/* These are separate functions so that they are so short and sweet
593   that the compiler won't save any registers (if there is a fault
594   to mem_fault, they won't get restored, so there better not be any
595   saved).  */
596static int
597get_char (char *addr)
598{
599  return *addr;
600}
601
602void
603set_char (char *addr, int val)
604{
605  *addr = val;
606}
607
608/* convert the memory pointed to by mem into hex, placing result in buf */
609/* return a pointer to the last char put in buf (null) */
610/* If MAY_FAULT is non-zero, then we should set mem_err in response to
611   a fault; if zero treat a fault like any other fault in the stub.  */
612char *
613mem2hex (char *mem, char *buf, int count, int may_fault)
614{
615  int i;
616  unsigned char ch;
617
618  if (may_fault)
619    mem_fault_routine = set_mem_err;
620  for (i = 0; i < count; i++)
621    {
622      ch = get_char (mem++);
623      if (may_fault && mem_err)
624        return (buf);
625      *buf++ = hexchars[ch >> 4];
626      *buf++ = hexchars[ch % 16];
627    }
628  *buf = 0;
629  if (may_fault)
630    mem_fault_routine = NULL;
631  return (buf);
632}
633
634/* convert the hex array pointed to by buf into binary to be placed in mem */
635/* return a pointer to the character AFTER the last byte written */
636char *
637hex2mem (char *buf, char *mem, int count, int may_fault)
638{
639  int i;
640  unsigned char ch;
641
642  if (may_fault)
643    mem_fault_routine = set_mem_err;
644  for (i = 0; i < count; i++)
645    {
646      ch = hex (*buf++) << 4;
647      ch = ch + hex (*buf++);
648      set_char (mem++, ch);
649      if (may_fault && mem_err)
650        return (mem);
651    }
652  if (may_fault)
653    mem_fault_routine = NULL;
654  return (mem);
655}
656
657/* this function takes the 386 exception vector and attempts to
658   translate this number into a unix compatible signal value */
659int
660computeSignal (int exceptionVector)
661{
662  int sigval;
663  switch (exceptionVector)
664    {
665    case 0:
666      sigval = 8;
667      break;                    /* divide by zero */
668    case 1:
669      sigval = 5;
670      break;                    /* debug exception */
671    case 3:
672      sigval = 5;
673      break;                    /* breakpoint */
674    case 4:
675      sigval = 16;
676      break;                    /* into instruction (overflow) */
677    case 5:
678      sigval = 16;
679      break;                    /* bound instruction */
680    case 6:
681      sigval = 4;
682      break;                    /* Invalid opcode */
683    case 7:
684      sigval = 8;
685      break;                    /* coprocessor not available */
686    case 8:
687      sigval = 7;
688      break;                    /* double fault */
689    case 9:
690      sigval = 11;
691      break;                    /* coprocessor segment overrun */
692    case 10:
693      sigval = 11;
694      break;                    /* Invalid TSS */
695    case 11:
696      sigval = 11;
697      break;                    /* Segment not present */
698    case 12:
699      sigval = 11;
700      break;                    /* stack exception */
701    case 13:
702      sigval = 11;
703      break;                    /* general protection */
704    case 14:
705      sigval = 11;
706      break;                    /* page fault */
707    case 16:
708      sigval = 7;
709      break;                    /* coprocessor error */
710    default:
711      sigval = 7;               /* "software generated" */
712    }
713  return (sigval);
714}
715
716/**********************************************/
717/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
718/* RETURN NUMBER OF CHARS PROCESSED           */
719/**********************************************/
720int
721hexToInt (char **ptr, int *intValue)
722{
723  int numChars = 0;
724  int hexValue;
725
726  *intValue = 0;
727
728  while (**ptr)
729    {
730      hexValue = hex (**ptr);
731      if (hexValue >= 0)
732        {
733          *intValue = (*intValue << 4) | hexValue;
734          numChars++;
735        }
736      else
737        break;
738
739      (*ptr)++;
740    }
741
742  return (numChars);
743}
744
745/*
746 * This function does all command procesing for interfacing to gdb.
747 */
748void
749handle_exception (int exceptionVector)
750{
751  int sigval;
752  int addr, length, reg;
753  char *ptr;
754  int newPC;
755
756  gdb_i386vector = exceptionVector;
757
758  if (remote_debug)
759    printf ("vector=%d, sr=0x%x, pc=0x%x\n",
760            exceptionVector,
761            registers[PS],
762            registers[PC]);
763
764  /* Reply to host that an exception has occurred.  Always return the
765     PC, SP, and FP, since gdb always wants them.  */
766  ptr = remcomOutBuffer;
767  *ptr++ = 'T';
768  sigval = computeSignal (exceptionVector);
769  *ptr++ = hexchars[sigval >> 4];
770  *ptr++ = hexchars[sigval % 16];
771
772  *ptr++ = hexchars[ESP];
773  *ptr++ = ':';
774  mem2hex ((char *) &registers[ESP], ptr, REGBYTES, 0);
775  ptr += REGBYTES * 2;
776  *ptr++ = ';';
777
778  *ptr++ = hexchars[EBP];
779  *ptr++ = ':';
780  mem2hex ((char *) &registers[EBP], ptr, REGBYTES, 0);
781  ptr += REGBYTES * 2;
782  *ptr++ = ';';
783
784  *ptr++ = hexchars[PC];
785  *ptr++ = ':';
786  mem2hex ((char *) &registers[PC], ptr, REGBYTES, 0);
787  ptr += REGBYTES * 2;
788  *ptr++ = ';';
789
790  *ptr = '\0';
791
792  putpacket (remcomOutBuffer);
793
794  while (1 == 1)
795    {
796      error = 0;
797      remcomOutBuffer[0] = 0;
798      getpacket (remcomInBuffer);
799      switch (remcomInBuffer[0])
800        {
801        case '?':
802          remcomOutBuffer[0] = 'S';
803          remcomOutBuffer[1] = hexchars[sigval >> 4];
804          remcomOutBuffer[2] = hexchars[sigval % 16];
805          remcomOutBuffer[3] = 0;
806          break;
807        case 'd':
808          remote_debug = !(remote_debug);       /* toggle debug flag */
809          break;
810        case 'g':               /* return the value of the CPU registers */
811          mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
812          break;
813        case 'G':               /* set the value of the CPU registers - return OK */
814          hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES, 0);
815          strcpy (remcomOutBuffer, "OK");
816          break;
817
818        case 'P':               /* Set specific register */
819          ptr = &remcomInBuffer[1];
820          if (hexToInt (&ptr, &reg)
821              && *ptr++ == '=')
822            {
823              hex2mem (ptr, (char *) &registers[reg], REGBYTES, 0);
824              strcpy (remcomOutBuffer, "OK");
825            }
826          else
827            {
828              strcpy (remcomOutBuffer, "E01");
829              debug_error ("malformed register set command; %s",
830                           remcomInBuffer);
831            }
832          break;
833
834          /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
835        case 'm':
836          /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
837          ptr = &remcomInBuffer[1];
838          if (hexToInt (&ptr, &addr))
839            if (*(ptr++) == ',')
840              if (hexToInt (&ptr, &length))
841                {
842                  ptr = 0;
843                  mem_err = 0;
844                  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
845                  if (mem_err)
846                    {
847                      strcpy (remcomOutBuffer, "E03");
848                      debug_error ("memory fault", 0);
849                    }
850                }
851
852          if (ptr)
853            {
854              strcpy (remcomOutBuffer, "E01");
855              debug_error ("malformed read memory command: %s", remcomInBuffer);
856            }
857          break;
858
859          /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
860        case 'M':
861          /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
862          ptr = &remcomInBuffer[1];
863          if (hexToInt (&ptr, &addr))
864            if (*(ptr++) == ',')
865              if (hexToInt (&ptr, &length))
866                if (*(ptr++) == ':')
867                  {
868                    mem_err = 0;
869                    hex2mem (ptr, (char *) addr, length, 1);
870
871                    if (mem_err)
872                      {
873                        strcpy (remcomOutBuffer, "E03");
874                        debug_error ("memory fault", 0);
875                      }
876                    else
877                      {
878                        strcpy (remcomOutBuffer, "OK");
879                      }
880
881                    ptr = 0;
882                  }
883          if (ptr)
884            {
885              strcpy (remcomOutBuffer, "E02");
886              debug_error ("malformed write memory command: %s", remcomInBuffer);
887            }
888          break;
889
890          /* cAA..AA    Continue at address AA..AA(optional) */
891          /* sAA..AA   Step one instruction from AA..AA(optional) */
892        case 'c':
893        case 's':
894          /* try to read optional parameter, pc unchanged if no parm */
895          ptr = &remcomInBuffer[1];
896          if (hexToInt (&ptr, &addr))
897            registers[PC] = addr;
898
899          newPC = registers[PC];
900
901          /* clear the trace bit */
902          registers[PS] &= 0xfffffeff;
903
904          /* set the trace bit if we're stepping */
905          if (remcomInBuffer[0] == 's')
906            registers[PS] |= 0x100;
907
908          _returnFromException ();      /* this is a jump */
909
910          break;
911
912          /* Detach.  */
913        case 'D':
914          putpacket (remcomOutBuffer);
915          registers[PS] &= 0xfffffeff;
916          _returnFromException ();      /* this is a jump */
917
918          break;
919
920          /* kill the program */
921        case 'k':               /* do nothing */
922          break;
923        }                       /* switch */
924
925      /* reply to the request */
926      putpacket (remcomOutBuffer);
927    }
928}
929
930/* this function is used to set up exception handlers for tracing and
931   breakpoints */
932void
933set_debug_traps (void)
934{
935  stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
936
937  exceptionHandler (0, _catchException0);
938  exceptionHandler (1, _catchException1);
939  exceptionHandler (3, _catchException3);
940  exceptionHandler (4, _catchException4);
941  exceptionHandler (5, _catchException5);
942  exceptionHandler (6, _catchException6);
943  exceptionHandler (7, _catchException7);
944  exceptionHandler (8, _catchException8);
945  exceptionHandler (9, _catchException9);
946  exceptionHandler (10, _catchException10);
947  exceptionHandler (11, _catchException11);
948  exceptionHandler (12, _catchException12);
949  exceptionHandler (13, _catchException13);
950  exceptionHandler (14, _catchException14);
951  exceptionHandler (16, _catchException16);
952
953  /* In case GDB is started before us, ack any packets (presumably
954     "$?#xx") sitting there.  */
955  putDebugChar ('+');
956
957  initialized = true;
958
959}
960
961/* This function will generate a breakpoint exception.  It is used at the
962   beginning of a program to sync up with a debugger and can be used
963   otherwise as a quick means to stop program execution and "break" into
964   the debugger. */
965
966void
967breakpoint (void)
968{
969  if (initialized)
970    {
971      BREAKPOINT ();
972    }
973  waitabit ();
974}
975
976int waitlimit = 1000000;
977
978void
979waitabit (void)
980{
981  int i;
982  for (i = 0; i < waitlimit; i++);
983}
Note: See TracBrowser for help on using the repository browser.