Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Hui Zhu <hui_zhu@mentor.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH] breakpoint remove fail handle bug fix
Date: Wed, 11 Apr 2012 09:32:00 -0000	[thread overview]
Message-ID: <4F8549BC.3050003@mentor.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3488 bytes --]

Hi,

I sent this patch with the autoload-breakpoints patches because I found 
this issue when I test the autoload-breakpoints.  But I think sent it 
together with a feature patch list is not a good idea.  So I move it out 
for review.

This is bug was found when I when I test autoload-breakpint code.  And I 
found that it affect target-async too.
It can be reproduce:
(gdb) set target-async on
(gdb) start
Temporary breakpoint 1 at 0x4004c8: file 1.c, line 4.
Starting program: /home/teawater/tmp/a.out

Temporary breakpoint 1, main () at 1.c:4
4		sleep (20);
(gdb) disassemble
Dump of assembler code for function main:
    0x00000000004004c4 <+0>:	push   %rbp
    0x00000000004004c5 <+1>:	mov    %rsp,%rbp
=> 0x00000000004004c8 <+4>:	mov    $0x14,%edi
    0x00000000004004cd <+9>:	mov    $0x0,%eax
    0x00000000004004d2 <+14>:	callq  0x4003d0 <sleep@plt>
    0x00000000004004d7 <+19>:	mov    $0x0,%eax
    0x00000000004004dc <+24>:	pop    %rbp
    0x00000000004004dd <+25>:	retq
End of assembler dump.
(gdb) list
1	int
2	main()
3	{
4		sleep (20);
5	
6		return 0;
7	}
8	
(gdb) b 6
Breakpoint 2 at 0x4004d7: file 1.c, line 6.
(gdb) c&
Continuing.
(gdb) d
Delete all breakpoints? (y or n) y
warning: Error removing breakpoint 2
(gdb)
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004004d8 in main () at 1.c:6
6		return 0;
c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x00000000004004d8 in main () at 1.c:6
6		return 0;
(gdb) info reg pc
pc: 0x4004d8
(gdb) disassemble main
Dump of assembler code for function main:
    0x00000000004004c4 <+0>:	push   %rbp
    0x00000000004004c5 <+1>:	mov    %rsp,%rbp
    0x00000000004004c8 <+4>:	mov    $0x14,%edi
    0x00000000004004cd <+9>:	mov    $0x0,%eax
    0x00000000004004d2 <+14>:	callq  0x4003d0 <sleep@plt>
    0x00000000004004d7 <+19>:	int3
=> 0x00000000004004d8 <+20>:	add    %al,(%rax)
    0x00000000004004da <+22>:	add    %al,(%rax)
    0x00000000004004dc <+24>:	pop    %rbp
    0x00000000004004dd <+25>:	retq
End of assembler dump.

This because is when GDB got fail when it remove the breakpoint, it give 
up the control of this breakpoint.
There are 2 issues about it:
1. When the GDB stop, this breakpoint is not be removed.
2. If inferior is stoped by this breakpoint, adjust_pc_after_break 
didn't know this stop is beauce the breakpoint, so the pc address will 
not be adjust to the right value.

I add a list called bp_location_remove_fail_chain, when GDB got fail 
with remove a breakpoint, add it to this list.  When 
adjust_pc_after_break check if this address is the breakpint, check this 
list too.  And when gdb remve all breakpoints, try remove breakpint in 
this list.

Thanks,
Hui

2012-04-11  Hui Zhu  <hui_zhu@mentor.com>

	* breakpoint.c (ALL_BP_LOCATION_REMOV_FAIL): New macro.
	(ALL_BP_LOCATION_REMOV_FAIL_SAFE): New macro.
	(bp_location_remove_fail_chain_inserted_here_p): New function.
	(bp_location_remove_fail_chain_insert): New function.
	(bp_location_remove_fail_chain_remove): New function.
	(remove_breakpoints): Call remove_breakpoint with the bp_locations
	inside the ALL_BP_LOCATION_REMOV_FAIL_SAFE.
	(software_breakpoint_inserted_here_p): Call
	bp_location_remove_fail_chain_inserted_here_p.
	(update_global_location_list): Call
	bp_location_remove_fail_chain_insert.
	* breakpoint.h (bp_location_remove_fail_chain_remove): New extern.
	* target.c (target_kill): Call bp_location_remove_fail_chain_remove.
	(target_detach): Ditto.
	(target_disconnect): Ditto.

[-- Attachment #2: break-remove-error-change.txt --]
[-- Type: text/plain, Size: 5910 bytes --]

---
 breakpoint.c |  132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 breakpoint.h |    2 
 target.c     |   15 +++++-
 3 files changed, 139 insertions(+), 10 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -569,6 +569,100 @@ static struct cmd_list_element *breakpoi
 static struct cmd_list_element *breakpoint_show_cmdlist;
 struct cmd_list_element *save_cmdlist;
 
+/* Chains of bp_location that have remove issue. */
+static struct bp_location *bp_location_remove_fail_chain = NULL;
+
+#define ALL_BP_LOCATION_REMOV_FAIL(BP)			\
+	for (BP = bp_location_remove_fail_chain;	\
+	     BP;					\
+	     BP = BP->next)
+
+#define ALL_BP_LOCATION_REMOV_FAIL_SAFE(BP,TMP)		\
+	for (BP = bp_location_remove_fail_chain;	\
+	     BP ? (TMP=BP->next, 1): 0;			\
+	     BP = TMP)
+
+static int
+bp_location_remove_fail_chain_inserted_here_p (struct address_space *aspace,
+					       CORE_ADDR pc)
+{
+  struct bp_location *bl;
+
+  ALL_BP_LOCATION_REMOV_FAIL (bl)
+    {
+      if (bl->loc_type != bp_loc_software_breakpoint)
+	continue;
+
+      if (bl->inserted
+	  && breakpoint_address_match (bl->pspace->aspace, bl->address,
+				       aspace, pc))
+	{
+	  if (overlay_debugging
+	      && section_is_overlay (bl->section)
+	      && !section_is_mapped (bl->section))
+	    continue;		/* unmapped overlay -- can't be a match */
+	  else
+	    return 1;
+	}
+    }
+
+  return 0;
+}
+
+static void
+bp_location_remove_fail_chain_insert (struct bp_location *bl)
+{
+  struct bp_location *bltmp;
+  struct breakpoint *b;
+
+  if (!bl->owner)
+    return;
+
+  ALL_BP_LOCATION_REMOV_FAIL (bltmp)
+    {
+      if (bltmp == bl)
+	return;
+    }
+
+  b = (struct breakpoint *) xzalloc (sizeof (struct breakpoint));
+  *b = *bl->owner;
+  bl->owner = b;
+
+  incref_bp_location (bl);
+  bl->next = bp_location_remove_fail_chain;
+  bp_location_remove_fail_chain = bl;
+}
+
+void
+bp_location_remove_fail_chain_remove (struct bp_location *bl)
+{
+  struct bp_location *bltmp, *bltmp2, *blprev = NULL;
+
+  ALL_BP_LOCATION_REMOV_FAIL_SAFE (bltmp, bltmp2)
+    {
+      if (!bl || bltmp == bl)
+	{
+	  if (bl)
+	    {
+	      if (blprev)
+		blprev->next = bl->next;
+	      else
+		bp_location_remove_fail_chain = bl->next;
+	    }
+	  xfree (bltmp->owner);
+	  bltmp->owner = NULL;
+	  decref_bp_location (&bltmp);
+	  if (bl)
+	    break;
+	}
+      else
+	blprev = bltmp;
+    }
+
+  if (!bl)
+    bp_location_remove_fail_chain = NULL;
+}
+
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
 breakpoint_enabled (struct breakpoint *b)
@@ -2594,7 +2688,7 @@ You may have requested too many hardware
 int
 remove_breakpoints (void)
 {
-  struct bp_location *bl, **blp_tmp;
+  struct bp_location *bl, *bltmp, **blp_tmp;
   int val = 0;
 
   ALL_BP_LOCATIONS (bl, blp_tmp)
@@ -2602,6 +2696,20 @@ remove_breakpoints (void)
     if (bl->inserted && !is_tracepoint (bl->owner))
       val |= remove_breakpoint (bl, mark_uninserted);
   }
+
+  ALL_BP_LOCATION_REMOV_FAIL_SAFE (bl, bltmp)
+    {
+      volatile struct gdb_exception e;
+      int ret;
+
+      TRY_CATCH (e, RETURN_MASK_ERROR)
+	{
+	  ret = remove_breakpoint (bl, mark_uninserted);
+	}
+      if (!ret && e.reason >= 0)
+	bp_location_remove_fail_chain_remove (bl);
+    }
+
   return val;
 }
 
@@ -3536,6 +3644,9 @@ software_breakpoint_inserted_here_p (str
   if (single_step_breakpoint_inserted_here_p (aspace, pc))
     return 1;
 
+  if (bp_location_remove_fail_chain_inserted_here_p (aspace, pc))
+    return 1;
+
   return 0;
 }
 
@@ -11650,7 +11761,14 @@ update_global_location_list (int should_
 
 	  if (!keep_in_target)
 	    {
-	      if (remove_breakpoint (old_loc, mark_uninserted))
+	      volatile struct gdb_exception e;
+	      int ret;
+
+	      TRY_CATCH (e, RETURN_MASK_ERROR)
+		{
+		  ret = remove_breakpoint (old_loc, mark_uninserted);
+		}
+	      if (ret || e.reason < 0)
 		{
 		  /* This is just about all we can do.  We could keep
 		     this location on the global list, and try to
@@ -11663,8 +11781,11 @@ update_global_location_list (int should_
 		  printf_filtered (_("warning: Error removing "
 				     "breakpoint %d\n"), 
 				   old_loc->owner->number);
+		  removed = 0;
+		  bp_location_remove_fail_chain_insert (old_loc);
 		}
-	      removed = 1;
+	      else
+		removed = 1;
 	    }
 	}
 
@@ -11725,10 +11846,7 @@ update_global_location_list (int should_
 	      VEC_safe_push (bp_location_p, moribund_locations, old_loc);
 	    }
 	  else
-	    {
-	      old_loc->owner = NULL;
-	      decref_bp_location (&old_loc);
-	    }
+	    decref_bp_location (&old_loc);
 	}
     }
 
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -1480,4 +1480,6 @@ extern struct gdbarch *get_sal_arch (str
 
 extern void handle_solib_event (void);
 
+extern void bp_location_remove_fail_chain_remove (struct bp_location *bl);
+
 #endif /* !defined (BREAKPOINT_H) */
--- a/target.c
+++ b/target.c
@@ -454,6 +454,9 @@ target_kill (void)
 	  fprintf_unfiltered (gdb_stdlog, "target_kill ()\n");
 
         t->to_kill (t);
+
+	bp_location_remove_fail_chain_remove (NULL);
+
 	return;
       }
 
@@ -2568,9 +2571,13 @@ target_detach (char *args, int from_tty)
        disconnection from the target.  */
     ;
   else
-    /* If we're in breakpoints-always-inserted mode, have to remove
-       them before detaching.  */
-    remove_breakpoints_pid (PIDGET (inferior_ptid));
+    {
+      /* If we're in breakpoints-always-inserted mode, have to remove
+	 them before detaching.  */
+      remove_breakpoints_pid (PIDGET (inferior_ptid));
+
+      bp_location_remove_fail_chain_remove (NULL);
+    }
 
   prepare_for_detach ();
 
@@ -2599,6 +2606,8 @@ target_disconnect (char *args, int from_
      disconnecting.  */
   remove_breakpoints ();
 
+  bp_location_remove_fail_chain_remove (NULL);
+
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     if (t->to_disconnect != NULL)
 	{

             reply	other threads:[~2012-04-11  9:07 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-11  9:32 Hui Zhu [this message]
2012-04-11 10:53 ` Yao Qi
2012-04-11 21:33 ` Jan Kratochvil
2012-04-12  4:04   ` Hui Zhu
2012-04-16 10:01     ` Jan Kratochvil
2012-04-16 16:42       ` Hui Zhu
2012-04-17 21:15     ` Jan Kratochvil
2012-04-12  4:45   ` Doug Evans
2012-04-12  4:35 ` Doug Evans
2012-04-16  9:50   ` Hui Zhu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F8549BC.3050003@mentor.com \
    --to=hui_zhu@mentor.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox