📄 generic-stub.c
字号:
strcpy (ptr, "INVALID"); return; } } for (regnum = sr; regnum < er; 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);#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING reg_valid = get_register_valid (regnum);#endif } vptr = ((char *) &addr); if (sizeof (addr) > REGSIZE(regnum)) { /* May need to cope with endian-ness */#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) vptr += sizeof (addr) - REGSIZE (regnum);#endif } else if (sizeof (addr) < REGSIZE (regnum)) { int off = REGSIZE (regnum) - sizeof (addr); int x; char extend_val = 0;#ifdef CYGARC_SIGN_EXTEND_REGISTERS { unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); if ((addr & sign_bit_mask) == sign_bit_mask) extend_val = ~0; }#endif#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) for (x = 0; x < off; x++) dummyDat[x + sizeof(addr)] = extend_val; _memcpy (dummyDat, &addr, sizeof (addr));#else for (x = 0; x < off; x++) dummyDat[x] = extend_val; _memcpy (dummyDat + off, &addr, sizeof (addr));#endif 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); } }}voidstub_update_registers(char *in_ptr, char *out_ptr){ char *ptr = &in_ptr[1]; int x; int sr = 0, er = NUMREGS_GDB; if (*in_ptr == 'P') { target_register_t regno; if (__hexToInt (&ptr, ®no) && (*ptr++ == '=')) { sr = regno; er = regno + 1; } else { strcpy (out_ptr, "P01"); return; } } 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);#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) vptr += sizeof (value) - REGSIZE (x);#endif __hex2mem (ptr, vptr, REGSIZE (x), 0); put_register (x, value); } ptr += REGSIZE (x) * 2; } strcpy (out_ptr, "OK");}int__process_packet (char *packet){ int is_binary = 0;#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) int is_Z = 0;#endif __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; }#ifdef __ECOS__#if !defined(CYG_HAL_STARTUP_RAM) // Only for ROM based stubs#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets case 'z': /* report IO buffer sizes so download can achieve optimal download speed */ { int i; i = __intToHex (__remcomOutBuffer, BUFMAX, 32); __remcomOutBuffer[i] = 0; break; }#endif case 'd': /* toggle debug flag */ strcpy(__remcomOutBuffer, GDB_stubs_version); break;#endif#endif // __ECOS__ case 'q': /* general query packet */ process_query (&packet[1]); break; case 'Q': /* general set packet */ process_set (&packet[1]); break; case 'p': /* return the value of a single CPU register */ case 'g': /* return the value of the CPU registers */ { stub_format_registers(&packet[0], __remcomOutBuffer); break; } case 'A': /* set program arguments */ {#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS 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"); }#else strcpy (__remcomOutBuffer, "E01");#endif } break; case 'P': case 'G': /* set the value of the CPU registers - return OK */ { char *in_ptr = &packet[0]; char *out_ptr = __remcomOutBuffer; stub_update_registers(in_ptr, out_ptr); break; } case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x. */ { target_register_t length; char *ptr = &packet[1]; target_addr_t addr; if (__hexToAddr (&ptr, &addr) && *ptr++ == ',' && __hexToInt (&ptr, &length)) { if (__mem2hex_safe (addr, __remcomOutBuffer, length)) 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 length; char *ptr = &packet[1], buf[128]; int i; target_addr_t addr; if (__hexToAddr (&ptr, &addr) && *ptr++ == ',' && __hexToInt (&ptr, &length) && *ptr++ == ':') { /* GDB sometimes sends an impossible length */ if (length < 0 || length >= BUFMAX) strcpy (__remcomOutBuffer, "E01"); else 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);#ifdef TARGET_HAS_HARVARD_MEMORY if (TARGET_ADDR_IS_PROGMEM(addr)) { if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) break; } else#endif if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) break; length -= i; addr += i; } if (length <= 0) strcpy (__remcomOutBuffer, "OK"); else strcpy (__remcomOutBuffer, "E03"); } else { if (__hex2mem_safe (ptr, addr, length) != 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_addr_t addr; target_register_t sigval = 0; if (packet[0] == 'C' || packet[0] == 'S') { __hexToInt (&ptr, &sigval); if (*ptr == ';') ptr++; } if (__hexToAddr (&ptr, &addr)) set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr)); /* Need to flush the instruction cache here, as we may have deposited a breakpoint, and the icache probably has no way of knowing that a data ref to some location may have changed something that is in the instruction cache. */#ifdef __ECOS__ __data_cache (CACHE_FLUSH) ;#endif __instruction_cache (CACHE_FLUSH) ; /* If we have a function to handle signals, call it. */ if (sigval != 0 && __process_signal_vec != NULL) { /* If 0 is returned, we either ignored the signal or invoked a user handler. Otherwise, the user program should die. */ if (! __process_signal_vec (sigval)) sigval = 0; } if (sigval != 0) { sigval = SIGKILL; /* Always nuke the program */ __kill_program (sigval); return 0; }#ifdef __ECOS__ // CASE 102327 - watchpoints fight with output, so do not step // through $O packet output routines.#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT if ( cyg_hal_gdb_break_is_set() ) { packet[0] = 'c'; // Force it to be a "continue" instead of step. cyg_hal_gdb_running_step = 1; // And tell the hal_stub... }#endif#endif /* Set machine state to force a single step. */ if (packet[0] == 's' || packet[0] == 'S') { lock_thread_scheduler (0); /* 0 == single-step */#ifdef __ECOS__ // PR 19845 workaround: // Make sure the single-step magic affects the correct registers. _registers = ®isters[0];#endif __single_step (); } else { lock_thread_scheduler (1); /* 1 == continue */ }#ifdef __ECOS__ /* Need to flush the data and instruction cache here, as we may have deposited a breakpoint in __single_step. */ __data_cache (CACHE_FLUSH) ; __instruction_cache (CACHE_FLUSH) ; hal_flush_output();#endif return -1; } case 'D' : /* detach */ __putpacket (__remcomOutBuffer); /* fall through */ case 'k' : /* kill the program */#ifdef __ECOS__ hal_flush_output();#endif __process_exit_vec (); return -1; case 'r': /* Reset */ /* With the next 'k' packet, reset the board */ __process_exit_vec = &__reset; break; case 'H': STUB_PKT_CHANGETHREAD (packet+1, __remcomOutBuffer, 300) ; break ; case 'T' : STUB_PKT_THREAD_ALIVE (packet+1, __remcomOutBuffer, 300) ; break ; case 'B': /* breakpoint */ { target_register_t addr; char mode; char *ptr = &packet[1]; if (__hexToInt (&ptr, &addr) && *(ptr++) == ',') { mode = *(ptr++); if (mode == 'C') __remove_breakpoint (addr,0); else __set_breakpoint (addr,0); strcpy (__remcomOutBuffer, "OK"); } else { strcpy (__remcomOutBuffer, "E01"); } break; } case 'b': /* bBB... Set baud rate to BB... */ { target_register_t baudrate; char *ptr = &packet[1]; if (!__hexToInt (&ptr, &baudrate)) { strcpy (__remcomOutBuffer, "B01"); break; } __putpacket ("OK"); /* Ack before changing speed */ __set_baud_rate (baudrate); break; }#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0) case 'Z': is_Z = 1; case 'z': { char *ptr = &packet[1]; target_register_t ztype, addr, length; int err; target_addr_t taddr; if (__hexToInt (&ptr, &ztype) && *(ptr++) == ',') { if (__hexToAddr (&ptr, &taddr)) { if (*(ptr++) == ',') { /* When there is a comma, there must be a length */ if (!__hexToInt (&ptr, &length)) { strcpy (__remcomOutBuffer, "E02"); break; } } else length = 0; addr = (target_register_t)TARGET_ADDR_TO_PTR(taddr); switch (ztype) { case ZTYPE_SW_BREAKPOINT: /* sw breakpoint */ if (is_Z) err = __set_breakpoint(addr,length); else err = __remove_breakpoint(addr,length); if (!err) strcpy (__remcomOutBuffer, "OK"); else strcpy (__remcomOutBuffer, "E02"); break; case ZTYPE_HW_BREAKPOINT:#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0) if (is_Z) err = __set_hw_breakpoint(addr, length); else err = __remove_hw_breakpoint(addr, length); if (!err) strcpy (__remcomOutBuffer, "OK"); else#endif strcpy (__remcomOutBuffer, "E02");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -