📄 generic-stub.c
字号:
char *mem; int count; int may_fault;{ hexMemSrc = (unsigned char *) buf; hexMemDst = (unsigned char *) mem; hexMemCount = count; may_fault_mode = may_fault; if (may_fault) { if (__set_mem_fault_trap (__hex2mem_helper)) return 0; } else __hex2mem_helper (); return (char *) hexMemDst;}voidset_debug_traps (void){ __install_traps (); initialized = 1; /* FIXME: Change this to dbg_stub_initialized */}/* * While we find nice hex chars, build an int. * Return number of chars processed. */unsigned int__hexToInt (char **ptr, target_register_t *intValue){ int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = stubhex (**ptr); if (hexValue < 0) break; *intValue = (*intValue << 4) | hexValue; numChars ++; (*ptr)++; } return (numChars);}/* * Complement of __hexToInt: take an int of size "numBits", * convert it to a hex string. Return length of (unterminated) output. */unsigned int__intToHex (char *ptr, target_register_t intValue, int numBits){ int numChars = 0; if (intValue == 0) { *(ptr++) = '0'; *(ptr++) = '0'; return 2; } numBits = (numBits + 7) / 8; while (numBits) { int v = (intValue >> ((numBits - 1) * 8)); if (v || (numBits == 1)) { v = v & 255; *(ptr++) = __tohex ((v / 16) & 15); *(ptr++) = __tohex (v & 15); numChars += 2; } numBits--; } return (numChars);}#if DEBUG_THREADS /* * Kernel Thread Control * * If the current thread is set to other than zero (or minus one), * then ask the kernel to lock it's scheduler so that only that thread * can run. */static unsigned char did_lock_scheduler = 0;static unsigned char did_disable_interrupts = 0;/* Pointer to "kernel call" for scheduler control */static int (*schedlock_fn) (int, int, long) = stub_lock_scheduler;/* Pointer to target stub call for disabling interrupts. Target stub will initialize this if it can. */int (*__disable_interrupts_hook) (int); /* don't initialize here! */#endifstatic voidlock_thread_scheduler (int kind) /* "step" or "continue" */{#if DEBUG_THREADS int ret = 0; /* GDB will signal its desire to run a single thread by setting _gdb_cont_thread to non-zero / non-negative. */ if (_gdb_cont_thread <= 0) return; if (schedlock_fn) /* kernel call */ ret = (*schedlock_fn) (1, kind, _gdb_cont_thread); if (ret == 1) { did_lock_scheduler = 1; return; } if (schedlock_fn == 0 || /* no kernel scheduler call */ ret == -1) /* kernel asks stub to handle it */ if (__disable_interrupts_hook) /* target stub has capability */ if ((*__disable_interrupts_hook) (1)) { did_disable_interrupts = 1; return; }#endif /* DEBUG_THREADS */}static voidunlock_thread_scheduler (){#if DEBUG_THREADS if (did_lock_scheduler) if (schedlock_fn) /* kernel call */ { (*schedlock_fn) (0, 0, _gdb_cont_thread); /* I could check the return value, but what would I do if it failed??? */ did_lock_scheduler = 0; } if (did_disable_interrupts) if (__disable_interrupts_hook) /* target stub call */ { (*__disable_interrupts_hook) (0); /* Again, I could check the return value, but what would I do if it failed??? */ did_disable_interrupts = 0; }#endif /* DEBUG_THREADS */}void__handle_exception (void){ int sigval;#ifdef TARGET_HAS_NEXT_STEP if (! __next_step_done ()) { __clear_breakpoints (); __install_breakpoints (); __single_step (); return; }#endif#ifdef __ECOS__ // We need to unpack the registers before they are accessed. if (__cleanup_vec != NULL) __cleanup_vec ();#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT // Special case for GDB BREAKs. This flag is set by cyg_stub_cleanup. if (cyg_hal_gdb_break) { cyg_hal_gdb_break = 0; sigval = SIGINT; } else#endif sigval = __computeSignal (__get_trap_number ());#else // __ECOS__ /* reply to host that an exception has occurred */ sigval = __computeSignal (__get_trap_number ());#endif // __ECOS__ if (__is_breakpoint_function ()) __skipinst ();#ifndef __ECOS__ if (__cleanup_vec != NULL) __cleanup_vec ();#endif // !__ECOS__ __clear_breakpoints (); /* Undo effect of previous single step. */ unlock_thread_scheduler (); __clear_single_step ();#ifdef SIGSYSCALL if (sigval == SIGSYSCALL) { int val; /* Do the skipinst FIRST. */#ifndef SYSCALL_PC_AFTER_INST __skipinst ();#endif val = __process_syscall_vec (__get_syscall_num ()); if (val < 0) sigval = -val; else sigval = 0; }#endif /* Indirect function call to stub, cygmon monitor or other */ if (sigval != 0) { while (__process_exception_vec (sigval)) { /* Empty! */ } } __install_breakpoints (); if (__init_vec != NULL) __init_vec ();}/* * _get_trace_register_hook: * This function pointer will be non-zero if the trace component * wants to intercept requests for register values. * * FIXME: evidently I need a new hook for large registers... */int (*_get_trace_register_hook) (regnames_t, target_register_t *);int__process_packet (char *packet){ int is_binary = 0; remcomOutBuffer[0] = 0; switch (packet[0]) { case '?': { int sigval = __computeSignal (__get_trap_number ()); remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf]; remcomOutBuffer[2] = hexchars[sigval & 0xf]; remcomOutBuffer[3] = 0; break; } case 'd': /* toggle debug flag */ break; case 'q': /* general query packet */ process_query (&packet[1]); break; case 'Q': /* general set packet */ process_set (&packet[1]); break; case 'g': /* return the value of the CPU registers */ { char *ptr = remcomOutBuffer; int regnum; for (regnum = 0; regnum < NUMREGS_GDB; regnum++) { /* We need to compensate for the value offset within the register. */ char dummyDat[32]; target_register_t addr; char *vptr; int reg_valid = 1;#ifdef TARGET_HAS_LARGE_REGISTERS if (sizeof (target_register_t) < REGSIZE (regnum)) { get_register_as_bytes (regnum, dummyDat); vptr = dummyDat; } else#endif { if (_get_trace_register_hook) reg_valid = _get_trace_register_hook (regnum, &addr); else addr = get_register (regnum); vptr = ((char *) &addr) + sizeof (addr) - REGSIZE (regnum); if (sizeof (addr) < REGSIZE (regnum)) { int off = REGSIZE (regnum) - sizeof (addr); int x; for (x = 0; x < off; x++) dummyDat[x] = 0; memcpy (dummyDat + off, &addr, sizeof (addr)); vptr = dummyDat; } } if (reg_valid) /* we have a valid reg value */ { ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0); } else { /* Trace component returned a failure code. This means that the register value is not available. We'll fill it with 'x's, and GDB will understand. */ memset (ptr, 'x', 2 * REGSIZE (regnum)); ptr += 2 * REGSIZE (regnum); } } break; } case 'A': /* set program arguments */ { if (packet[1] == '\0') { __free_program_args (); strcpy (remcomOutBuffer, "OK"); } else { target_register_t arglen, argnum; char *ptr = &packet[1]; while (1) { if (__hexToInt (&ptr, &arglen) && (*ptr++ == ',') && __hexToInt (&ptr, &argnum) && (*ptr++ == ',')) { if (arglen > 0) { char *s = __add_program_arg (argnum, arglen); if (s != NULL) { __hex2mem (ptr, s, arglen, 0); } ptr += arglen * 2; } if (*ptr == ',') ptr++; else break; } else break; } if (*ptr == '\0') strcpy (remcomOutBuffer, "OK"); else strcpy (remcomOutBuffer, "E01"); } } break; case 'P': case 'G': /* set the value of the CPU registers - return OK */ { int x; int sr = 0, er = NUMREGS_GDB; char *ptr = &packet[1]; if (packet[0] == 'P') { target_register_t regno; if (__hexToInt (&ptr, ®no) && (*ptr++ == '=')) { sr = regno; er = regno + 1; } else { strcpy (remcomOutBuffer, "P01"); break; } } for (x = sr; x < er; x++) { target_register_t value = 0; char *vptr;#ifdef TARGET_HAS_LARGE_REGISTERS if (sizeof (target_register_t) < REGSIZE (x)) { char dummyDat [32]; __hex2mem (ptr, dummyDat, REGSIZE (x), 0); put_register_as_bytes (x, dummyDat); } else#endif { vptr = ((char *) &value) + sizeof (value) - REGSIZE (x); __hex2mem (ptr, vptr, REGSIZE (x), 0); put_register (x, value); } ptr += REGSIZE (x) * 2; } strcpy (remcomOutBuffer, "OK"); break; } case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x. */ { target_register_t addr, length; char *ptr = &packet[1]; if (__hexToInt (&ptr, &addr) && *ptr++ == ',' && __hexToInt (&ptr, &length)) { if (__mem2hex ((char *) addr, remcomOutBuffer, length, 1)) break; strcpy (remcomOutBuffer, "E03"); } else strcpy (remcomOutBuffer, "E01"); break; } case 'X': /* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */ is_binary = 1; /* fall through */ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ /* Try to read '%x,%x:'. */ { target_register_t addr, length; char *ptr = &packet[1], buf[128]; int i; if (__hexToInt (&ptr, &addr) && *ptr++ == ',' && __hexToInt (&ptr, &length) && *ptr++ == ':') { if (is_binary) { while (length > 0) { for (i = 0; i < sizeof(buf) && i < length; i++) if ((buf[i] = *ptr++) == 0x7d) buf[i] = 0x20 | (*ptr++ & 0xff); if (__write_mem_safe (buf, addr, i) != i) break; length -= i; addr += i; } if (length <= 0) strcpy (remcomOutBuffer, "OK"); else strcpy (remcomOutBuffer, "E03"); } else { if (__hex2mem (ptr, (char *) addr, length, 1) != NULL) strcpy (remcomOutBuffer, "OK"); else strcpy (remcomOutBuffer, "E03"); } } else strcpy (remcomOutBuffer, "E02"); break; } case 'S': case 's': /* sAA..AA Step from address AA..AA (optional) */ case 'C': case 'c': /* cAA..AA Continue at address AA..AA (optional) */ /* try to read optional parameter, pc unchanged if no parm */ { char *ptr = &packet[1]; target_register_t addr; target_register_t sigval = 0; if (packet[0] == 'C' || packet[0] == 'S') { __hexToInt (&ptr, &sigval); if (*ptr == ';') ptr++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -