📄 core-lite.patch
字号:
+ shadowregs = kgdb_shadow_regs(linux_regs,+ kgdb_usethreadid -+ pid_max -+ num_online_cpus+ ());+ if (!shadowregs) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ regs_to_gdb_regs(gdb_regs, shadowregs);+ } else if (local_debuggerinfo)+ regs_to_gdb_regs(gdb_regs, local_debuggerinfo);+ else {+ /* Pull stuff saved during+ * switch_to; nothing else is+ * accessible (or even particularly relevant).+ * This should be enough for a stack trace. */+ sleeping_thread_to_gdb_regs(gdb_regs, thread);+ }+ kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer,+ NUMREGBYTES);+ break;++ /* set the value of the CPU registers - return OK */+ case 'G':+ kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs,+ NUMREGBYTES);++ if (kgdb_usethread && kgdb_usethread != current)+ error_packet(remcom_out_buffer, -EINVAL);+ else {+ gdb_regs_to_regs(gdb_regs, linux_regs);+ strcpy(remcom_out_buffer, "OK");+ }+ break;++ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */+ case 'm':+ ptr = &remcom_in_buffer[1];+ if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&+ kgdb_hex2long(&ptr, &length) > 0) {+ if (IS_ERR(ptr = kgdb_mem2hex((char *)addr,+ remcom_out_buffer,+ length)))+ error_packet(remcom_out_buffer,+ PTR_ERR(ptr));+ } else+ error_packet(remcom_out_buffer, -EINVAL);+ break;++ /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */+ case 'M':+ if (IS_ERR(ptr = write_mem_msg(0)))+ error_packet(remcom_out_buffer, PTR_ERR(ptr));+ else+ strcpy(remcom_out_buffer, "OK");+ break;+ /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */+ case 'X':+ if (IS_ERR(ptr = write_mem_msg(1)))+ error_packet(remcom_out_buffer, PTR_ERR(ptr));+ else+ strcpy(remcom_out_buffer, "OK");+ break;++ /* kill or detach. KGDB should treat this like a+ * continue.+ */+ case 'D':+ if ((error = remove_all_break()) < 0) {+ error_packet(remcom_out_buffer, error);+ } else {+ strcpy(remcom_out_buffer, "OK");+ kgdb_connected = 0;+ }+ put_packet(remcom_out_buffer);+ goto default_handle;++ case 'k':+ /* Don't care about error from remove_all_break */+ remove_all_break();+ kgdb_connected = 0;+ goto default_handle;++ /* Reboot */+ case 'R':+ /* For now, only honor R0 */+ if (strcmp(remcom_in_buffer, "R0") == 0) {+ printk(KERN_CRIT "Executing reboot\n");+ strcpy(remcom_out_buffer, "OK");+ put_packet(remcom_out_buffer);+ emergency_sync();+ /* Execution should not return from+ * machine_restart()+ */+ machine_restart(NULL);+ kgdb_connected = 0;+ goto default_handle;+ }++ /* query */+ case 'q':+ switch (remcom_in_buffer[1]) {+ case 's':+ case 'f':+ if (memcmp(remcom_in_buffer + 2, "ThreadInfo",+ 10)) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }++ /*+ * If we have not yet completed in+ * pidhash_init() there isn't much we+ * can give back.+ */+ if (!pidhash_init_done) {+ if (remcom_in_buffer[1] == 'f')+ strcpy(remcom_out_buffer,+ "m0000000000000001");+ break;+ }++ if (remcom_in_buffer[1] == 'f') {+ threadid = 1;+ }+ remcom_out_buffer[0] = 'm';+ ptr = remcom_out_buffer + 1;+ for (i = 0; i < 17 && threadid < pid_max ++ numshadowth; threadid++) {+ thread = getthread(linux_regs,+ threadid);+ if (thread) {+ int_to_threadref(&thref,+ threadid);+ pack_threadid(ptr, &thref);+ ptr += 16;+ *(ptr++) = ',';+ i++;+ }+ }+ *(--ptr) = '\0';+ break;++ case 'C':+ /* Current thread id */+ strcpy(remcom_out_buffer, "QC");++ threadid = shadow_pid(current->pid);++ int_to_threadref(&thref, threadid);+ pack_threadid(remcom_out_buffer + 2, &thref);+ break;+ case 'T':+ if (memcmp(remcom_in_buffer + 1,+ "ThreadExtraInfo,", 16)) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ threadid = 0;+ ptr = remcom_in_buffer + 17;+ kgdb_hex2long(&ptr, &threadid);+ if (!getthread(linux_regs, threadid)) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ if (threadid < pid_max) {+ kgdb_mem2hex(getthread(linux_regs,+ threadid)->comm,+ remcom_out_buffer, 16);+ } else if (threadid >= pid_max ++ num_online_cpus()) {+ kgdb_shadowinfo(linux_regs,+ remcom_out_buffer,+ threadid - pid_max -+ num_online_cpus());+ } else {+ static char tmpstr[23 ++ BUF_THREAD_ID_SIZE];+ sprintf(tmpstr, "Shadow task %d"+ " for pid 0",+ (int)(threadid - pid_max));+ kgdb_mem2hex(tmpstr, remcom_out_buffer,+ strlen(tmpstr));+ }+ break;+ }+ break;++ /* task related */+ case 'H':+ switch (remcom_in_buffer[1]) {+ case 'g':+ ptr = &remcom_in_buffer[2];+ kgdb_hex2long(&ptr, &threadid);+ thread = getthread(linux_regs, threadid);+ if (!thread && threadid > 0) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ kgdb_usethread = thread;+ kgdb_usethreadid = threadid;+ strcpy(remcom_out_buffer, "OK");+ break;++ case 'c':+ ptr = &remcom_in_buffer[2];+ kgdb_hex2long(&ptr, &threadid);+ if (!threadid) {+ kgdb_contthread = NULL;+ } else {+ thread = getthread(linux_regs,+ threadid);+ if (!thread && threadid > 0) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ kgdb_contthread = thread;+ }+ strcpy(remcom_out_buffer, "OK");+ break;+ }+ break;++ /* Query thread status */+ case 'T':+ ptr = &remcom_in_buffer[1];+ kgdb_hex2long(&ptr, &threadid);+ thread = getthread(linux_regs, threadid);+ if (thread)+ strcpy(remcom_out_buffer, "OK");+ else+ error_packet(remcom_out_buffer, -EINVAL);+ break;+ /* Since GDB-5.3, it's been drafted that '0' is a software+ * breakpoint, '1' is a hardware breakpoint, so let's do+ * that.+ */+ case 'z':+ case 'Z':+ bpt_type = &remcom_in_buffer[1];+ ptr = &remcom_in_buffer[2];++ if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') {+ /* Unsupported */+ if (*bpt_type > '4')+ break;+ } else if (*bpt_type != '0' && *bpt_type != '1')+ /* Unsupported. */+ break;+ /* Test if this is a hardware breakpoint, and+ * if we support it. */+ if (*bpt_type == '1' &&+ !kgdb_ops->flags & KGDB_HW_BREAKPOINT)+ /* Unsupported. */+ break;++ if (*(ptr++) != ',') {+ error_packet(remcom_out_buffer, -EINVAL);+ break;+ } else if (kgdb_hex2long(&ptr, &addr)) {+ if (*(ptr++) != ',' ||+ !kgdb_hex2long(&ptr, &length)) {+ error_packet(remcom_out_buffer,+ -EINVAL);+ break;+ }+ } else {+ error_packet(remcom_out_buffer, -EINVAL);+ break;+ }++ if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')+ error = kgdb_set_sw_break(addr);+ else if (remcom_in_buffer[0] == 'Z' && *bpt_type == '1')+ error = kgdb_set_hw_break(addr);+ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')+ error = kgdb_remove_sw_break(addr);+ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '1')+ error = kgdb_remove_hw_break(addr);+ else if (remcom_in_buffer[0] == 'Z')+ error = kgdb_ops->set_hw_breakpoint(addr,+ (int)length,+ *bpt_type);+ else if (remcom_in_buffer[0] == 'z')+ error = kgdb_ops->remove_hw_breakpoint(addr,+ (int)+ length,+ *bpt_type);++ if (error == 0)+ strcpy(remcom_out_buffer, "OK");+ else+ error_packet(remcom_out_buffer, error);++ break;+ case 'c':+ case 's':+ if (kgdb_contthread && kgdb_contthread != current) {+ /* Can't switch threads in kgdb */+ error_packet(remcom_out_buffer, -EINVAL);+ break;+ }+ kgdb_activate_sw_breakpoints();+ /* Followthrough to default processing */+ default:+ default_handle:+ error = kgdb_arch_handle_exception(ex_vector, signo,+ err_code,+ remcom_in_buffer,+ remcom_out_buffer,+ linux_regs);++ if (error >= 0 || remcom_in_buffer[0] == 'D' ||+ remcom_in_buffer[0] == 'k')+ goto kgdb_exit;++ } /* switch */++ /* reply to the request */+ put_packet(remcom_out_buffer);+ }++ kgdb_exit:+ /* Call the I/O driver's post_exception routine if the I/O+ * driver defined one.+ */+ if (kgdb_io_ops.post_exception)+ kgdb_io_ops.post_exception();++ kgdb_info[processor].debuggerinfo = NULL;+ kgdb_info[processor].task = NULL;+ atomic_set(&procindebug[processor], 0);++ if (!debugger_step || !kgdb_contthread) {+ for (i = 0; i < NR_CPUS; i++)+ spin_unlock(&slavecpulocks[i]);+ /* Wait till all the processors have quit+ * from the debugger. */+ for (i = 0; i < NR_CPUS; i++) {+ while (atomic_read(&procindebug[i])) {+ int j = 10; /* an arbitrary number */++ while (--j)+ cpu_relax();+ }+ }+ }++#ifdef CONFIG_SMP+ /* This delay has a real purpose. The problem is that if you+ * are single-stepping, you are sending an NMI to all the+ * other processors to stop them. Interrupts come in, but+ * don't get handled. Then you let them go just long enough+ * to get into their interrupt routines and use up some stack.+ * You stop them again, and then do the same thing. After a+ * while you blow the stack on the other processors. This+ * delay gives some time for interrupts to be cleared out on+ * the other processors.+ */+ if (debugger_step)+ mdelay(2);+#endif+kgdb_restore:+ /* Free debugger_active */+ atomic_set(&debugger_active, 0);+ local_irq_restore(flags);++ return error;+}++/*+ * GDB places a breakpoint at this function to know dynamically+ * loaded objects. It's not defined static so that only one instance with this+ * name exists in the kernel.+ */++int module_event(struct notifier_block *self, unsigned long val, void *data)+{+ return 0;+}++static struct notifier_block kgdb_module_load_nb = {+ .notifier_call = module_event,+};++void kgdb_nmihook(int cpu, void *regs)+{+#ifdef CONFIG_SMP+ if (!atomic_read(&procindebug[cpu]) && atomic_read(&debugger_active) != (cpu + 1))+ kgdb_wait((struct pt_regs *)regs);+#endif+}++/*+ * This is called when a panic happens. All we need to do is+ * breakpoint().+ */+static int kgdb_panic_notify(struct notifier_block *self, unsigned long cmd,+ void *ptr)+{+ breakpoint();++ return 0;+}++static struct notifier_block kgdb_panic_notifier = {+ .notifier_call = kgdb_panic_notify,+};++/*+ * Initialization that needs to be done in either of our entry points.+ */+static void __init kgdb_internal_init(void)+{+ int i;++ /* Initialize our spinlocks. */+ for (i = 0; i < NR_CPUS; i++)+ spin_lock_init(&slavecpulocks[i]);++ for (i = 0; i < MAX_BREAKPOINTS; i++)+ kgdb_break[i].state = bp_none;++ /* Initialize the I/O handles */+ memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev));++ /* We can't do much if this fails */+ register_module_notifier(&kgdb_module_load_nb);++ kgdb_initialized = 1;+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -