ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

i386-stub-win32.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003                 THIS SOFTWARE IS NOT COPYRIGHTED
00004 
00005    HP offers the following for use in the public domain.  HP makes no
00006    warranty with regard to the software or it's performance and the
00007    user accepts the software "AS IS" with all faults.
00008 
00009    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
00010    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00011    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 
00013 ****************************************************************************/
00014 
00015 /****************************************************************************
00016  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
00017  *
00018  *  Module name: remcom.c $
00019  *  Revision: 1.34 $
00020  *  Date: 91/03/09 12:29:49 $
00021  *  Contributor:     Lake Stevens Instrument Division$
00022  *
00023  *  Description:     low level support for gdb debugger. $
00024  *
00025  *  Considerations:  only works on target hardware $
00026  *
00027  *  Written by:      Glenn Engel $
00028  *  ModuleState:     Experimental $
00029  *
00030  *  NOTES:           See Below $
00031  *
00032  *  Modified for 386 by Jim Kingdon, Cygnus Support.
00033  *
00034  *  To enable debugger support, two things need to happen.  One, a
00035  *  call to set_debug_traps() is necessary in order to allow any breakpoints
00036  *  or error conditions to be properly intercepted and reported to gdb.
00037  *  Two, a breakpoint needs to be generated to begin communication.  This
00038  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
00039  *  simulates a breakpoint by executing a trap #1.
00040  *
00041  *  The external function exceptionHandler() is
00042  *  used to attach a specific handler to a specific 386 vector number.
00043  *  It should use the same privilege level it runs at.  It should
00044  *  install it as an interrupt gate so that interrupts are masked
00045  *  while the handler runs.
00046  *
00047  *  Because gdb will sometimes write to the stack area to execute function
00048  *  calls, this program cannot rely on using the supervisor stack so it
00049  *  uses it's own stack area reserved in the int array remcomStack.
00050  *
00051  *************
00052  *
00053  *    The following gdb commands are supported:
00054  *
00055  * command          function                               Return value
00056  *
00057  *    g             return the value of the CPU registers  hex data or ENN
00058  *    G             set the value of the CPU registers     OK or ENN
00059  *
00060  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
00061  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
00062  *
00063  *    c             Resume at current address              SNN   ( signal NN)
00064  *    cAA..AA       Continue at address AA..AA             SNN
00065  *
00066  *    s             Step one instruction                   SNN
00067  *    sAA..AA       Step one instruction from AA..AA       SNN
00068  *
00069  *    k             kill
00070  *
00071  *    ?             What was the last sigval ?             SNN   (signal NN)
00072  *
00073  * All commands and responses are sent with a packet which includes a
00074  * checksum.  A packet consists of
00075  *
00076  * $<packet info>#<checksum>.
00077  *
00078  * where
00079  * <packet info> :: <characters representing the command or response>
00080  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
00081  *
00082  * When a packet is received, it is first acknowledged with either '+' or '-'.
00083  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
00084  *
00085  * Example:
00086  *
00087  * Host:                  Reply:
00088  * $m0,10#2a               +$00010203040506070809101112131415#42
00089  *
00090  ****************************************************************************/
00091 
00092 #include <stdio.h>
00093 #include <string.h>
00094 
00095 #include "utility/utility.h"    // for strcpy_s()
00096 
00097 /************************************************************************
00098  *
00099  * external low-level support routines
00100  */
00101 
00102 extern void putDebugChar();     /* write a single character      */
00103 extern int getDebugChar();      /* read and return a single char */
00104 extern void exceptionHandler(); /* assign an exception handler   */
00105 
00106 /************************************************************************/
00107 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
00108 /* at least NUMREGBYTES*2 are needed for register packets */
00109 #define BUFMAX 400
00110 
00111 static char initialized;  /* boolean flag. != 0 means we've been initialized */
00112 
00113 int     remote_debug;
00114 /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
00115 
00116 static const char hexchars[]="0123456789abcdef";
00117 
00118 /* Number of registers.  */
00119 #define NUMREGS 16
00120 
00121 /* Number of bytes of registers.  */
00122 #define NUMREGBYTES (NUMREGS * 4)
00123 
00124 enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
00125                PC /* also known as eip */,
00126                PS /* also known as eflags */,
00127                CS, SS, DS, ES, FS, GS};
00128 
00129 /*
00130  * these should not be static cuz they can be used outside this module
00131  */
00132 int registers[NUMREGS];
00133 
00134 #ifndef WIN32 //MF
00135 
00136 #define STACKSIZE 10000
00137 int remcomStack[STACKSIZE/sizeof(int)];
00138 static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
00139 
00140 /***************************  ASSEMBLY CODE MACROS *************************/
00141 /*                                                                         */
00142 
00143 extern void
00144 return_to_prog ();
00145 
00146 /* Restore the program's registers (including the stack pointer, which
00147    means we get the right stack and don't have to worry about popping our
00148    return address and any stack frames and so on) and return.  */
00149 asm(".text");
00150 asm(".globl _return_to_prog");
00151 asm("_return_to_prog:");
00152 asm("        movw _registers+44, %ss");
00153 asm("        movl _registers+16, %esp");
00154 asm("        movl _registers+4, %ecx");
00155 asm("        movl _registers+8, %edx");
00156 asm("        movl _registers+12, %ebx");
00157 asm("        movl _registers+20, %ebp");
00158 asm("        movl _registers+24, %esi");
00159 asm("        movl _registers+28, %edi");
00160 asm("        movw _registers+48, %ds");
00161 asm("        movw _registers+52, %es");
00162 asm("        movw _registers+56, %fs");
00163 asm("        movw _registers+60, %gs");
00164 asm("        movl _registers+36, %eax");
00165 asm("        pushl %eax");  /* saved eflags */
00166 asm("        movl _registers+40, %eax");
00167 asm("        pushl %eax");  /* saved cs */
00168 asm("        movl _registers+32, %eax");
00169 asm("        pushl %eax");  /* saved eip */
00170 asm("        movl _registers, %eax");
00171 
00172 asm("ret");     //MF
00173 
00174 /* use iret to restore pc and flags together so
00175    that trace flag works right.  */
00176 asm("        iret");
00177 
00178 
00179 #ifdef WIN32 //MF
00180 asm(".data"); //MF
00181 #endif
00182 
00183 /* Put the error code here just in case the user cares.  */
00184 int gdb_i386errcode;
00185 /* Likewise, the vector number here (since GDB only gets the signal
00186    number through the usual means, and that's not very specific).  */
00187 int gdb_i386vector = -1;
00188 
00189 /* GDB stores segment registers in 32-bit words (that's just the way
00190    m-i386v.h is written).  So zero the appropriate areas in registers.  */
00191 #define SAVE_REGISTERS1() \
00192   asm ("movl %eax, _registers");                                          \
00193   asm ("movl %ecx, _registers+4");                                           \
00194   asm ("movl %edx, _registers+8");                                           \
00195   asm ("movl %ebx, _registers+12");                                          \
00196   asm ("movl %ebp, _registers+20");                                          \
00197   asm ("movl %esi, _registers+24");                                          \
00198   asm ("movl %edi, _registers+28");                                          \
00199   asm ("movw $0, %ax");                                                      \
00200   asm ("movw %ds, _registers+48");                                           \
00201   asm ("movw %ax, _registers+50");                                           \
00202   asm ("movw %es, _registers+52");                                           \
00203   asm ("movw %ax, _registers+54");                                           \
00204   asm ("movw %fs, _registers+56");                                           \
00205   asm ("movw %ax, _registers+58");                                           \
00206   asm ("movw %gs, _registers+60");                                           \
00207   asm ("movw %ax, _registers+62");
00208 #define SAVE_ERRCODE() \
00209   asm ("popl %ebx");                                  \
00210   asm ("movl %ebx, _gdb_i386errcode");
00211 #define SAVE_REGISTERS2() \
00212   asm ("popl %ebx"); /* old eip */                                           \
00213   asm ("movl %ebx, _registers+32");                                          \
00214   asm ("popl %ebx");     /* old cs */                                        \
00215   asm ("movl %ebx, _registers+40");                                          \
00216   asm ("movw %ax, _registers+42");                                           \
00217   asm ("popl %ebx");     /* old eflags */                                    \
00218   asm ("movl %ebx, _registers+36");                                          \
00219   /* Now that we've done the pops, we can save the stack pointer.");  */   \
00220   asm ("movw %ss, _registers+44");                                           \
00221   asm ("movw %ax, _registers+46");                                           \
00222   asm ("movl %esp, _registers+16");
00223 
00224 /* See if mem_fault_routine is set, if so just IRET to that address.  */
00225 #define CHECK_FAULT() \
00226   asm ("cmpl $0, _mem_fault_routine");                                     \
00227   asm ("jne mem_fault");
00228 
00229 asm (".text");
00230 asm ("mem_fault:");
00231 /* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
00232 /* Pop error code from the stack and save it.  */
00233 asm ("     popl %eax");
00234 asm ("     movl %eax, _gdb_i386errcode");
00235 
00236 asm ("     popl %eax"); /* eip */
00237 /* We don't want to return there, we want to return to the function
00238    pointed to by mem_fault_routine instead.  */
00239 asm ("     movl _mem_fault_routine, %eax");
00240 asm ("     popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits).  */
00241 asm ("     popl %edx"); /* eflags */
00242 
00243 /* Remove this stack frame; when we do the iret, we will be going to
00244    the start of a function, so we want the stack to look just like it
00245    would after a "call" instruction.  */
00246 asm ("     leave");
00247 
00248 /* Push the stuff that iret wants.  */
00249 asm ("     pushl %edx"); /* eflags */
00250 asm ("     pushl %ecx"); /* cs */
00251 asm ("     pushl %eax"); /* eip */
00252 
00253 /* Zero mem_fault_routine.  */
00254 asm ("     movl $0, %eax");
00255 asm ("     movl %eax, _mem_fault_routine");
00256 
00257 asm ("iret");
00258 
00259 
00260 #define CALL_HOOK() asm("call _remcomHandler");
00261 
00262 /* This function is called when a i386 exception occurs.  It saves
00263  * all the cpu regs in the _registers array, munges the stack a bit,
00264  * and invokes an exception handler (remcom_handler).
00265  *
00266  * stack on entry:                       stack on exit:
00267  *   old eflags                          vector number
00268  *   old cs (zero-filled to 32 bits)
00269  *   old eip
00270  *
00271  */
00272 extern void _catchException3();
00273 asm(".text");
00274 asm(".globl __catchException3");
00275 asm("__catchException3:");
00276 SAVE_REGISTERS1();
00277 SAVE_REGISTERS2();
00278 asm ("pushl $3");
00279 CALL_HOOK();
00280 
00281 /* Same thing for exception 1.  */
00282 extern void _catchException1();
00283 asm(".text");
00284 asm(".globl __catchException1");
00285 asm("__catchException1:");
00286 SAVE_REGISTERS1();
00287 SAVE_REGISTERS2();
00288 asm ("pushl $1");
00289 CALL_HOOK();
00290 
00291 /* Same thing for exception 0.  */
00292 extern void _catchException0();
00293 asm(".text");
00294 asm(".globl __catchException0");
00295 asm("__catchException0:");
00296 SAVE_REGISTERS1();
00297 SAVE_REGISTERS2();
00298 asm ("pushl $0");
00299 CALL_HOOK();
00300 
00301 /* Same thing for exception 4.  */
00302 extern void _catchException4();
00303 asm(".text");
00304 asm(".globl __catchException4");
00305 asm("__catchException4:");
00306 SAVE_REGISTERS1();
00307 SAVE_REGISTERS2();
00308 asm ("pushl $4");
00309 CALL_HOOK();
00310 
00311 /* Same thing for exception 5.  */
00312 extern void _catchException5();
00313 asm(".text");
00314 asm(".globl __catchException5");
00315 asm("__catchException5:");
00316 SAVE_REGISTERS1();
00317 SAVE_REGISTERS2();
00318 asm ("pushl $5");
00319 CALL_HOOK();
00320 
00321 /* Same thing for exception 6.  */
00322 extern void _catchException6();
00323 asm(".text");
00324 asm(".globl __catchException6");
00325 asm("__catchException6:");
00326 SAVE_REGISTERS1();
00327 SAVE_REGISTERS2();
00328 asm ("pushl $6");
00329 CALL_HOOK();
00330 
00331 /* Same thing for exception 7.  */
00332 extern void _catchException7();
00333 asm(".text");
00334 asm(".globl __catchException7");
00335 asm("__catchException7:");
00336 SAVE_REGISTERS1();
00337 SAVE_REGISTERS2();
00338 asm ("pushl $7");
00339 CALL_HOOK();
00340 
00341 /* Same thing for exception 8.  */
00342 extern void _catchException8();
00343 asm(".text");
00344 asm(".globl __catchException8");
00345 asm("__catchException8:");
00346 SAVE_REGISTERS1();
00347 SAVE_ERRCODE();
00348 SAVE_REGISTERS2();
00349 asm ("pushl $8");
00350 CALL_HOOK();
00351 
00352 /* Same thing for exception 9.  */
00353 extern void _catchException9();
00354 asm(".text");
00355 asm(".globl __catchException9");
00356 asm("__catchException9:");
00357 SAVE_REGISTERS1();
00358 SAVE_REGISTERS2();
00359 asm ("pushl $9");
00360 CALL_HOOK();
00361 
00362 /* Same thing for exception 10.  */
00363 extern void _catchException10();
00364 asm(".text");
00365 asm(".globl __catchException10");
00366 asm("__catchException10:");
00367 SAVE_REGISTERS1();
00368 SAVE_ERRCODE();
00369 SAVE_REGISTERS2();
00370 asm ("pushl $10");
00371 CALL_HOOK();
00372 
00373 /* Same thing for exception 12.  */
00374 extern void _catchException12();
00375 asm(".text");
00376 asm(".globl __catchException12");
00377 asm("__catchException12:");
00378 SAVE_REGISTERS1();
00379 SAVE_ERRCODE();
00380 SAVE_REGISTERS2();
00381 asm ("pushl $12");
00382 CALL_HOOK();
00383 
00384 /* Same thing for exception 16.  */
00385 extern void _catchException16();
00386 asm(".text");
00387 asm(".globl __catchException16");
00388 asm("__catchException16:");
00389 SAVE_REGISTERS1();
00390 SAVE_REGISTERS2();
00391 asm ("pushl $16");
00392 CALL_HOOK();
00393 
00394 /* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
00395 
00396 /* Same thing for exception 13.  */
00397 extern void _catchException13 ();
00398 asm (".text");
00399 asm (".globl __catchException13");
00400 asm ("__catchException13:");
00401 CHECK_FAULT();
00402 SAVE_REGISTERS1();
00403 SAVE_ERRCODE();
00404 SAVE_REGISTERS2();
00405 asm ("pushl $13");
00406 CALL_HOOK();
00407 
00408 /* Same thing for exception 11.  */
00409 extern void _catchException11 ();
00410 asm (".text");
00411 asm (".globl __catchException11");
00412 asm ("__catchException11:");
00413 CHECK_FAULT();
00414 SAVE_REGISTERS1();
00415 SAVE_ERRCODE();
00416 SAVE_REGISTERS2();
00417 asm ("pushl $11");
00418 CALL_HOOK();
00419 
00420 /* Same thing for exception 14.  */
00421 extern void _catchException14 ();
00422 asm (".text");
00423 asm (".globl __catchException14");
00424 asm ("__catchException14:");
00425 CHECK_FAULT();
00426 SAVE_REGISTERS1();
00427 SAVE_ERRCODE();
00428 SAVE_REGISTERS2();
00429 asm ("pushl $14");
00430 CALL_HOOK();
00431 
00432 /*
00433  * remcomHandler is a front end for handle_exception.  It moves the
00434  * stack pointer into an area reserved for debugger use.
00435  */
00436 asm("_remcomHandler:");
00437 asm("           popl %eax");        /* pop off return address     */
00438 asm("           popl %eax");      /* get the exception number   */
00439 asm("       movl _stackPtr, %esp"); /* move to remcom stack area  */
00440 asm("       pushl %eax");    /* push exception onto stack  */
00441 asm("       call  _handle_exception");    /* this never returns */
00442 
00443 
00444 void
00445 _returnFromException ()
00446 {
00447   return_to_prog ();
00448 }
00449 
00450 #endif  // !WIN32
00451 
00452 
00453 #ifdef _MSC_VER //MF
00454 #define BREAKPOINT() __asm int 3;
00455 #else
00456 #define BREAKPOINT() asm("   int $3");
00457 #endif
00458 
00459 
00460 #ifdef WIN32 //MF
00461 
00462 #define WIN32_LEAN_AND_MEAN
00463 #include <windows.h>
00464 
00465 void handle_exception(int exceptionVector);
00466 
00467 void win32_exception_handler(EXCEPTION_POINTERS* exc_info)
00468 {
00469   PCONTEXT ctx = exc_info->ContextRecord;
00470 
00471   registers[EAX] = ctx->Eax;
00472   registers[ECX] = ctx->Ecx;
00473   registers[EDX] = ctx->Edx;
00474   registers[EBX] = ctx->Ebx;
00475   registers[ESP] = ctx->Esp;
00476   registers[EBP] = ctx->Ebp;
00477   registers[ESI] = ctx->Esi;
00478   registers[EDI] = ctx->Edi;
00479    registers[PC] = ctx->Eip;
00480    registers[PS] = ctx->EFlags;
00481   registers[CS] = ctx->SegCs;
00482   registers[SS] = ctx->SegSs;
00483   registers[DS] = ctx->SegDs;
00484   registers[ES] = ctx->SegEs;
00485   registers[FS] = ctx->SegFs;
00486   registers[GS] = ctx->SegGs;
00487 
00488   handle_exception(exc_info->ExceptionRecord->ExceptionCode & 0xFFFF);
00489 
00490   ctx->Eax = registers[EAX];
00491   ctx->Ecx = registers[ECX];
00492   ctx->Edx = registers[EDX];
00493   ctx->Ebx = registers[EBX];
00494   ctx->Esp = registers[ESP];
00495   ctx->Ebp = registers[EBP];
00496   ctx->Esi = registers[ESI];
00497   ctx->Edi = registers[EDI];
00498    ctx->Eip = registers[PC];
00499    ctx->EFlags = registers[PS];
00500   ctx->SegCs = registers[CS];
00501   ctx->SegSs = registers[SS];
00502   ctx->SegDs = registers[DS];
00503   ctx->SegEs = registers[ES];
00504   ctx->SegFs = registers[FS];
00505   ctx->SegGs = registers[GS];
00506 }
00507 
00508 #endif // WIN32
00509 
00510 
00511 int
00512 hex (ch)
00513      char ch;
00514 {
00515   if ((ch >= 'a') && (ch <= 'f'))
00516     return (ch - 'a' + 10);
00517   if ((ch >= '0') && (ch <= '9'))
00518     return (ch - '0');
00519   if ((ch >= 'A') && (ch <= 'F'))
00520     return (ch - 'A' + 10);
00521   return (-1);
00522 }
00523 
00524 static char remcomInBuffer[BUFMAX];
00525 static char remcomOutBuffer[BUFMAX];
00526 
00527 /* scan for the sequence $<data>#<checksum>     */
00528 
00529 char *
00530 getpacket (void)
00531 {
00532   char *buffer = &remcomInBuffer[0];
00533   unsigned char checksum;
00534   unsigned char xmitcsum;
00535   int count;
00536   char ch;
00537 
00538   while (1)
00539     {
00540       /* wait around for the start character, ignore all other characters */
00541       while ((ch = getDebugChar ()) != '$')
00542         ;
00543 
00544     retry:
00545       checksum = 0;
00546       xmitcsum = -1;
00547       count = 0;
00548 
00549       /* now, read until a # or end of buffer is found */
00550       while (count < BUFMAX - 1)
00551         {
00552           ch = getDebugChar ();
00553           if (ch == '$')
00554             goto retry;
00555           if (ch == '#')
00556             break;
00557           checksum = checksum + ch;
00558           buffer[count] = ch;
00559           count = count + 1;
00560         }
00561       buffer[count] = 0;
00562 
00563       if (ch == '#')
00564         {
00565           ch = getDebugChar ();
00566           xmitcsum = hex (ch) << 4;
00567           ch = getDebugChar ();
00568           xmitcsum += hex (ch);
00569 
00570           if (checksum != xmitcsum)
00571             {
00572               if (remote_debug)
00573                 {
00574                   fprintf (stderr,
00575                            "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
00576                            checksum, xmitcsum, buffer);
00577                 }
00578               putDebugChar ('-');       /* failed checksum */
00579             }
00580           else
00581             {
00582               putDebugChar ('+');       /* successful transfer */
00583 
00584               /* if a sequence char is present, reply the sequence ID */
00585               if (buffer[2] == ':')
00586                 {
00587                   putDebugChar (buffer[0]);
00588                   putDebugChar (buffer[1]);
00589 
00590                   return &buffer[3];
00591                 }
00592 
00593               return &buffer[0];
00594             }
00595         }
00596     }
00597 }
00598 
00599 /* send the packet in buffer.  */
00600 
00601 void
00602 putpacket (char *buffer)
00603 {
00604   unsigned char checksum;
00605   int count;
00606   char ch;
00607 
00608   /*  $<packet info>#<checksum>. */
00609   do
00610     {
00611       putDebugChar ('$');
00612       checksum = 0;
00613       count = 0;
00614 
00615       while ((ch = buffer[count]) != 0)
00616         {
00617           putDebugChar (ch);
00618           checksum += ch;
00619           count += 1;
00620         }
00621 
00622       putDebugChar ('#');
00623       putDebugChar (hexchars[checksum >> 4]);
00624       putDebugChar (hexchars[checksum % 16]);
00625 
00626     }
00627   while (getDebugChar () != '+');
00628 }
00629 
00630 void debug_error (char* format/*, char* parm*/)
00631 {
00632   if (remote_debug)
00633     fprintf (stderr, format/*, parm*/);
00634 }
00635 
00636 /* Address of a routine to RTE to if we get a memory fault.  */
00637 static void (*volatile mem_fault_routine) () = NULL;
00638 
00639 /* Indicate to caller of mem2hex or hex2mem that there has been an
00640    error.  */
00641 static volatile int mem_err = 0;
00642 
00643 void
00644 set_mem_err (void)
00645 {
00646   mem_err = 1;
00647 }
00648 
00649 /* These are separate functions so that they are so short and sweet
00650    that the compiler won't save any registers (if there is a fault
00651    to mem_fault, they won't get restored, so there better not be any
00652    saved).  */
00653 int
00654 get_char (char *addr)
00655 {
00656   return *addr;
00657 }
00658 
00659 void
00660 set_char (char *addr, int val)
00661 {
00662   *addr = val;
00663 }
00664 
00665 /* convert the memory pointed to by mem into hex, placing result in buf */
00666 /* return a pointer to the last char put in buf (null) */
00667 /* If MAY_FAULT is non-zero, then we should set mem_err in response to
00668    a fault; if zero treat a fault like any other fault in the stub.  */
00669 char *
00670 mem2hex (mem, buf, count, may_fault)
00671      char *mem;
00672      char *buf;
00673      int count;
00674      int may_fault;
00675 {
00676   int i;
00677   unsigned char ch;
00678 
00679 #ifdef WIN32 //MF
00680   if (IsBadReadPtr(mem, count))
00681     return mem;
00682 #else
00683   if (may_fault)
00684     mem_fault_routine = set_mem_err;
00685 #endif
00686   for (i = 0; i < count; i++)
00687     {
00688       ch = get_char (mem++);
00689       if (may_fault && mem_err)
00690         return (buf);
00691       *buf++ = hexchars[ch >> 4];
00692       *buf++ = hexchars[ch % 16];
00693     }
00694   *buf = 0;
00695 #ifndef WIN32 //MF
00696   if (may_fault)
00697     mem_fault_routine = NULL;
00698 #endif
00699   return (buf);
00700 }
00701 
00702 /* convert the hex array pointed to by buf into binary to be placed in mem */
00703 /* return a pointer to the character AFTER the last byte written */
00704 char *
00705 hex2mem (buf, mem, count, may_fault)
00706      char *buf;
00707      char *mem;
00708      int count;
00709      int may_fault;
00710 {
00711   int i;
00712   unsigned char ch;
00713 
00714 #ifdef WIN32 //MF
00715    // MinGW does not support structured exception handling, so let's
00716    // go safe and make memory writable by default
00717   DWORD old_protect;
00718 
00719   VirtualProtect(mem, count, PAGE_EXECUTE_READWRITE, &old_protect);
00720 #else
00721   if (may_fault)
00722     mem_fault_routine = set_mem_err;
00723 #endif
00724 
00725   for (i = 0; i < count; i++)
00726     {
00727       ch = hex (*buf++) << 4;
00728       ch = ch + hex (*buf++);
00729       set_char (mem++, ch);
00730       if (may_fault && mem_err)
00731         return (mem);
00732     }
00733 
00734 #ifndef WIN32 //MF
00735   if (may_fault)
00736     mem_fault_routine = NULL;
00737 #endif
00738 
00739   return (mem);
00740 }
00741 
00742 /* this function takes the 386 exception vector and attempts to
00743    translate this number into a unix compatible signal value */
00744 int
00745 computeSignal (int exceptionVector)
00746 {
00747   int sigval;
00748   switch (exceptionVector)
00749     {
00750     case 0:
00751       sigval = 8;
00752       break;                    /* divide by zero */
00753     case 1:
00754       sigval = 5;
00755       break;                    /* debug exception */
00756     case 3:
00757       sigval = 5;
00758       break;                    /* breakpoint */
00759     case 4:
00760       sigval = 16;
00761       break;                    /* into instruction (overflow) */
00762     case 5:
00763       sigval = 16;
00764       break;                    /* bound instruction */
00765     case 6:
00766       sigval = 4;
00767       break;                    /* Invalid opcode */
00768     case 7:
00769       sigval = 8;
00770       break;                    /* coprocessor not available */
00771     case 8:
00772       sigval = 7;
00773       break;                    /* double fault */
00774     case 9:
00775       sigval = 11;
00776       break;                    /* coprocessor segment overrun */
00777     case 10:
00778       sigval = 11;
00779       break;                    /* Invalid TSS */
00780     case 11:
00781       sigval = 11;
00782       break;                    /* Segment not present */
00783     case 12:
00784       sigval = 11;
00785       break;                    /* stack exception */
00786     case 13:
00787       sigval = 11;
00788       break;                    /* general protection */
00789     case 14:
00790       sigval = 11;
00791       break;                    /* page fault */
00792     case 16:
00793       sigval = 7;
00794       break;                    /* coprocessor error */
00795     default:
00796       sigval = 7;               /* "software generated" */
00797     }
00798   return (sigval);
00799 }
00800 
00801 /**********************************************/
00802 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
00803 /* RETURN NUMBER OF CHARS PROCESSED           */
00804 /**********************************************/
00805 int
00806 hexToInt (char **ptr, int *intValue)
00807 {
00808   int numChars = 0;
00809   int hexValue;
00810 
00811   *intValue = 0;
00812 
00813   while (**ptr)
00814     {
00815       hexValue = hex (**ptr);
00816       if (hexValue >= 0)
00817         {
00818           *intValue = (*intValue << 4) | hexValue;
00819           numChars++;
00820         }
00821       else
00822         break;
00823 
00824       (*ptr)++;
00825     }
00826 
00827   return (numChars);
00828 }
00829 
00830 /*
00831  * This function does all command procesing for interfacing to gdb.
00832  */
00833 void
00834 handle_exception (int exceptionVector)
00835 {
00836   int sigval, stepping;
00837   int addr, length;
00838   char *ptr;
00839 
00840 #ifndef WIN32 //MF
00841   gdb_i386vector = exceptionVector;
00842 #endif
00843 
00844   if (remote_debug)
00845     {
00846       printf ("vector=%d, sr=0x%x, pc=0x%x\n",
00847               exceptionVector, registers[PS], registers[PC]);
00848     }
00849 
00850   /* reply to host that an exception has occurred */
00851   sigval = computeSignal (exceptionVector);
00852 
00853   ptr = remcomOutBuffer;
00854 
00855   *ptr++ = 'T';                 /* notify gdb with signo, PC, FP and SP */
00856   *ptr++ = hexchars[sigval >> 4];
00857   *ptr++ = hexchars[sigval & 0xf];
00858 
00859   *ptr++ = hexchars[ESP];
00860   *ptr++ = ':';
00861   ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0);    /* SP */
00862   *ptr++ = ';';
00863 
00864   *ptr++ = hexchars[EBP];
00865   *ptr++ = ':';
00866   ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0);    /* FP */
00867   *ptr++ = ';';
00868 
00869   *ptr++ = hexchars[PC];
00870   *ptr++ = ':';
00871   ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);     /* PC */
00872   *ptr++ = ';';
00873 
00874   *ptr = '\0';
00875 
00876   putpacket (remcomOutBuffer);
00877 
00878   stepping = 0;
00879 
00880   while (1 == 1)
00881     {
00882       remcomOutBuffer[0] = 0;
00883       ptr = getpacket ();
00884 
00885       switch (*ptr++)
00886         {
00887         case '?':
00888           remcomOutBuffer[0] = 'S';
00889           remcomOutBuffer[1] = hexchars[sigval >> 4];
00890           remcomOutBuffer[2] = hexchars[sigval % 16];
00891           remcomOutBuffer[3] = 0;
00892           break;
00893         case 'd':
00894           remote_debug = !(remote_debug);       /* toggle debug flag */
00895           break;
00896         case 'g':               /* return the value of the CPU registers */
00897           mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
00898           break;
00899         case 'G':               /* set the value of the CPU registers - return OK */
00900           hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
00901           strcpy_s(remcomOutBuffer, BUFMAX, "OK");
00902           break;
00903         case 'P':               /* set the value of a single CPU register - return OK */
00904           {
00905             int regno;
00906 
00907             if (hexToInt (&ptr, &regno) && *ptr++ == '=')
00908               if (regno >= 0 && regno < NUMREGS)
00909                 {
00910                   hex2mem (ptr, (char *) &registers[regno], 4, 0);
00911                   strcpy_s(remcomOutBuffer, BUFMAX, "OK");
00912                   break;
00913                 }
00914 
00915             strcpy_s(remcomOutBuffer, BUFMAX, "E01");
00916             break;
00917           }
00918 
00919           /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
00920         case 'm':
00921           /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
00922           if (hexToInt (&ptr, &addr))
00923             if (*(ptr++) == ',')
00924               if (hexToInt (&ptr, &length))
00925                 {
00926                   ptr = 0;
00927                   mem_err = 0;
00928                   mem2hex ((char *) addr, remcomOutBuffer, length, 1);
00929                   if (mem_err)
00930                     {
00931                       strcpy_s(remcomOutBuffer, BUFMAX, "E03");
00932                       debug_error ("memory fault");
00933                     }
00934                 }
00935 
00936           if (ptr)
00937             {
00938               strcpy_s(remcomOutBuffer, BUFMAX, "E01");
00939             }
00940           break;
00941 
00942           /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
00943         case 'M':
00944           /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
00945           if (hexToInt (&ptr, &addr))
00946             if (*(ptr++) == ',')
00947               if (hexToInt (&ptr, &length))
00948                 if (*(ptr++) == ':')
00949                   {
00950                     mem_err = 0;
00951                     hex2mem (ptr, (char *) addr, length, 1);
00952 
00953                     if (mem_err)
00954                       {
00955                         strcpy_s(remcomOutBuffer, BUFMAX, "E03");
00956                         debug_error ("memory fault");
00957                       }
00958                     else
00959                       {
00960                         strcpy_s(remcomOutBuffer, BUFMAX, "OK");
00961                       }
00962 
00963                     ptr = 0;
00964                   }
00965           if (ptr)
00966             {
00967               strcpy_s(remcomOutBuffer, BUFMAX, "E02");
00968             }
00969           break;
00970 
00971           /* cAA..AA    Continue at address AA..AA(optional) */
00972           /* sAA..AA   Step one instruction from AA..AA(optional) */
00973         case 's':
00974           stepping = 1;
00975         case 'c':
00976           /* try to read optional parameter, pc unchanged if no parm */
00977           if (hexToInt (&ptr, &addr))
00978             registers[PC] = addr;
00979 
00980           /* clear the trace bit */
00981           registers[PS] &= 0xfffffeff;
00982 
00983           /* set the trace bit if we're stepping */
00984           if (stepping)
00985             registers[PS] |= 0x100;
00986 
00987 #ifdef WIN32 //MF
00988           return;
00989 #else
00990           _returnFromException ();      /* this is a jump */
00991 #endif
00992           break;
00993 
00994           /* kill the program */
00995         case 'k':               /* do nothing */
00996 #if 0
00997           /* Huh? This doesn't look like "nothing".
00998              m68k-stub.c and sparc-stub.c don't have it.  */
00999           BREAKPOINT ();
01000 #endif
01001           break;
01002         }                       /* switch */
01003 
01004       /* reply to the request */
01005       putpacket (remcomOutBuffer);
01006     }
01007 }
01008 
01009 /* this function is used to set up exception handlers for tracing and
01010    breakpoints */
01011 void
01012 set_debug_traps (void)
01013 {
01014 #ifndef WIN32 //MF
01015   stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
01016 
01017   exceptionHandler (0, _catchException0);
01018   exceptionHandler (1, _catchException1);
01019   exceptionHandler (3, _catchException3);
01020   exceptionHandler (4, _catchException4);
01021   exceptionHandler (5, _catchException5);
01022   exceptionHandler (6, _catchException6);
01023   exceptionHandler (7, _catchException7);
01024   exceptionHandler (8, _catchException8);
01025   exceptionHandler (9, _catchException9);
01026   exceptionHandler (10, _catchException10);
01027   exceptionHandler (11, _catchException11);
01028   exceptionHandler (12, _catchException12);
01029   exceptionHandler (13, _catchException13);
01030   exceptionHandler (14, _catchException14);
01031   exceptionHandler (16, _catchException16);
01032 #endif // WIN32
01033 
01034   initialized = 1;
01035 }
01036 
01037 /* This function will generate a breakpoint exception.  It is used at the
01038    beginning of a program to sync up with a debugger and can be used
01039    otherwise as a quick means to stop program execution and "break" into
01040    the debugger. */
01041 
01042 void
01043 breakpoint (void)
01044 {
01045   if (initialized)
01046     BREAKPOINT ();
01047 }
01048 
01049 
01050 
01051  //
01052  // debugger stub implementation for WIN32 applications
01053  // M. Fuchs, 29.11.2003
01054  //
01055 
01056 #ifdef WIN32
01057 
01058 #include <stdlib.h>
01059 #include <errno.h>
01060 
01061 #include "utility/utility.h"
01062 
01063 
01064 int s_initial_breakpoint = 0;
01065 
01066 
01067 #ifdef DEBUG_SERIAL
01068 
01069 FILE* ser_port = NULL;
01070 
01071 int init_gdb_connect()
01072 {
01073          //TODO: set up connection using serial communication port
01074 
01075         ser_port = fopen("COM1:", "rwb");
01076 
01077         return 1;
01078 }
01079 
01080 int getDebugChar()
01081 {
01082         return fgetc(ser_port);
01083 }
01084 
01085 void putDebugChar(int c)
01086 {
01087         fputc(c, ser_port);
01088 }
01089 
01090 
01091 #else // DEBUG_SERIAL
01092 
01093 
01094 static LPTOP_LEVEL_EXCEPTION_FILTER s_prev_exc_handler = 0;
01095 
01096 
01097 #define I386_EXCEPTION_CNT      17
01098 
01099 LONG WINAPI exc_protection_handler(EXCEPTION_POINTERS* exc_info)
01100 {
01101         int exc_nr = exc_info->ExceptionRecord->ExceptionCode & 0xFFFF;
01102 
01103         if (exc_nr < I386_EXCEPTION_CNT) {
01104                 //LOG(FmtString(TEXT("exc_protection_handler: Exception %x"), exc_nr));
01105 
01106                 if (exc_nr==11 || exc_nr==13 || exc_nr==14) {
01107                         if (mem_fault_routine)
01108                                 mem_fault_routine();
01109                 }
01110 
01111                 ++exc_info->ContextRecord->Eip;
01112         }
01113 
01114         return EXCEPTION_CONTINUE_EXECUTION;
01115 }
01116 
01117 LONG WINAPI exc_handler(EXCEPTION_POINTERS* exc_info)
01118 {
01119         int exc_nr = exc_info->ExceptionRecord->ExceptionCode & 0xFFFF;
01120 
01121         if (exc_nr < I386_EXCEPTION_CNT) {
01122                 //LOG(FmtString("Exception %x", exc_nr));
01123                 //LOG(FmtString("EIP=%08X EFLAGS=%08X", exc_info->ContextRecord->Eip, exc_info->ContextRecord->EFlags));
01124 
01125                  // step over initial breakpoint
01126                 if (s_initial_breakpoint) {
01127                         s_initial_breakpoint = 0;
01128                         ++exc_info->ContextRecord->Eip;
01129                 }
01130 
01131                 SetUnhandledExceptionFilter(exc_protection_handler);
01132 
01133                 win32_exception_handler(exc_info);
01134                 //LOG(FmtString("EIP=%08X EFLAGS=%08X", exc_info->ContextRecord->Eip, exc_info->ContextRecord->EFlags));
01135 
01136                 SetUnhandledExceptionFilter(exc_handler);
01137 
01138                 return EXCEPTION_CONTINUE_EXECUTION;
01139         }
01140 
01141         return EXCEPTION_CONTINUE_SEARCH;
01142 }
01143 
01144 /* not needed because we use win32_exception_handler() instead of catchExceptionX()
01145 void exceptionHandler(int exc_nr, void* exc_addr)
01146 {
01147         if (exc_nr>=0 && exc_nr<I386_EXCEPTION_CNT)
01148                 exc_handlers[exc_nr] = exc_addr;
01149 }
01150 */
01151 
01152 void disable_debugging()
01153 {
01154         if (s_prev_exc_handler) {
01155                 SetUnhandledExceptionFilter(s_prev_exc_handler);
01156                 s_prev_exc_handler = 0;
01157         }
01158 }
01159 
01160 
01161 #include <winsock.h>
01162 #ifdef _MSC_VER
01163 #pragma comment(lib, "wsock32")
01164 #endif
01165 
01166 static int s_rem_fd = -1;
01167 
01168 int init_gdb_connect()
01169 {
01170         SOCKADDR_IN srv_addr = {0};
01171         SOCKADDR_IN rem_addr;
01172         WSADATA wsa_data;
01173         int srv_socket, rem_len;
01174 
01175         s_prev_exc_handler = SetUnhandledExceptionFilter(exc_handler);
01176 
01177         if (WSAStartup(MAKEWORD(2,2), &wsa_data)) {
01178                 fprintf(stderr, "WSAStartup() failed");
01179                 return 0;
01180         }
01181 
01182         srv_addr.sin_family = AF_INET;
01183         srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
01184         srv_addr.sin_port = htons(9999);
01185 
01186         srv_socket = socket(PF_INET, SOCK_STREAM, 0);
01187         if (srv_socket == -1) {
01188                 perror("socket()");
01189                 return 0;
01190         }
01191 
01192         if (bind(srv_socket, (struct sockaddr*) &srv_addr, sizeof(srv_addr)) == -1) {
01193                 perror("bind()");
01194                 return 0;
01195         }
01196 
01197         if (listen(srv_socket, 4) == -1) {
01198                 perror("listen()");
01199                 return 0;
01200         }
01201 
01202         rem_len = sizeof(rem_addr);
01203 
01204         for(;;) {
01205                 s_rem_fd = accept(srv_socket, (struct sockaddr*)&rem_addr, &rem_len);
01206 
01207                 if (s_rem_fd < 0) {
01208                         if (errno == EINTR)
01209                                 continue;
01210 
01211                         perror("accept()");
01212                         return 0;
01213                 }
01214 
01215                 break;
01216         }
01217 
01218         return 1;
01219 }
01220 
01221 #endif // DEBUG_SERIAL
01222 
01223 
01224 int getDebugChar()
01225 {
01226         char buffer[1024];
01227         int r;
01228 
01229         if (s_rem_fd == -1)
01230                 return EOF;
01231 
01232         r = recv(s_rem_fd, buffer, 1, 0);
01233         if (r == -1) {
01234                 perror("recv()");
01235                 LOG(TEXT("debugger connection broken"));
01236                 s_rem_fd = -1;
01237                 return EOF;
01238         }
01239 
01240         if (!r)
01241                 return EOF;
01242 
01243         return buffer[0];
01244 }
01245 
01246 void putDebugChar(int c)
01247 {
01248         if (s_rem_fd != -1) {
01249                 const char buffer[] = {c};
01250 
01251                 if (!send(s_rem_fd, buffer, 1, 0)) {
01252                         perror("send()");
01253                         LOG(TEXT("debugger connection broken"));
01254                         exit(-1);
01255                 }
01256         }
01257 }
01258 
01259 
01260  // start up GDB stub interface
01261 
01262 int initialize_gdb_stub()
01263 {
01264         if (!init_gdb_connect())
01265                 return 0;
01266 
01267         set_debug_traps();
01268 
01269         s_initial_breakpoint = 1;
01270         breakpoint();
01271 
01272         return 1;
01273 }
01274 
01275 #endif // WIN32

Generated on Sat May 26 2012 04:17:29 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.