📄 gdb_stub.c
字号:
unsigned 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. */voidputpacket (unsigned 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 () != '+');}voiddebug_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 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;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 (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 */intcomputeSignal (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 *//**********************************************/inthexToInt (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. */voidhandle_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]); } /* reply to host that an exception has occurred */ sigval = computeSignal (exceptionVector); ptr = remcomOutBuffer; *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */ *ptr++ = hexchars[sigval >> 4]; *ptr++ = hexchars[sigval & 0xf]; *ptr++ = hexchars[ESP]; *ptr++ = ':'; ptr = mem2hex((char *)®isters[ESP], ptr, 4, 0); /* SP */ *ptr++ = ';'; *ptr++ = hexchars[EBP]; *ptr++ = ':'; ptr = mem2hex((char *)®isters[EBP], ptr, 4, 0); /* FP */ *ptr++ = ';'; *ptr++ = hexchars[PC]; *ptr++ = ':'; ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); /* PC */ *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); /* 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 (ptr, (char *) registers, NUMREGBYTES, 0); strcpy (remcomOutBuffer, "OK"); break; case 'P': /* set the value of a single CPU register - return OK */ { 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; } /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ case 'm': /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ 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; /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ case 'M': /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ 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; /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ case 's': stepping = 1; case 'c': /* try to read optional parameter, pc unchanged if no parm */ 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 (stepping) registers[PS] |= 0x100; _returnFromException (); /* this is a jump */ break; /* kill the program */ case 'k': /* do nothing */#if 0 /* Huh? This doesn't look like "nothing". m68k-stub.c and sparc-stub.c don't have it. */ BREAKPOINT ();#endif break; } /* switch */ /* reply to the request */ putpacket (remcomOutBuffer); }}/* this function is used to set up exception handlers for tracing and breakpoints */voidset_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;}/* 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. *//*voidbreakpoint (void){ if (initialized) BREAKPOINT ();}*/void gdb_init(void){ if (serial_init()) return; set_debug_traps(); printk("Waiting to connect remote gdb...\n"); BREAKPOINT();}#endif /* CONFIG_GDB */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -