diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2008-08-01 15:39:34 +0200 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2008-08-01 15:39:34 +0200 |
commit | a9b60bf4c29e07a5a2f26a6f74937972fee9b58b (patch) | |
tree | 6862f0442a9ab4e2da20fb93e3cf3be2c36b76b2 /kernel | |
parent | kgdb: remove the requirement for CONFIG_FRAME_POINTER (diff) | |
download | linux-a9b60bf4c29e07a5a2f26a6f74937972fee9b58b.tar.xz linux-a9b60bf4c29e07a5a2f26a6f74937972fee9b58b.zip |
kgdb: fix kgdb_validate_break_address to perform a mem write
A regression to the kgdb core was found in the case of using the
CONFIG_DEBUG_RODATA kernel option. When this option is on, a breakpoint
cannot be written into any readonly memory page. When an external
debugger requests a breakpoint to get set, the
kgdb_validate_break_address() was only checking to see if the address
to place the breakpoint was readable and lacked a write check.
This patch changes the validate routine to try reading (via the
breakpoint set request) and also to try immediately writing the break
point. If either fails, an error is correctly returned and the
debugger behaves correctly. Then an end user can make the
descision to use hardware breakpoints.
Also update the documentation to reflect that using
CONFIG_DEBUG_RODATA will inhibit the use of software breakpoints.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/kgdb.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 3ec23c3ec97f..c0d45b2c4d79 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -166,13 +166,6 @@ early_param("nokgdbroundup", opt_nokgdbroundup); * Weak aliases for breakpoint management, * can be overriden by architectures when needed: */ -int __weak kgdb_validate_break_address(unsigned long addr) -{ - char tmp_variable[BREAK_INSTR_SIZE]; - - return probe_kernel_read(tmp_variable, (char *)addr, BREAK_INSTR_SIZE); -} - int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) { int err; @@ -191,6 +184,25 @@ int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) (char *)bundle, BREAK_INSTR_SIZE); } +int __weak kgdb_validate_break_address(unsigned long addr) +{ + char tmp_variable[BREAK_INSTR_SIZE]; + int err; + /* Validate setting the breakpoint and then removing it. In 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); + if (err) + return err; + err = kgdb_arch_remove_breakpoint(addr, tmp_variable); + if (err) + printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " + "memory destroyed at: %lx", addr); + return err; +} + unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) { return instruction_pointer(regs); |