[BACK]Return to gdb_stub.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / arch / i386 / i386

Annotation of prex-old/sys/arch/i386/i386/gdb_stub.c, Revision 1.1

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

CVSweb