Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*
0002  *  This is the gdb i386 remote debug stub from gdb 4.XX.
0003  */
0004 
0005 /****************************************************************************
0006 
0007   THIS SOFTWARE IS NOT COPYRIGHTED
0008 
0009   HP offers the following for use in the public domain.  HP makes no
0010   warranty with regard to the software or it's performance and the
0011   user accepts the software "AS IS" with all faults.
0012 
0013   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
0014   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
0015   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
0016 
0017   ****************************************************************************/
0018 
0019 /****************************************************************************
0020  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
0021  *
0022  *  Module name: remcom.c $
0023  *  Revision: 1.34 $
0024  *  Date: 91/03/09 12:29:49 $
0025  *  Contributor:     Lake Stevens Instrument Division$
0026  *
0027  *  Description:     low level support for gdb debugger. $
0028  *
0029  *  Considerations:  only works on target hardware $
0030  *
0031  *  Written by:      Glenn Engel $
0032  *  ModuleState:     Experimental $
0033  *
0034  *  NOTES:           See Below $
0035  *
0036  *  Modified for 386 by Jim Kingdon, Cygnus Support.
0037  *  Modified for RTEMS by Aleksey Romanov, Quality Quorum, Inc.
0038  *
0039  *  To enable debugger support, two things need to happen.  One, a
0040  *  call to set_debug_traps() is necessary in order to allow any breakpoints
0041  *  or error conditions to be properly intercepted and reported to gdb.
0042  *  Two, a breakpoint needs to be generated to begin communication.  This
0043  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
0044  *  simulates a breakpoint by executing a trap #1.
0045  *
0046  *  The external function exceptionHandler() is
0047  *  used to attach a specific handler to a specific 386 vector number.
0048  *  It should use the same privilege level it runs at.  It should
0049  *  install it as an interrupt gate so that interrupts are masked
0050  *  while the handler runs.
0051  *  Also, need to assign exceptionHook and oldExceptionHook.
0052  *
0053  *  Because gdb will sometimes write to the stack area to execute function
0054  *  calls, this program cannot rely on using the supervisor stack so it
0055  *  uses it's own stack area reserved in the int array remcomStack.
0056  *
0057  *************
0058  *
0059  *    The following gdb commands are supported:
0060  *
0061  * command          function                               Return value
0062  *
0063  *    g             return the value of the CPU registers  hex data or ENN
0064  *    G             set the value of the CPU registers     OK or ENN
0065  *
0066  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
0067  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
0068  *
0069  *    c             Resume at current address              SNN   ( signal NN)
0070  *    cAA..AA       Continue at address AA..AA             SNN
0071  *
0072  *    s             Step one instruction                   SNN
0073  *    sAA..AA       Step one instruction from AA..AA       SNN
0074  *
0075  *    k             kill
0076  *
0077  *    ?             What was the last sigval ?             SNN   (signal NN)
0078  *
0079  * All commands and responses are sent with a packet which includes a
0080  * checksum.  A packet consists of
0081  *
0082  * $<packet info>#<checksum>.
0083  *
0084  * where
0085  * <packet info> :: <characters representing the command or response>
0086  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
0087  *
0088  * When a packet is received, it is first acknowledged with either '+' or '-'.
0089  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
0090  *
0091  * Example:
0092  *
0093  * Host:                  Reply:
0094  * $m0,10#2a               +$00010203040506070809101112131415#42
0095  *
0096  ****************************************************************************/
0097 
0098 #include <stdio.h>
0099 #include <string.h>
0100 #include <stdbool.h>
0101 
0102 #include <bsp.h>
0103 #include <bsp/bootcard.h>
0104 
0105 /*
0106  * Number of debug registers.
0107  */
0108 #define NUM_DEBUG_REGISTERS 4
0109 
0110 /*
0111  * Prototypes we need to avoid warnings but not going into public space.
0112  */
0113 void breakpoint (void);
0114 void set_debug_traps(void);
0115 void set_mem_err(void);
0116 void _returnFromException(void);
0117 void exceptionHandler (int, void (*handler) (void));
0118 
0119 /************************************************************************
0120  *
0121  * external low-level support routines
0122  */
0123 extern int putDebugChar (int ch);      /* write a single character      */
0124 extern int getDebugChar (void);            /* read and return a single char */
0125 
0126 
0127 /************************************************************************/
0128 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers */
0129 /* at least NUMREGBYTES*2 are needed for register packets */
0130 #define BUFMAX 400
0131 
0132 static bool initialized = false;    /* boolean flag. != 0 means we've been initialized */
0133 
0134 extern int remote_debug;
0135 /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
0136 
0137 extern void waitabit (void);
0138 
0139 static const char hexchars[] = "0123456789abcdef";
0140 
0141 /* Number of registers.  */
0142 #define NUMREGS 16
0143 
0144 /* Number of bytes per register.  */
0145 #define REGBYTES 4
0146 
0147 /* Number of bytes of registers.  */
0148 #define NUMREGBYTES (NUMREGS * REGBYTES)
0149 
0150 enum regnames
0151   {
0152     EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
0153     PC /* also known as eip */ ,
0154     PS /* also known as eflags */ ,
0155     CS, SS, DS, ES, FS, GS
0156   };
0157 
0158 /*
0159  * these should not be static cuz they can be used outside this module
0160  */
0161 
0162 int i386_gdb_registers[NUMREGS];
0163 
0164 #define STACKSIZE 10000
0165 int i386_gdb_remcomStack[STACKSIZE / sizeof (int)];
0166 int *i386_gdb_stackPtr = &i386_gdb_remcomStack[STACKSIZE / sizeof (int) - 1];
0167 
0168 static int gdb_connected;
0169 
0170 /***************************  ASSEMBLY CODE MACROS *************************/
0171 /*                                                                         */
0172 
0173 extern void
0174   return_to_prog (void);
0175 
0176 /* Restore the program's registers (including the stack pointer, which
0177    means we get the right stack and don't have to worry about popping our
0178    return address and any stack frames and so on) and return.  */
0179 __asm__ (".text");
0180 __asm__ (".globl return_to_prog");
0181 __asm__ ("return_to_prog:");
0182 __asm__ ("        movw i386_gdb_registers+44, %ss");
0183 __asm__ ("        movl i386_gdb_registers+16, %esp");
0184 __asm__ ("        movl i386_gdb_registers+4, %ecx");
0185 __asm__ ("        movl i386_gdb_registers+8, %edx");
0186 __asm__ ("        movl i386_gdb_registers+12, %ebx");
0187 __asm__ ("        movl i386_gdb_registers+20, %ebp");
0188 __asm__ ("        movl i386_gdb_registers+24, %esi");
0189 __asm__ ("        movl i386_gdb_registers+28, %edi");
0190 __asm__ ("        movw i386_gdb_registers+48, %ds");
0191 __asm__ ("        movw i386_gdb_registers+52, %es");
0192 __asm__ ("        movw i386_gdb_registers+56, %fs");
0193 __asm__ ("        movw i386_gdb_registers+60, %gs");
0194 __asm__ ("        movl i386_gdb_registers+36, %eax");
0195 __asm__ ("        pushl %eax"); /* saved eflags */
0196 __asm__ ("        movl i386_gdb_registers+40, %eax");
0197 __asm__ ("        pushl %eax"); /* saved cs */
0198 __asm__ ("        movl i386_gdb_registers+32, %eax");
0199 __asm__ ("        pushl %eax"); /* saved eip */
0200 __asm__ ("        movl i386_gdb_registers, %eax");
0201 /* use iret to restore pc and flags together so
0202    that trace flag works right.  */
0203 __asm__ ("        iret");
0204 
0205 #define BREAKPOINT() __asm__ ("   int $3");
0206 
0207 /* Put the error code here just in case the user cares.  */
0208 int gdb_i386errcode;
0209 /* Likewise, the vector number here (since GDB only gets the signal
0210    number through the usual means, and that's not very specific).  */
0211 int gdb_i386vector = -1;
0212 
0213 /* GDB stores segment registers in 32-bit words (that's just the way
0214    m-i386v.h is written).  So zero the appropriate areas in registers.  */
0215 #define SAVE_REGISTERS1() \
0216   __asm__ ("movl %eax, i386_gdb_registers");                \
0217   __asm__ ("movl %ecx, i386_gdb_registers+4");              \
0218   __asm__ ("movl %edx, i386_gdb_registers+8");              \
0219   __asm__ ("movl %ebx, i386_gdb_registers+12");             \
0220   __asm__ ("movl %ebp, i386_gdb_registers+20");             \
0221   __asm__ ("movl %esi, i386_gdb_registers+24");             \
0222   __asm__ ("movl %edi, i386_gdb_registers+28");             \
0223   __asm__ ("movw $0, %ax");                     \
0224   __asm__ ("movw %ds, i386_gdb_registers+48");              \
0225   __asm__ ("movw %ax, i386_gdb_registers+50");              \
0226   __asm__ ("movw %es, i386_gdb_registers+52");              \
0227   __asm__ ("movw %ax, i386_gdb_registers+54");              \
0228   __asm__ ("movw %fs, i386_gdb_registers+56");              \
0229   __asm__ ("movw %ax, i386_gdb_registers+58");              \
0230   __asm__ ("movw %gs, i386_gdb_registers+60");              \
0231   __asm__ ("movw %ax, i386_gdb_registers+62");
0232 #define SAVE_ERRCODE() \
0233   __asm__ ("popl %ebx");            \
0234   __asm__ ("movl %ebx, gdb_i386errcode");
0235 #define SAVE_REGISTERS2() \
0236   __asm__ ("popl %ebx"); /* old eip */                  \
0237   __asm__ ("movl %ebx, i386_gdb_registers+32");             \
0238   __asm__ ("popl %ebx");     /* old cs */               \
0239   __asm__ ("movl %ebx, i386_gdb_registers+40");             \
0240   __asm__ ("movw %ax, i386_gdb_registers+42");              \
0241   __asm__ ("popl %ebx");     /* old eflags */           \
0242   __asm__ ("movl %ebx, i386_gdb_registers+36");             \
0243   /* Now that we've done the pops, we can save the stack pointer.");  */ \
0244   __asm__ ("movw %ss, i386_gdb_registers+44");              \
0245   __asm__ ("movw %ax, i386_gdb_registers+46");              \
0246   __asm__ ("movl %esp, i386_gdb_registers+16");
0247 
0248 /* See if mem_fault_routine is set, if so just IRET to that address.  */
0249 #define CHECK_FAULT() \
0250   __asm__ ("cmpl $0, mem_fault_routine");                      \
0251   __asm__ ("jne mem_fault");
0252 
0253 __asm__ (".text");
0254 __asm__ ("mem_fault:");
0255 /* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
0256 /* Pop error code from the stack and save it.  */
0257 __asm__ ("     popl %eax");
0258 __asm__ ("     movl %eax, gdb_i386errcode");
0259 
0260 __asm__ ("     popl %eax");     /* eip */
0261 /* We don't want to return there, we want to return to the function
0262    pointed to by mem_fault_routine instead.  */
0263 __asm__ ("     movl mem_fault_routine, %eax");
0264 __asm__ ("     popl %ecx");     /* cs (low 16 bits; junk in hi 16 bits).  */
0265 __asm__ ("     popl %edx");     /* eflags */
0266 
0267 /* Remove this stack frame; when we do the iret, we will be going to
0268    the start of a function, so we want the stack to look just like it
0269    would after a "call" instruction.  */
0270 __asm__ ("     leave");
0271 
0272 /* Push the stuff that iret wants.  */
0273 __asm__ ("     pushl %edx");    /* eflags */
0274 __asm__ ("     pushl %ecx");    /* cs */
0275 __asm__ ("     pushl %eax");    /* eip */
0276 
0277 /* Zero mem_fault_routine.  */
0278 __asm__ ("     movl $0, %eax");
0279 __asm__ ("     movl %eax, mem_fault_routine");
0280 
0281 __asm__ ("iret");
0282 
0283 #define CALL_HOOK() __asm__ ("call _remcomHandler");
0284 
0285 /* This function is called when a i386 exception occurs.  It saves
0286  * all the cpu regs in the registers array, munges the stack a bit,
0287  * and invokes an exception handler (remcom_handler).
0288  *
0289  * stack on entry:                       stack on exit:
0290  *   old eflags                          vector number
0291  *   old cs (zero-filled to 32 bits)
0292  *   old eip
0293  *
0294  */
0295 extern void _catchException3 (void);
0296 __asm__ (".text");
0297 __asm__ (".globl _catchException3");
0298 __asm__ ("_catchException3:");
0299 SAVE_REGISTERS1 ();
0300 SAVE_REGISTERS2 ();
0301 __asm__ ("pushl $3");
0302 CALL_HOOK ();
0303 
0304 /* Same thing for exception 1.  */
0305 extern void _catchException1 (void);
0306 __asm__ (".text");
0307 __asm__ (".globl _catchException1");
0308 __asm__ ("_catchException1:");
0309 SAVE_REGISTERS1 ();
0310 SAVE_REGISTERS2 ();
0311 __asm__ ("pushl $1");
0312 CALL_HOOK ();
0313 
0314 /* Same thing for exception 0.  */
0315 extern void _catchException0 (void);
0316 __asm__ (".text");
0317 __asm__ (".globl _catchException0");
0318 __asm__ ("_catchException0:");
0319 SAVE_REGISTERS1 ();
0320 SAVE_REGISTERS2 ();
0321 __asm__ ("pushl $0");
0322 CALL_HOOK ();
0323 
0324 /* Same thing for exception 4.  */
0325 extern void _catchException4 (void);
0326 __asm__ (".text");
0327 __asm__ (".globl _catchException4");
0328 __asm__ ("_catchException4:");
0329 SAVE_REGISTERS1 ();
0330 SAVE_REGISTERS2 ();
0331 __asm__ ("pushl $4");
0332 CALL_HOOK ();
0333 
0334 /* Same thing for exception 5.  */
0335 extern void _catchException5 (void);
0336 __asm__ (".text");
0337 __asm__ (".globl _catchException5");
0338 __asm__ ("_catchException5:");
0339 SAVE_REGISTERS1 ();
0340 SAVE_REGISTERS2 ();
0341 __asm__ ("pushl $5");
0342 CALL_HOOK ();
0343 
0344 /* Same thing for exception 6.  */
0345 extern void _catchException6 (void);
0346 __asm__ (".text");
0347 __asm__ (".globl _catchException6");
0348 __asm__ ("_catchException6:");
0349 SAVE_REGISTERS1 ();
0350 SAVE_REGISTERS2 ();
0351 __asm__ ("pushl $6");
0352 CALL_HOOK ();
0353 
0354 /* Same thing for exception 7.  */
0355 extern void _catchException7 (void);
0356 __asm__ (".text");
0357 __asm__ (".globl _catchException7");
0358 __asm__ ("_catchException7:");
0359 SAVE_REGISTERS1 ();
0360 SAVE_REGISTERS2 ();
0361 __asm__ ("pushl $7");
0362 CALL_HOOK ();
0363 
0364 /* Same thing for exception 8.  */
0365 extern void _catchException8 (void);
0366 __asm__ (".text");
0367 __asm__ (".globl _catchException8");
0368 __asm__ ("_catchException8:");
0369 SAVE_REGISTERS1 ();
0370 SAVE_ERRCODE ();
0371 SAVE_REGISTERS2 ();
0372 __asm__ ("pushl $8");
0373 CALL_HOOK ();
0374 
0375 /* Same thing for exception 9.  */
0376 extern void _catchException9 (void);
0377 __asm__ (".text");
0378 __asm__ (".globl _catchException9");
0379 __asm__ ("_catchException9:");
0380 SAVE_REGISTERS1 ();
0381 SAVE_REGISTERS2 ();
0382 __asm__ ("pushl $9");
0383 CALL_HOOK ();
0384 
0385 /* Same thing for exception 10.  */
0386 extern void _catchException10 (void);
0387 __asm__ (".text");
0388 __asm__ (".globl _catchException10");
0389 __asm__ ("_catchException10:");
0390 SAVE_REGISTERS1 ();
0391 SAVE_ERRCODE ();
0392 SAVE_REGISTERS2 ();
0393 __asm__ ("pushl $10");
0394 CALL_HOOK ();
0395 
0396 /* Same thing for exception 12.  */
0397 extern void _catchException12 (void);
0398 __asm__ (".text");
0399 __asm__ (".globl _catchException12");
0400 __asm__ ("_catchException12:");
0401 SAVE_REGISTERS1 ();
0402 SAVE_ERRCODE ();
0403 SAVE_REGISTERS2 ();
0404 __asm__ ("pushl $12");
0405 CALL_HOOK ();
0406 
0407 /* Same thing for exception 16.  */
0408 extern void _catchException16 (void);
0409 __asm__ (".text");
0410 __asm__ (".globl _catchException16");
0411 __asm__ ("_catchException16:");
0412 SAVE_REGISTERS1 ();
0413 SAVE_REGISTERS2 ();
0414 __asm__ ("pushl $16");
0415 CALL_HOOK ();
0416 
0417 /* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
0418 
0419 /* Same thing for exception 13.  */
0420 extern void _catchException13 (void);
0421 __asm__ (".text");
0422 __asm__ (".globl _catchException13");
0423 __asm__ ("_catchException13:");
0424 CHECK_FAULT ();
0425 SAVE_REGISTERS1 ();
0426 SAVE_ERRCODE ();
0427 SAVE_REGISTERS2 ();
0428 __asm__ ("pushl $13");
0429 CALL_HOOK ();
0430 
0431 /* Same thing for exception 11.  */
0432 extern void _catchException11 (void);
0433 __asm__ (".text");
0434 __asm__ (".globl _catchException11");
0435 __asm__ ("_catchException11:");
0436 CHECK_FAULT ();
0437 SAVE_REGISTERS1 ();
0438 SAVE_ERRCODE ();
0439 SAVE_REGISTERS2 ();
0440 __asm__ ("pushl $11");
0441 CALL_HOOK ();
0442 
0443 /* Same thing for exception 14.  */
0444 extern void _catchException14 (void);
0445 __asm__ (".text");
0446 __asm__ (".globl _catchException14");
0447 __asm__ ("_catchException14:");
0448 CHECK_FAULT ();
0449 SAVE_REGISTERS1 ();
0450 SAVE_ERRCODE ();
0451 SAVE_REGISTERS2 ();
0452 __asm__ ("pushl $14");
0453 CALL_HOOK ();
0454 
0455 /*
0456  * remcomHandler is a front end for handle_exception.  It moves the
0457  * stack pointer into an area reserved for debugger use.
0458  */
0459 extern void remcomHandler (void);
0460 __asm__ ("_remcomHandler:");
0461 __asm__ ("           popl %eax");   /* pop off return address     */
0462 __asm__ ("           popl %eax");   /* get the exception number   */
0463 __asm__ ("      movl i386_gdb_stackPtr, %esp"); /* move to remcom stack area */
0464 __asm__ ("      pushl %eax");   /* push exception onto stack  */
0465 __asm__ ("      call  handle_exception");   /* this never returns */
0466 
0467 void
0468 _returnFromException (void)
0469 {
0470   return_to_prog ();
0471 }
0472 
0473 static int
0474 hex (char ch)
0475 {
0476   if ((ch >= 'a') && (ch <= 'f'))
0477     return (ch - 'a' + 10);
0478   if ((ch >= '0') && (ch <= '9'))
0479     return (ch - '0');
0480   if ((ch >= 'A') && (ch <= 'F'))
0481     return (ch - 'A' + 10);
0482   return (-1);
0483 }
0484 
0485 /* scan for the sequence $<data>#<checksum>     */
0486 static void
0487 getpacket (char *buffer)
0488 {
0489   unsigned char checksum;
0490   unsigned char xmitcsum;
0491   int i;
0492   int count;
0493   char ch;
0494 
0495   do
0496     {
0497       /* wait around for the start character, ignore all other characters */
0498       while ((ch = (getDebugChar () & 0x7f)) != '$');
0499       checksum = 0;
0500       xmitcsum = -1;
0501 
0502       count = 0;
0503 
0504       /* now, read until a # or end of buffer is found */
0505       while (count < (BUFMAX - 1))
0506     {
0507       ch = getDebugChar () & 0x7f;
0508       if (ch == '#')
0509         break;
0510       checksum = checksum + ch;
0511       buffer[count] = ch;
0512       count = count + 1;
0513     }
0514       buffer[count] = 0;
0515 
0516       if (ch == '#')
0517     {
0518       xmitcsum = hex (getDebugChar () & 0x7f) << 4;
0519       xmitcsum += hex (getDebugChar () & 0x7f);
0520       if ((remote_debug) && (checksum != xmitcsum))
0521         {
0522           printk ("bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
0523               checksum, xmitcsum, buffer);
0524         }
0525 
0526       if (remote_debug) {
0527         printk("GETP: $%s...%s\n", buffer,
0528            checksum == xmitcsum ? "Ack" : "Nack");
0529       }
0530 
0531       if (checksum != xmitcsum)
0532         putDebugChar ('-'); /* failed checksum */
0533       else
0534         {
0535           putDebugChar ('+');   /* successful transfer */
0536           /* if a sequence char is present, reply the sequence ID */
0537           if (buffer[2] == ':')
0538         {
0539           putDebugChar (buffer[0]);
0540           putDebugChar (buffer[1]);
0541           /* remove sequence chars from buffer */
0542           count = strlen (buffer);
0543           for (i = 3; i <= count; i++)
0544             buffer[i - 3] = buffer[i];
0545         }
0546         }
0547     }
0548     }
0549   while (checksum != xmitcsum);
0550 
0551 }
0552 
0553 /* send the packet in buffer.  */
0554 
0555 static void
0556 putpacket (char *buffer)
0557 {
0558   /*  $<packet info>#<checksum>. */
0559   while (true)
0560     {
0561       unsigned char checksum;
0562       int count;
0563       char ch;
0564 
0565       if (remote_debug)
0566     printk("PUTP: $%s", buffer);
0567 
0568       putDebugChar ('$');
0569       checksum = 0;
0570       count = 0;
0571 
0572       while ((ch = buffer[count]))
0573     {
0574       if (!putDebugChar (ch))
0575         return;
0576       checksum += ch;
0577       count += 1;
0578     }
0579 
0580       putDebugChar ('#');
0581       putDebugChar (hexchars[checksum >> 4]);
0582       putDebugChar (hexchars[checksum % 16]);
0583 
0584       if (remote_debug)
0585     printk("#%c%c...", hexchars[checksum >> 4], hexchars[checksum % 16]);
0586 
0587       ch = getDebugChar () & 0x7f;
0588       if (ch == '+') {
0589     if (remote_debug)
0590       printk("Ack\n");
0591     break;
0592       }
0593       if (remote_debug)
0594     printk("Nack(%c)\n", ch);
0595     }
0596 }
0597 
0598 char remcomInBuffer[BUFMAX];
0599 char remcomOutBuffer[BUFMAX];
0600 static short error;
0601 
0602 static void
0603 debug_error (
0604      char *format,
0605      char *parm
0606 )
0607 {
0608   if (remote_debug)
0609     printk (format, parm);
0610 }
0611 
0612 /* Address of a routine to RTE to if we get a memory fault.  */
0613 static void (*volatile mem_fault_routine) (void) = NULL;
0614 
0615 /* Indicate to caller of mem2hex or hex2mem that there has been an
0616    error.  */
0617 static volatile int mem_err = 0;
0618 
0619 void
0620 set_mem_err (void)
0621 {
0622   mem_err = 1;
0623 }
0624 
0625 /* These are separate functions so that they are so short and sweet
0626    that the compiler won't save any registers (if there is a fault
0627    to mem_fault, they won't get restored, so there better not be any
0628    saved).  */
0629 static int
0630 get_char (char *addr)
0631 {
0632   return *addr;
0633 }
0634 
0635 static void
0636 set_char (char *addr, int val)
0637 {
0638   *addr = val;
0639 }
0640 
0641 /* convert the memory pointed to by mem into hex, placing result in buf */
0642 /* return a pointer to the last char put in buf (null) */
0643 /* If MAY_FAULT is non-zero, then we should set mem_err in response to
0644    a fault; if zero treat a fault like any other fault in the stub.  */
0645 static char *
0646 mem2hex (char *mem, char *buf, int count, int may_fault)
0647 {
0648   int i;
0649   unsigned char ch;
0650 
0651   if (may_fault)
0652     mem_fault_routine = set_mem_err;
0653   for (i = 0; i < count; i++)
0654     {
0655       ch = get_char (mem++);
0656       if (may_fault && mem_err)
0657     return (buf);
0658       *buf++ = hexchars[ch >> 4];
0659       *buf++ = hexchars[ch % 16];
0660     }
0661   *buf = 0;
0662   if (may_fault)
0663     mem_fault_routine = NULL;
0664   return (buf);
0665 }
0666 
0667 /* convert the hex array pointed to by buf into binary to be placed in mem */
0668 /* return a pointer to the character AFTER the last byte written */
0669 static char *
0670 hex2mem (char *buf, char *mem, int count, int may_fault)
0671 {
0672   int i;
0673   unsigned char ch;
0674 
0675   if (may_fault)
0676     mem_fault_routine = set_mem_err;
0677   for (i = 0; i < count; i++)
0678     {
0679       ch = hex (*buf++) << 4;
0680       ch = ch + hex (*buf++);
0681       set_char (mem++, ch);
0682       if (may_fault && mem_err)
0683     return (mem);
0684     }
0685   if (may_fault)
0686     mem_fault_routine = NULL;
0687   return (mem);
0688 }
0689 
0690 /* this function takes the 386 exception vector and attempts to
0691    translate this number into a unix compatible signal value */
0692 static int
0693 computeSignal (int exceptionVector)
0694 {
0695   int sigval;
0696   switch (exceptionVector)
0697     {
0698     case 0:
0699       sigval = 8;
0700       break;            /* divide by zero */
0701     case 1:
0702       sigval = 5;
0703       break;            /* debug exception */
0704     case 3:
0705       sigval = 5;
0706       break;            /* breakpoint */
0707     case 4:
0708       sigval = 16;
0709       break;            /* into instruction (overflow) */
0710     case 5:
0711       sigval = 16;
0712       break;            /* bound instruction */
0713     case 6:
0714       sigval = 4;
0715       break;            /* Invalid opcode */
0716     case 7:
0717       sigval = 8;
0718       break;            /* coprocessor not available */
0719     case 8:
0720       sigval = 7;
0721       break;            /* double fault */
0722     case 9:
0723       sigval = 11;
0724       break;            /* coprocessor segment overrun */
0725     case 10:
0726       sigval = 11;
0727       break;            /* Invalid TSS */
0728     case 11:
0729       sigval = 11;
0730       break;            /* Segment not present */
0731     case 12:
0732       sigval = 11;
0733       break;            /* stack exception */
0734     case 13:
0735       sigval = 11;
0736       break;            /* general protection */
0737     case 14:
0738       sigval = 11;
0739       break;            /* page fault */
0740     case 16:
0741       sigval = 7;
0742       break;            /* coprocessor error */
0743     default:
0744       sigval = 7;       /* "software generated" */
0745     }
0746   return (sigval);
0747 }
0748 
0749 /**********************************************/
0750 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
0751 /* RETURN NUMBER OF CHARS PROCESSED           */
0752 /**********************************************/
0753 static int
0754 hexToInt (char **ptr, int *intValue)
0755 {
0756   int numChars = 0;
0757   int hexValue;
0758 
0759   *intValue = 0;
0760 
0761   while (**ptr)
0762     {
0763       hexValue = hex (**ptr);
0764       if (hexValue >= 0)
0765     {
0766       *intValue = (*intValue << 4) | hexValue;
0767       numChars++;
0768     }
0769       else
0770     break;
0771 
0772       (*ptr)++;
0773     }
0774 
0775   return (numChars);
0776 }
0777 
0778 /*
0779  * Get/Set the DR registers.
0780  */
0781 static uint32_t getDR7(void)
0782 {
0783   uint32_t value = 0;
0784   asm volatile (" movl %%dr7, %0;" : "=r" (value) : : );
0785   return value;
0786 }
0787 
0788 static void setDR7(uint32_t value)
0789 {
0790   asm volatile (" movl %0, %%dr7;" : : "r" (value) : );
0791 }
0792 
0793 static uint32_t getDR(int reg)
0794 {
0795   uint32_t value = 0;
0796   switch (reg)
0797     {
0798     case 0:
0799       asm volatile (" movl %%dr0, %0;" : "=r" (value) : : );
0800       break;
0801     case 1:
0802       asm volatile (" movl %%dr1, %0;" : "=r" (value) : : );
0803       break;
0804     case 2:
0805       asm volatile (" movl %%dr2, %0;" : "=r" (value) : : );
0806       break;
0807     case 3:
0808       asm volatile (" movl %%dr3, %0;" : "=r" (value) : : );
0809       break;
0810     default:
0811       break;
0812     }
0813   return value;
0814 }
0815 
0816 static void setDR(int reg, uint32_t addr)
0817 {
0818   switch (reg)
0819     {
0820     case 0:
0821       asm volatile (" movl %0, %%dr0;" : : "r" (addr) : );
0822       break;
0823     case 1:
0824       asm volatile (" movl %0, %%dr1;" : : "r" (addr) : );
0825       break;
0826     case 2:
0827       asm volatile (" movl %0, %%dr2;" : : "r" (addr) : );
0828       break;
0829     case 3:
0830       asm volatile (" movl %0, %%dr3;" : : "r" (addr) : );
0831       break;
0832     default:
0833       break;
0834     }
0835 }
0836 
0837 /*
0838  * This function does all command procesing for interfacing to gdb.
0839  *
0840  * NOTE: This method is called from assembly code so must be marked
0841  *       as used.
0842  */
0843 static void handle_exception (int exceptionVector) __attribute__((used));
0844 static void
0845 handle_exception (int exceptionVector)
0846 {
0847   int sigval;
0848   int addr, length, reg;
0849   char *ptr;
0850 
0851   gdb_i386vector = exceptionVector;
0852 
0853   if (remote_debug)
0854     printk ("GDB: EXECPTION: vector=%d, sr=0x%x, pc=0x%x\n",
0855         exceptionVector,
0856         i386_gdb_registers[PS],
0857         i386_gdb_registers[PC]);
0858 
0859   /* Reply to host that an exception has occurred.  Always return the
0860      PC, SP, and FP, since gdb always wants them.  */
0861   ptr = remcomOutBuffer;
0862   *ptr++ = 'T';
0863   sigval = computeSignal (exceptionVector);
0864   *ptr++ = hexchars[sigval >> 4];
0865   *ptr++ = hexchars[sigval % 16];
0866 
0867   *ptr++ = hexchars[ESP];
0868   *ptr++ = ':';
0869   mem2hex ((char *) &i386_gdb_registers[ESP], ptr, REGBYTES, 0);
0870   ptr += REGBYTES * 2;
0871   *ptr++ = ';';
0872 
0873   *ptr++ = hexchars[EBP];
0874   *ptr++ = ':';
0875   mem2hex ((char *) &i386_gdb_registers[EBP], ptr, REGBYTES, 0);
0876   ptr += REGBYTES * 2;
0877   *ptr++ = ';';
0878 
0879   *ptr++ = hexchars[PC];
0880   *ptr++ = ':';
0881   mem2hex ((char *) &i386_gdb_registers[PC], ptr, REGBYTES, 0);
0882   ptr += REGBYTES * 2;
0883   *ptr++ = ';';
0884 
0885   *ptr = '\0';
0886 
0887   if (gdb_connected)
0888     putpacket (remcomOutBuffer);
0889 
0890   while (1 == 1)
0891     {
0892       error = 0;
0893       remcomOutBuffer[0] = 0;
0894       getpacket (remcomInBuffer);
0895       gdb_connected = 1;
0896       switch (remcomInBuffer[0])
0897     {
0898     case '?':
0899       remcomOutBuffer[0] = 'S';
0900       remcomOutBuffer[1] = hexchars[sigval >> 4];
0901       remcomOutBuffer[2] = hexchars[sigval % 16];
0902       remcomOutBuffer[3] = 0;
0903       break;
0904     case 'd': /* remove */
0905       remote_debug = !(remote_debug);   /* toggle debug flag */
0906       break;
0907     case 'g':       /* return the value of the CPU registers */
0908       mem2hex ((char *) i386_gdb_registers, remcomOutBuffer, NUMREGBYTES, 0);
0909       break;
0910     case 'G':       /* set the value of the CPU registers - return OK */
0911       hex2mem (&remcomInBuffer[1], (char *) i386_gdb_registers, NUMREGBYTES, 0);
0912       strcpy (remcomOutBuffer, "OK");
0913       break;
0914 
0915     case 'P':       /* Set specific register */
0916       ptr = &remcomInBuffer[1];
0917       if (hexToInt (&ptr, &reg)
0918           && *ptr++ == '=')
0919         {
0920           hex2mem (ptr, (char *) &i386_gdb_registers[reg], REGBYTES, 0);
0921           strcpy (remcomOutBuffer, "OK");
0922         }
0923       else
0924         {
0925           strcpy (remcomOutBuffer, "E01");
0926           debug_error ("malformed register set command; %s",
0927                remcomInBuffer);
0928         }
0929       break;
0930 
0931       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
0932     case 'm':
0933       /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
0934       ptr = &remcomInBuffer[1];
0935       if (hexToInt (&ptr, &addr))
0936         if (*(ptr++) == ',')
0937           if (hexToInt (&ptr, &length))
0938         {
0939           ptr = 0;
0940           mem_err = 0;
0941           mem2hex ((char *) addr, remcomOutBuffer, length, 1);
0942           if (mem_err)
0943             {
0944               strcpy (remcomOutBuffer, "E03");
0945               debug_error ("memory fault", 0);
0946             }
0947         }
0948 
0949       if (ptr)
0950         {
0951           strcpy (remcomOutBuffer, "E01");
0952           debug_error ("malformed read memory command: %s", remcomInBuffer);
0953         }
0954       break;
0955 
0956       /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
0957     case 'M':
0958       /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
0959       ptr = &remcomInBuffer[1];
0960       if (hexToInt (&ptr, &addr))
0961         if (*(ptr++) == ',')
0962           if (hexToInt (&ptr, &length))
0963         if (*(ptr++) == ':')
0964           {
0965             mem_err = 0;
0966             hex2mem (ptr, (char *) addr, length, 1);
0967 
0968             if (mem_err)
0969               {
0970             strcpy (remcomOutBuffer, "E03");
0971             debug_error ("memory fault", 0);
0972               }
0973             else
0974               {
0975             strcpy (remcomOutBuffer, "OK");
0976               }
0977 
0978             ptr = 0;
0979           }
0980       if (ptr)
0981         {
0982           strcpy (remcomOutBuffer, "E02");
0983           debug_error ("malformed write memory command: %s", remcomInBuffer);
0984         }
0985       break;
0986 
0987       /* cAA..AA    Continue at address AA..AA(optional) */
0988       /* sAA..AA   Step one instruction from AA..AA(optional) */
0989     case 'c':
0990     case 's':
0991       /* try to read optional parameter, pc unchanged if no parm */
0992       ptr = &remcomInBuffer[1];
0993       if (hexToInt (&ptr, &addr))
0994         i386_gdb_registers[PC] = addr;
0995 
0996       /* clear the trace bit */
0997       i386_gdb_registers[PS] &= 0xfffffeff;
0998 
0999       /* 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(RTEMS_FATAL_SOURCE_BSP, 0);
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 */
1120 void
1121 set_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 
1154 void
1155 breakpoint (void)
1156 {
1157   if (initialized)
1158     {
1159       BREAKPOINT ();
1160     }
1161   waitabit ();
1162 }
1163 
1164 int waitlimit = 1000000;
1165 
1166 void
1167 waitabit (void)
1168 {
1169   int i;
1170   for (i = 0; i < waitlimit; i++);
1171 }