* [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