📄 i386-stub.c
字号:
/* scan for the sequence $<data>#<checksum> */void getpacket(buffer)char * buffer;{ unsigned char checksum; unsigned char xmitcsum; int i; int count; char ch; do { /* wait around for the start character, ignore all other characters */ while ((ch = getDebugChar()) != '$'); checksum = 0; xmitcsum = -1; count = 0; /* now, read until a # or end of buffer is found */ while (count < BUFMAX) { ch = getDebugChar(); if (ch == '#') break; checksum = checksum + ch; buffer[count] = ch; count = count + 1; } buffer[count] = 0; if (ch == '#') { xmitcsum = hex(getDebugChar()) << 4; xmitcsum += hex(getDebugChar()); if ((remote_debug ) && (checksum != xmitcsum)) { fprintf(stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", checksum,xmitcsum,buffer); } if (checksum != xmitcsum) 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] ); /* remove sequence chars from buffer */ count = strlen(buffer); for (i=3; i <= count; i++) buffer[i-3] = buffer[i]; } } } } while (checksum != xmitcsum);}/* send the packet in buffer. */void putpacket(buffer)char * buffer;{ unsigned char checksum; int count; char ch; /* $<packet info>#<checksum>. */ do { putDebugChar('$'); checksum = 0; count = 0; while (ch=buffer[count]) { if (! putDebugChar(ch)) return; checksum += ch; count += 1; } putDebugChar('#'); putDebugChar(hexchars[checksum >> 4]); putDebugChar(hexchars[checksum % 16]); } while (getDebugChar() != '+');}char remcomInBuffer[BUFMAX];char remcomOutBuffer[BUFMAX];static short error;void debug_error(format, parm)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 NORETURN void (*mem_fault_routine)() = NULL;/* Indicate to caller of mem2hex or hex2mem that there has been an error. */static volatile int mem_err = 0;voidset_mem_err (){ 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). */intget_char (addr) char *addr;{ return *addr;}voidset_char (addr, val) 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; 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);}/* 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; 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);}/* this function takes the 386 exception vector and attempts to translate this number into a unix compatible signal value */int computeSignal( exceptionVector )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; 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 ]); /* reply to host that an exception has occurred */ sigval = computeSignal( exceptionVector ); remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[sigval >> 4]; remcomOutBuffer[2] = hexchars[sigval % 16]; remcomOutBuffer[3] = 0; putpacket(remcomOutBuffer); while (1==1) { error = 0; remcomOutBuffer[0] = 0; getpacket(remcomInBuffer); switch (remcomInBuffer[0]) { case '?' : remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[sigval >> 4]; remcomOutBuffer[2] = hexchars[sigval % 16]; remcomOutBuffer[3] = 0; break; case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */ break; case 'g' : /* return the value of the CPU registers */ mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0); break; case 'G' : /* set the value of the CPU registers - return OK */ hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0); strcpy(remcomOutBuffer,"OK"); break; /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ case 'm' : /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; 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"); debug_error("malformed read memory command: %s",remcomInBuffer); } break; /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ case 'M' : /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; 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"); debug_error("malformed write memory command: %s",remcomInBuffer); } break; /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ case 'c' : case 's' : /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr)) registers[ PC ] = addr; newPC = registers[ PC]; /* clear the trace bit */ registers[ PS ] &= 0xfffffeff; /* set the trace bit if we're stepping */ if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x100; /* * If we found a match for the PC AND we are not returning * as a result of a breakpoint (33), * trace exception (9), nmi (31), jmp to * the old exception handler as if this code never ran. */#if 0 /* Don't really think we need this, except maybe for protection exceptions. */ /* * invoke the previous handler. */ if (oldExceptionHook) (*oldExceptionHook) (frame->exceptionVector); newPC = registers[ PC ]; /* pc may have changed */#endif /* 0 */ _returnFromException(); /* this is a jump */ break; /* kill the program */ case 'k' : /* do nothing */ BREAKPOINT(); break; } /* switch */ /* reply to the request */ putpacket(remcomOutBuffer); }}/* this function is used to set up exception handlers for tracing and breakpoints */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); if (exceptionHook != remcomHandler) { oldExceptionHook = exceptionHook; exceptionHook = remcomHandler; } /* In case GDB is started before us, ack any packets (presumably "$?#xx") sitting there. */ putDebugChar ('+'); initialized = 1;}/* This function will generate a breakpoint exception. It is used at the beginning of a program to sync up with a debugger and can be used otherwise as a quick means to stop program execution and "break" into the debugger. */void breakpoint(){ if (initialized)#if 0 handle_exception(3);#else BREAKPOINT();#endif waitabit();}int waitlimit = 1000000;#if 0voidbogon(){ waitabit();}#endifvoidwaitabit(){ int i; for (i = 0; i < waitlimit; i++) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -