📄 mips-stub.c
字号:
#define GDB_STUB_ENABLE_THREAD_SUPPORT 1/******************************************************************************* THIS SOFTWARE IS NOT COPYRIGHTED The following software is offered for use in the public domain. There is no warranty with regard to this software or its performance and the user must accept the software "AS IS" with all faults. THE CONTRIBUTORS DISCLAIM 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. $Id: mips-stub.c,v 1.8.2.1 2003/07/17 21:59:00 joel Exp $********************************************************************************** r46kstub.c -- target debugging stub for the IDT R4600 Orion processor** This module is based on the stub for the Hitachi SH processor written by* Ben Lee and Steve Chamberlain and supplied with gdb 4.16. The latter* in turn "is originally based on an m68k software stub written by Glenn* Engel at HP, but has changed quite a bit." The changes for the R4600* were written by C. M. Heard at VVNET. They were based in part on the* Algorithmics R4000 version of Phil Bunce's PMON program.** Remote communication protocol:** A debug packet whose contents are <data>* is encapsulated for transmission in the form:** $ <data> # CSUM1 CSUM2** <data> must be ASCII alphanumeric and cannot include characters* '$' or '#'. If <data> starts with two characters followed by* ':', then the existing stubs interpret this as a sequence number.** CSUM1 and CSUM2 are ascii hex representation of an 8-bit* checksum of <data>, the most significant nibble is sent first.* the hex digits 0-9,a-f are used.** Receiver responds with:** + if CSUM is correct* - if CSUM is incorrect** <data> is as follows. All values are encoded in ascii hex digits.** Request Packet** read registers g* reply XX....X Each byte of register data* is described by two hex digits.* Registers are in the internal order* for GDB, and the bytes in a register* are in the same order the machine uses.* or ENN for an error.** write regs GXX..XX Each byte of register data* is described by two hex digits.* reply OK for success* ENN for an error** write reg Pn...=r... Write register n... with value r....* reply OK for success* ENN for an error** read mem mAA..AA,LLLL AA..AA is address, LLLL is length.* reply XX..XX XX..XX is mem contents* Can be fewer bytes than requested* if able to read only part of the data.* or ENN NN is errno** write mem MAA..AA,LLLL:XX..XX* AA..AA is address,* LLLL is number of bytes,* XX..XX is data* reply OK for success* ENN for an error (this includes the case* where only part of the data was* written).** cont cAA..AA AA..AA is address to resume* If AA..AA is omitted,* resume at same address.** step sAA..AA AA..AA is address to resume* If AA..AA is omitted,* resume at same address.** There is no immediate reply to step or cont.* The reply comes when the machine stops.* It is SAA AA is the "signal number"** last signal ? Reply with the reason for stopping.* This is the same reply as is generated* for step or cont: SAA where AA is the* signal number.** detach D Host is detaching. Reply OK and* end remote debugging session.** reserved <other> On other requests, the stub should* ignore the request and send an empty* response ($#<checksum>). This way* we can extend the protocol and GDB* can tell whether the stub it is* talking to uses the old or the new.** Responses can be run-length encoded to save space. A '*' means that* the next character is an ASCII encoding giving a repeat count which* stands for that many repetitions of the character preceding the '*'.* The encoding is n+29, yielding a printable character when n >=3* (which is where rle starts to win). Don't use n > 99 since gdb* masks each character is receives with 0x7f in order to strip off* the parity bit.** As an example, "0* " means the same thing as "0000".********************************************************************************/#include <string.h>#include <signal.h>#include "mips_opcode.h"/* #include "memlimits.h" */#include <rtems.h>#include "gdb_if.h"extern int printk(const char *fmt, ...);/* Change it to something meaningful when debugging */#undef ASSERT#define ASSERT(x) if(!(x)) printk("ASSERT: stub: %d\n", __LINE__)/***************//* Exception Codes */#define EXC_INT 0 /* External interrupt */#define EXC_MOD 1 /* TLB modification exception */#define EXC_TLBL 2 /* TLB miss (Load or Ifetch) */#define EXC_TLBS 3 /* TLB miss (Store) */#define EXC_ADEL 4 /* Address error (Load or Ifetch) */#define EXC_ADES 5 /* Address error (Store) */#define EXC_IBE 6 /* Bus error (Ifetch) */#define EXC_DBE 7 /* Bus error (data load or store) */#define EXC_SYS 8 /* System call */#define EXC_BP 9 /* Break point */#define EXC_RI 10 /* Reserved instruction */#define EXC_CPU 11 /* Coprocessor unusable */#define EXC_OVF 12 /* Arithmetic overflow */#define EXC_TRAP 13 /* Trap exception */#define EXC_FPE 15 /* Floating Point Exception *//* FPU Control/Status register fields */#define CSR_FS 0x01000000 /* Set to flush denormals to zero */#define CSR_C 0x00800000 /* Condition bit (set by FP compare) */#define CSR_CMASK (0x3f<<12)#define CSR_CE 0x00020000#define CSR_CV 0x00010000#define CSR_CZ 0x00008000#define CSR_CO 0x00004000#define CSR_CU 0x00002000#define CSR_CI 0x00001000#define CSR_EMASK (0x1f<<7)#define CSR_EV 0x00000800#define CSR_EZ 0x00000400#define CSR_EO 0x00000200#define CSR_EU 0x00000100#define CSR_EI 0x00000080#define CSR_FMASK (0x1f<<2)#define CSR_FV 0x00000040#define CSR_FZ 0x00000020#define CSR_FO 0x00000010#define CSR_FU 0x00000008#define CSR_FI 0x00000004#define CSR_RMODE_MASK (0x3<<0)#define CSR_RM 0x00000003#define CSR_RP 0x00000002#define CSR_RZ 0x00000001#define CSR_RN 0x00000000/***************//* * Saved register information. Must be prepared by the exception * preprocessor before handle_exception is invoked. */#if (__mips == 3)typedef long long mips_register_t;#define R_SZ 8#elif (__mips == 1)typedef unsigned int mips_register_t;#define R_SZ 4#else#error "unknown MIPS ISA"#endifstatic mips_register_t *registers;#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)static char do_threads; /* != 0 means we are supporting threads */#endif/* * The following external functions provide character input and output. */extern char getDebugChar (void);extern void putDebugChar (char);/* * The following definitions are used for the gdb stub memory map */struct memseg{ unsigned begin, end, opts;};static int is_readable(unsigned,unsigned);static int is_writeable(unsigned,unsigned);static int is_steppable(unsigned);/* * BUFMAX defines the maximum number of characters in the inbound & outbound * packet buffers. At least 4+(sizeof registers)*2 bytes will be needed for * register packets. Memory dump packets can profitably use even more. */#define BUFMAX 1500static char inBuffer[BUFMAX];static char outBuffer[BUFMAX];/* Structure to keep info on a z-breaks */#define BREAKNUM 32struct z0break{ /* List support */ struct z0break *next; struct z0break *prev; /* Location, preserved data */ /* the address pointer, really, really must be a pointer to ** a 32 bit quantity (likely 64 on the R4k), so the full instruction is read & ** written. Making it a char * as on the i386 will cause ** the zbreaks to mess up the breakpoint instructions */ unsigned *address; unsigned instr;};static struct z0break z0break_arr[BREAKNUM];static struct z0break *z0break_avail = NULL;static struct z0break *z0break_list = NULL;/* * Convert an int to hex. */const char gdb_hexchars[] = "0123456789abcdef";#define highhex(x) gdb_hexchars [(x >> 4) & 0xf]#define lowhex(x) gdb_hexchars [x & 0xf]/* * Convert length bytes of data starting at addr into hex, placing the * result in buf. Return a pointer to the last (null) char in buf. */static char *mem2hex (void *_addr, int length, char *buf){ unsigned int addr = (unsigned int) _addr; if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ { long long *source = (long long *) (addr); long long *limit = (long long *) (addr + length); while (source < limit) { int i; long long k = *source++; for (i = 15; i >= 0; i--) *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; } } else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ { int *source = (int *) (addr); int *limit = (int *) (addr + length); while (source < limit) { int i; int k = *source++; for (i = 7; i >= 0; i--) *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; } } else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ { short *source = (short *) (addr); short *limit = (short *) (addr + length); while (source < limit) { int i; short k = *source++; for (i = 3; i >= 0; i--) *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; } } else /* byte aligned */ { char *source = (char *) (addr); char *limit = (char *) (addr + length); while (source < limit) { int i; char k = *source++; for (i = 1; i >= 0; i--) *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; } } *buf = '\0'; return (buf);}/* * Convert a hex character to an int. */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 a string from hex to int until a non-hex digit * is found. Return the number of characters processed. */static inthexToInt (char **ptr, int *intValue){ int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = hex (**ptr); if (hexValue >= 0) { *intValue = (*intValue << 4) | hexValue; numChars++; } else break; (*ptr)++; } return (numChars);}/* * Convert a string from hex to long long until a non-hex * digit is found. Return the number of characters processed. */static inthexToLongLong (char **ptr, long long *intValue){ int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = hex (**ptr); if (hexValue >= 0) { *intValue = (*intValue << 4) | hexValue; numChars++; } else break; (*ptr)++; } return (numChars);}/* * Convert the hex array buf into binary, placing the result at the * specified address. If the conversion fails at any point (i.e., * if fewer bytes are written than indicated by the size parameter) * then return 0; otherwise return 1. */static inthex2mem (char *buf, void *_addr, int length){ unsigned int addr = (unsigned int) _addr; if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ { long long *target = (long long *) (addr); long long *limit = (long long *) (addr + length); while (target < limit) { int i, j; long long k = 0; for (i = 0; i < 16; i++) if ((j = hex(*buf++)) < 0) return 0; else k = (k << 4) + j; *target++ = k; } } else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ { int *target = (int *) (addr); int *limit = (int *) (addr + length); while (target < limit) { int i, j; int k = 0; for (i = 0; i < 8; i++) if ((j = hex(*buf++)) < 0) return 0; else k = (k << 4) + j; *target++ = k; } } else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ { short *target = (short *) (addr); short *limit = (short *) (addr + length); while (target < limit) { int i, j; short k = 0; for (i = 0; i < 4; i++) if ((j = hex(*buf++)) < 0) return 0; else k = (k << 4) + j; *target++ = k; } } else /* byte aligned */ { char *target = (char *) (addr); char *limit = (char *) (addr + length); while (target < limit) { int i, j; char k = 0; for (i = 0; i < 2; i++) if ((j = hex(*buf++)) < 0) return 0; else k = (k << 4) + j; *target++ = k; } } return 1;}/* Convert the binary stream in BUF to memory. Gdb will escape $, #, and the escape char (0x7d). COUNT is the total number of bytes to write into memory. */static unsigned char *bin2mem ( unsigned char *buf, unsigned char *mem, int count){ int i; for (i = 0; i < count; i++) { /* Check for any escaped characters. Be paranoid and only unescape chars that should be escaped. */ if (*buf == 0x7d) { switch (*(buf+1)) { case 0x3: /* # */ case 0x4: /* $ */ case 0x5d: /* escape char */ buf++; *buf |= 0x20; break; default: /* nothing */ break; } } *mem++ = *buf++; } return mem;}/* * Scan the input stream for a sequence for the form $<data>#<checksum>. */static voidgetpacket (char *buffer){ unsigned char checksum; unsigned char xmitcsum; int i; int count; char ch; do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -