* [PATCH 0/2] Fix KGDB to work with CONFIG_DEBUG_RODATA using kprobe API
@ 2012-03-21 17:55 Jason Wessel
2012-03-21 17:55 ` [PATCH 1/2] kgdb,debug_core: pass the breakpoint struct instead of address and memory Jason Wessel
2012-03-21 17:55 ` [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints Jason Wessel
0 siblings, 2 replies; 9+ messages in thread
From: Jason Wessel @ 2012-03-21 17:55 UTC (permalink / raw)
To: linux-kernel; +Cc: kgdb-bugreport, masami.hiramatsu.pt, tim.bird
The inability to use software breakpoints on a kernel built with
CONFIG_DEBUG_RODATA has been a problem for quite a few years. The
kprobes API has been working around this limitation for a long
time. This patch set changes the debug_core to use the kprobe
breakpoint API directly for a kernel compiled with CONFIG_DEBUG_RODATA.
Comments are welcome of course.
Thanks,
Jason.
---
Jason Wessel (2):
kgdb,debug_core: pass the breakpoint struct instead of address and memory
kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints
drivers/misc/kgdbts.c | 13 ------
include/linux/kgdb.h | 7 ++-
kernel/debug/debug_core.c | 93 ++++++++++++++++++++++++++++++--------------
3 files changed, 67 insertions(+), 46 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/2] kgdb,debug_core: pass the breakpoint struct instead of address and memory 2012-03-21 17:55 [PATCH 0/2] Fix KGDB to work with CONFIG_DEBUG_RODATA using kprobe API Jason Wessel @ 2012-03-21 17:55 ` Jason Wessel 2012-03-21 17:55 ` [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints Jason Wessel 1 sibling, 0 replies; 9+ messages in thread From: Jason Wessel @ 2012-03-21 17:55 UTC (permalink / raw) To: linux-kernel; +Cc: kgdb-bugreport, masami.hiramatsu.pt, tim.bird There is extra state information that needs to be exposed in the kgdb_bpt structure for tracking whether or not a breakpoint was installed via a kprobe or via a probe_kernel_write(). In order to access the structure it needs to be passed to the kgdb_arch_set_breakpoint() and kgdb_arch_remove_breakpoint(). A future commit adds the logic for the kprobe breakpoint type. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> --- include/linux/kgdb.h | 4 +- kernel/debug/debug_core.c | 53 ++++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index fa39183..e5d689c 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -207,8 +207,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc); /* Optional functions. */ extern int kgdb_validate_break_address(unsigned long addr); -extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); -extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); +extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt); +extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt); /** * kgdb_arch_late - Perform any architecture specific initalization. diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 3f88a45..a7e52ca 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -161,37 +161,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup); * Weak aliases for breakpoint management, * can be overriden by architectures when needed: */ -int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) +int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) { int err; - err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); + err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); if (err) return err; - - return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, - BREAK_INSTR_SIZE); + err = probe_kernel_write((char *)bpt->bpt_addr, + arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); + return err; } -int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) +int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) { - return probe_kernel_write((char *)addr, - (char *)bundle, BREAK_INSTR_SIZE); + return probe_kernel_write((char *)bpt->bpt_addr, + (char *)bpt->saved_instr, BREAK_INSTR_SIZE); } int __weak kgdb_validate_break_address(unsigned long addr) { - char tmp_variable[BREAK_INSTR_SIZE]; + struct kgdb_bkpt tmp; int err; - /* Validate setting the breakpoint and then removing it. In the + /* Validate setting the breakpoint and then removing it. If the * remove fails, the kernel needs to emit a bad message because we * are deep trouble not being able to put things back the way we * found them. */ - err = kgdb_arch_set_breakpoint(addr, tmp_variable); + tmp.bpt_addr = addr; + err = kgdb_arch_set_breakpoint(&tmp); if (err) return err; - err = kgdb_arch_remove_breakpoint(addr, tmp_variable); + err = kgdb_arch_remove_breakpoint(&tmp); if (err) printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " "memory destroyed at: %lx", addr); @@ -235,7 +237,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) */ int dbg_activate_sw_breakpoints(void) { - unsigned long addr; int error; int ret = 0; int i; @@ -244,16 +245,15 @@ int dbg_activate_sw_breakpoints(void) if (kgdb_break[i].state != BP_SET) continue; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_set_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_set_breakpoint(&kgdb_break[i]); if (error) { ret = error; - printk(KERN_INFO "KGDB: BP install failed: %lx", addr); + printk(KERN_INFO "KGDB: BP install failed: %lx", + kgdb_break[i].bpt_addr); continue; } - kgdb_flush_swbreak_addr(addr); + kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); kgdb_break[i].state = BP_ACTIVE; } return ret; @@ -302,7 +302,6 @@ int dbg_set_sw_break(unsigned long addr) int dbg_deactivate_sw_breakpoints(void) { - unsigned long addr; int error; int ret = 0; int i; @@ -310,15 +309,14 @@ int dbg_deactivate_sw_breakpoints(void) for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { if (kgdb_break[i].state != BP_ACTIVE) continue; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_remove_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); if (error) { - printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); + printk(KERN_INFO "KGDB: BP remove failed: %lx\n", + kgdb_break[i].bpt_addr); ret = error; } - kgdb_flush_swbreak_addr(addr); + kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); kgdb_break[i].state = BP_SET; } return ret; @@ -352,7 +350,6 @@ int kgdb_isremovedbreak(unsigned long addr) int dbg_remove_all_break(void) { - unsigned long addr; int error; int i; @@ -360,12 +357,10 @@ int dbg_remove_all_break(void) for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { if (kgdb_break[i].state != BP_ACTIVE) goto setundefined; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_remove_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); if (error) printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", - addr); + kgdb_break[i].bpt_addr); setundefined: kgdb_break[i].state = BP_UNDEFINED; } -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-21 17:55 [PATCH 0/2] Fix KGDB to work with CONFIG_DEBUG_RODATA using kprobe API Jason Wessel 2012-03-21 17:55 ` [PATCH 1/2] kgdb,debug_core: pass the breakpoint struct instead of address and memory Jason Wessel @ 2012-03-21 17:55 ` Jason Wessel 2012-03-22 2:53 ` Masami Hiramatsu 1 sibling, 1 reply; 9+ messages in thread From: Jason Wessel @ 2012-03-21 17:55 UTC (permalink / raw) To: linux-kernel; +Cc: kgdb-bugreport, masami.hiramatsu.pt, tim.bird There has long been a limitation using software breakpoints with a kernel compiled with CONFIG_DEBUG_RODATA. The kprobe breakpoint code has its own text_poke() function which accommodates writing a breakpoint into a read-only page. The debug_core can make use of the text_poke() capabilities by using the kprobes API, specifically arch_arm_kprobe() and arch_disarm_kprobe(). For now it is safe to use a single statically allocated kprobe structure to call the kprobes API because the debug_core breakpoint API is only used when the kernel is in the debug state. The debug_core will first attempt to use the traditional probe_kernel_write(), and next try using a kprobe breakpoint. The kgdb test suite was updated to run all the software breakpoint tests when using a kernel with built with CONFIG_DEBUG_RODATA. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> --- drivers/misc/kgdbts.c | 13 ------------- include/linux/kgdb.h | 3 ++- kernel/debug/debug_core.c | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3f7ad83..672b4a5 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -940,19 +940,6 @@ static void kgdbts_run_tests(void) run_nmi_sleep_test(nmi_sleep); } -#ifdef CONFIG_DEBUG_RODATA - /* Until there is an api to write to read-only text segments, use - * HW breakpoints for the remainder of any tests, else print a - * failure message if hw breakpoints do not work. - */ - if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { - eprintk("kgdbts: HW breakpoints do not work," - "skipping remaining tests\n"); - return; - } - force_hwbrks = 1; -#endif /* CONFIG_DEBUG_RODATA */ - /* If the do_fork test is run it will be the last test that is * executed because a kernel thread will be spawned at the very * end to unregister the debug hooks. diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index e5d689c..48f17d2 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -63,7 +63,8 @@ enum kgdb_bptype { BP_HARDWARE_BREAKPOINT, BP_WRITE_WATCHPOINT, BP_READ_WATCHPOINT, - BP_ACCESS_WATCHPOINT + BP_ACCESS_WATCHPOINT, + BP_KPROBE_BREAKPOINT, }; enum kgdb_bpstate { diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index a7e52ca..9051844 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -49,6 +49,7 @@ #include <linux/smp.h> #include <linux/mm.h> #include <linux/rcupdate.h> +#include <linux/kprobes.h> #include <asm/cacheflush.h> #include <asm/byteorder.h> @@ -108,6 +109,13 @@ module_param(kgdbreboot, int, 0644); static struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS] = { [0 ... KGDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED } }; +/* + * probe_write_tmp is used to r/w breakpoints with the kprobe + * interface, it is not protected for reentrancy + */ +#if defined(CONFIG_KPROBES) && defined(CONFIG_DEBUG_RODATA) +static struct kprobe probe_write_tmp; +#endif /* CONFIG_KPROBES && CONFIG_DEBUG_RODATA */ /* * The CPU# of the active CPU, or -1 if none: @@ -165,17 +173,48 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) { int err; + bpt->type = BP_BREAKPOINT; err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); if (err) return err; err = probe_kernel_write((char *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); +#if defined(CONFIG_KPROBES) && defined(CONFIG_DEBUG_RODATA) + if (!err) + return err; + probe_write_tmp.addr = (kprobe_opcode_t *)bpt->bpt_addr; + arch_arm_kprobe(&probe_write_tmp); + err = probe_kernel_read(&probe_write_tmp.opcode, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); + if (err) + return err; + if (memcmp(&probe_write_tmp.opcode, arch_kgdb_ops.gdb_bpt_instr, + BREAK_INSTR_SIZE)) + return -EINVAL; + bpt->type = BP_KPROBE_BREAKPOINT; +#endif /* CONFIG_KPROBES && CONFIG_DEBUG_RODATA */ return err; } int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) { +#if defined(CONFIG_KPROBES) && defined(CONFIG_DEBUG_RODATA) + int err; + + if (bpt->type != BP_KPROBE_BREAKPOINT) + goto knl_write; + probe_write_tmp.addr = (kprobe_opcode_t *)bpt->bpt_addr; + memcpy(&probe_write_tmp.opcode, bpt->saved_instr, BREAK_INSTR_SIZE); + arch_disarm_kprobe(&probe_write_tmp); + err = probe_kernel_read(&probe_write_tmp.opcode, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); + if (err || + memcmp(&probe_write_tmp.opcode, bpt->saved_instr, BREAK_INSTR_SIZE)) + goto knl_write; + return err; +knl_write: +#endif /* CONFIG_KPROBES && CONFIG_DEBUG_RODATA */ return probe_kernel_write((char *)bpt->bpt_addr, (char *)bpt->saved_instr, BREAK_INSTR_SIZE); } @@ -294,7 +333,6 @@ int dbg_set_sw_break(unsigned long addr) return -E2BIG; kgdb_break[breakno].state = BP_SET; - kgdb_break[breakno].type = BP_BREAKPOINT; kgdb_break[breakno].bpt_addr = addr; return 0; -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-21 17:55 ` [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints Jason Wessel @ 2012-03-22 2:53 ` Masami Hiramatsu 2012-03-22 11:57 ` Jason Wessel 0 siblings, 1 reply; 9+ messages in thread From: Masami Hiramatsu @ 2012-03-22 2:53 UTC (permalink / raw) To: Jason Wessel; +Cc: linux-kernel, kgdb-bugreport, tim.bird (2012/03/22 2:55), Jason Wessel wrote: > There has long been a limitation using software breakpoints with a > kernel compiled with CONFIG_DEBUG_RODATA. The kprobe breakpoint code > has its own text_poke() function which accommodates writing a > breakpoint into a read-only page. The debug_core can make use of the > text_poke() capabilities by using the kprobes API, specifically > arch_arm_kprobe() and arch_disarm_kprobe(). For now it is safe to use > a single statically allocated kprobe structure to call the kprobes API > because the debug_core breakpoint API is only used when the kernel is > in the debug state. You might misunderstand it. arch_*_kprobe() are not open APIs. Those are kprobes internal APIs (which means that those functions should be used only by kprobes). > The debug_core will first attempt to use the traditional > probe_kernel_write(), and next try using a kprobe breakpoint. The > kgdb test suite was updated to run all the software breakpoint tests > when using a kernel with built with CONFIG_DEBUG_RODATA. > > Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Nak. [...] > @@ -165,17 +173,48 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) > { > int err; > > + bpt->type = BP_BREAKPOINT; > err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, > BREAK_INSTR_SIZE); > if (err) > return err; > err = probe_kernel_write((char *)bpt->bpt_addr, > arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); > +#if defined(CONFIG_KPROBES) && defined(CONFIG_DEBUG_RODATA) > + if (!err) > + return err; > + probe_write_tmp.addr = (kprobe_opcode_t *)bpt->bpt_addr; > + arch_arm_kprobe(&probe_write_tmp); No, please don't use kprobes internal function this way, because you can't ensure that the arch_arm_kprobe() has no side-effect. Why don't you use text_poke()? I see that the text_poke() is only for x86, but you already have arch/x86/kernel/kgdb.c for making your own wrapper function. > + err = probe_kernel_read(&probe_write_tmp.opcode, (char *)bpt->bpt_addr, > + BREAK_INSTR_SIZE); > + if (err) > + return err; > + if (memcmp(&probe_write_tmp.opcode, arch_kgdb_ops.gdb_bpt_instr, > + BREAK_INSTR_SIZE)) > + return -EINVAL; > + bpt->type = BP_KPROBE_BREAKPOINT; > +#endif /* CONFIG_KPROBES && CONFIG_DEBUG_RODATA */ > return err; > } > > int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) > { > +#if defined(CONFIG_KPROBES) && defined(CONFIG_DEBUG_RODATA) > + int err; > + > + if (bpt->type != BP_KPROBE_BREAKPOINT) > + goto knl_write; > + probe_write_tmp.addr = (kprobe_opcode_t *)bpt->bpt_addr; > + memcpy(&probe_write_tmp.opcode, bpt->saved_instr, BREAK_INSTR_SIZE); > + arch_disarm_kprobe(&probe_write_tmp); Ditto. > + err = probe_kernel_read(&probe_write_tmp.opcode, (char *)bpt->bpt_addr, > + BREAK_INSTR_SIZE); > + if (err || > + memcmp(&probe_write_tmp.opcode, bpt->saved_instr, BREAK_INSTR_SIZE)) > + goto knl_write; > + return err; > +knl_write: > +#endif /* CONFIG_KPROBES && CONFIG_DEBUG_RODATA */ > return probe_kernel_write((char *)bpt->bpt_addr, > (char *)bpt->saved_instr, BREAK_INSTR_SIZE); > } > @@ -294,7 +333,6 @@ int dbg_set_sw_break(unsigned long addr) > return -E2BIG; > > kgdb_break[breakno].state = BP_SET; > - kgdb_break[breakno].type = BP_BREAKPOINT; > kgdb_break[breakno].bpt_addr = addr; > > return 0; Thank you, -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt@hitachi.com ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-22 2:53 ` Masami Hiramatsu @ 2012-03-22 11:57 ` Jason Wessel 2012-03-23 14:08 ` Masami Hiramatsu 0 siblings, 1 reply; 9+ messages in thread From: Jason Wessel @ 2012-03-22 11:57 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: linux-kernel, kgdb-bugreport, tim.bird On 03/21/2012 09:53 PM, Masami Hiramatsu wrote: > (2012/03/22 2:55), Jason Wessel wrote: >> There has long been a limitation using software breakpoints with a >> kernel compiled with CONFIG_DEBUG_RODATA. The kprobe breakpoint code >> has its own text_poke() function which accommodates writing a >> breakpoint into a read-only page. The debug_core can make use of the >> text_poke() capabilities by using the kprobes API, specifically >> arch_arm_kprobe() and arch_disarm_kprobe(). For now it is safe to use >> a single statically allocated kprobe structure to call the kprobes API >> because the debug_core breakpoint API is only used when the kernel is >> in the debug state. > > You might misunderstand it. arch_*_kprobe() are not open APIs. > Those are kprobes internal APIs (which means that those functions > should be used only by kprobes). > I was looking for an interface that solved the problem, without having to use text_poke directly which is arch specific. Eventually I would like to use the kprobes high level API, but it cannot not be used without taking a mutex presently. This is a separate problem to deal with at a later time, because the generic use of kprobes would be aimed at having robust single stepping. > >> The debug_core will first attempt to use the traditional >> probe_kernel_write(), and next try using a kprobe breakpoint. The >> kgdb test suite was updated to run all the software breakpoint tests >> when using a kernel with built with CONFIG_DEBUG_RODATA. >> >> Signed-off-by: Jason Wessel <jason.wessel@windriver.com> > > Nak. > > No, please don't use kprobes internal function this way, because > you can't ensure that the arch_arm_kprobe() has no side-effect. > > Why don't you use text_poke()? I see that the text_poke() > is only for x86, but you already have arch/x86/kernel/kgdb.c for > making your own wrapper function. I will use the arch specific provision to override the kgdb_arch_set_breakpoint() and use the text_poke() directly. Eventually I would like to use the same software breakpoint reservation system as kprobes, and that would happen if kgdb ever starts using kprobes for single stepping. A few years back we solved the problem for hardware breakpoints reservations where the kernel debugger, perf, ptrace, and kprobes all play nice. Thanks, Jason. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-22 11:57 ` Jason Wessel @ 2012-03-23 14:08 ` Masami Hiramatsu 2012-03-23 14:38 ` Jason Wessel 0 siblings, 1 reply; 9+ messages in thread From: Masami Hiramatsu @ 2012-03-23 14:08 UTC (permalink / raw) To: Jason Wessel; +Cc: linux-kernel, kgdb-bugreport, tim.bird (2012/03/22 20:57), Jason Wessel wrote: > On 03/21/2012 09:53 PM, Masami Hiramatsu wrote: >> (2012/03/22 2:55), Jason Wessel wrote: >>> There has long been a limitation using software breakpoints with a >>> kernel compiled with CONFIG_DEBUG_RODATA. The kprobe breakpoint code >>> has its own text_poke() function which accommodates writing a >>> breakpoint into a read-only page. The debug_core can make use of the >>> text_poke() capabilities by using the kprobes API, specifically >>> arch_arm_kprobe() and arch_disarm_kprobe(). For now it is safe to use >>> a single statically allocated kprobe structure to call the kprobes API >>> because the debug_core breakpoint API is only used when the kernel is >>> in the debug state. >> >> You might misunderstand it. arch_*_kprobe() are not open APIs. >> Those are kprobes internal APIs (which means that those functions >> should be used only by kprobes). >> > > > I was looking for an interface that solved the problem, without having > to use text_poke directly which is arch specific. Eventually I would > like to use the kprobes high level API, but it cannot not be used > without taking a mutex presently. This is a separate problem to deal > with at a later time, because the generic use of kprobes would be > aimed at having robust single stepping. I see. >>> The debug_core will first attempt to use the traditional >>> probe_kernel_write(), and next try using a kprobe breakpoint. The >>> kgdb test suite was updated to run all the software breakpoint tests >>> when using a kernel with built with CONFIG_DEBUG_RODATA. >>> >>> Signed-off-by: Jason Wessel <jason.wessel@windriver.com> >> >> Nak. >> >> No, please don't use kprobes internal function this way, because >> you can't ensure that the arch_arm_kprobe() has no side-effect. >> >> Why don't you use text_poke()? I see that the text_poke() >> is only for x86, but you already have arch/x86/kernel/kgdb.c for >> making your own wrapper function. > > I will use the arch specific provision to override the > kgdb_arch_set_breakpoint() and use the text_poke() directly. Thanks! that's what I meant. You can use __weak attribute. > Eventually I would like to use the same software breakpoint > reservation system as kprobes, and that would happen if kgdb ever > starts using kprobes for single stepping. Yeah, as far as I can see, current kprobes design assumes that there is no other part uses sw breakpoint in kernel. But there is kgdb now. I think kprobes can share the sw breakpoint instrumentation and single stepping with kgdb. Thank you, -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt@hitachi.com ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-23 14:08 ` Masami Hiramatsu @ 2012-03-23 14:38 ` Jason Wessel 2012-03-26 9:46 ` Masami Hiramatsu 0 siblings, 1 reply; 9+ messages in thread From: Jason Wessel @ 2012-03-23 14:38 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: linux-kernel, kgdb-bugreport, tim.bird On 03/23/2012 09:08 AM, Masami Hiramatsu wrote: > (2012/03/22 20:57), Jason Wessel wrote: >> I will use the arch specific provision to override the >> kgdb_arch_set_breakpoint() and use the text_poke() directly. > > Thanks! that's what I meant. You can use __weak attribute. > I created and tested a patch yesterday which is show below. I will post a new series at some point soon which addresses this problem as well as a number of problems found with the kgdb test suite. Cheers, Jason. Subject: [PATCH] x86,kgdb: End DEBUG_RODATA limitation using text_poke() There has long been a limitation using software breakpoints with a kernel compiled with CONFIG_DEBUG_RODATA. The kprobes code has long used the text_poke() function which accommodates writing a breakpoint into a read-only page. The x86 arch can override the default breakpoint install remove routines and make use of the text_poke() code that comes from the x86 alternatives. The x86 arch will first attempt to use the traditional probe_kernel_write(), and next try using a the text_poke() function. The break point install method is tracked such that the correct break point removal routine will get called later on. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> --- arch/x86/kernel/kgdb.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/kgdb.h | 3 ++- 2 files changed, 48 insertions(+), 1 deletion(-) --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -63,7 +63,8 @@ enum kgdb_bptype { BP_HARDWARE_BREAKPOINT, BP_WRITE_WATCHPOINT, BP_READ_WATCHPOINT, - BP_ACCESS_WATCHPOINT + BP_ACCESS_WATCHPOINT, + BP_POKE_BREAKPOINT, }; enum kgdb_bpstate { --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -742,6 +742,52 @@ void kgdb_arch_set_pc(struct pt_regs *re regs->ip = ip; } +int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) +{ + int err; + char opc[BREAK_INSTR_SIZE]; + + bpt->type = BP_BREAKPOINT; + err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); + if (err) + return err; + err = probe_kernel_write((char *)bpt->bpt_addr, + arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); +#ifdef CONFIG_DEBUG_RODATA + if (!err) + return err; + text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, + BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + if (err) + return err; + if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE)) + return -EINVAL; + bpt->type = BP_POKE_BREAKPOINT; +#endif /* CONFIG_DEBUG_RODATA */ + return err; +} + +int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) +{ +#ifdef CONFIG_DEBUG_RODATA + int err; + char opc[BREAK_INSTR_SIZE]; + + if (bpt->type != BP_POKE_BREAKPOINT) + goto knl_write; + text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) + goto knl_write; + return err; +knl_write: +#endif /* CONFIG_DEBUG_RODATA */ + return probe_kernel_write((char *)bpt->bpt_addr, + (char *)bpt->saved_instr, BREAK_INSTR_SIZE); +} + struct kgdb_arch arch_kgdb_ops = { /* Breakpoint instruction: */ .gdb_bpt_instr = { 0xcc }, ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-23 14:38 ` Jason Wessel @ 2012-03-26 9:46 ` Masami Hiramatsu 2012-03-26 16:39 ` Jason Wessel 0 siblings, 1 reply; 9+ messages in thread From: Masami Hiramatsu @ 2012-03-26 9:46 UTC (permalink / raw) To: Jason Wessel; +Cc: linux-kernel, kgdb-bugreport, tim.bird (2012/03/23 23:38), Jason Wessel wrote: > On 03/23/2012 09:08 AM, Masami Hiramatsu wrote: >> (2012/03/22 20:57), Jason Wessel wrote: >>> I will use the arch specific provision to override the >>> kgdb_arch_set_breakpoint() and use the text_poke() directly. >> >> Thanks! that's what I meant. You can use __weak attribute. >> > > I created and tested a patch yesterday which is show below. I will > post a new series at some point soon which addresses this problem as > well as a number of problems found with the kgdb test suite. Yeah, that's better. BTW, I'm not sure the policy of kgdb about mutex, but it seems that you need to hold a text_mutex when you call the text_poke() since it uses a fixmap page-area for mapping read-only text page to writable page. So, without locking (at least ensuring no one using) text_mutex, it seems not be safe. (some other code may be trying to change the code by using same fixmap pages) Thank you, -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt@hitachi.com ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints 2012-03-26 9:46 ` Masami Hiramatsu @ 2012-03-26 16:39 ` Jason Wessel 0 siblings, 0 replies; 9+ messages in thread From: Jason Wessel @ 2012-03-26 16:39 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: linux-kernel, kgdb-bugreport, tim.bird On 03/26/2012 04:46 AM, Masami Hiramatsu wrote: > (2012/03/23 23:38), Jason Wessel wrote: >> On 03/23/2012 09:08 AM, Masami Hiramatsu wrote: >>> (2012/03/22 20:57), Jason Wessel wrote: >>>> I will use the arch specific provision to override the >>>> kgdb_arch_set_breakpoint() and use the text_poke() directly. >>> >>> Thanks! that's what I meant. You can use __weak attribute. >>> >> >> I created and tested a patch yesterday which is show below. I will >> post a new series at some point soon which addresses this problem as >> well as a number of problems found with the kgdb test suite. > > Yeah, that's better. > > BTW, I'm not sure the policy of kgdb about mutex, but it seems > that you need to hold a text_mutex when you call the text_poke() > since it uses a fixmap page-area for mapping read-only text page > to writable page. So, without locking (at least ensuring no one > using) text_mutex, it seems not be safe. (some other code may be > trying to change the code by using same fixmap pages) Thank you very much for the advice. I had run the kgdb mutex validation which checks for mutex's taken any time I change the kgdb code and it passed. However, this did not check for incorrect usage where the debug core should really be taking a mutex to prevent corruption. The comments in the text_poke code clearly indicate a caller must hold the text_mutex(). I started looking through all the code that uses text_mutex and what it actually protects. It looked like it is probably possible to make things re-entrant in order to deal with the case where debugger changes a location with a fixmap when kernel execution is stopped. I am not convinced this is a good idea, given complexity of the code, vs the small number of users and the likely hood of interference being on the low side. For now, I am not going to pursue making any kind of changes with fix map or the text_mutex protected regions. Today there are only 3 users of the text_mutex, SMP alternatives, jump labels updates, and kprobes, so the risk for collision is fairly low. At the point in time that the collisions become a real problem, such as kgdb starting to use kprobes directly, changing some code for special re-entrance considerations after using the kernel debugger might get considered again. Until then, I will use the simple approach of checking the mutex and use text_poke() if it is not locked when the normal kernel execution is stopped on all cores. The delta to the previous patch is shown below. Thanks, Jason. diff -u b/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c --- b/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -757,6 +757,12 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) #ifdef CONFIG_DEBUG_RODATA if (!err) return err; + /* + * It is safe to call text_poke() because normal kernel execution + * is stopped on all cores, so long as the text_mutex is not locked. + */ + if (mutex_is_locked(&text_mutex) + return -EBUSY; text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); @@ -777,6 +783,12 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) if (bpt->type != BP_POKE_BREAKPOINT) goto knl_write; + /* + * It is safe to call text_poke() because normal kernel execution + * is stopped on all cores, so long as the text_mutex is not locked. + */ + if (mutex_is_locked(&text_mutex) + goto knl_write; text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE); err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-03-26 16:40 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-03-21 17:55 [PATCH 0/2] Fix KGDB to work with CONFIG_DEBUG_RODATA using kprobe API Jason Wessel 2012-03-21 17:55 ` [PATCH 1/2] kgdb,debug_core: pass the breakpoint struct instead of address and memory Jason Wessel 2012-03-21 17:55 ` [PATCH 2/2] kgdb,debug_core,kgdbts: End DEBUG_RODATA limitation using kprobe breakpoints Jason Wessel 2012-03-22 2:53 ` Masami Hiramatsu 2012-03-22 11:57 ` Jason Wessel 2012-03-23 14:08 ` Masami Hiramatsu 2012-03-23 14:38 ` Jason Wessel 2012-03-26 9:46 ` Masami Hiramatsu 2012-03-26 16:39 ` Jason Wessel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox