aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kgdb.c
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2009-12-11 09:43:20 -0500
committerJason Wessel <jason.wessel@windriver.com>2009-12-11 09:43:20 -0500
commit7f8b7ed6f825c729332b8190aca55c6bf95b158e (patch)
tree29496e5c24361945a38a240263c04d9ba5b3bd2b /kernel/kgdb.c
parentd625e9c0d706eb43afbf52634d5cecacae1d57cc (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.c23
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)
625static int kgdb_activate_sw_breakpoints(void) 625static 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
647static int kgdb_set_sw_break(unsigned long addr) 651static int kgdb_set_sw_break(unsigned long addr)
@@ -688,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr)
688static int kgdb_deactivate_sw_breakpoints(void) 692static 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
709static int kgdb_remove_sw_break(unsigned long addr) 716static int kgdb_remove_sw_break(unsigned long addr)