#include <stdio.h>
#include <string.h>
extern void putDebugChar();
extern int getDebugChar();
extern void exceptionHandler();
#define BUFMAX 400
static char initialized;
int remote_debug;
static const char hexchars[]="0123456789abcdef";
#define NUMREGS 16
#define NUMREGBYTES (NUMREGS * 4)
enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
PC ,
PS ,
CS, SS, DS, ES, FS, GS};
int registers[NUMREGS];
#define STACKSIZE 10000
int remcomStack[STACKSIZE/sizeof(int)];
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
extern void
return_to_prog ();
asm(".text");
asm(".globl _return_to_prog");
asm("_return_to_prog:");
asm(" movw _registers+44, %ss");
asm(" movl _registers+16, %esp");
asm(" movl _registers+4, %ecx");
asm(" movl _registers+8, %edx");
asm(" movl _registers+12, %ebx");
asm(" movl _registers+20, %ebp");
asm(" movl _registers+24, %esi");
asm(" movl _registers+28, %edi");
asm(" movw _registers+48, %ds");
asm(" movw _registers+52, %es");
asm(" movw _registers+56, %fs");
asm(" movw _registers+60, %gs");
asm(" movl _registers+36, %eax");
asm(" pushl %eax");
asm(" movl _registers+40, %eax");
asm(" pushl %eax");
asm(" movl _registers+32, %eax");
asm(" pushl %eax");
asm(" movl _registers, %eax");
asm(" iret");
#define BREAKPOINT() asm(" int $3");
int gdb_i386errcode;
int gdb_i386vector = -1;
#define SAVE_REGISTERS1() \
asm ("movl %eax, _registers"); \
asm ("movl %ecx, _registers+4"); \
asm ("movl %edx, _registers+8"); \
asm ("movl %ebx, _registers+12"); \
asm ("movl %ebp, _registers+20"); \
asm ("movl %esi, _registers+24"); \
asm ("movl %edi, _registers+28"); \
asm ("movw $0, %ax"); \
asm ("movw %ds, _registers+48"); \
asm ("movw %ax, _registers+50"); \
asm ("movw %es, _registers+52"); \
asm ("movw %ax, _registers+54"); \
asm ("movw %fs, _registers+56"); \
asm ("movw %ax, _registers+58"); \
asm ("movw %gs, _registers+60"); \
asm ("movw %ax, _registers+62");
#define SAVE_ERRCODE() \
asm ("popl %ebx"); \
asm ("movl %ebx, _gdb_i386errcode");
#define SAVE_REGISTERS2() \
asm ("popl %ebx"); \
asm ("movl %ebx, _registers+32"); \
asm ("popl %ebx"); \
asm ("movl %ebx, _registers+40"); \
asm ("movw %ax, _registers+42"); \
asm ("popl %ebx"); \
asm ("movl %ebx, _registers+36"); \
\
asm ("movw %ss, _registers+44"); \
asm ("movw %ax, _registers+46"); \
asm ("movl %esp, _registers+16");
#define CHECK_FAULT() \
asm ("cmpl $0, _mem_fault_routine"); \
asm ("jne mem_fault");
asm (".text");
asm ("mem_fault:");
asm (" popl %eax");
asm (" movl %eax, _gdb_i386errcode");
asm (" popl %eax");
asm (" movl _mem_fault_routine, %eax");
asm (" popl %ecx");
asm (" popl %edx");
asm (" leave");
asm (" pushl %edx");
asm (" pushl %ecx");
asm (" pushl %eax");
asm (" movl $0, %eax");
asm (" movl %eax, _mem_fault_routine");
asm ("iret");
#define CALL_HOOK() asm("call _remcomHandler");
extern void _catchException3();
asm(".text");
asm(".globl __catchException3");
asm("__catchException3:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $3");
CALL_HOOK();
extern void _catchException1();
asm(".text");
asm(".globl __catchException1");
asm("__catchException1:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $1");
CALL_HOOK();
extern void _catchException0();
asm(".text");
asm(".globl __catchException0");
asm("__catchException0:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $0");
CALL_HOOK();
extern void _catchException4();
asm(".text");
asm(".globl __catchException4");
asm("__catchException4:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $4");
CALL_HOOK();
extern void _catchException5();
asm(".text");
asm(".globl __catchException5");
asm("__catchException5:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $5");
CALL_HOOK();
extern void _catchException6();
asm(".text");
asm(".globl __catchException6");
asm("__catchException6:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $6");
CALL_HOOK();
extern void _catchException7();
asm(".text");
asm(".globl __catchException7");
asm("__catchException7:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $7");
CALL_HOOK();
extern void _catchException8();
asm(".text");
asm(".globl __catchException8");
asm("__catchException8:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $8");
CALL_HOOK();
extern void _catchException9();
asm(".text");
asm(".globl __catchException9");
asm("__catchException9:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $9");
CALL_HOOK();
extern void _catchException10();
asm(".text");
asm(".globl __catchException10");
asm("__catchException10:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $10");
CALL_HOOK();
extern void _catchException12();
asm(".text");
asm(".globl __catchException12");
asm("__catchException12:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $12");
CALL_HOOK();
extern void _catchException16();
asm(".text");
asm(".globl __catchException16");
asm("__catchException16:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $16");
CALL_HOOK();
extern void _catchException13 ();
asm (".text");
asm (".globl __catchException13");
asm ("__catchException13:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $13");
CALL_HOOK();
extern void _catchException11 ();
asm (".text");
asm (".globl __catchException11");
asm ("__catchException11:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $11");
CALL_HOOK();
extern void _catchException14 ();
asm (".text");
asm (".globl __catchException14");
asm ("__catchException14:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $14");
CALL_HOOK();
asm("_remcomHandler:");
asm(" popl %eax");
asm(" popl %eax");
asm(" movl _stackPtr, %esp");
asm(" pushl %eax");
asm(" call _handle_exception");
void _returnFromException()
{
return_to_prog ();
}
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];
unsigned char *
getpacket (void)
{
unsigned char *buffer = &remcomInBuffer[0];
unsigned char checksum;
unsigned char xmitcsum;
int count;
char ch;
while (1)
{
while ((ch = getDebugChar ()) != '$')
;
retry:
checksum = 0;
xmitcsum = -1;
count = 0;
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 ('-');
}
else
{
putDebugChar ('+');
if (buffer[2] == ':')
{
putDebugChar (buffer[0]);
putDebugChar (buffer[1]);
return &buffer[3];
}
return &buffer[0];
}
}
}
}
void putpacket(buffer)
unsigned char *buffer;
{
unsigned char checksum;
int count;
char ch;
do {
putDebugChar('$');
checksum = 0;
count = 0;
while (ch=buffer[count]) {
putDebugChar(ch);
checksum += ch;
count += 1;
}
putDebugChar('#');
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum % 16]);
} while (getDebugChar() != '+');
}
void debug_error(format, parm)
char * format;
char * parm;
{
if (remote_debug) fprintf (stderr,format,parm);
}
static void (*volatile mem_fault_routine)() = NULL;
static volatile int mem_err = 0;
void
set_mem_err (void)
{
mem_err = 1;
}
int
get_char (char *addr)
{
return *addr;
}
void
set_char (char *addr, int val)
{
*addr = val;
}
char* mem2hex(mem, buf, count, may_fault)
char* mem;
char* buf;
int count;
int may_fault;
{
int i;
unsigned char ch;
if (may_fault)
mem_fault_routine = set_mem_err;
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;
if (may_fault)
mem_fault_routine = NULL;
return(buf);
}
char* hex2mem(buf, mem, count, may_fault)
char* buf;
char* mem;
int count;
int may_fault;
{
int i;
unsigned char ch;
if (may_fault)
mem_fault_routine = set_mem_err;
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);
}
if (may_fault)
mem_fault_routine = NULL;
return(mem);
}
int computeSignal( exceptionVector )
int exceptionVector;
{
int sigval;
switch (exceptionVector) {
case 0 : sigval = 8; break;
case 1 : sigval = 5; break;
case 3 : sigval = 5; break;
case 4 : sigval = 16; break;
case 5 : sigval = 16; break;
case 6 : sigval = 4; break;
case 7 : sigval = 8; break;
case 8 : sigval = 7; break;
case 9 : sigval = 11; break;
case 10 : sigval = 11; break;
case 11 : sigval = 11; break;
case 12 : sigval = 11; break;
case 13 : sigval = 11; break;
case 14 : sigval = 11; break;
case 16 : sigval = 7; break;
default:
sigval = 7;
}
return (sigval);
}
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);
}
void handle_exception(int exceptionVector)
{
int sigval, stepping;
int addr, length;
char * ptr;
int newPC;
gdb_i386vector = exceptionVector;
if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
exceptionVector,
registers[ PS ],
registers[ PC ]);
sigval = computeSignal( exceptionVector );
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
putpacket(remcomOutBuffer);
stepping = 0;
while (1==1) {
remcomOutBuffer[0] = 0;
ptr = getpacket();
switch (*ptr++) {
case '?' : remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
break;
case 'd' : remote_debug = !(remote_debug);
break;
case 'g' :
mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
break;
case 'G' :
hex2mem(ptr, (char*) registers, NUMREGBYTES, 0);
strcpy(remcomOutBuffer,"OK");
break;
case 'P' :
{
int regno;
if (hexToInt (&ptr, ®no) && *ptr++ == '=')
if (regno >= 0 && regno < NUMREGS)
{
hex2mem (ptr, (char *)®isters[regno], 4, 0);
strcpy(remcomOutBuffer,"OK");
break;
}
strcpy (remcomOutBuffer, "E01");
break;
}
case 'm' :
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
{
ptr = 0;
mem_err = 0;
mem2hex((char*) addr, remcomOutBuffer, length, 1);
if (mem_err) {
strcpy (remcomOutBuffer, "E03");
debug_error ("memory fault");
}
}
if (ptr)
{
strcpy(remcomOutBuffer,"E01");
}
break;
case 'M' :
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
if (*(ptr++) == ':')
{
mem_err = 0;
hex2mem(ptr, (char*) addr, length, 1);
if (mem_err) {
strcpy (remcomOutBuffer, "E03");
debug_error ("memory fault");
} else {
strcpy(remcomOutBuffer,"OK");
}
ptr = 0;
}
if (ptr)
{
strcpy(remcomOutBuffer,"E02");
}
break;
case 's' :
stepping = 1;
case 'c' :
if (hexToInt(&ptr,&addr))
registers[ PC ] = addr;
newPC = registers[ PC];
registers[ PS ] &= 0xfffffeff;
if (stepping) registers[ PS ] |= 0x100;
_returnFromException();
break;
case 'k' :
#if 0
BREAKPOINT();
#endif
break;
}
putpacket(remcomOutBuffer);
}
}
void set_debug_traps()
{
extern void remcomHandler();
int exception;
stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
exceptionHandler (0, _catchException0);
exceptionHandler (1, _catchException1);
exceptionHandler (3, _catchException3);
exceptionHandler (4, _catchException4);
exceptionHandler (5, _catchException5);
exceptionHandler (6, _catchException6);
exceptionHandler (7, _catchException7);
exceptionHandler (8, _catchException8);
exceptionHandler (9, _catchException9);
exceptionHandler (10, _catchException10);
exceptionHandler (11, _catchException11);
exceptionHandler (12, _catchException12);
exceptionHandler (13, _catchException13);
exceptionHandler (14, _catchException14);
exceptionHandler (16, _catchException16);
initialized = 1;
}
void breakpoint()
{
if (initialized)
BREAKPOINT();
}