aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2008-08-01 09:39:34 -0400
committerJason Wessel <jason.wessel@windriver.com>2008-08-01 09:39:34 -0400
commita9b60bf4c29e07a5a2f26a6f74937972fee9b58b (patch)
tree6862f0442a9ab4e2da20fb93e3cf3be2c36b76b2 /kernel
parent5f5ddfb3605d2a4f555a7ff034859e623eafcd27 (diff)
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.c26
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);
166 * Weak aliases for breakpoint management, 166 * Weak aliases for breakpoint management,
167 * can be overriden by architectures when needed: 167 * can be overriden by architectures when needed:
168 */ 168 */
169int __weak kgdb_validate_break_address(unsigned long addr)
170{
171 char tmp_variable[BREAK_INSTR_SIZE];
172
173 return probe_kernel_read(tmp_variable, (char *)addr, BREAK_INSTR_SIZE);
174}
175
176int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) 169int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
177{ 170{
178 int err; 171 int err;
@@ -191,6 +184,25 @@ int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
191 (char *)bundle, BREAK_INSTR_SIZE); 184 (char *)bundle, BREAK_INSTR_SIZE);
192} 185}
193 186
187int __weak kgdb_validate_break_address(unsigned long addr)
188{
189 char tmp_variable[BREAK_INSTR_SIZE];
190 int err;
191 /* Validate setting the breakpoint and then removing it. In the
192 * remove fails, the kernel needs to emit a bad message because we
193 * are deep trouble not being able to put things back the way we
194 * found them.
195 */
196 err = kgdb_arch_set_breakpoint(addr, tmp_variable);
197 if (err)
198 return err;
199 err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
200 if (err)
201 printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
202 "memory destroyed at: %lx", addr);
203 return err;
204}
205
194unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) 206unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs)
195{ 207{
196 return instruction_pointer(regs); 208 return instruction_pointer(regs);