⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core-lite.patch

📁 Linux-2.6.18内核调试工具补丁程序KGDB。
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
++	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 + -