Commit 7f8b7ed6 authored by Jason Wessel's avatar Jason Wessel

kgdb: Always process the whole breakpoint list on activate or deactivate

This patch fixes 2 edge cases in using kgdb in conjunction with gdb.

1) kgdb_deactivate_sw_breakpoints() should process the entire array of
   breakpoints.  The failure to do so results in breakpoints that you
   cannot remove, because a break point can only be removed if its
   state flag is set to BP_SET.

   The easy way to duplicate this problem is to plant a break point in
   a kernel module and then unload the kernel module.

2) kgdb_activate_sw_breakpoints() should process the entire array of
   breakpoints.  The failure to do so results in missed breakpoints
   when a breakpoint cannot be activated.
Signed-off-by: default avatarJason Wessel <jason.wessel@windriver.com>
parent d625e9c0
...@@ -625,7 +625,8 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) ...@@ -625,7 +625,8 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
static int kgdb_activate_sw_breakpoints(void) static int kgdb_activate_sw_breakpoints(void)
{ {
unsigned long addr; unsigned long addr;
int error = 0; int error;
int ret = 0;
int i; int i;
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
...@@ -635,13 +636,16 @@ static int kgdb_activate_sw_breakpoints(void) ...@@ -635,13 +636,16 @@ static int kgdb_activate_sw_breakpoints(void)
addr = kgdb_break[i].bpt_addr; addr = kgdb_break[i].bpt_addr;
error = kgdb_arch_set_breakpoint(addr, error = kgdb_arch_set_breakpoint(addr,
kgdb_break[i].saved_instr); kgdb_break[i].saved_instr);
if (error) if (error) {
return error; ret = error;
printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
continue;
}
kgdb_flush_swbreak_addr(addr); kgdb_flush_swbreak_addr(addr);
kgdb_break[i].state = BP_ACTIVE; kgdb_break[i].state = BP_ACTIVE;
} }
return 0; return ret;
} }
static int kgdb_set_sw_break(unsigned long addr) static int kgdb_set_sw_break(unsigned long addr)
...@@ -688,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr) ...@@ -688,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr)
static int kgdb_deactivate_sw_breakpoints(void) static int kgdb_deactivate_sw_breakpoints(void)
{ {
unsigned long addr; unsigned long addr;
int error = 0; int error;
int ret = 0;
int i; int i;
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
...@@ -697,13 +702,15 @@ static int kgdb_deactivate_sw_breakpoints(void) ...@@ -697,13 +702,15 @@ static int kgdb_deactivate_sw_breakpoints(void)
addr = kgdb_break[i].bpt_addr; addr = kgdb_break[i].bpt_addr;
error = kgdb_arch_remove_breakpoint(addr, error = kgdb_arch_remove_breakpoint(addr,
kgdb_break[i].saved_instr); kgdb_break[i].saved_instr);
if (error) if (error) {
return error; printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
ret = error;
}
kgdb_flush_swbreak_addr(addr); kgdb_flush_swbreak_addr(addr);
kgdb_break[i].state = BP_SET; kgdb_break[i].state = BP_SET;
} }
return 0; return ret;
} }
static int kgdb_remove_sw_break(unsigned long addr) static int kgdb_remove_sw_break(unsigned long addr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment