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

📄 ia64-lite.patch

📁 Linux-2.6.18内核调试工具补丁程序KGDB。
💻 PATCH
📖 第 1 页 / 共 4 页
字号:
+		printk(KERN_INFO "do_init_hw_break: %d exceeds max %d\n",+		       (int)HW_BREAKPOINT, (int)MAX_HW_BREAKPOINT);++		while ((HW_BREAKPOINT > MAX_HW_BREAKPOINT)+		       && hw_break_total_ibr != 1)+			hw_break_total_ibr--;+		while (HW_BREAKPOINT > MAX_HW_BREAKPOINT)+			hw_break_total_dbr--;+	}++	breakinfo = hwbreaks;++	memset(breakinfo, 0, HW_BREAKPOINT * sizeof(struct hw_breakpoint));++	for (i = 0; i < hw_break_total_dbr; i++)+		breakinfo[i].capable = HWCAP_DBR;++	for (; i < HW_BREAKPOINT; i++)+		breakinfo[i].capable = HWCAP_IBR;++	return;+}++void kgdb_correct_hw_break(void)+{+	int breakno;++	if (!breakinfo)+		return;++	for (breakno = 0; breakno < HW_BREAKPOINT; breakno++) {+		if (breakinfo[breakno].enabled) {+			if (breakinfo[breakno].capable & HWCAP_IBR) {+				int ibreakno = breakno - hw_break_total_dbr;+				ia64_set_ibr(ibreakno << 1,+					     breakinfo[breakno].addr);+				ia64_set_ibr((ibreakno << 1) + 1,+					     (~breakinfo[breakno].mask &+					      ((1UL << 56UL) - 1)) |+					      (1UL << 56UL) | (1UL << 63UL));+			} else {+				ia64_set_dbr(breakno << 1,+					     breakinfo[breakno].addr);+				ia64_set_dbr((breakno << 1) + 1,+					     (~breakinfo[breakno].+					      mask & ((1UL << 56UL) - 1)) |+					     (1UL << 56UL) |+					     (breakinfo[breakno].type << 62UL));+			}+		} else {+			if (breakinfo[breakno].capable & HWCAP_IBR)+				ia64_set_ibr(((breakno -+					       hw_break_total_dbr) << 1) + 1,+					     0);+			else+				ia64_set_dbr((breakno << 1) + 1, 0);+		}+	}++	return;+}++int hardware_breakpoint(unsigned long addr, int length, int type, int action)+{+	int breakno, found, watch;+	unsigned long mask;+	extern unsigned long _start[];++	if (!hw_breakpoint_init)+		do_init_hw_break();++	if (!breakinfo)+		return 0;+	else if (addr == (unsigned long)_start)+		return 1;++	if (type == WATCH_ACCESS)+		mask = HWCAP_DBR;+	else+		mask = 1UL << type;++	for (watch = 0, found = 0, breakno = 0; breakno < HW_BREAKPOINT;+	     breakno++) {+		if (action) {+			if (breakinfo[breakno].enabled+			    || !(breakinfo[breakno].capable & mask))+				continue;+			breakinfo[breakno].enabled = 1;+			breakinfo[breakno].type = type;+			breakinfo[breakno].mask = length - 1;+			breakinfo[breakno].addr = addr;+			watch = breakno;+		} else if (breakinfo[breakno].enabled &&+			   ((length < 0 && breakinfo[breakno].addr == addr) ||+			    ((breakinfo[breakno].capable & mask) &&+			     (breakinfo[breakno].mask == (length - 1)) &&+			     (breakinfo[breakno].addr == addr)))) {+			breakinfo[breakno].enabled = 0;+			breakinfo[breakno].type = 0UL;+		} else+			continue;+		found++;+		if (type != WATCH_ACCESS)+			break;+		else if (found == 2)+			break;+		else+			mask = HWCAP_IBR;+	}++	if (type == WATCH_ACCESS && found == 1) {+		breakinfo[watch].enabled = 0;+		found = 0;+	}++	mb();+	return found;+}++int kgdb_arch_set_hw_breakpoint(unsigned long addr, int len,+				enum kgdb_bptype type)+{+	return hardware_breakpoint(addr, len, type - '1', 1);+}++int kgdb_arch_remove_hw_breakpoint(unsigned long addr, int len,+				   enum kgdb_bptype type)+{+	return hardware_breakpoint(addr, len, type - '1', 0);+}++int kgdb_remove_hw_break(unsigned long addr)+{+	return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 0);++}++void kgdb_remove_all_hw_break(void)+{+	int i;++	for (i = 0; i < HW_BREAKPOINT; i++)+		memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));+}++int kgdb_set_hw_break(unsigned long addr)+{+	return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 1);+}++void kgdb_disable_hw_debug(struct pt_regs *regs)+{+	unsigned long hw_breakpoint_status;++	hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);+	if (hw_breakpoint_status & IA64_PSR_DB)+		ia64_setreg(_IA64_REG_PSR_L,+			    hw_breakpoint_status ^ IA64_PSR_DB);+}++volatile static struct smp_unw {+	struct unw_frame_info *unw;+	struct task_struct *task;+} smp_unw[NR_CPUS];++static int inline kgdb_get_blocked_state(struct task_struct *p,+					 struct unw_frame_info *unw)+{+	unsigned long ip;+	int count = 0;++	unw_init_from_blocked_task(unw, p);+	ip = 0UL;+	do {+		if (unw_unwind(unw) < 0)+			return -1;+		unw_get_ip(unw, &ip);+		if (!in_sched_functions(ip))+			break;+	} while (count++ < 16);++	if (!ip)+		return -1;+	else+		return 0;+}++static void inline kgdb_wait(struct pt_regs *regs)+{+	unsigned long hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);+	if (hw_breakpoint_status & IA64_PSR_DB)+		ia64_setreg(_IA64_REG_PSR_L,+			    hw_breakpoint_status ^ IA64_PSR_DB);+	kgdb_nmihook(smp_processor_id(), regs);+	if (hw_breakpoint_status & IA64_PSR_DB)+		ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status);++	return;+}++static void inline normalize(struct unw_frame_info *running,+			     struct pt_regs *regs)+{+	unsigned long sp;++	do {+		unw_get_sp(running, &sp);+		if ((sp + 0x10) >= (unsigned long)regs)+			break;+	} while (unw_unwind(running) >= 0);++	return;+}++static void kgdb_init_running(struct unw_frame_info *unw, void *data)+{+	struct pt_regs *regs;++	regs = data;+	normalize(unw, regs);+	smp_unw[smp_processor_id()].unw = unw;+	kgdb_wait(regs);+}++void kgdb_wait_ipi(struct pt_regs *regs)+{+	struct unw_frame_info unw;++	smp_unw[smp_processor_id()].task = current;++	if (user_mode(regs)) {+		smp_unw[smp_processor_id()].unw = (struct unw_frame_info *)1;+		kgdb_wait(regs);+	} else {+		if (current->state == TASK_RUNNING)+			unw_init_running(kgdb_init_running, regs);+		else {+			if (kgdb_get_blocked_state(current, &unw))+				smp_unw[smp_processor_id()].unw =+				    (struct unw_frame_info *)1;+			else+				smp_unw[smp_processor_id()].unw = &unw;+			kgdb_wait(regs);+		}+	}++	smp_unw[smp_processor_id()].unw = NULL;+	return;+}++void kgdb_roundup_cpus(unsigned long flags)+{+	if (num_online_cpus() > 1)+		smp_send_nmi_allbutself();+}++static volatile int kgdb_hwbreak_sstep[NR_CPUS];++static int kgdb_notify(struct notifier_block *self, unsigned long cmd,+	void *ptr)+{+	struct die_args *args = ptr;+	struct pt_regs *regs = args->regs;+	unsigned long err = args->err;++	switch (cmd) {+	default:+		return NOTIFY_DONE;+	case DIE_PAGE_FAULT_NO_CONTEXT:+		if (atomic_read(&debugger_active) && kgdb_may_fault) {+			kgdb_fault_longjmp(kgdb_fault_jmp_regs);+			return NOTIFY_STOP;+		}+		break;+	case DIE_BREAK:+		if (user_mode(regs) || err == 0x80001)+			return NOTIFY_DONE;+		break;+	case DIE_FAULT:+		if (user_mode(regs))+			return NOTIFY_DONE;+		else if (err == 36 && kgdb_hwbreak_sstep[smp_processor_id()]) {+			kgdb_hwbreak_sstep[smp_processor_id()] = 0;+			regs->cr_ipsr &= ~IA64_PSR_SS;+			return NOTIFY_STOP;+		}+	case DIE_MCA_MONARCH_PROCESS:+	case DIE_INIT_MONARCH_PROCESS:+		break;+	}++	kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);+	return NOTIFY_STOP;+}++static struct notifier_block kgdb_notifier = {+	.notifier_call = kgdb_notify,+};++int kgdb_arch_init(void)+{+	notifier_chain_register(&ia64die_chain, &kgdb_notifier);+	return 0;+}++static void do_kgdb_handle_exception(struct unw_frame_info *, void *data);++struct kgdb_state {+	int e_vector;+	int signo;+	unsigned long err_code;+	struct pt_regs *regs;+	struct unw_frame_info *unw;+	char *inbuf;+	char *outbuf;+	int unwind;+	int ret;+};++static void inline kgdb_pc(struct pt_regs *regs, unsigned long pc)+{+	regs->cr_iip = pc & ~0xf;+	ia64_psr(regs)->ri = pc & 0x3;+	return;+}++int kgdb_arch_handle_exception(int e_vector, int signo,+			       int err_code, char *remcom_in_buffer,+			       char *remcom_out_buffer,+			       struct pt_regs *linux_regs)+{+	struct kgdb_state info;++	info.e_vector = e_vector;+	info.signo = signo;+	info.err_code = err_code;+	info.unw = (void *)0;+	info.inbuf = remcom_in_buffer;+	info.outbuf = remcom_out_buffer;+	info.unwind = 0;+	info.ret = -1;++	if (remcom_in_buffer[0] == 'c' || remcom_in_buffer[0] == 's') {+		info.regs = linux_regs;+		do_kgdb_handle_exception(NULL, &info);+	} else if (kgdb_usethread == current) {+		info.regs = linux_regs;+		info.unwind = 1;+		unw_init_running(do_kgdb_handle_exception, &info);+	} else if (kgdb_usethread->state != TASK_RUNNING) {+		struct unw_frame_info unw_info;++		if (kgdb_get_blocked_state(kgdb_usethread, &unw_info)) {+			info.ret = 1;+			goto bad;+		}+		info.regs = NULL;+		do_kgdb_handle_exception(&unw_info, &info);+	} else {+		int i;++		for (i = 0; i < NR_CPUS; i++)+			if (smp_unw[i].task == kgdb_usethread && smp_unw[i].unw+			    && smp_unw[i].unw != (struct unw_frame_info *)1) {+				info.regs = NULL;+				do_kgdb_handle_exception(smp_unw[i].unw, &info);+				break;+			} else {+				info.ret = 1;+				goto bad;+			}+	}++      bad:+	if (info.ret != -1 && remcom_in_buffer[0] == 'p') {+		unsigned long bad = 0xbad4badbadbadbadUL;++		printk("kgdb_arch_handle_exception: p packet bad (%s)\n",+		       remcom_in_buffer);+		kgdb_mem2hex((char *)&bad, remcom_out_buffer, sizeof(bad));+		remcom_out_buffer[sizeof(bad) * 2] = 0;+		info.ret = -1;+	}+	return info.ret;+}++/*+ * This is done because I evidently made an incorrect 'p' encoding+ * when my patch for gdb was committed. It was later corrected. This+ * check supports both my wrong encoding of the register number and+ * the correct encoding. Eventually this should be eliminated and+ * kgdb_hex2long should be demarshalling the regnum.+ */+static inline int check_packet(unsigned int regnum, char *packet)+{+	static int check_done, swap;+	unsigned long reglong;++	if (likely(check_done)) {+		if (swap) {+			kgdb_hex2long(&packet, &reglong);+			regnum = (int) reglong;+		}++	} else {+		if (regnum > NUM_REGS) {+			kgdb_hex2long(&packet, &reglong);+			regnum = (int) reglong;+			swap = 1;+		}+		check_done = 1;+	}+	return regnum;+}++static void do_kgdb_handle_exception(struct unw_frame_info *unw_info,+	void *data)+{+	long addr;+	char *ptr;+	unsigned long newPC;+	int e_vector, signo;+	unsigned long err_code;+	struct pt_regs *linux_regs;+	struct kgdb_state *info;+	char *remcom_in_buffer, *remcom_out_buffer;++	info = data;+	info->unw = unw_info;+	e_vector = info->e_vector;+	signo = info->signo;+	err_code = info->err_code;+	remcom_in_buffer = info->inbuf;+	remcom_out_buffer = info->outbuf;+	linux_regs = info->regs;++	if (info->unwind)+		normalize(unw_info, linux_regs);++	switch (remcom_in_buffer[0]) {+	case 'p':+		{+			unsigned int regnum;++			kgdb_hex2mem(&remcom_in_buffer[1], (char *)&regnum,+				     sizeof(regnum));+			regnum = check_packet(regnum, &remcom_in_buffer[1]);+			if (regnum >= NUM_REGS) {+				remcom_out_buffer[0] = 'E';+				remcom_out_buffer[1] = 0;+			} else+				kgdb_get_reg(remcom_out_buffer, regnum,+					     unw_info, linux_regs);+			break;+		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -