📄 i386-stub-win32.c
字号:
SAVE_REGISTERS2();
asm ("pushl $14");
CALL_HOOK();
/*
* remcomHandler is a front end for handle_exception. It moves the
* stack pointer into an area reserved for debugger use.
*/
asm("_remcomHandler:");
asm(" popl %eax"); /* pop off return address */
asm(" popl %eax"); /* get the exception number */
asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
asm(" pushl %eax"); /* push exception onto stack */
asm(" call _handle_exception"); /* this never returns */
void
_returnFromException ()
{
return_to_prog ();
}
#endif // !WIN32
#ifdef _MSC_VER //MF
#define BREAKPOINT() __asm int 3;
#else
#define BREAKPOINT() asm(" int $3");
#endif
#ifdef WIN32 //MF
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void handle_exception(int exceptionVector);
void win32_exception_handler(EXCEPTION_POINTERS* exc_info)
{
PCONTEXT ctx = exc_info->ContextRecord;
registers[EAX] = ctx->Eax;
registers[ECX] = ctx->Ecx;
registers[EDX] = ctx->Edx;
registers[EBX] = ctx->Ebx;
registers[ESP] = ctx->Esp;
registers[EBP] = ctx->Ebp;
registers[ESI] = ctx->Esi;
registers[EDI] = ctx->Edi;
registers[PC] = ctx->Eip;
registers[PS] = ctx->EFlags;
registers[CS] = ctx->SegCs;
registers[SS] = ctx->SegSs;
registers[DS] = ctx->SegDs;
registers[ES] = ctx->SegEs;
registers[FS] = ctx->SegFs;
registers[GS] = ctx->SegGs;
handle_exception(exc_info->ExceptionRecord->ExceptionCode & 0xFFFF);
ctx->Eax = registers[EAX];
ctx->Ecx = registers[ECX];
ctx->Edx = registers[EDX];
ctx->Ebx = registers[EBX];
ctx->Esp = registers[ESP];
ctx->Ebp = registers[EBP];
ctx->Esi = registers[ESI];
ctx->Edi = registers[EDI];
ctx->Eip = registers[PC];
ctx->EFlags = registers[PS];
ctx->SegCs = registers[CS];
ctx->SegSs = registers[SS];
ctx->SegDs = registers[DS];
ctx->SegEs = registers[ES];
ctx->SegFs = registers[FS];
ctx->SegGs = registers[GS];
}
#endif // WIN32
int
hex (ch)
char ch;
{
if ((ch >= 'a') && (ch <= 'f'))
return (ch - 'a' + 10);
if ((ch >= '0') && (ch <= '9'))
return (ch - '0');
if ((ch >= 'A') && (ch <= 'F'))
return (ch - 'A' + 10);
return (-1);
}
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
/* scan for the sequence $<data>#<checksum> */
char *
getpacket (void)
{
char *buffer = &remcomInBuffer[0];
unsigned char checksum;
unsigned char xmitcsum;
int count;
char ch;
while (1)
{
/* wait around for the start character, ignore all other characters */
while ((ch = getDebugChar ()) != '$')
;
retry:
checksum = 0;
xmitcsum = -1;
count = 0;
/* now, read until a # or end of buffer is found */
while (count < BUFMAX)
{
ch = getDebugChar ();
if (ch == '$')
goto retry;
if (ch == '#')
break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
buffer[count] = 0;
if (ch == '#')
{
ch = getDebugChar ();
xmitcsum = hex (ch) << 4;
ch = getDebugChar ();
xmitcsum += hex (ch);
if (checksum != xmitcsum)
{
if (remote_debug)
{
fprintf (stderr,
"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
checksum, xmitcsum, buffer);
}
putDebugChar ('-'); /* failed checksum */
}
else
{
putDebugChar ('+'); /* successful transfer */
/* if a sequence char is present, reply the sequence ID */
if (buffer[2] == ':')
{
putDebugChar (buffer[0]);
putDebugChar (buffer[1]);
return &buffer[3];
}
return &buffer[0];
}
}
}
}
/* send the packet in buffer. */
void
putpacket (char *buffer)
{
unsigned char checksum;
int count;
char ch;
/* $<packet info>#<checksum>. */
do
{
putDebugChar ('$');
checksum = 0;
count = 0;
while ((ch = buffer[count]) != 0)
{
putDebugChar (ch);
checksum += ch;
count += 1;
}
putDebugChar ('#');
putDebugChar (hexchars[checksum >> 4]);
putDebugChar (hexchars[checksum % 16]);
}
while (getDebugChar () != '+');
}
void debug_error (char* format/*, char* parm*/)
{
if (remote_debug)
fprintf (stderr, format/*, parm*/);
}
/* Address of a routine to RTE to if we get a memory fault. */
static void (*volatile mem_fault_routine) () = NULL;
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
static volatile int mem_err = 0;
void
set_mem_err (void)
{
mem_err = 1;
}
/* These are separate functions so that they are so short and sweet
that the compiler won't save any registers (if there is a fault
to mem_fault, they won't get restored, so there better not be any
saved). */
int
get_char (char *addr)
{
return *addr;
}
void
set_char (char *addr, int val)
{
*addr = val;
}
/* convert the memory pointed to by mem into hex, placing result in buf */
/* return a pointer to the last char put in buf (null) */
/* If MAY_FAULT is non-zero, then we should set mem_err in response to
a fault; if zero treat a fault like any other fault in the stub. */
char *
mem2hex (mem, buf, count, may_fault)
char *mem;
char *buf;
int count;
int may_fault;
{
int i;
unsigned char ch;
#ifdef WIN32 //MF
if (IsBadReadPtr(mem, count))
return mem;
#else
if (may_fault)
mem_fault_routine = set_mem_err;
#endif
for (i = 0; i < count; i++)
{
ch = get_char (mem++);
if (may_fault && mem_err)
return (buf);
*buf++ = hexchars[ch >> 4];
*buf++ = hexchars[ch % 16];
}
*buf = 0;
#ifndef WIN32 //MF
if (may_fault)
mem_fault_routine = NULL;
#endif
return (buf);
}
/* convert the hex array pointed to by buf into binary to be placed in mem */
/* return a pointer to the character AFTER the last byte written */
char *
hex2mem (buf, mem, count, may_fault)
char *buf;
char *mem;
int count;
int may_fault;
{
int i;
unsigned char ch;
#ifdef WIN32 //MF
// MinGW does not support structured exception handling, so let's
// go safe and make memory writable by default
DWORD old_protect;
VirtualProtect(mem, count, PAGE_EXECUTE_READWRITE, &old_protect);
#else
if (may_fault)
mem_fault_routine = set_mem_err;
#endif
for (i = 0; i < count; i++)
{
ch = hex (*buf++) << 4;
ch = ch + hex (*buf++);
set_char (mem++, ch);
if (may_fault && mem_err)
return (mem);
}
#ifndef WIN32 //MF
if (may_fault)
mem_fault_routine = NULL;
#endif
return (mem);
}
/* this function takes the 386 exception vector and attempts to
translate this number into a unix compatible signal value */
int
computeSignal (int exceptionVector)
{
int sigval;
switch (exceptionVector)
{
case 0:
sigval = 8;
break; /* divide by zero */
case 1:
sigval = 5;
break; /* debug exception */
case 3:
sigval = 5;
break; /* breakpoint */
case 4:
sigval = 16;
break; /* into instruction (overflow) */
case 5:
sigval = 16;
break; /* bound instruction */
case 6:
sigval = 4;
break; /* Invalid opcode */
case 7:
sigval = 8;
break; /* coprocessor not available */
case 8:
sigval = 7;
break; /* double fault */
case 9:
sigval = 11;
break; /* coprocessor segment overrun */
case 10:
sigval = 11;
break; /* Invalid TSS */
case 11:
sigval = 11;
break; /* Segment not present */
case 12:
sigval = 11;
break; /* stack exception */
case 13:
sigval = 11;
break; /* general protection */
case 14:
sigval = 11;
break; /* page fault */
case 16:
sigval = 7;
break; /* coprocessor error */
default:
sigval = 7; /* "software generated" */
}
return (sigval);
}
/**********************************************/
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
/* RETURN NUMBER OF CHARS PROCESSED */
/**********************************************/
int
hexToInt (char **ptr, int *intValue)
{
int numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr)
{
hexValue = hex (**ptr);
if (hexValue >= 0)
{
*intValue = (*intValue << 4) | hexValue;
numChars++;
}
else
break;
(*ptr)++;
}
return (numChars);
}
/*
* This function does all command procesing for interfacing to gdb.
*/
void
handle_exception (int exceptionVector)
{
int sigval, stepping;
int addr, length;
char *ptr;
int newPC;
#ifndef WIN32 //MF
gdb_i386vector = exceptionVector;
#endif
if (remote_debug)
{
printf ("vector=%d, sr=0x%x, pc=0x%x\n",
exceptionVector, registers[PS], registers[PC]);
}
/* reply to host that an exception has occurred */
sigval = computeSignal (exceptionVector);
ptr = remcomOutBuffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -