📄 sh-lite.patch
字号:
- *- * $ <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 and ready for next packet- * - - if CSUM is incorrect- *- * 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 repititions of the character preceding the '*'.- * The encoding is n+29, yielding a printable character where n >=3 - * (which is where RLE starts to win). Don't use an n > 126. - *- * So "0* " means the same as "0000".- */--#include <linux/string.h>-#include <linux/kernel.h>-#include <linux/sched.h>-#include <linux/smp.h>-#include <linux/spinlock.h>-#include <linux/delay.h>-#include <linux/linkage.h>-#include <linux/init.h>--#include <asm/system.h>-#include <asm/current.h>-#include <asm/signal.h>-#include <asm/pgtable.h>-#include <asm/ptrace.h>-#include <asm/kgdb.h>--#ifdef CONFIG_SH_KGDB_CONSOLE-#include <linux/console.h>-#endif--/* Function pointers for linkage */-kgdb_debug_hook_t *kgdb_debug_hook;-kgdb_bus_error_hook_t *kgdb_bus_err_hook;--int (*kgdb_getchar)(void);-void (*kgdb_putchar)(int);--static void put_debug_char(int c)-{- if (!kgdb_putchar)- return;- (*kgdb_putchar)(c);-}-static int get_debug_char(void)-{- if (!kgdb_getchar)- return -1;- return (*kgdb_getchar)();-}--/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */-#define BUFMAX 1024-#define NUMREGBYTES (MAXREG*4)-#define OUTBUFMAX (NUMREGBYTES*2+512)--enum regs {- R0 = 0, R1, R2, R3, R4, R5, R6, R7,- R8, R9, R10, R11, R12, R13, R14, R15,- PC, PR, GBR, VBR, MACH, MACL, SR,- /* */- MAXREG-};--static unsigned int registers[MAXREG];-struct kgdb_regs trap_registers;--char kgdb_in_gdb_mode;-char in_nmi; /* Set during NMI to prevent reentry */-int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */-int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */-int kgdb_halt;--/* Exposed for user access */-struct task_struct *kgdb_current;-unsigned int kgdb_g_imask;-int kgdb_trapa_val;-int kgdb_excode;--/* Default values for SCI (can override via kernel args in setup.c) */-#ifndef CONFIG_KGDB_DEFPORT-#define CONFIG_KGDB_DEFPORT 1-#endif--#ifndef CONFIG_KGDB_DEFBAUD-#define CONFIG_KGDB_DEFBAUD 115200-#endif--#if defined(CONFIG_KGDB_DEFPARITY_E)-#define CONFIG_KGDB_DEFPARITY 'E'-#elif defined(CONFIG_KGDB_DEFPARITY_O)-#define CONFIG_KGDB_DEFPARITY 'O'-#else /* CONFIG_KGDB_DEFPARITY_N */-#define CONFIG_KGDB_DEFPARITY 'N'-#endif--#ifdef CONFIG_KGDB_DEFBITS_7-#define CONFIG_KGDB_DEFBITS '7'-#else /* CONFIG_KGDB_DEFBITS_8 */-#define CONFIG_KGDB_DEFBITS '8'-#endif--/* SCI/UART settings, used in kgdb_console_setup() */-int kgdb_portnum = CONFIG_KGDB_DEFPORT;-int kgdb_baud = CONFIG_KGDB_DEFBAUD;-char kgdb_parity = CONFIG_KGDB_DEFPARITY;-char kgdb_bits = CONFIG_KGDB_DEFBITS;--/* Jump buffer for setjmp/longjmp */-static jmp_buf rem_com_env;--/* TRA differs sh3/4 */-#if defined(CONFIG_CPU_SH3)-#define TRA 0xffffffd0-#elif defined(CONFIG_CPU_SH4)-#define TRA 0xff000020-#endif--/* Macros for single step instruction identification */-#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900)-#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00)-#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \- (((op) & 0x7f ) << 1))-#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00)-#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00)-#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000)-#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \- (((op) & 0x7ff) << 1))-#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023)-#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8)-#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000)-#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \- (((op) & 0x7ff) << 1))-#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003)-#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf)-#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b)-#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf)-#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b)-#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf)-#define OPCODE_RTS(op) ((op) == 0xb)-#define OPCODE_RTE(op) ((op) == 0x2b)--#define SR_T_BIT_MASK 0x1-#define STEP_OPCODE 0xc320-#define BIOS_CALL_TRAP 0x3f--/* Exception codes as per SH-4 core manual */-#define ADDRESS_ERROR_LOAD_VEC 7-#define ADDRESS_ERROR_STORE_VEC 8-#define TRAP_VEC 11-#define INVALID_INSN_VEC 12-#define INVALID_SLOT_VEC 13-#define NMI_VEC 14-#define USER_BREAK_VEC 15-#define SERIAL_BREAK_VEC 58--/* Misc static */-static int stepped_address;-static short stepped_opcode;-static const char hexchars[] = "0123456789abcdef";-static char in_buffer[BUFMAX];-static char out_buffer[OUTBUFMAX];--static void kgdb_to_gdb(const char *s);--#ifdef CONFIG_KGDB_THREAD-static struct task_struct *trapped_thread;-static struct task_struct *current_thread;-typedef unsigned char threadref[8];-#define BUF_THREAD_ID_SIZE 16-#endif--/* Return addr as a real volatile address */-static inline unsigned int ctrl_inl(const unsigned long addr)-{- return *(volatile unsigned long *) addr;-}--/* Correctly set *addr using volatile */-static inline void ctrl_outl(const unsigned int b, unsigned long addr)-{- *(volatile unsigned long *) addr = b;-}--/* Get high hex bits */-static char highhex(const int x)-{- return hexchars[(x >> 4) & 0xf];-}--/* Get low hex bits */-static char lowhex(const int x)-{- return hexchars[x & 0xf];-}--/* Convert ch to hex */-static int hex(const 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 hex, placing result in buf.- Returns a pointer to the last char put in buf (null) */-static char *mem_to_hex(const char *mem, char *buf, const int count)-{- int i;- int ch;- unsigned short s_val;- unsigned long l_val;-- /* Check for 16 or 32 */- if (count == 2 && ((long) mem & 1) == 0) {- s_val = *(unsigned short *) mem;- mem = (char *) &s_val;- } else if (count == 4 && ((long) mem & 3) == 0) {- l_val = *(unsigned long *) mem;- mem = (char *) &l_val;- }- for (i = 0; i < count; i++) {- ch = *mem++;- *buf++ = highhex(ch);- *buf++ = lowhex(ch);- }- *buf = 0;- return (buf);-}--/* Convert 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 */-static char *hex_to_mem(const char *buf, char *mem, const 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);-}--/* While finding valid hex chars, convert to an integer, then return it */-static int hex_to_int(char **ptr, int *int_value)-{- int num_chars = 0;- int hex_value;-- *int_value = 0;-- while (**ptr) {- hex_value = hex(**ptr);- if (hex_value >= 0) {- *int_value = (*int_value << 4) | hex_value;- num_chars++;- } else- break;- (*ptr)++;- }- return num_chars;-}--/* Copy the binary array pointed to by buf into mem. Fix $, #,- and 0x7d escaped with 0x7d. Return a pointer to the character - after the last byte written. */-static char *ebin_to_mem(const char *buf, char *mem, int count)-{- for (; count > 0; count--, buf++) {- if (*buf == 0x7d)- *mem++ = *(++buf) ^ 0x20;- else- *mem++ = *buf;- }- return mem;-}--/* Pack a hex byte */-static char *pack_hex_byte(char *pkt, int byte)-{- *pkt++ = hexchars[(byte >> 4) & 0xf];- *pkt++ = hexchars[(byte & 0xf)];- return pkt;-}--#ifdef CONFIG_KGDB_THREAD--/* Pack a thread ID */-static char *pack_threadid(char *pkt, threadref * id)-{- char *limit;- unsigned char *altid;-- altid = (unsigned char *) id;-- limit = pkt + BUF_THREAD_ID_SIZE;- while (pkt < limit)- pkt = pack_hex_byte(pkt, *altid++);- return pkt;-}--/* Convert an integer into our threadref */-static void int_to_threadref(threadref * id, const int value)-{- unsigned char *scan = (unsigned char *) id;- int i = 4;-- while (i--)- *scan++ = 0;-- *scan++ = (value >> 24) & 0xff;- *scan++ = (value >> 16) & 0xff;- *scan++ = (value >> 8) & 0xff;- *scan++ = (value & 0xff);-}--/* Return a task structure ptr for a particular pid */-static struct task_struct *get_thread(int pid)-{- struct task_struct *thread;-- /* Use PID_MAX w/gdb for pid 0 */- if (pid == PID_MAX) pid = 0;-- /* First check via PID */- thread = find_task_by_pid(pid);-- if (thread)- return thread;-- /* Start at the start */- thread = init_tasks[0];-- /* Walk along the linked list of tasks */- do {- if (thread->pid == pid)- return thread;- thread = thread->next_task;- } while (thread != init_tasks[0]);-- return NULL;-}--#endif /* CONFIG_KGDB_THREAD */--/* Scan for the start char '$', read the packet and check the checksum */-static void get_packet(char *buffer, int buflen)-{- unsigned char checksum;- unsigned char xmitcsum;- int i;- int count;- char ch;-- do {- /* Ignore everything until the start character */- while ((ch = get_debug_char()) != '$');-- checksum = 0;- xmitcsum = -1;- count = 0;-- /* Now, read until a # or end of buffer is found */- while (count < (buflen - 1)) {- ch = get_debug_char();-- if (ch == '#')- break;-- checksum = checksum + ch;- buffer[count] = ch;- count = count + 1;- }-- buffer[count] = 0;-- /* Continue to read checksum following # */- if (ch == '#') {- xmitcsum = hex(get_debug_char()) << 4;- xmitcsum += hex(get_debug_char());-- /* Checksum */- if (checksum != xmitcsum)- put_debug_char('-'); /* Failed checksum */- else {- /* Ack successful transfer */- put_debug_char('+');-- /* If a sequence char is present, reply - the sequence ID */- if (buffer[2] == ':') {- put_debug_char(buffer[0]);- put_debug_char(buffer[1]);-- /* Remove sequence chars from buffer */- count = strlen(buffer);- for (i = 3; i <= count; i++)- buffer[i - 3] = buffer[i];- }- }- }- }- while (checksum != xmitcsum); /* Keep trying while we fail */-}--/* Send the packet in the buffer with run-length encoding */-static void put_packet(char *buffer)-{- int checksum;- char *src;- int runlen;- int encode;-- do {- src = buffer;- put_debug_char('$');- checksum = 0;-- /* Continue while we still have chars left */- while (*src) {- /* Check for runs up to 99 chars long */- for (runlen = 1; runlen < 99; runlen++) {- if (src[0] != src[runlen])- break;- }-- if (runlen > 3) {- /* Got a useful amount, send encoding */- encode = runlen + ' ' - 4;- put_debug_char(*src); checksum += *src;- put_debug_char('*'); checksum += '*';- put_debug_char(encode); checksum += encode;- src += runlen;- } else {- /* Otherwise just send the current char */- put_debug_char(*src); checksum += *src;- src += 1;- }- }-- /* '#' Separator, put high and low components of checksum */- put_debug_char('#');- put_debug_char(highhex(checksum));- put_debug_char(lowhex(checksum));- }- while ((get_debug_char()) != '+'); /* While no ack */-}--/* A bus error has occurred - perform a longjmp to return execution and- allow handling of the error */-static void kgdb_handle_bus_error(void)-{- longjmp(rem_com_env, 1);-}--/* Translate SH-3/4 exception numbers to unix-like signal values */-static int compute_signal(const int excep_code)-{- int sigval;-- switch (excep_code) {-- case INVALID_INSN_VEC:- case INVALID_SLOT_VEC:- sigval = SIGILL;- break;- case ADDRESS_ERROR_LOAD_VEC:- case ADDRESS_ERROR_STORE_VEC:- sigval = SIGSEGV;- break;-- case SERIAL_BREAK_VEC:- case NMI_VEC:- sigval = SIGINT;- break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -