📄 core-lite.patch
字号:
++ local_irq_save(flags);+ processor = smp_processor_id();+ kgdb_info[processor].debuggerinfo = regs;+ kgdb_info[processor].task = current;+ atomic_set(&procindebug[processor], 1);++ /* Wait till master processor goes completely into the debugger.+ * FIXME: this looks racy */+ while (!atomic_read(&procindebug[atomic_read(&debugger_active) - 1])) {+ int i = 10; /* an arbitrary number */++ while (--i)+ cpu_relax();+ }++ /* Wait till master processor is done with debugging */+ spin_lock(&slavecpulocks[processor]);++ /* This has been taken from x86 kgdb implementation and+ * will be needed by architectures that have SMP support+ */+ kgdb_correct_hw_break();++ kgdb_info[processor].debuggerinfo = NULL;+ kgdb_info[processor].task = NULL;++ /* Signal the master processor that we are done */+ atomic_set(&procindebug[processor], 0);+ spin_unlock(&slavecpulocks[processor]);+ local_irq_restore(flags);+}+#endif++int kgdb_get_mem(char *addr, unsigned char *buf, int count)+{+ kgdb_may_fault = 1;+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {+ kgdb_may_fault = 0;+ return -EINVAL;+ }+ while (count) {+ if ((unsigned long)addr < TASK_SIZE)+ return -EINVAL;+ *buf++ = *addr++;+ count--;+ }+ kgdb_may_fault = 0;+ return 0;+}++int kgdb_set_mem(char *addr, unsigned char *buf, int count)+{+ kgdb_may_fault = 1;+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {+ kgdb_may_fault = 0;+ return -EINVAL;+ }+ while (count) {+ if ((unsigned long)addr < TASK_SIZE)+ return -EINVAL;+ *addr++ = *buf++;+ count--;+ }+ kgdb_may_fault = 0;+ return 0;+}+int kgdb_activate_sw_breakpoints(void)+{+ int i;+ int error = 0;+ unsigned long addr;+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if (kgdb_break[i].state != bp_set)+ continue;+ addr = kgdb_break[i].bpt_addr;+ if ((error = kgdb_arch_set_breakpoint(addr,+ kgdb_break[i].saved_instr)))+ return error;++ if (CACHE_FLUSH_IS_SAFE) {+ if (current->mm && addr < TASK_SIZE)+ flush_cache_range(current->mm->mmap_cache,+ addr, addr + BREAK_INSTR_SIZE);+ else+ flush_icache_range(addr, addr ++ BREAK_INSTR_SIZE);+ }++ kgdb_break[i].state = bp_active;+ }+ return 0;+}++static int kgdb_set_sw_break(unsigned long addr)+{+ int i, breakno = -1;+ int error = 0;+ if ((error = kgdb_validate_break_address(addr)) < 0)+ return error;+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if ((kgdb_break[i].state == bp_set) &&+ (kgdb_break[i].bpt_addr == addr))+ return -EEXIST;+ }+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if (kgdb_break[i].state == bp_removed &&+ kgdb_break[i].bpt_addr == addr) {+ breakno = i;+ break;+ }+ }++ if (breakno == -1) {+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if (kgdb_break[i].state == bp_none) {+ breakno = i;+ break;+ }+ }+ }+ if (breakno == -1)+ return -E2BIG;++ kgdb_break[breakno].state = bp_set;+ kgdb_break[breakno].type = bp_breakpoint;+ kgdb_break[breakno].bpt_addr = addr;++ return 0;+}++int kgdb_deactivate_sw_breakpoints(void)+{+ int i;+ int error = 0;+ unsigned long addr;+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if (kgdb_break[i].state != bp_active)+ continue;+ addr = kgdb_break[i].bpt_addr;+ if ((error = kgdb_arch_remove_breakpoint(addr,+ kgdb_break[i].saved_instr)))+ return error;++ if (CACHE_FLUSH_IS_SAFE && current->mm &&+ addr < TASK_SIZE)+ flush_cache_range(current->mm->mmap_cache,+ addr, addr + BREAK_INSTR_SIZE);+ else if (CACHE_FLUSH_IS_SAFE)+ flush_icache_range(addr,+ addr + BREAK_INSTR_SIZE);+ kgdb_break[i].state = bp_set;+ }+ return 0;+}++static int kgdb_remove_sw_break(unsigned long addr)+{+ int i;++ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if ((kgdb_break[i].state == bp_set) &&+ (kgdb_break[i].bpt_addr == addr)) {+ kgdb_break[i].state = bp_removed;+ return 0;+ }+ }+ return -ENOENT;+}++int kgdb_isremovedbreak(unsigned long addr)+{+ int i;+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if ((kgdb_break[i].state == bp_removed) &&+ (kgdb_break[i].bpt_addr == addr)) {+ return 1;+ }+ }+ return 0;+}++int remove_all_break(void)+{+ int i;+ int error;+ unsigned long addr;++ /* Clear memory breakpoints. */+ for (i = 0; i < MAX_BREAKPOINTS; i++) {+ if (kgdb_break[i].state != bp_set)+ continue;+ addr = kgdb_break[i].bpt_addr;+ if ((error = kgdb_arch_remove_breakpoint(addr,+ kgdb_break[i].saved_instr)))+ return error;+ kgdb_break[i].state = bp_removed;+ }++ /* Clear hardware breakpoints. */+ kgdb_remove_all_hw_break();++ return 0;+}++static inline int shadow_pid(int realpid)+{+ if (realpid) {+ return realpid;+ }+ return pid_max + smp_processor_id();+}++static char gdbmsgbuf[BUFMAX + 1];+static void kgdb_msg_write(const char *s, int len)+{+ int i;+ int wcount;+ char *bufptr;++ /* 'O'utput */+ gdbmsgbuf[0] = 'O';++ /* Fill and send buffers... */+ while (len > 0) {+ bufptr = gdbmsgbuf + 1;++ /* Calculate how many this time */+ if ((len << 1) > (BUFMAX - 2))+ wcount = (BUFMAX - 2) >> 1;+ else+ wcount = len;++ /* Pack in hex chars */+ for (i = 0; i < wcount; i++)+ bufptr = pack_hex_byte(bufptr, s[i]);+ *bufptr = '\0';++ /* Move up */+ s += wcount;+ len -= wcount;++ /* Write packet */+ put_packet(gdbmsgbuf);+ }+}++/*+ * This function does all command procesing for interfacing to gdb.+ *+ * Locking hierarchy:+ * interface locks, if any (begin_session)+ * kgdb lock (debugger_active)+ *+ * Note that since we can be in here prior to our cpumask being filled+ * out, we err on the side of caution and loop over NR_CPUS instead+ * of a for_each_online_cpu.+ *+ */+int kgdb_handle_exception(int ex_vector, int signo, int err_code,+ struct pt_regs *linux_regs)+{+ unsigned long length, addr;+ char *ptr;+ unsigned long flags;+ unsigned i;+ long threadid;+ threadref thref;+ struct task_struct *thread = NULL;+ unsigned procid;+ int numshadowth = num_online_cpus() + kgdb_ops->shadowth;+ long kgdb_usethreadid = 0;+ int error = 0, all_cpus_synced = 0;+ struct pt_regs *shadowregs;+ int processor = smp_processor_id();+ void *local_debuggerinfo;++ /* Panic on recursive debugger calls. */+ if (atomic_read(&debugger_active) == smp_processor_id() + 1)+ return 0;++ acquirelock:++ /* Call the I/O drivers pre_exception routine if the I/O+ * driver defined one+ */+ if (kgdb_io_ops.pre_exception)+ kgdb_io_ops.pre_exception();++ /*+ * Interrupts will be restored by the 'trap return' code, except when+ * single stepping.+ */+ local_irq_save(flags);++ /* Hold debugger_active */+ procid = smp_processor_id();++ while (cmpxchg(&atomic_read(&debugger_active), 0, (procid + 1)) != 0) {+ int i = 25; /* an arbitrary number */++ while (--i)+ cpu_relax();++ if (atomic_read(&cpu_doing_single_step) != -1 &&+ atomic_read(&cpu_doing_single_step) != procid)+ udelay(1);+ }++ /*+ * Don't enter if the last instance of the exception handler wanted to+ * come into the debugger again.+ */+ if (atomic_read(&cpu_doing_single_step) != -1 &&+ atomic_read(&cpu_doing_single_step) != procid) {+ atomic_set(&debugger_active, 0);+ local_irq_restore(flags);+ goto acquirelock;+ }++ /*+ * Don't enter if we have hit a removed breakpoint.+ */+ if (kgdb_skipexception(ex_vector, linux_regs))+ goto kgdb_restore;++ kgdb_info[processor].debuggerinfo = linux_regs;+ kgdb_info[processor].task = current;++ kgdb_disable_hw_debug(linux_regs);++ if (!debugger_step || !kgdb_contthread)+ for (i = 0; i < NR_CPUS; i++)+ spin_lock(&slavecpulocks[i]);++ /* Make sure we get the other CPUs */+ if (!debugger_step || !kgdb_contthread)+ kgdb_roundup_cpus(flags);++ /* spin_lock code is good enough as a barrier so we don't+ * need one here */+ atomic_set(&procindebug[processor], 1);++ /* Wait a reasonable time for the other CPUs to be notified and+ * be waiting for us. Very early on this could be imperfect+ * as num_online_cpus() could be 0.*/+ for (i = 0; i < ROUNDUP_WAIT; i++) {+ int cpu, num = 0;+ for (cpu = 0; cpu < NR_CPUS; cpu++) {+ if (atomic_read(&procindebug[cpu]))+ num++;+ }+ if (num >= num_online_cpus()) {+ all_cpus_synced = 1;+ break;+ }+ }++ /* Clear the out buffer. */+ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));++ /* Master processor is completely in the debugger */+ kgdb_post_master_code(linux_regs, ex_vector, err_code);+ kgdb_deactivate_sw_breakpoints();+ debugger_step = 0;+ kgdb_contthread = NULL;++ if (kgdb_connected) {+ /* If we're still unable to roundup all of the CPUs,+ * send an 'O' packet informing the user again. */+ if (!all_cpus_synced)+ kgdb_msg_write("Not all CPUs have been synced for "+ "KGDB\n", 39);+ /* Reply to host that an exception has occurred */+ ptr = remcom_out_buffer;+ *ptr++ = 'T';+ *ptr++ = hexchars[(signo >> 4) % 16];+ *ptr++ = hexchars[signo % 16];+ ptr += strlen(strcpy(ptr, "thread:"));+ int_to_threadref(&thref, shadow_pid(current->pid));+ ptr = pack_threadid(ptr, &thref);+ *ptr++ = ';';++ put_packet(remcom_out_buffer);+ }++ kgdb_usethread = kgdb_info[processor].task;+ kgdb_usethreadid = shadow_pid(kgdb_info[processor].task->pid);++ while (kgdb_io_ops.read_char) {+ char *bpt_type;+ error = 0;++ /* Clear the out buffer. */+ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));++ get_packet(remcom_in_buffer);++ switch (remcom_in_buffer[0]) {+ case '?':+ /* We know that this packet is only sent+ * during initial connect. So to be safe,+ * we clear out our breakpoints now incase+ * GDB is reconnecting. */+ remove_all_break();+ /* Also, if we haven't been able to roundup all+ * CPUs, send an 'O' packet informing the user+ * as much. Only need to do this once. */+ if (!all_cpus_synced)+ kgdb_msg_write("Not all CPUs have been "+ "synced for KGDB\n", 39);+ remcom_out_buffer[0] = 'S';+ remcom_out_buffer[1] = hexchars[signo >> 4];+ remcom_out_buffer[2] = hexchars[signo % 16];+ break;++ case 'g': /* return the value of the CPU registers */+ thread = kgdb_usethread;++ if (!thread) {+ thread = kgdb_info[processor].task;+ local_debuggerinfo =+ kgdb_info[processor].debuggerinfo;+ } else {+ local_debuggerinfo = NULL;+ for (i = 0; i < NR_CPUS; i++) {+ /* Try to find the task on some other+ * or possibly this node if we do not+ * find the matching task then we try+ * to approximate the results.+ */+ if (thread == kgdb_info[i].task)+ local_debuggerinfo =+ kgdb_info[i].debuggerinfo;+ }+ }++ /* All threads that don't have debuggerinfo should be+ * in __schedule() sleeping, since all other CPUs+ * are in kgdb_wait, and thus have debuggerinfo. */+ if (kgdb_ops->shadowth &&+ kgdb_usethreadid >= pid_max + num_online_cpus()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -