Commit 7f8b7ed6f825c729332b8190aca55c6bf95b158e

Authored by Jason Wessel
1 parent d625e9c0d7

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

... ... @@ -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)