📄 kgdb.c
字号:
/* The number of characters used for a 64 bit thread identifier. */#define HEXCHARS_IN_THREAD_ID 16/* 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 */#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 remcomInBuffer[BUFMAX];static char remcomOutBuffer[BUFMAX];/* Error and warning messages. */enum error_type{ SUCCESS, E01, E02, E03, E04, E05, E06, E07};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.", "E07 Change register content - P - the register is not stored on the stack"};/********************************* Register image ****************************//* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's Reference", p. 1-1, with the additional register definitions of the ETRAX 100LX in cris-opc.h. There are 16 general 32-bit registers, R0-R15, where R14 is the stack pointer, SP, and R15 is the program counter, PC. There are 16 special registers, P0-P15, where three of the unimplemented registers, P0, P4 and P8, are reserved as zero-registers. A read from any of these registers returns zero and a write has no effect. */enum register_name{ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, SP, PC, P0, VR, P2, P3, P4, CCR, P6, MOF, P8, IBR, IRP, SRP, BAR, DCCR, BRP, USP};/* The register sizes of the registers in register_name. An unimplemented register is designated by size 0 in this array. */static int register_size[] ={ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 0, 0, 2, 2, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4};/* Contains the register image of the executing thread in the assembler part of the code in order to avoid horrible addressing modes. */static registers reg;/* FIXME: Should this be used? Delete otherwise. *//* Contains the assumed consistency state of the register image. Uses the enum error_type for state information. */static int consistency_status = SUCCESS;/********************************** Handle exceptions ************************//* The variable reg contains the register image associated with the current_thread_c variable. It is a complete register image created at entry. The reg_g contains a register image of a task where the general registers are taken from the stack and all special registers are taken from the executing task. It is associated with current_thread_g and used in order to provide access mainly for 'g', 'G' and 'P'.*//* Need two task id pointers in order to handle Hct and Hgt commands. */static int current_thread_c = 0;static int current_thread_g = 0;/* Need two register images in order to handle Hct and Hgt commands. The variable reg_g is in addition to reg above. */static registers reg_g;/********************************** Breakpoint *******************************//* Use an internal stack in the breakpoint and interrupt response routines */#define INTERNAL_STACK_SIZE 1024static char 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 BRP as it is whereas a dynamic breakpoint requires subtraction with 2 in order to execute the instruction. The first breakpoint is static. */static unsigned char is_dyn_brkp = 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;}intdouble_this(int x){ return 2 * x;}/********************************* Register image ****************************//* Copy the content of a register image into another. The size n is the size of the register image. Due to struct assignment generation of memcpy in libc. */static voidcopy_registers (registers *dptr, registers *sptr, int n){ unsigned char *dreg; unsigned char *sreg; for (dreg = (unsigned char*)dptr, sreg = (unsigned char*)sptr; n > 0; n--) *dreg++ = *sreg++;}#ifdef PROCESS_SUPPORT/* Copy the stored registers from the stack. Put the register contents of thread thread_id in the struct reg. */static voidcopy_registers_from_stack (int thread_id, registers *regptr){ int j; stack_registers *s = (stack_registers *)stack_list[thread_id]; unsigned int *d = (unsigned int *)regptr; for (j = 13; j >= 0; j--) *d++ = s->r[j]; regptr->sp = (unsigned int)stack_list[thread_id]; regptr->pc = s->pc; regptr->dccr = s->dccr; regptr->srp = s->srp;}/* Copy the registers to the stack. Put the register contents of thread thread_id from struct reg to the stack. */static voidcopy_registers_to_stack (int thread_id, registers *regptr){ int i; stack_registers *d = (stack_registers *)stack_list[thread_id]; unsigned int *s = (unsigned int *)regptr; for (i = 0; i < 14; i++) { d->r[i] = *s++; } d->pc = regptr->pc; d->dccr = regptr->dccr; d->srp = regptr->srp;}#endif/* 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; registers *current_reg = ® if (regno >= R0 && regno <= PC) { /* 32-bit register with simple offset. */ hex2mem ((unsigned char *)current_reg + regno * sizeof(unsigned int), val, sizeof(unsigned int)); } else if (regno == P0 || regno == VR || regno == P4 || regno == P8) { /* Do not support read-only registers. */ status = E02; } else if (regno == CCR) { /* 16 bit register with complex offset. (P4 is read-only, P6 is not implemented, and P7 (MOF) is 32 bits in ETRAX 100LX. */ hex2mem ((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short), val, sizeof(unsigned short)); } else if (regno >= MOF && regno <= USP) { /* 32 bit register with complex offset. (P8 has been taken care of.) */ hex2mem ((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int), val, sizeof(unsigned int)); } else { /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ status = E05; } return status;}#ifdef PROCESS_SUPPORT/* Write a value to a specified register in the stack of a thread other than the current thread. Returns status code SUCCESS or E07. */static intwrite_stack_register (int thread_id, int regno, char *valptr){ int status = SUCCESS; stack_registers *d = (stack_registers *)stack_list[thread_id]; unsigned int val; hex2mem ((unsigned char *)&val, valptr, sizeof(unsigned int)); if (regno >= R0 && regno < SP) { d->r[regno] = val; } else if (regno == SP) { stack_list[thread_id] = val; } else if (regno == PC) { d->pc = val; } else if (regno == SRP) { d->srp = val; } else if (regno == DCCR) { d->dccr = val; } else { /* Do not support registers in the current thread. */ status = E07; } return status;}#endif/* Read a value from a specified register in the register image. Returns the value in the register or -1 for non-implemented registers. Should check consistency_status after a call which may be E05 after changes in the implementation. */static intread_register (char regno, unsigned int *valptr){ registers *current_reg = ® if (regno >= R0 && regno <= PC) { /* 32-bit register with simple offset. */ *valptr = *(unsigned int *)((char *)current_reg + regno * sizeof(unsigned int)); return SUCCESS; } else if (regno == P0 || regno == VR) { /* 8 bit register with complex offset. */ *valptr = (unsigned int)(*(unsigned char *) ((char *)&(current_reg->p0) + (regno-P0) * sizeof(char))); return SUCCESS; } else if (regno == P4 || regno == CCR) { /* 16 bit register with complex offset. */ *valptr = (unsigned int)(*(unsigned short *) ((char *)&(current_reg->p4) + (regno-P4) * sizeof(unsigned short))); return SUCCESS; } else if (regno >= MOF && regno <= USP) { /* 32 bit register with complex offset. */ *valptr = *(unsigned int *)((char *)&(current_reg->p8) + (regno-P8) * sizeof(unsigned int)); return SUCCESS; } else { /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ consistency_status = E05; return E05; }}/********************************** 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 int do_printk = 0;static char *mem2hex(char *buf, unsigned char *mem, int count){ int i; int ch; if (mem == NULL) { /* Bogus read from m0. FIXME: What constitutes a valid address? */ 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); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -