#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 (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 (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);
ptr = remcomOutBuffer;
*ptr++ = 'T';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
*ptr++ = hexchars[ESP];
*ptr++ = ':';
ptr = mem2hex((char *)®isters[ESP], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[EBP];
*ptr++ = ':';
ptr = mem2hex((char *)®isters[EBP], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[PC];
*ptr++ = ':';
ptr = mem2hex((char *)®isters[PC], ptr, 4, 0);
*ptr++ = ';';
*ptr = '\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 (void)
{
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 (void)
{
if (initialized)
BREAKPOINT ();
}