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

Last change on this file since 1503c1c3 was 1503c1c3, checked in by Chris Johns <chrisj@…>, on May 23, 2016 at 5:24:34 AM

i386/pc386: Fix printk formatting warnings.

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