source: rtems/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c @ 37bb9bf

4.104.114.84.95
Last change on this file since 37bb9bf was db6cc07, checked in by Joel Sherrill <joel.sherrill@…>, on 03/08/02 at 17:36:58

2001-03-08 Joel Sherrill <joel@…>

  • mips-stub.c: Removed warnings.
  • Property mode set to 100644
File size: 43.4 KB
Line 
1#define  GDB_STUB_ENABLE_THREAD_SUPPORT 1
2/*******************************************************************************
3
4                     THIS SOFTWARE IS NOT COPYRIGHTED
5
6    The following software is offered for use in the public domain.
7    There is no warranty with regard to this software or its performance
8    and the user must accept the software "AS IS" with all faults.
9
10    THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH
11    REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13
14    $Id$
15
16********************************************************************************
17*
18*   r46kstub.c -- target debugging stub for the IDT R4600 Orion processor
19*
20*   This module is based on the stub for the Hitachi SH processor written by
21*   Ben Lee and Steve Chamberlain and supplied with gdb 4.16.  The latter
22*   in turn "is originally based on an m68k software stub written by Glenn
23*   Engel at HP, but has changed quite a bit."  The changes for the R4600
24*   were written by C. M. Heard at VVNET.  They were based in part on the
25*   Algorithmics R4000 version of Phil Bunce's PMON program.
26*
27*  Remote communication protocol:
28*
29*  A debug packet whose contents are <data>
30*  is encapsulated for transmission in the form:
31*
32*       $ <data> # CSUM1 CSUM2
33*
34*       <data> must be ASCII alphanumeric and cannot include characters
35*       '$' or '#'.  If <data> starts with two characters followed by
36*       ':', then the existing stubs interpret this as a sequence number.
37*
38*       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
39*       checksum of <data>, the most significant nibble is sent first.
40*       the hex digits 0-9,a-f are used.
41*
42*  Receiver responds with:
43*
44*       +    if CSUM is correct
45*       -    if CSUM is incorrect
46*
47*  <data> is as follows.  All values are encoded in ascii hex digits.
48*
49*       Request         Packet
50*
51*       read registers  g
52*       reply           XX....X         Each byte of register data
53*                                       is described by two hex digits.
54*                                       Registers are in the internal order
55*                                       for GDB, and the bytes in a register
56*                                       are in the same order the machine uses.
57*                       or ENN          for an error.
58*
59*       write regs      GXX..XX         Each byte of register data
60*                                       is described by two hex digits.
61*       reply           OK              for success
62*                       ENN             for an error
63*
64*       write reg       Pn...=r...      Write register n... with value r....
65*       reply           OK              for success
66*                       ENN             for an error
67*
68*       read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
69*       reply           XX..XX          XX..XX is mem contents
70*                                       Can be fewer bytes than requested
71*                                       if able to read only part of the data.
72*                       or ENN          NN is errno
73*
74*       write mem       MAA..AA,LLLL:XX..XX
75*                                       AA..AA is address,
76*                                       LLLL is number of bytes,
77*                                       XX..XX is data
78*       reply           OK              for success
79*                       ENN             for an error (this includes the case
80*                                       where only part of the data was
81*                                       written).
82*
83*       cont            cAA..AA         AA..AA is address to resume
84*                                       If AA..AA is omitted,
85*                                       resume at same address.
86*
87*       step            sAA..AA         AA..AA is address to resume
88*                                       If AA..AA is omitted,
89*                                       resume at same address.
90*
91*       There is no immediate reply to step or cont.
92*       The reply comes when the machine stops.
93*       It is           SAA             AA is the "signal number"
94*
95*       last signal     ?               Reply with the reason for stopping.
96*                                       This is the same reply as is generated
97*                                       for step or cont: SAA where AA is the
98*                                       signal number.
99*
100*       detach          D               Host is detaching.  Reply OK and
101*                                       end remote debugging session.
102*
103*       reserved        <other>         On other requests, the stub should
104*                                       ignore the request and send an empty
105*                                       response ($#<checksum>).  This way
106*                                       we can extend the protocol and GDB
107*                                       can tell whether the stub it is
108*                                       talking to uses the old or the new.
109*
110*       Responses can be run-length encoded to save space.  A '*' means that
111*       the next character is an ASCII encoding giving a repeat count which
112*       stands for that many repetitions of the character preceding the '*'.
113*       The encoding is n+29, yielding a printable character when n >=3
114*       (which is where rle starts to win).  Don't use n > 99 since gdb
115*       masks each character is receives with 0x7f in order to strip off
116*       the parity bit.
117*
118*       As an example, "0* " means the same thing as "0000".
119*
120*******************************************************************************/
121
122
123#include <string.h>
124#include <signal.h>
125#include "mips_opcode.h"
126/* #include "memlimits.h" */
127#include <rtems.h>
128#include "gdb_if.h"
129
130extern int printk(const char *fmt, ...);
131
132/* Change it to something meaningful when debugging */
133#undef ASSERT
134#define ASSERT(x) if(!(x)) printk("ASSERT: stub: %d\n", __LINE__)
135
136/***************/
137/* Exception Codes */
138#define EXC_INT         0               /* External interrupt */
139#define EXC_MOD         1               /* TLB modification exception */
140#define EXC_TLBL        2               /* TLB miss (Load or Ifetch) */
141#define EXC_TLBS        3               /* TLB miss (Store) */
142#define EXC_ADEL        4               /* Address error (Load or Ifetch) */
143#define EXC_ADES        5               /* Address error (Store) */
144#define EXC_IBE         6               /* Bus error (Ifetch) */
145#define EXC_DBE         7               /* Bus error (data load or store) */
146#define EXC_SYS         8               /* System call */
147#define EXC_BP          9               /* Break point */
148#define EXC_RI          10              /* Reserved instruction */
149#define EXC_CPU         11              /* Coprocessor unusable */
150#define EXC_OVF         12              /* Arithmetic overflow */
151#define EXC_TRAP        13              /* Trap exception */
152#define EXC_FPE         15              /* Floating Point Exception */
153
154/* FPU Control/Status register fields */
155#define CSR_FS          0x01000000      /* Set to flush denormals to zero */
156#define CSR_C           0x00800000      /* Condition bit (set by FP compare) */
157
158#define CSR_CMASK       (0x3f<<12)
159#define CSR_CE          0x00020000
160#define CSR_CV          0x00010000
161#define CSR_CZ          0x00008000
162#define CSR_CO          0x00004000
163#define CSR_CU          0x00002000
164#define CSR_CI          0x00001000
165
166#define CSR_EMASK       (0x1f<<7)
167#define CSR_EV          0x00000800
168#define CSR_EZ          0x00000400
169#define CSR_EO          0x00000200
170#define CSR_EU          0x00000100
171#define CSR_EI          0x00000080
172
173#define CSR_FMASK       (0x1f<<2)
174#define CSR_FV          0x00000040
175#define CSR_FZ          0x00000020
176#define CSR_FO          0x00000010
177#define CSR_FU          0x00000008
178#define CSR_FI          0x00000004
179
180#define CSR_RMODE_MASK  (0x3<<0)
181#define CSR_RM          0x00000003
182#define CSR_RP          0x00000002
183#define CSR_RZ          0x00000001
184#define CSR_RN          0x00000000
185
186/***************/
187
188/*
189 * Saved register information.  Must be prepared by the exception
190 * preprocessor before handle_exception is invoked.
191 */
192#if (__mips == 3)
193typedef long long mips_register_t;
194#define R_SZ 8
195#elif (__mips == 1)
196typedef unsigned int mips_register_t;
197#define R_SZ 4
198#else
199#error "unknown MIPS ISA"
200#endif
201static mips_register_t *registers;
202
203#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
204static char do_threads;      /* != 0 means we are supporting threads */
205#endif
206
207/*
208 * The following external functions provide character input and output.
209 */
210extern char getDebugChar (void);
211extern void putDebugChar (char);
212
213
214
215/*
216 * The following definitions are used for the gdb stub memory map
217 */
218struct memseg
219{
220      unsigned begin, end, opts;
221};
222
223static int is_readable(unsigned,unsigned);
224static int is_writeable(unsigned,unsigned);
225static int is_steppable(unsigned);
226
227
228
229
230
231
232/*
233 * BUFMAX defines the maximum number of characters in the inbound & outbound
234 * packet buffers.  At least 4+(sizeof registers)*2 bytes will be needed for
235 * register packets.  Memory dump packets can profitably use even more.
236 */
237#define BUFMAX 1500
238
239static char inBuffer[BUFMAX];
240static char outBuffer[BUFMAX];
241
242/* Structure to keep info on a z-breaks */
243#define BREAKNUM 32
244
245struct z0break
246{
247  /* List support */
248  struct z0break *next;
249  struct z0break *prev;
250
251  /* Location, preserved data */
252  unsigned char *address;
253  unsigned instr;
254};
255
256static struct z0break z0break_arr[BREAKNUM];
257static struct z0break *z0break_avail = NULL;
258static struct z0break *z0break_list  = NULL;
259
260
261/*
262 * Convert an int to hex.
263 */
264const char gdb_hexchars[] = "0123456789abcdef";
265
266#define highhex(x) gdb_hexchars [(x >> 4) & 0xf]
267#define lowhex(x) gdb_hexchars [x & 0xf]
268
269
270/*
271 * Convert length bytes of data starting at addr into hex, placing the
272 * result in buf.  Return a pointer to the last (null) char in buf.
273 */
274static char *
275mem2hex (void *_addr, int length, char *buf)
276{
277  unsigned int addr = (unsigned int) _addr;
278
279  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
280    {
281      long long *source = (long long *) (addr);
282      long long *limit  = (long long *) (addr + length);
283
284      while (source < limit)
285        {
286          int i;
287          long long k = *source++;
288
289          for (i = 15; i >= 0; i--)
290            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
291        }
292    }
293  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
294    {
295      int *source = (int *) (addr);
296      int *limit  = (int *) (addr + length);
297
298      while (source < limit)
299        {
300          int i;
301          int k = *source++;
302
303          for (i = 7; i >= 0; i--)
304            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
305        }
306    }
307  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
308    {
309      short *source = (short *) (addr);
310      short *limit  = (short *) (addr + length);
311
312      while (source < limit)
313        {
314          int i;
315          short k = *source++;
316
317          for (i = 3; i >= 0; i--)
318            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
319        }
320    }
321  else                                                   /* byte aligned */
322    {
323      char *source = (char *) (addr);
324      char *limit  = (char *) (addr + length);
325
326      while (source < limit)
327        {
328          int i;
329          char k = *source++;
330
331          for (i = 1; i >= 0; i--)
332            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
333        }
334    }
335
336  *buf = '\0';
337  return (buf);
338}
339
340
341/*
342 * Convert a hex character to an int.
343 */
344static int
345hex (char ch)
346{
347  if ((ch >= 'a') && (ch <= 'f'))
348    return (ch - 'a' + 10);
349  if ((ch >= '0') && (ch <= '9'))
350    return (ch - '0');
351  if ((ch >= 'A') && (ch <= 'F'))
352    return (ch - 'A' + 10);
353  return (-1);
354}
355
356
357/*
358 * Convert a string from hex to int until a non-hex digit
359 * is found.  Return the number of characters processed.
360 */
361static int
362hexToInt (char **ptr, int *intValue)
363{
364  int numChars = 0;
365  int hexValue;
366
367  *intValue = 0;
368
369  while (**ptr)
370    {
371      hexValue = hex (**ptr);
372      if (hexValue >= 0)
373        {
374          *intValue = (*intValue << 4) | hexValue;
375          numChars++;
376        }
377      else
378        break;
379
380      (*ptr)++;
381    }
382
383  return (numChars);
384}
385
386
387/*
388 * Convert a string from hex to long long until a non-hex
389 * digit is found.  Return the number of characters processed.
390 */
391static int
392hexToLongLong (char **ptr, long long *intValue)
393{
394  int numChars = 0;
395  int hexValue;
396
397  *intValue = 0;
398
399  while (**ptr)
400    {
401      hexValue = hex (**ptr);
402      if (hexValue >= 0)
403        {
404          *intValue = (*intValue << 4) | hexValue;
405          numChars++;
406        }
407      else
408        break;
409
410      (*ptr)++;
411    }
412
413  return (numChars);
414}
415
416
417/*
418 * Convert the hex array buf into binary, placing the result at the
419 * specified address.  If the conversion fails at any point (i.e.,
420 * if fewer bytes are written than indicated by the size parameter)
421 * then return 0;  otherwise return 1.
422 */
423static int
424hex2mem (char *buf, void *_addr, int length)
425{
426  unsigned int addr = (unsigned int) _addr;
427  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
428    {
429      long long *target = (long long *) (addr);
430      long long *limit  = (long long *) (addr + length);
431
432      while (target < limit)
433        {
434          int i, j;
435          long long k = 0;
436
437          for (i = 0; i < 16; i++)
438            if ((j = hex(*buf++)) < 0)
439              return 0;
440            else
441              k = (k << 4) + j;
442          *target++ = k;
443        }
444    }
445  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
446    {
447      int *target = (int *) (addr);
448      int *limit  = (int *) (addr + length);
449
450      while (target < limit)
451        {
452          int i, j;
453          int k = 0;
454
455          for (i = 0; i < 8; i++)
456            if ((j = hex(*buf++)) < 0)
457              return 0;
458            else
459              k = (k << 4) + j;
460          *target++ = k;
461        }
462    }
463  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
464    {
465      short *target = (short *) (addr);
466      short *limit  = (short *) (addr + length);
467
468      while (target < limit)
469        {
470          int i, j;
471          short k = 0;
472
473          for (i = 0; i < 4; i++)
474            if ((j = hex(*buf++)) < 0)
475              return 0;
476            else
477              k = (k << 4) + j;
478          *target++ = k;
479        }
480    }
481  else                                                   /* byte aligned */
482    {
483      char *target = (char *) (addr);
484      char *limit  = (char *) (addr + length);
485
486      while (target < limit)
487        {
488          int i, j;
489          char k = 0;
490
491          for (i = 0; i < 2; i++)
492            if ((j = hex(*buf++)) < 0)
493              return 0;
494            else
495              k = (k << 4) + j;
496          *target++ = k;
497        }
498    }
499
500  return 1;
501}
502
503
504/* Convert the binary stream in BUF to memory.
505
506   Gdb will escape $, #, and the escape char (0x7d).
507   COUNT is the total number of bytes to write into
508   memory. */
509static unsigned char *
510bin2mem (
511  unsigned char *buf,
512  unsigned char *mem,
513  int   count
514)
515{
516  int i;
517
518  for (i = 0; i < count; i++) {
519      /* Check for any escaped characters. Be paranoid and
520         only unescape chars that should be escaped. */
521      if (*buf == 0x7d) {
522          switch (*(buf+1)) {
523            case 0x3:  /* # */
524            case 0x4:  /* $ */
525            case 0x5d: /* escape char */
526              buf++;
527              *buf |= 0x20;
528              break;
529            default:
530              /* nothing */
531              break;
532            }
533        }
534
535      *mem++ = *buf++;
536    }
537
538  return mem;
539}
540
541
542
543/*
544 * Scan the input stream for a sequence for the form $<data>#<checksum>.
545 */
546static void
547getpacket (char *buffer)
548{
549  unsigned char checksum;
550  unsigned char xmitcsum;
551  int i;
552  int count;
553  char ch;
554  do
555    {
556      /* wait around for the start character, ignore all other characters */
557      while ((ch = getDebugChar ()) != '$');
558      checksum = 0;
559      xmitcsum = -1;
560
561      count = 0;
562
563      /* now, read until a # or end of buffer is found */
564      while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') )
565          checksum += (buffer[count++] = ch);
566
567      /* make sure that the buffer is null-terminated */
568      buffer[count] = '\0';
569
570      if (ch == '#')
571        {
572          xmitcsum = hex (getDebugChar ()) << 4;
573          xmitcsum += hex (getDebugChar ());
574          if (checksum != xmitcsum)
575            putDebugChar ('-'); /* failed checksum */
576          else
577            {
578              putDebugChar ('+');       /* successful transfer */
579              /* if a sequence char is present, reply the sequence ID */
580              if (buffer[2] == ':')
581                {
582                  putDebugChar (buffer[0]);
583                  putDebugChar (buffer[1]);
584                  /* remove sequence chars from buffer */
585                  for (i = 3; i <= count; i++)
586                    buffer[i - 3] = buffer[i];
587                }
588            }
589        }
590    }
591  while (checksum != xmitcsum);
592}
593
594
595/*
596 * Send the packet in buffer and wait for a positive acknowledgement.
597 */
598static void
599putpacket (char *buffer)
600{
601  int checksum;
602
603  /* $<packet info>#<checksum> */
604  do
605    {
606      char *src = buffer;
607      putDebugChar ('$');
608      checksum = 0;
609
610      while (*src != '\0')
611        {
612          int runlen = 0;
613
614          /* Do run length encoding */
615          while ((src[runlen] == src[0]) && (runlen < 99))
616            runlen++;
617          if (runlen > 3)
618            {
619              int encode;
620              /* Got a useful amount */
621              putDebugChar (*src);
622              checksum += *src;
623              putDebugChar ('*');
624              checksum += '*';
625              checksum += (encode = (runlen - 4) + ' ');
626              putDebugChar (encode);
627              src += runlen;
628            }
629          else
630            {
631              putDebugChar (*src);
632              checksum += *src;
633              src++;
634             }
635        }
636
637      putDebugChar ('#');
638      putDebugChar (highhex (checksum));
639      putDebugChar (lowhex (checksum));
640    }
641  while  (getDebugChar () != '+');
642}
643
644
645
646
647
648
649
650/*
651 * Saved instruction data for single step support
652 */
653static struct
654  {
655    unsigned *targetAddr;
656    unsigned savedInstr;
657  }
658instrBuffer;
659
660
661/*
662 * If a step breakpoint was planted restore the saved instruction.
663 */
664static void
665undoSStep (void)
666{
667  if (instrBuffer.targetAddr != NULL)
668    {
669      *instrBuffer.targetAddr = instrBuffer.savedInstr;
670      instrBuffer.targetAddr = NULL;
671    }
672  instrBuffer.savedInstr = NOP_INSTR;
673}
674
675
676/*
677 * If a single step is requested put a temporary breakpoint at the instruction
678 * which logically follows the next one to be executed.  If the next instruction
679 * is a branch instruction then skip the instruction in the delay slot.  NOTE:
680 * ERET instructions are NOT handled, as it is impossible to single-step through
681 * the exit code in an exception handler.  In addition, no attempt is made to
682 * do anything about BC0T and BC0F, since a condition bit for coprocessor 0
683 * is not defined on the R4600.  Finally, BC2T and BC2F are ignored since there
684 * is no coprocessor 2 on a 4600.
685 */
686static void
687doSStep (void)
688{
689   InstFmt inst;
690
691   instrBuffer.targetAddr = (unsigned *)(registers[PC]+4);    /* set default */
692
693   inst.word = *(unsigned *)registers[PC];     /* read the next instruction  */
694
695   switch (inst.RType.op) {                    /* override default if branch */
696      case OP_SPECIAL:
697         switch (inst.RType.func) {
698            case OP_JR:
699            case OP_JALR:
700               instrBuffer.targetAddr =
701                  (unsigned *)registers[inst.RType.rs];
702               break;
703         };
704         break;
705
706      case OP_REGIMM:
707         switch (inst.IType.rt) {
708            case OP_BLTZ:
709            case OP_BLTZL:
710            case OP_BLTZAL:
711            case OP_BLTZALL:
712               if (registers[inst.IType.rs] < 0 )
713                  instrBuffer.targetAddr =
714                     (unsigned *)(((signed short)inst.IType.imm<<2)
715                                  + (registers[PC]+4));
716               else
717                  instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
718               break;
719            case OP_BGEZ:
720            case OP_BGEZL:
721            case OP_BGEZAL:
722            case OP_BGEZALL:
723               if (registers[inst.IType.rs] >= 0 )
724                  instrBuffer.targetAddr =
725                     (unsigned *)(((signed short)inst.IType.imm<<2)
726                                  + (registers[PC]+4));
727               else
728                  instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
729               break;
730         };
731         break;
732
733      case OP_J:
734      case OP_JAL:
735         instrBuffer.targetAddr =
736            (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000));
737         break;
738
739      case OP_BEQ:
740      case OP_BEQL:
741         if (registers[inst.IType.rs] == registers[inst.IType.rt])
742            instrBuffer.targetAddr =
743               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
744         else
745            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
746         break;
747      case OP_BNE:
748      case OP_BNEL:
749         if (registers[inst.IType.rs] != registers[inst.IType.rt])
750            instrBuffer.targetAddr =
751               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
752         else
753            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
754         break;
755      case OP_BLEZ:
756      case OP_BLEZL:
757         if (registers[inst.IType.rs] <= 0)
758            instrBuffer.targetAddr =
759               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
760         else
761            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
762         break;
763      case OP_BGTZ:
764      case OP_BGTZL:
765         if (registers[inst.IType.rs] > 0)
766            instrBuffer.targetAddr =
767               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
768         else
769            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
770         break;
771
772      case OP_COP1:
773         if (inst.RType.rs == OP_BC)
774            switch (inst.RType.rt) {
775               case COPz_BCF:
776               case COPz_BCFL:
777                  if (registers[FCSR] & CSR_C)
778                     instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
779                  else
780                     instrBuffer.targetAddr =
781                        (unsigned *)(((signed short)inst.IType.imm<<2)
782                                     + (registers[PC]+4));
783                  break;
784               case COPz_BCT:
785               case COPz_BCTL:
786                  if (registers[FCSR] & CSR_C)
787                     instrBuffer.targetAddr =
788                        (unsigned *)(((signed short)inst.IType.imm<<2)
789                                     + (registers[PC]+4));
790                  else
791                     instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
792                  break;
793            };
794         break;
795   }
796
797
798   if( is_steppable((unsigned)instrBuffer.targetAddr) && *(instrBuffer.targetAddr) != BREAK_INSTR )
799   {
800      instrBuffer.savedInstr = *instrBuffer.targetAddr;
801      *instrBuffer.targetAddr = BREAK_INSTR;
802   }
803   else
804   {
805      instrBuffer.targetAddr = NULL;
806      instrBuffer.savedInstr = NOP_INSTR;
807   }
808   return;
809}
810
811
812
813
814
815
816/*
817 * Translate the R4600 exception code into a Unix-compatible signal.
818 */
819static int
820computeSignal (void)
821{
822  int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
823
824  switch (exceptionCode)
825    {
826    case EXC_INT:
827      /* External interrupt */
828      return SIGINT;
829
830    case EXC_RI:
831      /* Reserved instruction */
832    case EXC_CPU:
833      /* Coprocessor unusable */
834      return SIGILL;
835
836    case EXC_BP:
837      /* Break point */
838      return SIGTRAP;
839
840    case EXC_OVF:
841      /* Arithmetic overflow */
842    case EXC_TRAP:
843      /* Trap exception */
844    case EXC_FPE:
845      /* Floating Point Exception */
846      return SIGFPE;
847
848    case EXC_IBE:
849      /* Bus error (Ifetch) */
850    case EXC_DBE:
851      /* Bus error (data load or store) */
852      return SIGBUS;
853
854    case EXC_MOD:
855      /* TLB modification exception */
856    case EXC_TLBL:
857      /* TLB miss (Load or Ifetch) */
858    case EXC_TLBS:
859      /* TLB miss (Store) */
860    case EXC_ADEL:
861      /* Address error (Load or Ifetch) */
862    case EXC_ADES:
863      /* Address error (Store) */
864      return SIGSEGV;
865
866    case EXC_SYS:
867      /* System call */
868      return SIGSYS;
869
870    default:
871      return SIGTERM;
872    }
873}
874
875/*
876 *  This support function prepares and sends the message containing the
877 *  basic information about this exception.
878 */
879
880void gdb_stub_report_exception_info(
881  rtems_vector_number vector,
882  CPU_Interrupt_frame *frame,
883  int                  thread
884)
885{
886   char *optr;
887   int sigval;
888
889   optr = outBuffer;
890   *optr++ = 'T';
891   sigval = computeSignal ();
892   *optr++ = highhex (sigval);
893   *optr++ = lowhex (sigval);
894
895   *optr++ = highhex(SP); /*gdb_hexchars[SP]; */
896   *optr++ = lowhex(SP);
897   *optr++ = ':';
898   optr    = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ );
899   *optr++ = ';';
900 
901   *optr++ = highhex(PC); /*gdb_hexchars[PC]; */
902   *optr++ = lowhex(PC);
903   *optr++ = ':';
904   optr    = mem2hstr(optr, (unsigned char *)&frame->epc, R_SZ );
905   *optr++ = ';';
906
907#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
908   if (do_threads)
909   {
910      *optr++ = 't';
911      *optr++ = 'h';
912      *optr++ = 'r';
913      *optr++ = 'e';
914      *optr++ = 'a';
915      *optr++ = 'd';
916      *optr++ = ':';
917      optr   = thread2vhstr(optr, thread);
918      *optr++ = ';';
919   }
920#endif
921   *optr++ = '\0';
922}
923
924
925
926
927/*
928 * Scratch frame used to retrieve contexts for different threads, so as
929 * not to disrupt our current context on the stack
930 */
931CPU_Interrupt_frame current_thread_registers;
932
933
934
935/*
936 * This function handles all exceptions.  It only does two things:
937 * it figures out why it was activated and tells gdb, and then it
938 * reacts to gdb's requests.
939 */
940
941
942void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
943{
944   int          host_has_detached = 0;
945   int          regno, addr, length;
946   char         *ptr;
947   int          current_thread;  /* current generic thread */
948   int          thread;          /* stopped thread: context exception happened in */
949
950   long long    regval;
951   void         *regptr;
952   int          binary;
953   
954
955   registers = (mips_register_t *)frame;
956
957   thread = 0;
958#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
959   if (do_threads) {
960      thread = rtems_gdb_stub_get_current_thread();
961   }
962#endif
963   current_thread = thread;
964
965
966   {
967      /* reapply all breakpoints regardless of how we came in */
968      struct z0break *z0, *zother;
969
970      for (zother=z0break_list; zother!=NULL; zother=zother->next)
971      {
972         if( zother->instr == 0xffffffff )
973         {
974            /* grab the instruction */
975            zother->instr = *(zother->address);
976            /* and insert the breakpoint */
977            *(zother->address) = BREAK_INSTR;
978         }
979      }
980
981
982
983      /* see if we're coming from a breakpoint */
984      if( *((unsigned *)frame->epc) == BREAK_INSTR )
985      {
986         /* see if its one of our zbreaks */
987         for (z0=z0break_list; z0!=NULL; z0=z0->next)
988         {
989            if( (unsigned)z0->address == frame->epc)
990               break;
991         }
992         if( z0 )
993         {
994            /* restore the original instruction */
995            *(z0->address) = z0->instr;
996            /* flag the breakpoint */
997            z0->instr = 0xffffffff;
998
999            /*
1000               now when we return, we'll execute the original code in
1001               the original state.  This leaves our breakpoint inactive
1002               since the break instruction isn't there, but we'll reapply
1003               it the next time we come in via step or breakpoint
1004            */
1005         }
1006         else
1007         {
1008            /* not a zbreak, see if its our trusty stepping code */
1009
1010            /*
1011             * Restore the saved instruction at
1012             * the single-step target address.
1013             */
1014            undoSStep();
1015         }
1016      }
1017   }
1018
1019
1020
1021
1022
1023   /* reply to host that an exception has occurred with some basic info */
1024   gdb_stub_report_exception_info(vector, frame, thread);
1025   putpacket (outBuffer);
1026
1027
1028
1029   while (!(host_has_detached)) {
1030      outBuffer[0] = '\0';
1031      getpacket (inBuffer);
1032      binary = 0;
1033
1034      switch (inBuffer[0]) {
1035         case '?':
1036            gdb_stub_report_exception_info(vector, frame, thread);
1037            break;
1038
1039         case 'd': /* toggle debug flag */
1040            /* can print ill-formed commands in valid packets & checksum errors */
1041            break;
1042
1043         case 'D':
1044            /* remote system is detaching - return OK and exit from debugger */
1045            strcpy (outBuffer, "OK");
1046            host_has_detached = 1;
1047            break;
1048
1049         case 'g':               /* return the values of the CPU registers */
1050            regptr = registers;
1051#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1052            if (do_threads && current_thread != thread )
1053               regptr = &current_thread_registers;
1054#endif
1055            mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer);
1056            break;
1057
1058
1059         case 'G':       /* set the values of the CPU registers - return OK */
1060            regptr = registers;
1061#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1062            if (do_threads && current_thread != thread )
1063               regptr = &current_thread_registers;
1064#endif
1065            if (hex2mem (&inBuffer[1], regptr, NUM_REGS * (sizeof registers)))
1066               strcpy (outBuffer, "OK");
1067            else
1068               strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1069            break;
1070
1071
1072         case 'P':
1073            /* Pn...=r...  Write register n... with value r... - return OK */
1074            ptr = &inBuffer[1];
1075            if (hexToInt(&ptr, &regno) &&
1076                *ptr++ == '=' &&
1077                hexToLongLong(&ptr, &regval))
1078            {
1079               registers[regno] = regval;
1080               strcpy (outBuffer, "OK");
1081            }
1082            else
1083               strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1084            break;
1085
1086
1087         case 'm':
1088            /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
1089            ptr = &inBuffer[1];
1090            if (hexToInt (&ptr, &addr)
1091                && *ptr++ == ','
1092                && hexToInt (&ptr, &length)
1093                && is_readable (addr, length)
1094                && (length < (BUFMAX - 4)/2))
1095               mem2hex ((void *)addr, length, outBuffer);
1096            else
1097               strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */
1098            break;
1099
1100
1101         case 'X':  /* XAA..AA,LLLL:<binary data>#cs */
1102            binary = 1;
1103         case 'M':
1104            /* MAA..AA,LLLL:  Write LLLL bytes at address AA..AA - return OK */
1105            ptr = &inBuffer[1];
1106            if (hexToInt (&ptr, &addr)
1107                && *ptr++ == ','
1108                && hexToInt (&ptr, &length)
1109                && *ptr++ == ':'
1110                && is_writeable (addr, length) ) {
1111               if ( binary )
1112                  hex2mem (ptr, (void *)addr, length);
1113               else
1114                  bin2mem (ptr, (void *)addr, length);
1115               strcpy (outBuffer, "OK");
1116            }
1117            else
1118               strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */
1119            break;
1120
1121
1122
1123         case 'c':
1124            /* cAA..AA    Continue at address AA..AA(optional) */
1125         case 's':
1126            /* sAA..AA    Step one instruction from AA..AA(optional) */
1127         {
1128            /* try to read optional parameter, pc unchanged if no parm */
1129            ptr = &inBuffer[1];
1130            if (hexToInt (&ptr, &addr))
1131               registers[PC] = addr;
1132
1133            if (inBuffer[0] == 's')
1134               doSStep ();
1135         }
1136         goto stubexit;
1137
1138
1139
1140
1141
1142         case 'k':  /* remove all zbreaks if any */
1143        dumpzbreaks:
1144         {
1145            {
1146               /* Unlink the entire list */
1147               struct z0break *z0, *znxt;
1148
1149               while( (z0= z0break_list) )
1150               {
1151
1152                  /* put back the instruction */
1153                  if( z0->instr != 0xffffffff )
1154                     *(z0->address) = z0->instr;
1155
1156                  /* pop off the top entry */
1157                  znxt = z0->next;
1158                  if( znxt ) znxt->prev = NULL;
1159                  z0break_list = znxt;
1160
1161                  /* and put it on the free list */
1162                  z0->prev = NULL;
1163                  z0->next = z0break_avail;
1164                  z0break_avail = z0;
1165               }
1166            }
1167
1168            strcpy(outBuffer, "OK");
1169         }
1170         break;
1171
1172
1173
1174
1175
1176         case 'q':   /* queries */
1177#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1178            rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread );
1179#endif
1180            break;
1181
1182#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1183         case 'T':
1184         {
1185            int testThread;
1186
1187            if( vhstr2thread(&inBuffer[1], &testThread) == NULL )
1188            {
1189               strcpy(outBuffer, "E01");
1190               break;
1191            }
1192
1193            if( rtems_gdb_index_to_stub_id(testThread) == NULL )
1194            {
1195               strcpy(outBuffer, "E02");
1196            }
1197            else
1198            {
1199               strcpy(outBuffer, "OK");
1200            }
1201         }
1202         break;
1203#endif
1204       
1205         case 'H':  /* set new thread */
1206#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1207            if (inBuffer[1] != 'g') {
1208               break;
1209            }
1210         
1211            if (!do_threads) {
1212               break;
1213            }
1214         
1215            {
1216               int tmp, ret;
1217           
1218               /* Set new generic thread */
1219               if (vhstr2thread(&inBuffer[2], &tmp) == NULL) {
1220                  strcpy(outBuffer, "E01");
1221                  break;
1222               }
1223
1224               /* 0 means `thread' */
1225               if (tmp == 0) {
1226                  tmp = thread;
1227               }
1228
1229               if (tmp == current_thread) {
1230                  /* No changes */
1231                  strcpy(outBuffer, "OK");
1232                  break;
1233               }
1234
1235               /* Save current thread registers if necessary */
1236               if (current_thread != thread) {
1237                  ret = rtems_gdb_stub_set_thread_regs(
1238                     current_thread, (unsigned int *) &current_thread_registers);
1239                  ASSERT(ret);
1240               }
1241
1242               /* Read new registers if necessary */
1243               if (tmp != thread) {
1244                  ret = rtems_gdb_stub_get_thread_regs(
1245                     tmp, (unsigned int *) &current_thread_registers);
1246
1247                  if (!ret) {
1248                     /* Thread does not exist */
1249                     strcpy(outBuffer, "E02");
1250                     break;
1251                  }
1252               }
1253           
1254               current_thread = tmp;
1255               strcpy(outBuffer, "OK");
1256            }
1257#endif
1258            break;
1259
1260
1261
1262
1263         case 'Z':  /* Add breakpoint */
1264         {
1265            int ret, type, len;
1266            unsigned char *address;
1267            struct z0break *z0;
1268
1269            ret = parse_zbreak(inBuffer, &type, &address, &len);
1270            if (!ret) {
1271               strcpy(outBuffer, "E01");
1272               break;
1273            }
1274
1275            if (type != 0) {
1276               /* We support only software break points so far */
1277               strcpy(outBuffer, "E02");
1278               break;
1279            }
1280
1281            if (len != R_SZ) {     /* was 1 */
1282               strcpy(outBuffer, "E03");
1283               break;
1284            }
1285
1286            /* Let us check whether this break point already set */
1287            for (z0=z0break_list; z0!=NULL; z0=z0->next) {
1288               if (z0->address == address) {
1289                  break;
1290               }
1291            }
1292
1293            if (z0 != NULL) {
1294               /* we already have a breakpoint for this address */
1295               strcpy(outBuffer, "E04");
1296               break;
1297            }
1298
1299            /* Let us allocate new break point */
1300            if (z0break_avail == NULL) {
1301               strcpy(outBuffer, "E05");
1302               break;
1303            }
1304
1305
1306            /* Get entry */
1307            z0 = z0break_avail;
1308            z0break_avail = z0break_avail->next;
1309
1310            /* Let us copy memory from address add stuff the break point in */
1311            /*
1312            *if (mem2hstr(z0->buf, address, 1) == NULL ||
1313              !hstr2mem(address, "cc" , 1)) {
1314
1315               * Memory error *
1316               z0->next = z0break_avail;
1317               z0break_avail = z0;
1318               strcpy(outBuffer, "E05");
1319               break;
1320            }*/
1321
1322            /* Fill it */
1323            z0->address = address;
1324
1325            if( z0->address == (unsigned char *) frame->epc )
1326            {
1327               /* re-asserting the breakpoint that put us in here, so
1328               we'll add the breakpoint but leave the code in place
1329               since we'll be returning to it when the user continues */
1330               z0->instr = 0xffffffff;
1331            }
1332            else
1333            {
1334               /* grab the instruction */
1335               z0->instr = *(z0->address);
1336               /* and insert the break */
1337               *(z0->address) = BREAK_INSTR;
1338            }
1339
1340            /* Add to the list */
1341            {
1342               struct z0break *znxt = z0break_list;
1343
1344               z0->prev = NULL;
1345               z0->next = znxt;
1346               
1347               if( znxt ) znxt->prev = z0;
1348               z0break_list = z0;
1349            }
1350
1351            strcpy(outBuffer, "OK");
1352         }
1353         break;
1354
1355
1356         case 'z': /* remove breakpoint */
1357            if (inBuffer[1] == 'z')
1358            {
1359               goto dumpzbreaks;
1360               
1361
1362               /*
1363                * zz packet - remove all breaks *
1364                z0last = NULL;
1365
1366                for (z0=z0break_list; z0!=NULL; z0=z0->next)
1367                {
1368                if(!hstr2mem(z0->address, z0->buf, R_SZ))
1369                {
1370                ret = 0;
1371                }
1372                z0last = z0;
1373                }
1374
1375                * Free entries if any *
1376                if (z0last != NULL) {
1377                z0last->next  = z0break_avail;
1378                z0break_avail = z0break_list;
1379                z0break_list  = NULL;
1380                }
1381
1382                if (ret) {
1383                strcpy(outBuffer, "OK");
1384                } else {
1385                strcpy(outBuffer, "E04");
1386                }
1387                break;
1388               */
1389            }
1390            else
1391            {
1392               int ret, type, len;
1393               unsigned char *address;
1394               struct z0break *z0;
1395             
1396               ret = parse_zbreak(inBuffer, &type, &address, &len);
1397               if (!ret) {
1398                  strcpy(outBuffer, "E01");
1399                  break;
1400               }
1401
1402               if (type != 0) {
1403                  /* We support only software break points so far */
1404                  break;
1405               }
1406
1407               if (len != R_SZ) {
1408                  strcpy(outBuffer, "E02");
1409                  break;
1410               }
1411           
1412               /* Let us check whether this break point set */
1413               for (z0=z0break_list; z0!=NULL; z0=z0->next) {
1414                  if (z0->address == address) {
1415                     break;
1416                  }
1417               }
1418             
1419               if (z0 == NULL) {
1420                  /* Unknown breakpoint */
1421                  strcpy(outBuffer, "E03");
1422                  break;
1423               }
1424           
1425               /*
1426               if (!hstr2mem(z0->address, z0->buf, R_SZ)) {
1427                  strcpy(outBuffer, "E04");
1428                  break;
1429                  }*/
1430
1431               if( z0->instr != 0xffffffff )
1432               {
1433                  /* put the old instruction back  */
1434                  *(z0->address) = z0->instr;
1435               }
1436   
1437               /* Unlink entry */
1438               {
1439                  struct z0break *zprv = z0->prev, *znxt = z0->next;
1440
1441                  if( zprv ) zprv->next = znxt;
1442                  if( znxt ) znxt->prev = zprv;
1443
1444                  if( !zprv ) z0break_list = znxt;
1445
1446                  znxt = z0break_avail;
1447
1448                  z0break_avail = z0;
1449                  z0->prev = NULL;
1450                  z0->next = znxt;
1451               }
1452   
1453               strcpy(outBuffer, "OK");
1454            }
1455            break;
1456
1457
1458         default: /* do nothing */
1459            break;
1460      }
1461
1462      /* reply to the request */
1463      putpacket (outBuffer);
1464   }
1465
1466  stubexit:
1467
1468   /*
1469    *  The original code did this in the assembly wrapper.  We should consider
1470    *  doing it here before we return.
1471    *
1472    *  On exit from the exception handler invalidate each line in the I-cache
1473    *  and write back each dirty line in the D-cache.  This needs to be done
1474    *  before the target program is resumed in order to ensure that software
1475    *  breakpoints and downloaded code will actually take effect.  This
1476    *  is because modifications to code in ram will affect the D-cache,
1477    *  but not necessarily the I-cache.
1478    */
1479
1480   {
1481      extern void clear_cache();
1482      clear_cache();
1483   }
1484
1485   return;
1486}
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497static int numsegs;
1498static struct memseg   memsegments[NUM_MEMSEGS];
1499
1500int gdbstub_add_memsegment( unsigned base, unsigned end, int opts )
1501{
1502   if( numsegs == NUM_MEMSEGS ) return -1;
1503
1504   memsegments[numsegs].begin = base;
1505   memsegments[numsegs].end   = end;
1506   memsegments[numsegs].opts   = opts;
1507
1508   ++numsegs;
1509   return RTEMS_SUCCESSFUL;
1510}
1511
1512
1513
1514
1515static int is_readable(unsigned ptr, unsigned len)
1516{
1517   struct memseg *ms;
1518   int i;
1519
1520   if( (ptr & 0x3) ) return -1;
1521
1522   for(i=0; i<numsegs; i++)
1523   {
1524      ms= &memsegments[i];
1525
1526      if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) )
1527         return -1;
1528   }
1529   return 0;
1530}
1531
1532
1533static int is_writeable(unsigned ptr, unsigned len)
1534{
1535   struct memseg *ms;
1536   int i;
1537
1538   if( (ptr & 0x3) ) return -1;
1539
1540   for(i=0; i<numsegs; i++)
1541   {
1542      ms= &memsegments[i];
1543
1544      if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1545         return -1;
1546   }
1547   return 0;
1548}
1549
1550
1551static int is_steppable(unsigned ptr)
1552{
1553   struct memseg *ms;
1554   int i;
1555
1556   if( (ptr & 0x3) ) return -1;
1557
1558   for(i=0; i<numsegs; i++)
1559   {
1560      ms= &memsegments[i];
1561
1562      if( ms->begin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1563         return -1;
1564   }
1565   return 0;
1566}
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581static char initialized = 0;   /* 0 means we are not initialized */
1582
1583void mips_gdb_stub_install(int enableThreads)
1584{
1585   /*
1586     These are the RTEMS-defined vectors for all the MIPS exceptions
1587   */
1588   int exceptionVector[]= { MIPS_EXCEPTION_MOD, \
1589                            MIPS_EXCEPTION_TLBL, \
1590                            MIPS_EXCEPTION_TLBS, \
1591                            MIPS_EXCEPTION_ADEL, \
1592                            MIPS_EXCEPTION_ADES, \
1593                            MIPS_EXCEPTION_IBE, \
1594                            MIPS_EXCEPTION_DBE, \
1595                            MIPS_EXCEPTION_SYSCALL, \
1596                            MIPS_EXCEPTION_BREAK, \
1597                            MIPS_EXCEPTION_RI, \
1598                            MIPS_EXCEPTION_CPU, \
1599                            MIPS_EXCEPTION_OVERFLOW, \
1600                            MIPS_EXCEPTION_TRAP, \
1601                            MIPS_EXCEPTION_VCEI, \
1602                            MIPS_EXCEPTION_FPE, \
1603                            MIPS_EXCEPTION_C2E, \
1604                            MIPS_EXCEPTION_WATCH, \
1605                            MIPS_EXCEPTION_VCED, \
1606                            -1 };
1607   int  i;
1608   rtems_isr_entry old;
1609
1610   if (initialized)
1611   {
1612      ASSERT(0);
1613      return;
1614   }
1615
1616   memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS );
1617   numsegs = 0;
1618
1619#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1620   if( enableThreads )
1621      do_threads = 1;
1622   else
1623      do_threads = 0;
1624#endif
1625
1626   {
1627      struct z0break *z0;
1628
1629      z0break_avail = NULL;
1630      z0break_list  = NULL;
1631   
1632      /* z0breaks list init, now we'll do it so it makes sense... */
1633      for (i=0; i<BREAKNUM; i++)
1634      {
1635         memset( (z0= &z0break_arr[i]), 0, sizeof(struct z0break));
1636
1637         z0->next = z0break_avail;
1638         z0break_avail = z0;
1639      }
1640   }     
1641
1642   for(i=0; exceptionVector[i] > -1; i++)
1643   {
1644      rtems_interrupt_catch( (rtems_isr_entry) handle_exception, exceptionVector[i], &old );
1645   }
1646
1647   initialized = 1;
1648
1649   /* get the attention of gdb */
1650   /* mips_break(1);  disabled so user code can choose to invoke it or not */
1651}
1652
1653
1654
Note: See TracBrowser for help on using the repository browser.