Commit 7f8b7ed6f825c729332b8190aca55c6bf95b158e
1 parent
d625e9c0d7
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 15 additions and 8 deletions Side-by-side Diff
kernel/kgdb.c
... | ... | @@ -625,7 +625,8 @@ |
625 | 625 | static int kgdb_activate_sw_breakpoints(void) |
626 | 626 | { |
627 | 627 | unsigned long addr; |
628 | - int error = 0; | |
628 | + int error; | |
629 | + int ret = 0; | |
629 | 630 | int i; |
630 | 631 | |
631 | 632 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
632 | 633 | |
... | ... | @@ -635,13 +636,16 @@ |
635 | 636 | addr = kgdb_break[i].bpt_addr; |
636 | 637 | error = kgdb_arch_set_breakpoint(addr, |
637 | 638 | kgdb_break[i].saved_instr); |
638 | - if (error) | |
639 | - return error; | |
639 | + if (error) { | |
640 | + ret = error; | |
641 | + printk(KERN_INFO "KGDB: BP install failed: %lx", addr); | |
642 | + continue; | |
643 | + } | |
640 | 644 | |
641 | 645 | kgdb_flush_swbreak_addr(addr); |
642 | 646 | kgdb_break[i].state = BP_ACTIVE; |
643 | 647 | } |
644 | - return 0; | |
648 | + return ret; | |
645 | 649 | } |
646 | 650 | |
647 | 651 | static int kgdb_set_sw_break(unsigned long addr) |
... | ... | @@ -688,7 +692,8 @@ |
688 | 692 | static int kgdb_deactivate_sw_breakpoints(void) |
689 | 693 | { |
690 | 694 | unsigned long addr; |
691 | - int error = 0; | |
695 | + int error; | |
696 | + int ret = 0; | |
692 | 697 | int i; |
693 | 698 | |
694 | 699 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
695 | 700 | |
... | ... | @@ -697,13 +702,15 @@ |
697 | 702 | addr = kgdb_break[i].bpt_addr; |
698 | 703 | error = kgdb_arch_remove_breakpoint(addr, |
699 | 704 | kgdb_break[i].saved_instr); |
700 | - if (error) | |
701 | - return error; | |
705 | + if (error) { | |
706 | + printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); | |
707 | + ret = error; | |
708 | + } | |
702 | 709 | |
703 | 710 | kgdb_flush_swbreak_addr(addr); |
704 | 711 | kgdb_break[i].state = BP_SET; |
705 | 712 | } |
706 | - return 0; | |
713 | + return ret; | |
707 | 714 | } |
708 | 715 | |
709 | 716 | static int kgdb_remove_sw_break(unsigned long addr) |