📄 generic-stub.c
字号:
#include "board.h"#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS/* Eventually, this should default to ON */#if USE_GDBSTUB_PROTOTYPES#include "stub-tservice.h"#include "generic-stub.h"#else// Function declarations (prevents compiler warnings)int stubhex (unsigned char ch);static void getpacket (char *buffer);static void unlock_thread_scheduler (void);static uint32 crc32 (unsigned char *ptr, int len, uint32 crc);#endif#include "thread-pkts.h" /* Defines function macros if thread support is not selected in board.h *//**************************************************************************** THIS SOFTWARE IS NOT COPYRIGHTED HP offers the following for use in the public domain. HP makes no warranty with regard to the software or it's performance and the user accepts the software "AS IS" with all faults. HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.****************************************************************************//**************************************************************************** * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ * * Module name: remcom.c $ * Revision: 1.34 $ * Date: 91/03/09 12:29:49 $ * Contributor: Lake Stevens Instrument Division$ * * Description: low level support for gdb debugger. $ * * Considerations: only works on target hardware $ * * Written by: Glenn Engel $ * ModuleState: Experimental $ * * NOTES: See Below $ * * Modified for SPARC by Stu Grossman, Cygnus Solutions. * Modified for generic CygMON stub support by Bob Manson, Cygnus Solutions. * * To enable debugger support, two things need to happen. One, a * call to set_debug_traps () is necessary in order to allow any breakpoints * or error conditions to be properly intercepted and reported to gdb. * Two, a breakpoint needs to be generated to begin communication. This * is most easily accomplished by a call to breakpoint (). Breakpoint () * simulates a breakpoint by executing a trap #1. * ************* * * The following gdb commands are supported: * * command function Return value * * g return the value of the CPU registers hex data or ENN * G set the value of the CPU registers OK or ENN * * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN * * c Resume at current address SNN ( signal NN) * cAA..AA Continue at address AA..AA SNN * * s Step one instruction SNN * sAA..AA Step one instruction from AA..AA SNN * * k kill * * ? What was the last sigval ? SNN (signal NN) * * bBB..BB Set baud rate to BB..BB OK or BNN, then sets * baud rate * * All commands and responses are sent with a packet which includes a * checksum. A packet consists of * * $<packet info>#<checksum>. * * where * <packet info> :: <characters representing the command or response> * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> * * When a packet is received, it is first acknowledged with either '+' or '-'. * '+' indicates a successful transfer. '-' indicates a failed transfer. * * Example: * * Host: Reply: * $m0,10#2a +$00010203040506070809101112131415#42 * ****************************************************************************/#ifndef __ECOS__#include <string.h>#include <signal.h>#endif // __ECOS__/************************************************************************//* BUFMAX defines the maximum number of characters in inbound/outbound buffers*//* at least NUMREGBYTES*2 are needed for register packets */#define BUFMAX 2048static int initialized = 0; /* !0 means we've been initialized */static int process_exception (int sigval);static void do_nothing (void); /* and do it gracefully */static int syscall_do_nothing (int);void __free_program_args (void);volatile __PFI __process_exception_vec = process_exception;volatile __PFV __process_exit_vec = do_nothing;volatile __PFI __process_syscall_vec = syscall_do_nothing;volatile __PFI __process_signal_vec = NULL;volatile __PFV __init_vec = NULL;volatile __PFV __cleanup_vec = NULL;static char *__add_program_arg (int argnum, uint32 arglen);static const char hexchars[] = "0123456789abcdef";static void process_query (char *pkt);static void process_set (char *pkt);char__tohex (int c){ return hexchars [c & 15];}#define __tohex(c) hexchars[(c) & 15]#ifndef NUMREGS_GDB#define NUMREGS_GDB NUMREGS#endif/* One pushback character. */int ungot_char = -1;static intreadDebugChar (void){ if (ungot_char > 0) { int result = ungot_char; ungot_char = -1; return result; } else return getDebugChar ();}/* Convert ch from a hex digit to an int. */intstubhex (ch) unsigned char ch;{ if (ch >= 'a' && ch <= 'f') return ch-'a'+10; if (ch >= '0' && ch <= '9') return ch-'0'; if (ch >= 'A' && ch <= 'F') return ch-'A'+10; return -1;}static voidgetpacket (buffer) char *buffer;{ struct gdb_packet packet; packet.state = 0; packet.contents = buffer; while (__add_char_to_packet (readDebugChar () & 0xff, &packet) != 1) { /* Empty */ }}int__add_char_to_packet (ch, packet) unsigned int ch; struct gdb_packet *packet;{ if (packet->state == 0) { if (ch == '$') { packet->state = 1; packet->length = 0; packet->checksum = 0; packet->xmitcsum = -1; } return 0; } if (packet->state == 1) { if (ch == '#') { packet->contents[packet->length] = 0; packet->state = 2; } else { if (packet->length == BUFMAX) { packet->state = 0; return -1; } packet->checksum += ch; packet->contents[packet->length++] = ch; } return 0; } if (packet->state == 2) { packet->xmitcsum = stubhex (ch) << 4; packet->state = 3; return 0; } if (packet->state == 3) { packet->xmitcsum |= stubhex (ch); if ((packet->checksum & 255) != packet->xmitcsum) { putDebugChar ('-'); /* failed checksum */ packet->state = 0; return -1; } else { putDebugChar ('+'); /* successful transfer */ /* if a sequence char is present, reply the sequence ID */ if (packet->contents[2] == ':') { uint32 count = packet->length; uint32 i; putDebugChar (packet->contents[0]); putDebugChar (packet->contents[1]); /* remove sequence chars from buffer */ for (i=3; i <= count; i++) packet->contents[i-3] = packet->contents[i]; } return 1; } } /* We should never get here. */ packet->state = 0; return -1;}/* send the packet in buffer. */void__putpacket (buffer) char *buffer;{ unsigned char checksum; uint32 count; unsigned char ch; /* $<packet info>#<checksum>. */ do { putDebugChar ('$'); checksum = 0; count = 0; while ((ch = buffer[count])) { putDebugChar (ch); checksum += ch; count += 1; } putDebugChar ('#'); putDebugChar (hexchars[(checksum >> 4) & 0xf]); putDebugChar (hexchars[checksum & 0xf]); } while ((readDebugChar () & 0x7f) != '+');}static char remcomInBuffer[BUFMAX];static char remcomOutBuffer[BUFMAX];/* Indicate to caller of mem2hex or hex2mem that there has been an error. */volatile int __mem_fault = 0;#ifndef TARGET_HAS_OWN_MEM_FUNCS/* * _target_readmem_hook / _target_writemem_hook: * Allow target to get involved in reading/writing memory. * * If these hooks are defined by the target, they will be * called for each user program memory access. Otherwise, the stub * will simply dereference a pointer to access user program memory. */unsigned char (*_target_readmem_hook) (unsigned char* addr);void (*_target_writemem_hook) (unsigned char* addr, unsigned char value);static unsigned charget_target_byte (volatile unsigned char *address){ if (_target_readmem_hook) /* target needs to control memory access */ return _target_readmem_hook ((unsigned char *) address); else return *address;}static voidput_target_byte (volatile unsigned char *address, unsigned char value){ if (_target_writemem_hook) /* target needs to control memory access */ _target_writemem_hook ((unsigned char *) address, value); else *address = value;}/* These are the "arguments" to __do_read_mem and __do_write_mem, which are passed as globals to avoid squeezing them thru __set_mem_fault_trap. */static volatile target_register_t memCount;static volatile unsigned char *memSrc, *memDst;/* * __do_read_mem: * Copy from target memory to trusted memory. */static void__do_read_mem (void){ __mem_fault = 0; while (memCount) { unsigned char ch = get_target_byte (memSrc++); if (__mem_fault) return; *memDst++ = ch; memCount--; }}/* * __do_write_mem: * Copy from trusted memory to target memory. */static void__do_write_mem (void){ __mem_fault = 0; while (memCount) { unsigned char ch = *memSrc++; put_target_byte (memDst++, ch); if (__mem_fault) return; memCount--; }}/* * __read_mem_safe: * Get contents of target memory, abort on error. */int__read_mem_safe (unsigned char *dst, target_register_t src, int count){ memCount = count; memSrc = (unsigned char *) src; memDst = (unsigned char *) dst; __set_mem_fault_trap (__do_read_mem); return count - memCount; /* return number of bytes successfully read */}/* * __write_mem_safe: * Set contents of target memory, abort on error. */int__write_mem_safe (unsigned char *src, target_register_t dst, int count){ memCount = count; memSrc = (unsigned char *) src; memDst = (unsigned char *) dst; __set_mem_fault_trap (__do_write_mem); return count - memCount; /* return number of bytes successfully read */}#endif /* TARGET_HAS_OWN_MEM_FUNCS *//* These are the "arguments" to __mem2hex_helper and __hex2mem_helper, which are passed as globals to avoid squeezing them thru __set_mem_fault_trap. */static int hexMemCount;static char *hexMemSrc, *hexMemDst;static int may_fault_mode;/* Hamburger helper? */static void__mem2hex_helper (void){ __mem_fault = 0; while (hexMemCount-- > 0) { unsigned char ch; if (may_fault_mode) __read_mem_safe (&ch, (target_register_t) (hexMemSrc++), 1); else ch = *(hexMemSrc++); if (__mem_fault) return; *(hexMemDst++) = hexchars[(ch >> 4) & 0xf]; if (__mem_fault) return; *(hexMemDst++) = hexchars[ch & 0xf]; if (__mem_fault) return; }}/* Convert the memory pointed to by MEM into HEX, placing result in BUF. * Return a pointer to the last char put in buf (NUL). In case of a memory * fault, return 0. * If MAY_FAULT is non-zero, then we will handle memory faults by returning * a 0 (and assume that MEM is a pointer into the user program), else we * treat a fault like any other fault in the stub (and assume that MEM is * a pointer into the stub's memory). */char *__mem2hex (mem, buf, count, may_fault) char *mem; char *buf; int count; int may_fault;{ hexMemDst = (unsigned char *) buf; hexMemSrc = (unsigned char *) mem; hexMemCount = count; may_fault_mode = may_fault; if (may_fault) { if (__set_mem_fault_trap (__mem2hex_helper)) return 0; } else __mem2hex_helper (); *hexMemDst = 0; return (char *) hexMemDst;}static void__hex2mem_helper (void){ target_register_t i; unsigned char ch; __mem_fault = 0; for (i=0; i < hexMemCount && *hexMemSrc; i++) { ch = stubhex (*(hexMemSrc++)) << 4; if (__mem_fault) return; ch |= stubhex (*(hexMemSrc++)); if (__mem_fault) return; if (may_fault_mode) __write_mem_safe (&ch, (target_register_t) (hexMemDst++), 1); else *(hexMemDst++) = ch; if (__mem_fault) return; }}/* Convert COUNT bytes of 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. If MAY_FAULT is set, we will return a non-zero value if a memory fault occurs (and we assume that MEM is a pointer into the user program). Otherwise, we will take a trap just like any other memory fault (and assume that MEM points into the stub's memory). */char *__hex2mem (buf, mem, count, may_fault) char *buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -