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

4.104.114.84.95
Last change on this file since 3299388d was dabe72e, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 31, 2002 at 9:51:53 PM

2002-10-31 Joel Sherrill <joel@…>

  • comm/i386-stub.c: Fixed places where debug_error() was not called with enough arguments.
  • Property mode set to 100644
File size: 25.3 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 char initialized;        /* boolean flag. != 0 means we've been initialized */
119
120int remote_debug;
121/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
122
123void waitabit ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 ();
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 */
442asm ("_remcomHandler:");
443asm ("           popl %eax");   /* pop off return address     */
444asm ("           popl %eax");   /* get the exception number   */
445asm ("          movl stackPtr, %esp");  /* move to remcom stack area  */
446asm ("          pushl %eax");   /* push exception onto stack  */
447asm ("          call  handle_exception");       /* this never returns */
448
449void 
450_returnFromException (void)
451{
452  return_to_prog ();
453}
454
455int 
456hex (char ch)
457{
458  if ((ch >= 'a') && (ch <= 'f'))
459    return (ch - 'a' + 10);
460  if ((ch >= '0') && (ch <= '9'))
461    return (ch - '0');
462  if ((ch >= 'A') && (ch <= 'F'))
463    return (ch - 'A' + 10);
464  return (-1);
465}
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
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).  */
596int
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  extern void remcomHandler ();
936
937  stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
938
939  exceptionHandler (0, _catchException0);
940  exceptionHandler (1, _catchException1);
941  exceptionHandler (3, _catchException3);
942  exceptionHandler (4, _catchException4);
943  exceptionHandler (5, _catchException5);
944  exceptionHandler (6, _catchException6);
945  exceptionHandler (7, _catchException7);
946  exceptionHandler (8, _catchException8);
947  exceptionHandler (9, _catchException9);
948  exceptionHandler (10, _catchException10);
949  exceptionHandler (11, _catchException11);
950  exceptionHandler (12, _catchException12);
951  exceptionHandler (13, _catchException13);
952  exceptionHandler (14, _catchException14);
953  exceptionHandler (16, _catchException16);
954
955  /* In case GDB is started before us, ack any packets (presumably
956     "$?#xx") sitting there.  */
957  putDebugChar ('+');
958
959  initialized = 1;
960
961}
962
963/* This function will generate a breakpoint exception.  It is used at the
964   beginning of a program to sync up with a debugger and can be used
965   otherwise as a quick means to stop program execution and "break" into
966   the debugger. */
967
968void 
969breakpoint (void)
970{
971  if (initialized)
972    {
973      BREAKPOINT ();
974    }
975  waitabit ();
976}
977
978int waitlimit = 1000000;
979
980void
981waitabit (void)
982{
983  int i;
984  for (i = 0; i < waitlimit; i++);
985}
986
987
988
989
990
Note: See TracBrowser for help on using the repository browser.