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: Jason Wessel <jason.wessel@windriver.com>
This commit is contained in:
Родитель
d625e9c0d7
Коммит
7f8b7ed6f8
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче