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

4.115
Last change on this file since 1ecb21d8 was 1ecb21d8, checked in by Joel Sherrill <joel.sherrill@…>, on 10/14/14 at 00:08:14

libbsp/i386/shared: Fix warnings

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