📄 sh-lite.patch
字号:
--/* Is a thread alive? */-static void thread_status_msg(void)-{- char *ptr;- int threadid;- struct task_struct *thread = NULL;-- ptr = &in_buffer[1];- hex_to_int(&ptr, &threadid);- thread = get_thread(threadid);- if (thread)- send_ok_msg();- else- send_err_msg();-}-/* Send the current thread ID */-static void thread_id_msg(void)-{- int threadid;- threadref thref;-- out_buffer[0] = 'Q';- out_buffer[1] = 'C';-- if (current_thread)- threadid = current_thread->pid;- else if (trapped_thread)- threadid = trapped_thread->pid;- else /* Impossible, but just in case! */- {- send_err_msg();- return;- }-- /* Translate pid 0 to PID_MAX for gdb */- if (threadid == 0) threadid = PID_MAX;-- int_to_threadref(&thref, threadid);- pack_threadid(out_buffer + 2, &thref);- out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';- put_packet(out_buffer);-}--/* Send thread info */-static void thread_info_msg(void)-{- struct task_struct *thread = NULL;- int threadid;- char *pos;- threadref thref;-- /* Start with 'm' */- out_buffer[0] = 'm';- pos = &out_buffer[1];-- /* For all possible thread IDs - this will overrun if > 44 threads! */- /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */- for (threadid = 1; threadid <= PID_MAX; threadid++) {-- read_lock(&tasklist_lock);- thread = get_thread(threadid);- read_unlock(&tasklist_lock);-- /* If it's a valid thread */- if (thread) {- int_to_threadref(&thref, threadid);- pack_threadid(pos, &thref);- pos += BUF_THREAD_ID_SIZE;- *pos++ = ',';- }- }- *--pos = 0; /* Lose final comma */- put_packet(out_buffer);--}--/* Return printable info for gdb's 'info threads' command */-static void thread_extra_info_msg(void)-{- int threadid;- struct task_struct *thread = NULL;- char buffer[20], *ptr;- int i;-- /* Extract thread ID */- ptr = &in_buffer[17];- hex_to_int(&ptr, &threadid);- thread = get_thread(threadid);-- /* If we don't recognise it, say so */- if (thread == NULL)- strcpy(buffer, "(unknown)");- else- strcpy(buffer, thread->comm);-- /* Construct packet */- for (i = 0, ptr = out_buffer; buffer[i]; i++)- ptr = pack_hex_byte(ptr, buffer[i]);-- if (thread->thread.pc == (unsigned long)ret_from_fork) {- strcpy(buffer, "<new fork>");- for (i = 0; buffer[i]; i++)- ptr = pack_hex_byte(ptr, buffer[i]);- }-- *ptr = '\0';- put_packet(out_buffer);-}--/* Handle all qFooBarBaz messages - have to use an if statement as- opposed to a switch because q messages can have > 1 char id. */-static void query_msg(void)-{- const char *q_start = &in_buffer[1];-- /* qC = return current thread ID */- if (strncmp(q_start, "C", 1) == 0)- thread_id_msg();-- /* qfThreadInfo = query all threads (first) */- else if (strncmp(q_start, "fThreadInfo", 11) == 0)- thread_info_msg();-- /* qsThreadInfo = query all threads (subsequent). We know we have sent- them all after the qfThreadInfo message, so there are no to send */- else if (strncmp(q_start, "sThreadInfo", 11) == 0)- put_packet("l"); /* el = last */-- /* qThreadExtraInfo = supply printable information per thread */- else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)- thread_extra_info_msg();-- /* Unsupported - empty message as per spec */- else- send_empty_msg();-}-#endif /* CONFIG_KGDB_THREAD */--/*- * Bring up the ports..- */-static int kgdb_serial_setup(void)-{- extern int kgdb_console_setup(struct console *co, char *options);- struct console dummy;-- kgdb_console_setup(&dummy, 0);-- return 0;-}--/* The command loop, read and act on requests */-static void kgdb_command_loop(const int excep_code, const int trapa_value)-{- int sigval;-- if (excep_code == NMI_VEC) {-#ifndef CONFIG_KGDB_NMI- KGDB_PRINTK("Ignoring unexpected NMI?\n");- return;-#else /* CONFIG_KGDB_NMI */- if (!kgdb_enabled) {- kgdb_enabled = 1;- kgdb_init();- }-#endif /* CONFIG_KGDB_NMI */- }-- /* Ignore if we're disabled */- if (!kgdb_enabled)- return;--#ifdef CONFIG_KGDB_THREAD- /* Until GDB specifies a thread */- current_thread = NULL;- trapped_thread = current;-#endif-- /* Enter GDB mode (e.g. after detach) */- if (!kgdb_in_gdb_mode) {- /* Do serial setup, notify user, issue preemptive ack */- kgdb_serial_setup();- KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",- (kgdb_porttype ? kgdb_porttype->name : ""),- kgdb_portnum, kgdb_baud);- kgdb_in_gdb_mode = 1;- put_debug_char('+');- }-- /* Reply to host that an exception has occurred */- sigval = compute_signal(excep_code);- send_signal_msg(sigval);-- /* TRAP_VEC exception indicates a software trap inserted in place of- code by GDB so back up PC by one instruction, as this instruction- will later be replaced by its original one. Do NOT do this for- trap 0xff, since that indicates a compiled-in breakpoint which- will not be replaced (and we would retake the trap forever) */- if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {- trap_registers.pc -= 2;- }-- /* Undo any stepping we may have done */- undo_single_step();-- while (1) {-- out_buffer[0] = 0;- get_packet(in_buffer, BUFMAX);-- /* Examine first char of buffer to see what we need to do */- switch (in_buffer[0]) {-- case '?': /* Send which signal we've received */- send_signal_msg(sigval);- break;-- case 'g': /* Return the values of the CPU registers */- send_regs_msg();- break;-- case 'G': /* Set the value of the CPU registers */- set_regs_msg();- break;-- case 'm': /* Read LLLL bytes address AA..AA */- read_mem_msg();- break;-- case 'M': /* Write LLLL bytes address AA..AA, ret OK */- write_mem_msg(0); /* 0 = data in hex */- break;-- case 'X': /* Write LLLL bytes esc bin address AA..AA */- if (kgdb_bits == '8')- write_mem_msg(1); /* 1 = data in binary */- else- send_empty_msg();- break;-- case 'C': /* Continue, signum included, we ignore it */- continue_with_sig_msg();- return;-- case 'c': /* Continue at address AA..AA (optional) */- continue_msg();- return;-- case 'S': /* Step, signum included, we ignore it */- step_with_sig_msg();- return;-- case 's': /* Step one instruction from AA..AA */- step_msg();- return;--#ifdef CONFIG_KGDB_THREAD-- case 'H': /* Task related */- set_thread_msg();- break;-- case 'T': /* Query thread status */- thread_status_msg();- break;-- case 'q': /* Handle query - currently thread-related */- query_msg();- break;-#endif-- case 'k': /* 'Kill the program' with a kernel ? */- break;-- case 'D': /* Detach from program, send reply OK */- kgdb_in_gdb_mode = 0;- send_ok_msg();- get_debug_char();- return;-- default:- send_empty_msg();- break;- }- }-}--/* There has been an exception, most likely a breakpoint. */-void kgdb_handle_exception(struct pt_regs *regs)-{- int excep_code, vbr_val;- int count;- int trapa_value = ctrl_inl(TRA);-- /* Copy kernel regs (from stack) */- for (count = 0; count < 16; count++)- trap_registers.regs[count] = regs->regs[count];- trap_registers.pc = regs->pc;- trap_registers.pr = regs->pr;- trap_registers.sr = regs->sr;- trap_registers.gbr = regs->gbr;- trap_registers.mach = regs->mach;- trap_registers.macl = regs->macl;-- asm("stc vbr, %0":"=r"(vbr_val));- trap_registers.vbr = vbr_val;-- /* Get excode for command loop call, user access */- asm("stc r2_bank, %0":"=r"(excep_code));- kgdb_excode = excep_code;-- /* Other interesting environment items for reference */- asm("stc r6_bank, %0":"=r"(kgdb_g_imask));- kgdb_current = current;- kgdb_trapa_val = trapa_value;-- /* Act on the exception */- kgdb_command_loop(excep_code >> 5, trapa_value);-- kgdb_current = NULL;-- /* Copy back the (maybe modified) registers */- for (count = 0; count < 16; count++)- regs->regs[count] = trap_registers.regs[count];- regs->pc = trap_registers.pc;- regs->pr = trap_registers.pr;- regs->sr = trap_registers.sr;- regs->gbr = trap_registers.gbr;- regs->mach = trap_registers.mach;- regs->macl = trap_registers.macl;-- vbr_val = trap_registers.vbr;- asm("ldc %0, vbr": :"r"(vbr_val));-- return;-}--/* Trigger a breakpoint by function */-void breakpoint(void)-{- if (!kgdb_enabled) {- kgdb_enabled = 1;- kgdb_init();- }- BREAKPOINT();-}--/* Initialise the KGDB data structures and serial configuration */-int kgdb_init(void)-{- if (!kgdb_enabled)- return 1;-- in_nmi = 0;- kgdb_nofault = 0;- stepped_opcode = 0;- kgdb_in_gdb_mode = 0;-- if (kgdb_serial_setup() != 0) {- KGDB_PRINTK("serial setup error\n");- return -1;- }-- /* Init ptr to exception handler */- kgdb_debug_hook = kgdb_handle_exception;- kgdb_bus_err_hook = kgdb_handle_bus_error;-- /* Enter kgdb now if requested, or just report init done */- if (kgdb_halt) {- kgdb_in_gdb_mode = 1;- put_debug_char('+');- breakpoint();- }- else- {- KGDB_PRINTK("stub is initialized.\n");- }-- return 0;-}--/* Make function available for "user messages"; console will use it too. */--char gdbmsgbuf[BUFMAX];-#define MAXOUT ((BUFMAX-2)/2)--static void kgdb_msg_write(const char *s, unsigned count)-{- int i;- int wcount;- char *bufptr;-- /* 'O'utput */- gdbmsgbuf[0] = 'O';-- /* Fill and send buffers... */- while (count > 0) {- bufptr = gdbmsgbuf + 1;-- /* Calculate how many this time */- wcount = (count > MAXOUT) ? MAXOUT : count;- - /* Pack in hex chars */- for (i = 0; i < wcount; i++)- bufptr = pack_hex_byte(bufptr, s[i]);- *bufptr = '\0';-- /* Move up */- s += wcount;- count -= wcount;-- /* Write packet */- put_packet(gdbmsgbuf);- }-}--static void kgdb_to_gdb(const char *s)-{- kgdb_msg_write(s, strlen(s));-}--#ifdef CONFIG_SH_KGDB_CONSOLE-void kgdb_console_write(struct console *co, const char *s, unsigned count)-{- /* Bail if we're not talking to GDB */- if (!kgdb_in_gdb_mode)- return;-- kgdb_msg_write(s, count);-}-#endifIndex: linux-2.6.16/arch/sh/kernel/kgdb.c===================================================================--- linux-2.6.16.orig/arch/sh/kernel/kgdb.c 2006-04-25 10:59:23.506518750 +0530+++ linux-2.6.16/arch/sh/kernel/kgdb.c 2006-04-25 11:34:01.000000000 +0530@@ -0,0 +1,363 @@+/*+ * arch/sh/kernel/kgdb.c+ *+ * Contains SH-specific low-level support for KGDB.+ *+ * Containes extracts from code by Glenn Engel, Jim Kingdon,+ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,+ * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>,+ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>,+ * Henry Bell <henry.bell@st.com> and Jeremy Siegel <jsiegel@mvista.com>+ *+ * Maintainer: Tom Rini <trini@kernel.crashing.org>+ *+ * 2004 (c) MontaVista Software, Inc. This file is licensed under+ * the terms of the GNU General Public License version 2. This program+ * is licensed "as is" without any warranty of any kind, whether express+ * or implied.+ */++#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 <linux/kgdb.h>++#include <asm/system.h>+#include <asm/current.h>+#include <asm/signal.h>+#include <asm/pgtable.h>+#include <asm/ptrace.h>++extern void per_cpu_trap_init(void);+extern atomic_t cpu_doing_single_step;++/* Function pointers for linkage */+static struct kgdb_regs trap_registers;++/* Globals. */+char in_nmi; /* Set during NMI to prevent reentry */++/* 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)+#def
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -