📄 kgdb.c
字号:
/* Convert the array, in hexadecimal representation, pointed to by buf into binary representation. Put the result in mem, and return a pointer to the character after the last byte written. */static unsigned char *hex2mem(unsigned char *mem, char *buf, int count);/* Put the content of the array, in binary representation, pointed to by buf into memory pointed to by mem, and return a pointer to the character after the last byte written. */static unsigned char *bin2mem(unsigned char *mem, unsigned char *buf, int count);/* Await the sequence $<data>#<checksum> and store <data> in the array buffer returned. */static void getpacket(char *buffer);/* Send $<data>#<checksum> from the <data> in the array buffer. */static void putpacket(char *buffer);/* Build and send a response packet in order to inform the host the stub is stopped. */static void stub_is_stopped(int sigval);/* All expected commands are sent from remote.c. Send a response according to the description in remote.c. Not static since it needs to be reached from assembler code. */void handle_exception(int sigval);/* Performs a complete re-start from scratch. ETRAX specific. */static void kill_restart(void);/******************** Prototypes for global functions. ***********************//* The string str is prepended with the GDB printout token and sent. */void putDebugString(const unsigned char *str, int len);/* A static breakpoint to be used at startup. */void breakpoint(void);/* Avoid warning as the internal_stack is not used in the C-code. */#define USEDVAR(name) { if (name) { ; } }#define USEDFUN(name) { void (*pf)(void) = (void *)name; USEDVAR(pf) }/********************************** Packet I/O ******************************//* BUFMAX defines the maximum number of characters in inbound/outbound buffers *//* FIXME: How do we know it's enough? */#define BUFMAX 512/* Run-length encoding maximum length. Send 64 at most. */#define RUNLENMAX 64/* Definition of all valid hexadecimal characters */static const char hexchars[] = "0123456789abcdef";/* The inbound/outbound buffers used in packet I/O */static char input_buffer[BUFMAX];static char output_buffer[BUFMAX];/* Error and warning messages. */enum error_type{ SUCCESS, E01, E02, E03, E04, E05, E06,};static char *error_message[] ={ "", "E01 Set current or general thread - H[c,g] - internal error.", "E02 Change register content - P - cannot change read-only register.", "E03 Thread is not alive.", /* T, not used. */ "E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.", "E05 Change register content - P - the register is not implemented..", "E06 Change memory content - M - internal error.",};/********************************** Breakpoint *******************************//* Use an internal stack in the breakpoint and interrupt response routines. FIXME: How do we know the size of this stack is enough? Global so it can be reached from assembler code. */#define INTERNAL_STACK_SIZE 1024char internal_stack[INTERNAL_STACK_SIZE];/* Due to the breakpoint return pointer, a state variable is needed to keep track of whether it is a static (compiled) or dynamic (gdb-invoked) breakpoint to be handled. A static breakpoint uses the content of register ERP as it is whereas a dynamic breakpoint requires subtraction with 2 in order to execute the instruction. The first breakpoint is static; all following are assumed to be dynamic. */static int dynamic_bp = 0;/********************************* String library ****************************//* Single-step over library functions creates trap loops. *//* Copy char s2[] to s1[]. */static char*gdb_cris_strcpy(char *s1, const char *s2){ char *s = s1; for (s = s1; (*s++ = *s2++) != '\0'; ) ; return s1;}/* Find length of s[]. */static intgdb_cris_strlen(const char *s){ const char *sc; for (sc = s; *sc != '\0'; sc++) ; return (sc - s);}/* Find first occurrence of c in s[n]. */static void*gdb_cris_memchr(const void *s, int c, int n){ const unsigned char uc = c; const unsigned char *su; for (su = s; 0 < n; ++su, --n) if (*su == uc) return (void *)su; return NULL;}/******************************* Standard library ****************************//* Single-step over library functions creates trap loops. *//* Convert string to long. */static intgdb_cris_strtol(const char *s, char **endptr, int base){ char *s1; char *sd; int x = 0; for (s1 = (char*)s; (sd = gdb_cris_memchr(hexchars, *s1, base)) != NULL; ++s1) x = x * base + (sd - hexchars); if (endptr) { /* Unconverted suffix is stored in endptr unless endptr is NULL. */ *endptr = s1; } return x;}/********************************* Register image ****************************//* Write a value to a specified register in the register image of the current thread. Returns status code SUCCESS, E02 or E05. */static intwrite_register(int regno, char *val){ int status = SUCCESS; if (regno >= R0 && regno <= ACR) { /* Consecutive 32-bit registers. */ hex2mem((unsigned char *)®.r0 + (regno - R0) * sizeof(unsigned int), val, sizeof(unsigned int)); } else if (regno == BZ || regno == VR || regno == WZ || regno == DZ) { /* Read-only registers. */ status = E02; } else if (regno == PID) { /* 32-bit register. (Even though we already checked SRS and WZ, we cannot combine this with the EXS - SPC write since SRS and WZ have different size.) */ hex2mem((unsigned char *)®.pid, val, sizeof(unsigned int)); } else if (regno == SRS) { /* 8-bit register. */ hex2mem((unsigned char *)®.srs, val, sizeof(unsigned char)); } else if (regno >= EXS && regno <= SPC) { /* Consecutive 32-bit registers. */ hex2mem((unsigned char *)®.exs + (regno - EXS) * sizeof(unsigned int), val, sizeof(unsigned int)); } else if (regno == PC) { /* Pseudo-register. Treat as read-only. */ status = E02; } else if (regno >= S0 && regno <= S15) { /* 32-bit registers. */ hex2mem((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int), val, sizeof(unsigned int)); } else { /* Non-existing register. */ status = E05; } return status;}/* Read a value from a specified register in the register image. Returns the value in the register or -1 for non-implemented registers. */static intread_register(char regno, unsigned int *valptr){ int status = SUCCESS; /* We read the zero registers from the register struct (instead of just returning 0) to catch errors. */ if (regno >= R0 && regno <= ACR) { /* Consecutive 32-bit registers. */ *valptr = *(unsigned int *)((char *)®.r0 + (regno - R0) * sizeof(unsigned int)); } else if (regno == BZ || regno == VR) { /* Consecutive 8-bit registers. */ *valptr = (unsigned int)(*(unsigned char *) ((char *)®.bz + (regno - BZ) * sizeof(char))); } else if (regno == PID) { /* 32-bit register. */ *valptr = *(unsigned int *)((char *)®.pid); } else if (regno == SRS) { /* 8-bit register. */ *valptr = (unsigned int)(*(unsigned char *)((char *)®.srs)); } else if (regno == WZ) { /* 16-bit register. */ *valptr = (unsigned int)(*(unsigned short *)(char *)®.wz); } else if (regno >= EXS && regno <= PC) { /* Consecutive 32-bit registers. */ *valptr = *(unsigned int *)((char *)®.exs + (regno - EXS) * sizeof(unsigned int)); } else if (regno >= S0 && regno <= S15) { /* Consecutive 32-bit registers, located elsewhere. */ *valptr = *(unsigned int *)((char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int)); } else { /* Non-existing register. */ status = E05; } return status;}/********************************** Packet I/O ******************************//* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte, represented by int x. */static inline charhighhex(int x){ return hexchars[(x >> 4) & 0xf];}/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte, represented by int x. */static inline charlowhex(int x){ return hexchars[x & 0xf];}/* Returns the integer equivalent of a hexadecimal character. */static inthex(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;}/* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */static char *mem2hex(char *buf, unsigned char *mem, int count){ int i; int ch; if (mem == NULL) { /* Invalid address, caught by 'm' packet handler. */ for (i = 0; i < count; i++) { *buf++ = '0'; *buf++ = '0'; } } else { /* Valid mem address. */ for (i = 0; i < count; i++) { ch = *mem++; *buf++ = highhex (ch); *buf++ = lowhex (ch); } } /* Terminate properly. */ *buf = '\0'; return buf;}/* Same as mem2hex, but puts it in network byte order. */static char *mem2hex_nbo(char *buf, unsigned char *mem, int count){ int i; int ch; mem += count - 1; for (i = 0; i < count; i++) { ch = *mem--; *buf++ = highhex (ch); *buf++ = lowhex (ch); } /* Terminate properly. */ *buf = '\0'; return buf;}/* Convert the array, in hexadecimal representation, pointed to by buf into binary representation. Put the result in mem, and return a pointer to the character after the last byte written. */static unsigned char*hex2mem(unsigned char *mem, char *buf, int count){ int i; unsigned char ch; for (i = 0; i < count; i++) { ch = hex (*buf++) << 4; ch = ch + hex (*buf++); *mem++ = ch; } return mem;}/* Put the content of the array, in binary representation, pointed to by buf into memory pointed to by mem, and return a pointer to the character after the last byte written. Gdb will escape $, #, and the escape char (0x7d). */static unsigned char*bin2mem(unsigned char *mem, unsigned char *buf, int count){ int i; unsigned char *next; for (i = 0; i < count; i++) { /* Check for any escaped characters. Be paranoid and only unescape chars that should be escaped. */ if (*buf == 0x7d) { next = buf + 1; if (*next == 0x3 || *next == 0x4 || *next == 0x5D) { /* #, $, ESC */ buf++; *buf += 0x20; } } *mem++ = *buf++; } return mem;}/* Await the sequence $<data>#<checksum> and store <data> in the array buffer returned. */static voidgetpacket(char *buffer){ unsigned char checksum; unsigned char xmitcsum; int i; int count; char ch; do { while((ch = getDebugChar ()) != '$') /* Wait for the start character $ and ignore all other characters */; checksum = 0; xmitcsum = -1; count = 0; /* Read until a # or the end of the buffer is reached */ while (count < BUFMAX) { ch = getDebugChar(); if (ch == '#') break; checksum = checksum + ch; buffer[count] = ch; count = count + 1; } if (count >= BUFMAX) continue; buffer[count] = 0; if (ch == '#') { xmitcsum = hex(getDebugChar()) << 4; xmitcsum += hex(getDebugChar()); if (checksum != xmitcsum) { /* Wrong checksum */ putDebugChar('-'); } else { /* Correct checksum */ putDebugChar('+'); /* If sequence characters are received, reply with them */ if (buffer[2] == ':') { putDebugChar(buffer[0]); putDebugChar(buffer[1]); /* Remove the sequence characters from the buffer */ count = gdb_cris_strlen(buffer); for (i = 3; i <= count; i++) buffer[i - 3] = buffer[i]; } } } } while (checksum != xmitcsum);}/* Send $<data>#<checksum> from the <data> in the array buffer. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -