📄 i386-stub.c
字号:
buffer[count] = 0; if (ch == '#') { xmitcsum = hex (getDebugChar () & 0x7f) << 4; xmitcsum += hex (getDebugChar () & 0x7f); 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 (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 () & 0x7f) != '+');}char remcomInBuffer[BUFMAX];char remcomOutBuffer[BUFMAX];static short error;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) (void) = NULL;/* Indicate to caller of mem2hex or hex2mem that there has been an error. */static volatile int mem_err = 0;voidset_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). */intget_char (char *addr){ return *addr;}voidset_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 (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 (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 (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, reg; 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. Always return the PC, SP, and FP, since gdb always wants them. */ ptr = remcomOutBuffer; *ptr++ = 'T'; sigval = computeSignal (exceptionVector); *ptr++ = hexchars[sigval >> 4]; *ptr++ = hexchars[sigval % 16]; *ptr++ = hexchars[ESP]; *ptr++ = ':'; mem2hex ((char *) ®isters[ESP], ptr, REGBYTES, 0); ptr += REGBYTES * 2; *ptr++ = ';'; *ptr++ = hexchars[EBP]; *ptr++ = ':'; mem2hex ((char *) ®isters[EBP], ptr, REGBYTES, 0); ptr += REGBYTES * 2; *ptr++ = ';'; *ptr++ = hexchars[PC]; *ptr++ = ':'; mem2hex ((char *) ®isters[PC], ptr, REGBYTES, 0); ptr += REGBYTES * 2; *ptr++ = ';'; *ptr = '\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; case 'P': /* Set specific register */ ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, ®) && *ptr++ == '=') { hex2mem (ptr, (char *) ®isters[reg], REGBYTES, 0); strcpy (remcomOutBuffer, "OK"); } else { strcpy (remcomOutBuffer, "E01"); debug_error ("malformed register set command; %s", remcomInBuffer); } 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", 0); } } 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", 0); } 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; _returnFromException (); /* this is a jump */ break; /* Detach. */ case 'D': putpacket (remcomOutBuffer); registers[PS] &= 0xfffffeff; _returnFromException (); /* this is a jump */ break; /* kill the program */ case 'k': /* do nothing */ 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 (void){ extern void remcomHandler (); 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); /* 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 (void){ if (initialized) { BREAKPOINT (); } waitabit ();}int waitlimit = 1000000;voidwaitabit (void){ int i; for (i = 0; i < waitlimit; i++);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -