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

4.104.114.95
Last change on this file since a902c8d4 was a902c8d4, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/06/08 at 17:01:15

Misc. "bool" changes.

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