diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2009-12-11 09:43:20 -0500 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2009-12-11 09:43:20 -0500 |
commit | 7f8b7ed6f825c729332b8190aca55c6bf95b158e (patch) | |
tree | 29496e5c24361945a38a240263c04d9ba5b3bd2b /kernel/kgdb.c | |
parent | d625e9c0d706eb43afbf52634d5cecacae1d57cc (diff) |
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>
Diffstat (limited to 'kernel/kgdb.c')
-rw-r--r-- | kernel/kgdb.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 8584eac55e30..2eb517e23514 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
@@ -625,7 +625,8 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) | |||
625 | static int kgdb_activate_sw_breakpoints(void) | 625 | static int kgdb_activate_sw_breakpoints(void) |
626 | { | 626 | { |
627 | unsigned long addr; | 627 | unsigned long addr; |
628 | int error = 0; | 628 | int error; |
629 | int ret = 0; | ||
629 | int i; | 630 | int i; |
630 | 631 | ||
631 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 632 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
@@ -635,13 +636,16 @@ static int kgdb_activate_sw_breakpoints(void) | |||
635 | addr = kgdb_break[i].bpt_addr; | 636 | addr = kgdb_break[i].bpt_addr; |
636 | error = kgdb_arch_set_breakpoint(addr, | 637 | error = kgdb_arch_set_breakpoint(addr, |
637 | kgdb_break[i].saved_instr); | 638 | kgdb_break[i].saved_instr); |
638 | if (error) | 639 | if (error) { |
639 | return error; | 640 | ret = error; |
641 | printk(KERN_INFO "KGDB: BP install failed: %lx", addr); | ||
642 | continue; | ||
643 | } | ||
640 | 644 | ||
641 | kgdb_flush_swbreak_addr(addr); | 645 | kgdb_flush_swbreak_addr(addr); |
642 | kgdb_break[i].state = BP_ACTIVE; | 646 | kgdb_break[i].state = BP_ACTIVE; |
643 | } | 647 | } |
644 | return 0; | 648 | return ret; |
645 | } | 649 | } |
646 | 650 | ||
647 | static int kgdb_set_sw_break(unsigned long addr) | 651 | static int kgdb_set_sw_break(unsigned long addr) |
@@ -688,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr) | |||
688 | static int kgdb_deactivate_sw_breakpoints(void) | 692 | static int kgdb_deactivate_sw_breakpoints(void) |
689 | { | 693 | { |
690 | unsigned long addr; | 694 | unsigned long addr; |
691 | int error = 0; | 695 | int error; |
696 | int ret = 0; | ||
692 | int i; | 697 | int i; |
693 | 698 | ||
694 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 699 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
@@ -697,13 +702,15 @@ static int kgdb_deactivate_sw_breakpoints(void) | |||
697 | addr = kgdb_break[i].bpt_addr; | 702 | addr = kgdb_break[i].bpt_addr; |
698 | error = kgdb_arch_remove_breakpoint(addr, | 703 | error = kgdb_arch_remove_breakpoint(addr, |
699 | kgdb_break[i].saved_instr); | 704 | kgdb_break[i].saved_instr); |
700 | if (error) | 705 | if (error) { |
701 | return error; | 706 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); |
707 | ret = error; | ||
708 | } | ||
702 | 709 | ||
703 | kgdb_flush_swbreak_addr(addr); | 710 | kgdb_flush_swbreak_addr(addr); |
704 | kgdb_break[i].state = BP_SET; | 711 | kgdb_break[i].state = BP_SET; |
705 | } | 712 | } |
706 | return 0; | 713 | return ret; |
707 | } | 714 | } |
708 | 715 | ||
709 | static int kgdb_remove_sw_break(unsigned long addr) | 716 | static int kgdb_remove_sw_break(unsigned long addr) |