Blob Blame History Raw
Fix:
	FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dsub
	FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dmul
	FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly ddiv
	FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dcmpu
	
2007-10-15  Peter Bergner  <bergner@vnet.ibm.com>

	* ppc-opc.c (powerpc_opcodes): Fix the first two operands of
	dquaiq. to use the TE and FRT macros.

--- ./opcodes/ppc-opc.c	16 Oct 2007 02:26:30 -0000	1.100
+++ ./opcodes/ppc-opc.c	16 Oct 2007 02:55:30 -0000	1.101
@@ -4680,7 +4680,7 @@ const struct powerpc_opcode powerpc_opco
 { "dscliq.", ZRC(63,66,1), Z_MASK,	POWER6,		{ FRT, FRA, SH16 } },
 
 { "dquaiq",  ZRC(63,67,0), Z2_MASK,	POWER6,		{ TE,  FRT, FRB, RMC } },
-{ "dquaiq.", ZRC(63,67,1), Z2_MASK,	POWER6,		{ FRT, FRA, FRB, RMC } },
+{ "dquaiq.", ZRC(63,67,1), Z2_MASK,	POWER6,		{ TE,  FRT, FRB, RMC } },
 
 { "mtfsb0",  XRC(63,70,0), XRARB_MASK,	COM,		{ BT } },
 { "mtfsb0.", XRC(63,70,1), XRARB_MASK,	COM,		{ BT } },

2007-10-15  Peter Bergner  <bergner@vnet.ibm.com>

	* ppc-opc.c (TE): Correct signedness.
	(powerpc_opcodes): Sort psq_st and psq_stu according to major
	opcode number.

--- ./opcodes/ppc-opc.c	24 Aug 2007 00:56:30 -0000	1.99
+++ ./opcodes/ppc-opc.c	16 Oct 2007 02:26:30 -0000	1.100
@@ -492,13 +492,13 @@ const struct powerpc_operand powerpc_ope
 #define VS VD
   { 0x1f, 21, NULL, NULL, PPC_OPERAND_VR },
 
-  /* The SIMM field in a VX form instruction.  */
+  /* The SIMM field in a VX form instruction, and TE in Z form.  */
 #define SIMM VD + 1
+#define TE SIMM
   { 0x1f, 16, NULL, NULL, PPC_OPERAND_SIGNED},
 
-  /* The UIMM field in a VX form instruction, and TE in Z form.  */
+  /* The UIMM field in a VX form instruction.  */
 #define UIMM SIMM + 1
-#define TE UIMM
   { 0x1f, 16, NULL, NULL, 0 },
 
   /* The SHB field in a VA form instruction.  */
@@ -4495,9 +4495,6 @@ const struct powerpc_opcode powerpc_opco
 { "fnmadds", A(59,31,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
 { "fnmadds.",A(59,31,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
 
-{ "psq_st",  OP(60),    OP_MASK,        PPCPS,          { FRS, PSD, RA, PSW, PSQ } },
-{ "psq_stu", OP(61),    OP_MASK,        PPCPS,          { FRS, PSD, RA, PSW, PSQ } },
-
 { "dmul",    XRC(59,34,0), X_MASK,	POWER6,		{ FRT, FRA, FRB } },
 { "dmul.",   XRC(59,34,1), X_MASK,	POWER6,		{ FRT, FRA, FRB } },
 
@@ -4561,6 +4558,9 @@ const struct powerpc_opcode powerpc_opco
 
 { "stfq",    OP(60),	OP_MASK,	POWER2,		{ FRS, D, RA } },
 
+{ "psq_st",  OP(60),    OP_MASK,        PPCPS,          { FRS, PSD, RA, PSW, PSQ } },
+{ "psq_stu", OP(61),    OP_MASK,        PPCPS,          { FRS, PSD, RA, PSW, PSQ } },
+
 { "stfqu",   OP(61),	OP_MASK,	POWER2,		{ FRS, D, RA } },
 
 { "stfdp",   OP(61),	OP_MASK,	POWER6,		{ FRT, D, RA0 } },



2007-09-22  Vladimir Prus  <vladimir@codesourcery.com>

	Associate bp_stat with bp_location, not breakpoint.
	* breakpoint.h (breakpoint_at): Change type
	to bp_location*.
	* breakpoint.c (bpstat_alloc): Take bp_location,
	not breakpoint.
	(bpstat_find_breakpoint): Look at bpstat's location's
	owner, not at bpstat->breakpoint_at.
	(bpstat_find_step_resume_breakpoint): Likewise.
	(bpstat_num): Likewise.
	(print_it_typical): Likewise.
	(print_bp_stop_message): Likewise.
	(watchpoint_check): Likewise.
	(bpstat_what): Likewise.
	(bpstat_get_triggered_catchpoints): Likewise.
	(breakpoint_auto_delete): Likewise.
	(delete_breakpoint): Likewise.	
	(bpstat_stop_status): Pass location, not breakpoint,
	to bpstat_alloc.  Look at bpstat's location's
	owner, not at bpstat->breakpoint_at.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.263
retrieving revision 1.264
diff -u -r1.263 -r1.264
--- src/gdb/breakpoint.c	2007/08/29 22:07:47	1.263
+++ src/gdb/breakpoint.c	2007/09/22 17:49:40	1.264
@@ -109,7 +109,7 @@
 
 static void breakpoint_1 (int, int);
 
-static bpstat bpstat_alloc (struct breakpoint *, bpstat);
+static bpstat bpstat_alloc (struct bp_location *, bpstat);
 
 static int breakpoint_cond_eval (void *);
 
@@ -1968,7 +1968,7 @@
 
   for (; bsp != NULL; bsp = bsp->next)
     {
-      if (bsp->breakpoint_at == breakpoint)
+      if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint)
 	return bsp;
     }
   return NULL;
@@ -1994,10 +1994,10 @@
   for (; bsp != NULL; bsp = bsp->next)
     {
       if ((bsp->breakpoint_at != NULL) &&
-	  (bsp->breakpoint_at->type == bp_step_resume) &&
-	  (bsp->breakpoint_at->thread == current_thread || 
-	   bsp->breakpoint_at->thread == -1))
-	return bsp->breakpoint_at;
+	  (bsp->breakpoint_at->owner->type == bp_step_resume) &&
+	  (bsp->breakpoint_at->owner->thread == current_thread || 
+	   bsp->breakpoint_at->owner->thread == -1))
+	return bsp->breakpoint_at->owner;
     }
 
   internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found."));
@@ -2021,7 +2021,11 @@
   if ((*bsp) == NULL)
     return 0;			/* No more breakpoint values */
 
-  b = (*bsp)->breakpoint_at;
+  /* We assume we'll never have several bpstats that
+     correspond to a single breakpoint -- otherwise, 
+     this function might return the same number more
+     than once and this will look ugly.  */
+  b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL;
   *bsp = (*bsp)->next;
   if (b == NULL)
     return -1;			/* breakpoint that's been deleted since */
@@ -2152,6 +2156,7 @@
 print_it_typical (bpstat bs)
 {
   struct cleanup *old_chain, *ui_out_chain;
+  struct breakpoint *b;
   struct ui_stream *stb;
   stb = ui_out_stream_new (uiout);
   old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2159,21 +2164,22 @@
      which has since been deleted.  */
   if (bs->breakpoint_at == NULL)
     return PRINT_UNKNOWN;
+  b = bs->breakpoint_at->owner;
 
-  switch (bs->breakpoint_at->type)
+  switch (b->type)
     {
     case bp_breakpoint:
     case bp_hardware_breakpoint:
-      if (bs->breakpoint_at->loc->address != bs->breakpoint_at->loc->requested_address)
-	breakpoint_adjustment_warning (bs->breakpoint_at->loc->requested_address,
-	                               bs->breakpoint_at->loc->address,
-				       bs->breakpoint_at->number, 1);
-      annotate_breakpoint (bs->breakpoint_at->number);
+      if (b->loc->address != b->loc->requested_address)
+	breakpoint_adjustment_warning (b->loc->requested_address,
+	                               b->loc->address,
+				       b->number, 1);
+      annotate_breakpoint (b->number);
       ui_out_text (uiout, "\nBreakpoint ");
       if (ui_out_is_mi_like_p (uiout))
 	ui_out_field_string (uiout, "reason", 
 			     async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
-      ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number);
+      ui_out_field_int (uiout, "bkptno", b->number);
       ui_out_text (uiout, ", ");
       return PRINT_SRC_AND_LOC;
       break;
@@ -2200,42 +2206,42 @@
       break;
 
     case bp_catch_load:
-      annotate_catchpoint (bs->breakpoint_at->number);
+      annotate_catchpoint (b->number);
       printf_filtered (_("\nCatchpoint %d (loaded %s), "),
-		       bs->breakpoint_at->number,
-		       bs->breakpoint_at->triggered_dll_pathname);
+		       b->number,
+		       b->triggered_dll_pathname);
       return PRINT_SRC_AND_LOC;
       break;
 
     case bp_catch_unload:
-      annotate_catchpoint (bs->breakpoint_at->number);
+      annotate_catchpoint (b->number);
       printf_filtered (_("\nCatchpoint %d (unloaded %s), "),
-		       bs->breakpoint_at->number,
-		       bs->breakpoint_at->triggered_dll_pathname);
+		       b->number,
+		       b->triggered_dll_pathname);
       return PRINT_SRC_AND_LOC;
       break;
 
     case bp_catch_fork:
-      annotate_catchpoint (bs->breakpoint_at->number);
+      annotate_catchpoint (b->number);
       printf_filtered (_("\nCatchpoint %d (forked process %d), "),
-		       bs->breakpoint_at->number, 
-		       bs->breakpoint_at->forked_inferior_pid);
+		       b->number, 
+		       b->forked_inferior_pid);
       return PRINT_SRC_AND_LOC;
       break;
 
     case bp_catch_vfork:
-      annotate_catchpoint (bs->breakpoint_at->number);
+      annotate_catchpoint (b->number);
       printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
-		       bs->breakpoint_at->number, 
-		       bs->breakpoint_at->forked_inferior_pid);
+		       b->number, 
+		       b->forked_inferior_pid);
       return PRINT_SRC_AND_LOC;
       break;
 
     case bp_catch_exec:
-      annotate_catchpoint (bs->breakpoint_at->number);
+      annotate_catchpoint (b->number);
       printf_filtered (_("\nCatchpoint %d (exec'd %s), "),
-		       bs->breakpoint_at->number,
-		       bs->breakpoint_at->exec_pathname);
+		       b->number,
+		       b->exec_pathname);
       return PRINT_SRC_AND_LOC;
       break;
 
@@ -2243,9 +2249,9 @@
       if (current_exception_event && 
 	  (CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH))
 	{
-	  annotate_catchpoint (bs->breakpoint_at->number);
+	  annotate_catchpoint (b->number);
 	  printf_filtered (_("\nCatchpoint %d (exception caught), "), 
-			   bs->breakpoint_at->number);
+			   b->number);
 	  if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
 	    printf_filtered (_("throw location %s:%d, "),
 			     CURRENT_EXCEPTION_THROW_FILE,
@@ -2274,9 +2280,9 @@
       if (current_exception_event && 
 	  (CURRENT_EXCEPTION_KIND == EX_EVENT_THROW))
 	{
-	  annotate_catchpoint (bs->breakpoint_at->number);
+	  annotate_catchpoint (b->number);
 	  printf_filtered (_("\nCatchpoint %d (exception thrown), "),
-			   bs->breakpoint_at->number);
+			   b->number);
 	  if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
 	    printf_filtered (_("throw location %s:%d, "),
 			     CURRENT_EXCEPTION_THROW_FILE,
@@ -2305,18 +2311,18 @@
     case bp_hardware_watchpoint:
       if (bs->old_val != NULL)
 	{
-	  annotate_watchpoint (bs->breakpoint_at->number);
+	  annotate_watchpoint (b->number);
 	  if (ui_out_is_mi_like_p (uiout))
 	    ui_out_field_string
 	      (uiout, "reason",
 	       async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
-	  mention (bs->breakpoint_at);
+	  mention (b);
 	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
 	  ui_out_text (uiout, "\nOld value = ");
 	  value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
 	  ui_out_field_stream (uiout, "old", stb);
 	  ui_out_text (uiout, "\nNew value = ");
-	  value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+	  value_print (b->val, stb->stream, 0, Val_pretty_default);
 	  ui_out_field_stream (uiout, "new", stb);
 	  do_cleanups (ui_out_chain);
 	  ui_out_text (uiout, "\n");
@@ -2332,10 +2338,10 @@
 	ui_out_field_string
 	  (uiout, "reason",
 	   async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
-      mention (bs->breakpoint_at);
+      mention (b);
       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
       ui_out_text (uiout, "\nValue = ");
-      value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+      value_print (b->val, stb->stream, 0, Val_pretty_default);
       ui_out_field_stream (uiout, "value", stb);
       do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
@@ -2345,12 +2351,12 @@
     case bp_access_watchpoint:
       if (bs->old_val != NULL)     
 	{
-	  annotate_watchpoint (bs->breakpoint_at->number);
+	  annotate_watchpoint (b->number);
 	  if (ui_out_is_mi_like_p (uiout))
 	    ui_out_field_string
 	      (uiout, "reason",
 	       async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
-	  mention (bs->breakpoint_at);
+	  mention (b);
 	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
 	  ui_out_text (uiout, "\nOld value = ");
 	  value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
@@ -2361,7 +2367,7 @@
 	}
       else 
 	{
-	  mention (bs->breakpoint_at);
+	  mention (b);
 	  if (ui_out_is_mi_like_p (uiout))
 	    ui_out_field_string
 	      (uiout, "reason",
@@ -2369,7 +2375,7 @@
 	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
 	  ui_out_text (uiout, "\nValue = ");
 	}
-      value_print (bs->breakpoint_at->val, stb->stream, 0,Val_pretty_default);
+      value_print (b->val, stb->stream, 0,Val_pretty_default);
       ui_out_field_stream (uiout, "new", stb);
       do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
@@ -2429,14 +2435,19 @@
       break;
 
     case print_it_normal:
-      /* Normal case.  Call the breakpoint's print_it method, or
-	 print_it_typical.  */
-      if (bs->breakpoint_at != NULL && bs->breakpoint_at->ops != NULL
-	  && bs->breakpoint_at->ops->print_it != NULL)
-	return bs->breakpoint_at->ops->print_it (bs->breakpoint_at);
-      else
-	return print_it_typical (bs);
-      break;
+      {
+	struct bp_location *bl = bs->breakpoint_at;
+	struct breakpoint *b = bl ? bl->owner : NULL;
+	
+	/* Normal case.  Call the breakpoint's print_it method, or
+	   print_it_typical.  */
+	/* FIXME: how breakpoint can ever be NULL here?  */
+	if (b != NULL && b->ops != NULL && b->ops->print_it != NULL)
+	  return b->ops->print_it (b);
+	else
+	  return print_it_typical (bs);
+      }
+	break;
 
     default:
       internal_error (__FILE__, __LINE__,
@@ -2505,13 +2516,13 @@
 /* Allocate a new bpstat and chain it to the current one.  */
 
 static bpstat
-bpstat_alloc (struct breakpoint *b, bpstat cbs /* Current "bs" value */ )
+bpstat_alloc (struct bp_location *bl, bpstat cbs /* Current "bs" value */ )
 {
   bpstat bs;
 
   bs = (bpstat) xmalloc (sizeof (*bs));
   cbs->next = bs;
-  bs->breakpoint_at = b;
+  bs->breakpoint_at = bl;
   /* If the condition is false, etc., don't do the commands.  */
   bs->commands = NULL;
   bs->old_val = NULL;
@@ -2541,7 +2552,7 @@
   struct frame_info *fr;
   int within_current_scope;
 
-  b = bs->breakpoint_at;
+  b = bs->breakpoint_at->owner;
 
   if (b->exp_valid_block == NULL)
     within_current_scope = 1;
@@ -2588,7 +2599,7 @@
          we might be in the middle of evaluating a function call.  */
 
       struct value *mark = value_mark ();
-      struct value *new_val = evaluate_expression (bs->breakpoint_at->exp);
+      struct value *new_val = evaluate_expression (b->exp);
       if (!value_equal (b->val, new_val))
 	{
 	  release_value (new_val);
@@ -2624,7 +2635,7 @@
 	ui_out_field_string
 	  (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
       ui_out_text (uiout, "\nWatchpoint ");
-      ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number);
+      ui_out_field_int (uiout, "wpnum", b->number);
       ui_out_text (uiout, " deleted because the program has left the block in\n\
 which its expression is valid.\n");     
 
@@ -2760,7 +2771,7 @@
 
     /* Come here if it's a watchpoint, or if the break address matches */
 
-    bs = bpstat_alloc (b, bs);	/* Alloc a bpstat to explain stop */
+    bs = bpstat_alloc (b->loc, bs);	/* Alloc a bpstat to explain stop */
 
     /* Watchpoints may change this, if not found to have triggered. */
     bs->stop = 1;
@@ -2971,9 +2982,9 @@
   /* The value of a hardware watchpoint hasn't changed, but the
      intermediate memory locations we are watching may have.  */
   if (bs && !bs->stop &&
-      (bs->breakpoint_at->type == bp_hardware_watchpoint ||
-       bs->breakpoint_at->type == bp_read_watchpoint ||
-       bs->breakpoint_at->type == bp_access_watchpoint))
+      (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
+       bs->breakpoint_at->owner->type == bp_read_watchpoint ||
+       bs->breakpoint_at->owner->type == bp_access_watchpoint))
     {
       remove_breakpoints ();
       insert_breakpoints ();
@@ -3134,7 +3145,7 @@
 	/* I suspect this can happen if it was a momentary breakpoint
 	   which has since been deleted.  */
 	continue;
-      switch (bs->breakpoint_at->type)
+      switch (bs->breakpoint_at->owner->type)
 	{
 	case bp_none:
 	  continue;
@@ -3289,7 +3300,7 @@
   for (; ep_list != NULL; ep_list = ep_list->next)
     {
       /* Is this eventpoint a catchpoint?  If not, ignore it. */
-      ep = ep_list->breakpoint_at;
+      ep = ep_list->breakpoint_at->owner;
       if (ep == NULL)
 	break;
       if ((ep->type != bp_catch_load) &&
@@ -3300,7 +3311,7 @@
 	continue;
 
       /* Yes; add it to the list. */
-      bs = bpstat_alloc (ep, bs);
+      bs = bpstat_alloc (ep_list->breakpoint_at, bs);
       *bs = *ep_list;
       bs->next = NULL;
       bs = root_bs->next;
@@ -6849,9 +6860,9 @@
   struct breakpoint *b, *temp;
 
   for (; bs; bs = bs->next)
-    if (bs->breakpoint_at && bs->breakpoint_at->disposition == disp_del
+    if (bs->breakpoint_at && bs->breakpoint_at->owner->disposition == disp_del
 	&& bs->stop)
-      delete_breakpoint (bs->breakpoint_at);
+      delete_breakpoint (bs->breakpoint_at->owner);
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
@@ -7041,7 +7052,7 @@
      in event-top.c won't do anything, and temporary breakpoints
      with commands won't work.  */
   for (bs = stop_bpstat; bs; bs = bs->next)
-    if (bs->breakpoint_at == bpt)
+    if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
       {
 	bs->breakpoint_at = NULL;
 	bs->old_val = NULL;
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- src/gdb/breakpoint.h	2007/08/23 18:08:26	1.47
+++ src/gdb/breakpoint.h	2007/09/22 17:49:41	1.48
@@ -603,7 +603,7 @@
        place, and a bpstat reflects the fact that both have been hit.  */
     bpstat next;
     /* Breakpoint that we are at.  */
-    struct breakpoint *breakpoint_at;
+    struct bp_location *breakpoint_at;
     /* Commands left to be done.  */
     struct command_line *commands;
     /* Old value associated with a watchpoint.  */

2007-09-22  Vladimir Prus  <vladimir@codesourcery.com>

	* breakpoint.h (struct breakpoint): Move the cond 
	field to...
	(struct bp_location): Here.
	* breakpoint.c (condition_command, bpstat_stop_status)
	(print_one_breakpoint, allocate_bp_location)
	(solib_load_unload_1, create_fork_vfork_event_catchpoint)
	(create_exec_event_catchpoint, create_breakpoints)
	(break_command_1, watch_command_1, handle_gnu_v3_exceptions)
	(create_ada_exception_breakpoint, set_breakpoint_sal)
	(delete_breakpoint, breakpoint_re_set_one): Adjust.
	* tui/tui-winsource.c (tui_update_breakpoint_info): Adjust.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.264
retrieving revision 1.265
diff -u -r1.264 -r1.265
--- src/gdb/breakpoint.c	2007/09/22 17:49:40	1.264
+++ src/gdb/breakpoint.c	2007/09/22 19:06:59	1.265
@@ -569,17 +569,17 @@
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
     {
-      if (b->cond)
+      struct bp_location *loc = b->loc;
+      if (loc->cond)
 	{
-	  xfree (b->cond);
-	  b->cond = 0;
+	  xfree (loc->cond);
+	  loc->cond = 0;
 	}
       if (b->cond_string != NULL)
 	xfree (b->cond_string);
 
       if (*p == 0)
 	{
-	  b->cond = 0;
 	  b->cond_string = NULL;
 	  if (from_tty)
 	    printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
@@ -592,7 +592,8 @@
 	  b->cond_string = savestring (arg, strlen (arg));
 	  if (!b->pending)
 	    {
-	      b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+	      b->loc->cond = parse_exp_1 (&arg, 
+					  block_for_pc (b->loc->address), 0);
 	      if (*arg)
 		error (_("Junk at end of expression"));
 	    }
@@ -2923,19 +2924,19 @@
       {
 	int value_is_zero = 0;
 
-	if (b->cond)
+	if (b->loc->cond)
 	  {
 	    /* Need to select the frame, with all that implies
 	       so that the conditions will have the right context.  */
 	    select_frame (get_current_frame ());
 	    value_is_zero
-	      = catch_errors (breakpoint_cond_eval, (b->cond),
+	      = catch_errors (breakpoint_cond_eval, (b->loc->cond),
 			      "Error in testing breakpoint condition:\n",
 			      RETURN_MASK_ALL);
 	    /* FIXME-someday, should give breakpoint # */
 	    free_all_values ();
 	  }
-	if (b->cond && value_is_zero)
+	if (b->loc->cond && value_is_zero)
 	  {
 	    bs->stop = 0;
 	    /* Don't consider this a hit.  */
@@ -3606,14 +3607,14 @@
       ui_out_text (uiout, "\n");
     }
   
-  if (b->cond && !ada_exception_catchpoint_p (b))
+  if (b->loc->cond && !ada_exception_catchpoint_p (b))
     {
       /* We do not print the condition for Ada exception catchpoints
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
       ui_out_text (uiout, "\tstop only if ");
-      print_expression (b->cond, stb->stream);
+      print_expression (b->loc->cond, stb->stream);
       ui_out_field_stream (uiout, "cond", stb);
       ui_out_text (uiout, "\n");
     }
@@ -4085,6 +4086,7 @@
   memset (loc, 0, sizeof (*loc));
 
   loc->owner = bpt;
+  loc->cond = NULL;
 
   switch (bp_type)
     {
@@ -4604,7 +4606,6 @@
   b = set_raw_breakpoint (sals.sals[0], bp_kind);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = NULL;
   b->cond_string = (cond_string == NULL) ? 
     NULL : savestring (cond_string, strlen (cond_string));
   b->thread = thread;
@@ -4661,7 +4662,6 @@
   b = set_raw_breakpoint (sal, bp_kind);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = NULL;
   b->cond_string = (cond_string == NULL) ? 
     NULL : savestring (cond_string, strlen (cond_string));
   b->thread = thread;
@@ -4700,7 +4700,6 @@
   b = set_raw_breakpoint (sal, bp_catch_exec);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = NULL;
   b->cond_string = (cond_string == NULL) ?
     NULL : savestring (cond_string, strlen (cond_string));
   b->thread = thread;
@@ -5033,7 +5032,7 @@
 	b = set_raw_breakpoint (sal, type);
 	set_breakpoint_count (breakpoint_count + 1);
 	b->number = breakpoint_count;
-	b->cond = cond[i];
+	b->loc->cond = cond[i];
 	b->thread = thread;
 	if (addr_string[i])
 	  b->addr_string = addr_string[i];
@@ -5056,7 +5055,7 @@
 	      {
 		arg = pending_bp->cond_string;
 		b->cond_string = savestring (arg, strlen (arg));
-		b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+		b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
 		if (*arg)
 		  error (_("Junk at end of pending breakpoint condition expression"));
 	      }
@@ -5399,7 +5398,7 @@
 		              : bp_breakpoint);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
-      b->cond = *cond;
+      b->loc->cond = *cond;
       b->thread = thread;
       b->addr_string = *addr_string;
       b->cond_string = *cond_string;
@@ -5792,7 +5791,7 @@
   b->exp_valid_block = exp_valid_block;
   b->exp_string = savestring (exp_start, exp_end - exp_start);
   b->val = val;
-  b->cond = cond;
+  b->loc->cond = cond;
   if (cond_start)
     b->cond_string = savestring (cond_start, cond_end - cond_start);
   else
@@ -6352,7 +6351,6 @@
   b = set_raw_breakpoint (*sal, bptype);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = NULL;
   b->cond_string = (cond_string == NULL) ? 
     NULL : savestring (cond_string, strlen (cond_string));
   b->thread = thread;
@@ -6432,7 +6430,6 @@
   b = set_raw_breakpoint (sals.sals[0], bp_breakpoint);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = NULL;
   b->cond_string = (cond_string == NULL) ? 
     NULL : savestring (cond_string, strlen (cond_string));
   b->thread = -1;
@@ -6519,7 +6516,7 @@
   b->disposition = tempflag ? disp_del : disp_donttouch;
   b->number = breakpoint_count;
   b->ignore_count = 0;
-  b->cond = cond;
+  b->loc->cond = cond;
   b->addr_string = addr_string;
   b->language = language_ada;
   b->cond_string = cond_string;
@@ -6701,7 +6698,6 @@
   b = set_raw_breakpoint (sal, bp_breakpoint);
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
-  b->cond = 0;
   b->thread = -1;
   return b;
 }
@@ -7021,8 +7017,6 @@
     }
 
   free_command_lines (&bpt->commands);
-  if (bpt->cond)
-    xfree (bpt->cond);
   if (bpt->cond_string != NULL)
     xfree (bpt->cond_string);
   if (bpt->addr_string != NULL)
@@ -7062,6 +7056,8 @@
      bp, we mark it as deleted before freeing its storage. */
   bpt->type = bp_none;
 
+  if (bpt->loc->cond)
+    xfree (bpt->loc->cond);
   xfree (bpt->loc);
   xfree (bpt);
 }
@@ -7215,14 +7211,14 @@
 	  if (b->cond_string != NULL)
 	    {
 	      s = b->cond_string;
-	      if (b->cond)
+	      if (b->loc->cond)
 		{
-		  xfree (b->cond);
+		  xfree (b->loc->cond);
 		  /* Avoid re-freeing b->exp if an error during the call
 		     to parse_exp_1.  */
-		  b->cond = NULL;
+		  b->loc->cond = NULL;
 		}
-	      b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+	      b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
 	    }
 
 	  /* We need to re-set the breakpoint if the address changes... */
@@ -7314,14 +7310,14 @@
       if (b->cond_string != NULL)
 	{
 	  s = b->cond_string;
-	  if (b->cond)
+	  if (b->loc->cond)
 	    {
-	      xfree (b->cond);
+	      xfree (b->loc->cond);
 	      /* Avoid re-freeing b->exp if an error during the call
 		 to parse_exp_1.  */
-	      b->cond = NULL;
+	      b->loc->cond = NULL;
 	    }
-	  b->cond = parse_exp_1 (&s, (struct block *) 0, 0);
+	  b->loc->cond = parse_exp_1 (&s, (struct block *) 0, 0);
 	}
       if (breakpoint_enabled (b))
 	mention (b);
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- src/gdb/breakpoint.h	2007/09/22 17:49:41	1.48
+++ src/gdb/breakpoint.h	2007/09/22 19:06:59	1.49
@@ -243,6 +243,13 @@
      than reference counting.  */
   struct breakpoint *owner;
 
+  /* Conditional.  Break only if this expression's value is nonzero.  
+     Unlike string form of condition, which is associated with breakpoint,
+     this is associated with location, since if breakpoint has several
+     locations,  the evaluation of expression can be different for
+     different locations.  */
+  struct expression *cond;
+  
   /* Nonzero if this breakpoint is now inserted.  */
   char inserted;
 
@@ -341,8 +348,6 @@
     /* Stack depth (address of frame).  If nonzero, break only if fp
        equals this.  */
     struct frame_id frame_id;
-    /* Conditional.  Break only if this expression's value is nonzero.  */
-    struct expression *cond;
 
     /* String we used to set the breakpoint (malloc'd).  */
     char *addr_string;
===================================================================
RCS file: /cvs/src/src/gdb/tui/tui-winsource.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- src/gdb/tui/tui-winsource.c	2007/08/23 18:08:50	1.28
+++ src/gdb/tui/tui-winsource.c	2007/09/22 19:06:59	1.29
@@ -449,7 +449,7 @@
                 mode |= TUI_BP_ENABLED;
               if (bp->hit_count)
                 mode |= TUI_BP_HIT;
-              if (bp->cond)
+              if (bp->loc->cond)
                 mode |= TUI_BP_CONDITIONAL;
               if (bp->type == bp_hardware_breakpoint)
                 mode |= TUI_BP_HARDWARE;

2007-09-22  Vladimir Prus  <vladimir@codesourcery.com>

	* breakpoint.c (create_breakpoint): Split from
	create_breakpoints, implementing most of its logic.
	Take just a single sal, single address string and
	single condition.  Do not take parsed condition at
	all.
	(create_breakpoints): Just call create_breakpoint
	for each sal.
	(find_condition_and_thread): New.
	(break_command_1): Use find_condition_and_thread.
	Do not keep parsed conditions.
	(do_captured_breakpoint): Don't convert
	condition string to struct expression.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.265
retrieving revision 1.266
diff -u -r1.265 -r1.266
--- src/gdb/breakpoint.c	2007/09/22 19:06:59	1.265
+++ src/gdb/breakpoint.c	2007/09/22 19:10:05	1.266
@@ -4984,93 +4984,125 @@
 }
 
 
-/* Add SALS.nelts breakpoints to the breakpoint table.  For each
-   SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i],
-   COND[i] and COND_STRING[i] values.
 
+/* Create a breakpoint with SAL as location.  Use ADDR_STRING
+   as textual description of the location, and COND_STRING
+   as condition expression.
+
+   The paramter PENDING_BP is same as for the
+   create_breakpoints function.  */
+
+static void
+create_breakpoint (struct symtab_and_line sal, char *addr_string,
+		   char *cond_string,
+		   enum bptype type, enum bpdisp disposition,
+		   int thread, int ignore_count, int from_tty,
+		   struct breakpoint *pending_bp)
+{
+  struct breakpoint *b;
+
+  if (type == bp_hardware_breakpoint)
+    {
+      int i = hw_breakpoint_used_count ();
+      int target_resources_ok = 
+	TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+					    i + 1, 0);
+      if (target_resources_ok == 0)
+	error (_("No hardware breakpoint support in the target."));
+      else if (target_resources_ok < 0)
+	error (_("Hardware breakpoints used exceeds limit."));
+    }
+
+  if (from_tty)
+    describe_other_breakpoints (sal.pc, sal.section, thread);
+  
+  b = set_raw_breakpoint (sal, type);
+  set_breakpoint_count (breakpoint_count + 1);
+  b->number = breakpoint_count;
+  b->thread = thread;
+  
+  b->cond_string = cond_string;
+  b->ignore_count = ignore_count;
+  b->enable_state = bp_enabled;
+  b->disposition = disposition;
+  /* If resolving a pending breakpoint, a check must be made to see if
+     the user has specified a new condition or commands for the 
+     breakpoint.  A new condition will override any condition that was 
+     initially specified with the initial breakpoint command.  */
+  if (pending_bp)
+    {
+      if (pending_bp->cond_string)
+	b->cond_string = savestring (pending_bp->cond_string, 
+				     strlen (pending_bp->cond_string));
+      
+      /* If there are commands associated with the breakpoint, they should 
+	 be copied too.  */
+      if (pending_bp->commands)
+	b->commands = copy_command_lines (pending_bp->commands);
+	    
+      /* We have to copy over the ignore_count and thread as well.  */
+      b->ignore_count = pending_bp->ignore_count;
+      b->thread = pending_bp->thread;
+    }
+
+  if (b->cond_string)
+    {
+      char *arg = b->cond_string;
+      b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+      if (*arg)
+	{
+	  if (pending_bp)
+	    error (_("Junk at end of pending breakpoint condition expression"));
+	  else
+	    error (_("Garbage %s follows condition"), arg);
+	}
+    }	    
+
+  if (addr_string)
+    b->addr_string = addr_string;
+  else
+    /* addr_string has to be used or breakpoint_re_set will delete
+       me.  */
+    b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
+
+  mention (b);
+}
+
+/* Add SALS.nelts breakpoints to the breakpoint table.  For each
+   SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
+   value.  COND_STRING, if not NULL, specified the condition to be
+   used for all breakpoints.  Essentially the only case where
+   SALS.nelts is not 1 is when we set a breakpoint on an overloaded
+   function.  In that case, it's still not possible to specify
+   separate conditions for different overloaded functions, so
+   we take just a single condition string.
+   
    The parameter PENDING_BP points to a pending breakpoint that is
    the basis of the breakpoints currently being created.  The pending
    breakpoint may contain a separate condition string or commands
    that were added after the initial pending breakpoint was created.
 
    NOTE: If the function succeeds, the caller is expected to cleanup
-   the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the
+   the arrays ADDR_STRING, COND_STRING, and SALS (but not the
    array contents).  If the function fails (error() is called), the
    caller is expected to cleanups both the ADDR_STRING, COND_STRING,
    COND and SALS arrays and each of those arrays contents. */
 
 static void
 create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
-		    struct expression **cond, char **cond_string,
+		    char *cond_string,
 		    enum bptype type, enum bpdisp disposition,
 		    int thread, int ignore_count, int from_tty,
 		    struct breakpoint *pending_bp)
 {
-  if (type == bp_hardware_breakpoint)
+  int i;
+  for (i = 0; i < sals.nelts; ++i)
     {
-      int i = hw_breakpoint_used_count ();
-      int target_resources_ok = 
-	TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
-					    i + sals.nelts, 0);
-      if (target_resources_ok == 0)
-	error (_("No hardware breakpoint support in the target."));
-      else if (target_resources_ok < 0)
-	error (_("Hardware breakpoints used exceeds limit."));
+      create_breakpoint (sals.sals[i], addr_string[i],
+			 cond_string, type, disposition,
+			 thread, ignore_count, from_tty,
+			 pending_bp);
     }
-
-  /* Now set all the breakpoints.  */
-  {
-    int i;
-    for (i = 0; i < sals.nelts; i++)
-      {
-	struct breakpoint *b;
-	struct symtab_and_line sal = sals.sals[i];
-
-	if (from_tty)
-	  describe_other_breakpoints (sal.pc, sal.section, thread);
-	
-	b = set_raw_breakpoint (sal, type);
-	set_breakpoint_count (breakpoint_count + 1);
-	b->number = breakpoint_count;
-	b->loc->cond = cond[i];
-	b->thread = thread;
-	if (addr_string[i])
-	  b->addr_string = addr_string[i];
-	else
-	  /* addr_string has to be used or breakpoint_re_set will delete
-	     me.  */
-	  b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
-	b->cond_string = cond_string[i];
-	b->ignore_count = ignore_count;
-	b->enable_state = bp_enabled;
-	b->disposition = disposition;
-	/* If resolving a pending breakpoint, a check must be made to see if
-	   the user has specified a new condition or commands for the 
-	   breakpoint.  A new condition will override any condition that was 
-	   initially specified with the initial breakpoint command.  */
-	if (pending_bp)
-	  {
-	    char *arg;
-	    if (pending_bp->cond_string)
-	      {
-		arg = pending_bp->cond_string;
-		b->cond_string = savestring (arg, strlen (arg));
-		b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
-		if (*arg)
-		  error (_("Junk at end of pending breakpoint condition expression"));
-	      }
-	    /* If there are commands associated with the breakpoint, they should 
-	       be copied too.  */
-	    if (pending_bp->commands)
-	      b->commands = copy_command_lines (pending_bp->commands);
-	    
-	    /* We have to copy over the ignore_count and thread as well.  */
-	    b->ignore_count = pending_bp->ignore_count;
-	    b->thread = pending_bp->thread;
-	  }
-	mention (b);
-      }
-  }    
 }
 
 /* Parse ARG which is assumed to be a SAL specification possibly
@@ -5192,6 +5224,59 @@
 		         args->not_found_ptr);
 }
 
+/* Given TOK, a string specification of condition and thread, as
+   accepted by the 'break' command, extract the condition
+   string and thread number and set *COND_STRING and *THREAD.
+   PC identifies the context at which the condition should be parsed.  
+   If no condition is found, *COND_STRING is set to NULL.
+   If no thread is found, *THREAD is set to -1.  */
+static void 
+find_condition_and_thread (char *tok, CORE_ADDR pc, 
+			   char **cond_string, int *thread)
+{
+  *cond_string = NULL;
+  *thread = -1;
+  while (tok && *tok)
+    {
+      char *end_tok;
+      int toklen;
+      char *cond_start = NULL;
+      char *cond_end = NULL;
+      while (*tok == ' ' || *tok == '\t')
+	tok++;
+      
+      end_tok = tok;
+      
+      while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
+	end_tok++;
+      
+      toklen = end_tok - tok;
+      
+      if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+	{
+	  tok = cond_start = end_tok + 1;
+	  parse_exp_1 (&tok, block_for_pc (pc), 0);
+	  cond_end = tok;
+	  *cond_string = savestring (cond_start, 
+				     cond_end - cond_start);
+	}
+      else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+	{
+	  char *tmptok;
+	  
+	  tok = end_tok + 1;
+	  tmptok = tok;
+	  *thread = strtol (tok, &tok, 0);
+	  if (tok == tmptok)
+	    error (_("Junk after thread keyword."));
+	  if (!valid_thread_id (*thread))
+	    error (_("Unknown thread %d."), *thread);
+	}
+      else
+	error (_("Junk at end of arguments."));
+    }
+}
+
 /* Set a breakpoint according to ARG (function, linenum or *address)
    flag: first bit  : 0 non-temporary, 1 temporary.
    second bit : 0 normal breakpoint, 1 hardware breakpoint. 
@@ -5205,9 +5290,8 @@
   struct gdb_exception e;
   int tempflag, hardwareflag;
   struct symtabs_and_lines sals;
-  struct expression **cond = 0;
   struct symtab_and_line pending_sal;
-  char **cond_string = (char **) NULL;
+  char *cond_string = NULL;
   char *copy_arg;
   char *err_msg;
   char *addr_start = arg;
@@ -5297,14 +5381,6 @@
       make_cleanup (xfree, addr_string);
     }
 
-  /* Allocate space for all the cond expressions. */
-  cond = xcalloc (sals.nelts, sizeof (struct expression *));
-  make_cleanup (xfree, cond);
-
-  /* Allocate space for all the cond strings. */
-  cond_string = xcalloc (sals.nelts, sizeof (char **));
-  make_cleanup (xfree, cond_string);
-
   /* ----------------------------- SNIP -----------------------------
      Anything added to the cleanup chain beyond this point is assumed
      to be part of a breakpoint.  If the breakpoint create succeeds
@@ -5328,56 +5404,16 @@
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
      breakpoint. */
-  thread = -1;			/* No specific thread yet */
   if (!pending)
     {
-      for (i = 0; i < sals.nelts; i++)
-	{
-	  char *tok = arg;
-	  while (tok && *tok)
-	    {
-	      char *end_tok;
-	      int toklen;
-	      char *cond_start = NULL;
-	      char *cond_end = NULL;
-	      while (*tok == ' ' || *tok == '\t')
-		tok++;
-	      
-	      end_tok = tok;
-	      
-	      while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
-		end_tok++;
-	      
-	      toklen = end_tok - tok;
-	      
-	      if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
-		{
-		  tok = cond_start = end_tok + 1;
-		  cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 
-				         0);
-		  make_cleanup (xfree, cond[i]);
-		  cond_end = tok;
-		  cond_string[i] = savestring (cond_start, 
-				               cond_end - cond_start);
-		  make_cleanup (xfree, cond_string[i]);
-		}
-	      else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
-		{
-		  char *tmptok;
-		  
-		  tok = end_tok + 1;
-		  tmptok = tok;
-		  thread = strtol (tok, &tok, 0);
-		  if (tok == tmptok)
-		    error (_("Junk after thread keyword."));
-		  if (!valid_thread_id (thread))
-		    error (_("Unknown thread %d."), thread);
-		}
-	      else
-		error (_("Junk at end of arguments."));
-	    }
-	}
-      create_breakpoints (sals, addr_string, cond, cond_string,
+      /* Here we only parse 'arg' to separate condition
+	 from thread number, so parsing in context of first
+	 sal is OK.  When setting the breakpoint we'll 
+	 re-parse it in context of each sal.  */
+      find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
+      if (cond_string)
+	make_cleanup (xfree, cond_string);
+      create_breakpoints (sals, addr_string, cond_string,
 			  hardwareflag ? bp_hardware_breakpoint 
 			  : bp_breakpoint,
 			  tempflag ? disp_del : disp_donttouch,
@@ -5398,10 +5434,10 @@
 		              : bp_breakpoint);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
-      b->loc->cond = *cond;
+      b->loc->cond = NULL;
       b->thread = thread;
-      b->addr_string = *addr_string;
-      b->cond_string = *cond_string;
+      b->addr_string = addr_string[0];
+      b->cond_string = cond_string;
       b->ignore_count = ignore_count;
       b->pending = 1;
       b->disposition = tempflag ? disp_del : disp_donttouch;
@@ -5445,7 +5481,7 @@
   struct cleanup *breakpoint_chain = NULL;
   int i;
   char **addr_string;
-  char **cond_string;
+  char *cond_string;
 
   char *address_end;
 
@@ -5502,22 +5538,13 @@
   /* Resolve all line numbers to PC's.  */
   breakpoint_sals_to_pc (&sals, args->address);
 
-  /* Verify that conditions can be parsed, before setting any
-     breakpoints.  */
-  for (i = 0; i < sals.nelts; i++)
+  if (args->condition != NULL)
     {
-      if (args->condition != NULL)
-	{
-	  char *tok = args->condition;
-	  cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
-	  if (*tok != '\0')
-	    error (_("Garbage %s follows condition"), tok);
-	  make_cleanup (xfree, cond[i]);
-	  cond_string[i] = xstrdup (args->condition);
-	}
+      cond_string = xstrdup (args->condition);
+      make_cleanup (xfree, cond_string);
     }
 
-  create_breakpoints (sals, addr_string, cond, cond_string,
+  create_breakpoints (sals, addr_string, args->condition,
 		      args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
 		      args->tempflag ? disp_del : disp_donttouch,
 		      args->thread, args->ignore_count, 0/*from-tty*/, 

2007-09-22  Vladimir Prus  <vladimir@codesourcery.com>

	* breakpoint.c (do_restore_lang_radix_cleanup): Remove.
	(resolve_pending_breakpoint): Remove.
	(re_enable_breakpoints_in_shlibs): Remove.
	(unlink_locations_from_global_list): New.
	(update_breakpoint_locations): New.
	(breakpoint_re_set_one): Don't bail out on pending breakpoints.
	Use parse_condition and update_breakpoint_location to
	reset breakpoint.  Ignore 'symbol not found' error from
	decode_line_1.
	(breakpoint_re_set): Don't emit newline before the
	reason why breakpoint is not reset.
	(do_enable_breakpoint): Don't specially process pending
	breakpoints.
	(free_bp_location): New.
	(break_command_1): For pending breakpoints, initialize
	all fields of a sal with zeroes.
	* breakpoint.h (re_enable_breakpoints_in_shlibs): Remove.
	* infcmd.c (post_create_inferior): Don't call
	re_enable_breakpoints_in_shlibs.
	* infrun.c (handle_inferior_event): Likewise.
	* solib-irix.c (irix_solib_create_inferior_hook): Likewise.
	* solib-osf.c (osf_solib_create_inferior_hook): Likewise.
	* win32-nat.c (get_win32_debug_event): Likewise.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.266
retrieving revision 1.267
diff -u -r1.266 -r1.267
--- src/gdb/breakpoint.c	2007/09/22 19:10:05	1.266
+++ src/gdb/breakpoint.c	2007/09/22 19:33:31	1.267
@@ -203,6 +203,8 @@
 
 static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc);
 
+static void free_bp_location (struct bp_location *loc);
+
 /* Prototypes for exported functions. */
 
 /* If FALSE, gdb will not use hardware support for watchpoints, even
@@ -4140,6 +4142,13 @@
   return loc;
 }
 
+static void free_bp_location (struct bp_location *loc)
+{
+  if (loc->cond)
+    xfree (loc->cond);
+  xfree (loc);
+}
+
 /* set_raw_breakpoint() is a low level routine for allocating and
    partially initializing a breakpoint of type BPTYPE.  The newly
    created breakpoint's address, section, source file name, and line
@@ -4396,51 +4405,6 @@
     int radix;
   };
 
-/* Cleanup helper routine to restore the current language and
-   input radix.  */
-static void
-do_restore_lang_radix_cleanup (void *old)
-{
-  struct lang_and_radix *p = old;
-  set_language (p->lang);
-  input_radix = p->radix;
-}
-
-/* Try and resolve a pending breakpoint.  */
-static int
-resolve_pending_breakpoint (struct breakpoint *b)
-{
-  /* Try and reparse the breakpoint in case the shared library
-     is now loaded.  */
-  struct symtabs_and_lines sals;
-  struct symtab_and_line pending_sal;
-  char **cond_string = (char **) NULL;
-  char *copy_arg = b->addr_string;
-  char **addr_string;
-  char *errmsg;
-  int rc;
-  int not_found = 0;
-  struct ui_file *old_gdb_stderr;
-  struct lang_and_radix old_lr;
-  struct cleanup *old_chain;
-  
-  /* Set language, input-radix, then reissue breakpoint command. 
-     Ensure the language and input-radix are restored afterwards.  */
-  old_lr.lang = current_language->la_language;
-  old_lr.radix = input_radix;
-  old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr);
-  
-  set_language (b->language);
-  input_radix = b->input_radix;
-  rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b);
-  
-  if (rc == GDB_RC_OK)
-    /* Pending breakpoint has been resolved.  */
-    printf_filtered (_("Pending breakpoint \"%s\" resolved\n"), b->addr_string);
-
-  do_cleanups (old_chain);
-  return rc;
-}
 
 void
 remove_solib_event_breakpoints (void)
@@ -4523,37 +4487,6 @@
   }
 }
 
-/* Try to reenable any breakpoints in shared libraries.  */
-void
-re_enable_breakpoints_in_shlibs (void)
-{
-  struct breakpoint *b, *tmp;
-
-  ALL_BREAKPOINTS_SAFE (b, tmp)
-  {
-    if (b->enable_state == bp_shlib_disabled)
-      {
-	gdb_byte buf[1];
-	char *lib;
-	
-	/* Do not reenable the breakpoint if the shared library is
-	   still not mapped in.  */
-#ifdef PC_SOLIB
-	lib = PC_SOLIB (b->loc->address);
-#else
-	lib = solib_address (b->loc->address);
-#endif
-	if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
-	  b->enable_state = bp_enabled;
-      }
-    else if (b->pending && (b->enable_state == bp_enabled))
-      {
-	if (resolve_pending_breakpoint (b) == GDB_RC_OK)
-	  delete_breakpoint (b);
-      }
-  }
-}
-
 static void
 solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname,
 		     char *cond_string, enum bptype bp_kind)
@@ -5422,12 +5355,9 @@
     }
   else
     {
-      struct symtab_and_line sal;
+      struct symtab_and_line sal = {0};
       struct breakpoint *b;
 
-      sal.symtab = NULL;
-      sal.pc = 0;
-
       make_cleanup (xfree, copy_arg);
 
       b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint 
@@ -7153,6 +7083,97 @@
     map_breakpoint_numbers (arg, delete_breakpoint);
 }
 
+static void
+unlink_locations_from_global_list (struct breakpoint *bpt)
+  /* Remove locations of this breakpoint from the list of
+     all breakpoint locations.  */
+{
+  struct bp_location **tmp = &bp_location_chain;
+  struct bp_location *here = bpt->loc;
+
+  if (here == NULL)
+    return;
+
+  for (; *tmp && *tmp != here; tmp = &((*tmp)->next));
+  gdb_assert (*tmp);
+       
+  *tmp = here->next;	
+}
+
+
+static void
+update_breakpoint_location (struct breakpoint *b,
+			    struct symtabs_and_lines sals)
+{
+  int i;
+  char *s;
+  /* FIXME: memleak.  */
+  struct bp_location *existing = b->loc;
+  struct bp_location *loc;
+  struct symtab_and_line sal;
+  
+  if (b->enable_state == bp_shlib_disabled && sals.nelts == 0)
+    return;
+
+  unlink_locations_from_global_list (b);
+  b->loc = NULL;
+
+  gdb_assert (sals.nelts == 0 || sals.nelts == 1);
+  if (sals.nelts == 0)
+    return;
+  sal = sals.sals[0];
+
+  loc = allocate_bp_location (b, b->type);
+  loc->requested_address = sal.pc;
+  loc->address = adjust_breakpoint_address (loc->requested_address,
+					    b->type);
+  loc->section = sal.section;
+  b->loc = loc;
+
+  /* Reparse conditions, they might contain references to the
+     old symtab.  */
+  if (b->cond_string != NULL)
+    {
+      struct gdb_exception e;
+      
+      s = b->cond_string;
+      TRY_CATCH (e, RETURN_MASK_ERROR)
+	{
+	  loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc), 
+				   0);
+	}
+      if (e.reason < 0)
+	{
+	  warning (_("failed to reevaluate condition for breakpoint %d: %s"), 
+		   b->number, e.message);
+	  b->enable_state = bp_disabled;
+	}
+    }
+
+  if (b->source_file != NULL)
+    xfree (b->source_file);
+  if (sal.symtab == NULL)
+    b->source_file = NULL;
+  else
+    b->source_file =
+      savestring (sal.symtab->filename,
+		  strlen (sal.symtab->filename));
+
+  if (b->line_number == 0)
+    b->line_number = sal.line;
+
+  if (b->enable_state == bp_shlib_disabled)
+    b->enable_state = bp_enabled;
+
+  b->pending = 0;
+
+  check_duplicates (b);
+
+  if (existing)
+    free_bp_location (existing);
+}
+
+
 /* Reset a breakpoint given it's struct breakpoint * BINT.
    The value we return ends up being the return value from catch_errors.
    Unused in this case.  */
@@ -7164,11 +7185,13 @@
   struct breakpoint *b = (struct breakpoint *) bint;
   struct value *mark;
   int i;
-  int not_found;
-  int *not_found_ptr = NULL;
-  struct symtabs_and_lines sals;
+  int not_found = 0;
+  int *not_found_ptr = &not_found;
+  struct symtabs_and_lines sals = {};
   char *s;
   enum enable_state save_enable;
+  struct gdb_exception e;
+
 
   switch (b->type)
     {
@@ -7186,115 +7209,59 @@
 	  delete_breakpoint (b);
 	  return 0;
 	}
-      /* HACK: cagney/2001-11-11: kettenis/2001-11-11: MarkK wrote:
-
-	 ``And a hack it is, although Apple's Darwin version of GDB
-	 contains an almost identical hack to implement a "future
-	 break" command.  It seems to work in many real world cases,
-	 but it is easy to come up with a test case where the patch
-	 doesn't help at all.''
-
-	 ``It seems that the way GDB implements breakpoints - in -
-	 shared - libraries was designed for a.out shared library
-	 systems (SunOS 4) where shared libraries were loaded at a
-	 fixed address in memory.  Since ELF shared libraries can (and
-	 will) be loaded at any address in memory, things break.
-	 Fixing this is not trivial.  Therefore, I'm not sure whether
-	 we should add this hack to the branch only.  I cannot
-	 guarantee that things will be fixed on the trunk in the near
-	 future.''
-
-         In case we have a problem, disable this breakpoint.  We'll
-         restore its status if we succeed.  Don't disable a
-         shlib_disabled breakpoint though.  There's a fair chance we
-         can't re-set it if the shared library it's in hasn't been
-         loaded yet.  */
-
-      if (b->pending)
-	break;
-
-      save_enable = b->enable_state;
-      if (b->enable_state != bp_shlib_disabled)
-        b->enable_state = bp_disabled;
-      else
-	/* If resetting a shlib-disabled breakpoint, we don't want to
-	   see an error message if it is not found since we will expect
-	   this to occur until the shared library is finally reloaded.
-	   We accomplish this by giving decode_line_1 a pointer to use
-	   for silent notification that the symbol is not found.  */
-	not_found_ptr = &not_found;
 
       set_language (b->language);
       input_radix = b->input_radix;
       s = b->addr_string;
-      sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
-		            not_found_ptr);
-      for (i = 0; i < sals.nelts; i++)
-	{
-	  resolve_sal_pc (&sals.sals[i]);
-
-	  /* Reparse conditions, they might contain references to the
-	     old symtab.  */
-	  if (b->cond_string != NULL)
-	    {
-	      s = b->cond_string;
-	      if (b->loc->cond)
-		{
-		  xfree (b->loc->cond);
-		  /* Avoid re-freeing b->exp if an error during the call
-		     to parse_exp_1.  */
-		  b->loc->cond = NULL;
-		}
-	      b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
-	    }
+      TRY_CATCH (e, RETURN_MASK_ERROR)
+	{
+	  sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+				not_found_ptr);
+	}
+      if (e.reason < 0)
+	{
+	  int not_found_and_ok = 0;
+	  /* For pending breakpoints, it's expected that parsing
+	     will fail until the right shared library is loaded.
+	     User has already told to create pending breakpoints and
+	     don't need extra messages.  If breakpoint is in bp_shlib_disabled
+	     state, then user already saw the message about that breakpoint
+	     being disabled, and don't want to see more errors.  */
+	  if (not_found && (b->pending || b->enable_state == bp_shlib_disabled
+			    || b->enable_state == bp_disabled))
+	    not_found_and_ok = 1;
 
-	  /* We need to re-set the breakpoint if the address changes... */
-	  if (b->loc->address != sals.sals[i].pc
-	  /* ...or new and old breakpoints both have source files, and
-	     the source file name or the line number changes...  */
-	      || (b->source_file != NULL
-		  && sals.sals[i].symtab != NULL
-		  && (strcmp (b->source_file, sals.sals[i].symtab->filename) != 0
-		      || b->line_number != sals.sals[i].line)
-	      )
-	  /* ...or we switch between having a source file and not having
-	     one.  */
-	      || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
-	    )
+	  if (!not_found_and_ok)
 	    {
-	      if (b->source_file != NULL)
-		xfree (b->source_file);
-	      if (sals.sals[i].symtab == NULL)
-		b->source_file = NULL;
-	      else
-		b->source_file =
-		  savestring (sals.sals[i].symtab->filename,
-			      strlen (sals.sals[i].symtab->filename));
-	      b->line_number = sals.sals[i].line;
-	      b->loc->requested_address = sals.sals[i].pc;
-	      b->loc->address
-	        = adjust_breakpoint_address (b->loc->requested_address,
-		                             b->type);
-
-	      /* Used to check for duplicates here, but that can
-	         cause trouble, as it doesn't check for disabled
-	         breakpoints. */
-
-	      mention (b);
-
-	      /* Might be better to do this just once per breakpoint_re_set,
-	         rather than once for every breakpoint.  */
-	      breakpoints_changed ();
+	      /* We surely don't want to warn about the same breakpoint
+		 10 times.  One solution, implemented here, is disable
+		 the breakpoint on error.  Another solution would be to
+		 have separate 'warning emitted' flag.  Since this
+		 happens only when a binary has changed, I don't know
+		 which approach is better.  */
+	      b->enable_state = bp_disabled;
+	      throw_exception (e);
 	    }
-	  b->loc->section = sals.sals[i].section;
-	  b->enable_state = save_enable;	/* Restore it, this worked. */
+	}
 
+      if (not_found)
+	break;
+      
+      gdb_assert (sals.nelts == 1);
+      resolve_sal_pc (&sals.sals[0]);
+      if (b->pending && s && s[0])
+	{
+	  char *cond_string = 0;
+	  int thread = -1;
+	  find_condition_and_thread (s, sals.sals[0].pc, 
+				     &cond_string, &thread);
+	  if (cond_string)
+	    b->cond_string = cond_string;
+	  b->thread = thread;
+	}
 
-	  /* Now that this is re-enabled, check_duplicates
-	     can be used. */
-	  check_duplicates (b);
+      update_breakpoint_location (b, sals);
 
-	}
       xfree (sals.sals);
       break;
 
@@ -7408,7 +7375,7 @@
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
     /* Format possible error msg */
-    char *message = xstrprintf ("Error in re-setting breakpoint %d:\n",
+    char *message = xstrprintf ("Error in re-setting breakpoint %d: ",
 				b->number);
     struct cleanup *cleanups = make_cleanup (xfree, message);
     catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
@@ -7635,88 +7602,68 @@
 	error (_("Hardware breakpoints used exceeds limit."));
     }
 
-  if (bpt->pending)
+  if (bpt->enable_state != bp_permanent)
+    bpt->enable_state = bp_enabled;
+  bpt->disposition = disposition;
+  check_duplicates (bpt);
+  breakpoints_changed ();
+  
+  if (bpt->type == bp_watchpoint || 
+      bpt->type == bp_hardware_watchpoint ||
+      bpt->type == bp_read_watchpoint || 
+      bpt->type == bp_access_watchpoint)
     {
-      if (bpt->enable_state != bp_enabled)
+      struct frame_id saved_frame_id;
+      
+      saved_frame_id = get_frame_id (get_selected_frame (NULL));
+      if (bpt->exp_valid_block != NULL)
 	{
-	  /* When enabling a pending breakpoint, we need to check if the breakpoint
-	     is resolvable since shared libraries could have been loaded
-	     after the breakpoint was disabled.  */
-	  breakpoints_changed ();
- 	  if (resolve_pending_breakpoint (bpt) == GDB_RC_OK)
+	  struct frame_info *fr =
+	    fr = frame_find_by_id (bpt->watchpoint_frame);
+	  if (fr == NULL)
 	    {
-	      delete_breakpoint (bpt);
+	      printf_filtered (_("\
+Cannot enable watchpoint %d because the block in which its expression\n\
+is valid is not currently in scope.\n"), bpt->number);
+	      bpt->enable_state = bp_disabled;
 	      return;
 	    }
-	  bpt->enable_state = bp_enabled;
-	  bpt->disposition = disposition;
+	  select_frame (fr);
 	}
-    }
-  else  /* Not a pending breakpoint.  */
-    {
-      if (bpt->enable_state != bp_permanent)
-	bpt->enable_state = bp_enabled;
-      bpt->disposition = disposition;
-      check_duplicates (bpt);
-      breakpoints_changed ();
       
-      if (bpt->type == bp_watchpoint || 
-	  bpt->type == bp_hardware_watchpoint ||
-	  bpt->type == bp_read_watchpoint || 
+      value_free (bpt->val);
+      mark = value_mark ();
+      bpt->val = evaluate_expression (bpt->exp);
+      release_value (bpt->val);
+      if (value_lazy (bpt->val))
+	value_fetch_lazy (bpt->val);
+      
+      if (bpt->type == bp_hardware_watchpoint ||
+	  bpt->type == bp_read_watchpoint ||
 	  bpt->type == bp_access_watchpoint)
 	{
-	  struct frame_id saved_frame_id;
-
-	  saved_frame_id = get_frame_id (get_selected_frame (NULL));
-	  if (bpt->exp_valid_block != NULL)
-	    {
-	      struct frame_info *fr =
-		fr = frame_find_by_id (bpt->watchpoint_frame);
-	      if (fr == NULL)
-		{
-		  printf_filtered (_("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n"), bpt->number);
-		  bpt->enable_state = bp_disabled;
-		  return;
-		}
-	      select_frame (fr);
-	    }
-	  
-	  value_free (bpt->val);
-	  mark = value_mark ();
-	  bpt->val = evaluate_expression (bpt->exp);
-	  release_value (bpt->val);
-	  if (value_lazy (bpt->val))
-	    value_fetch_lazy (bpt->val);
+	  int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
+	  int mem_cnt = can_use_hardware_watchpoint (bpt->val);
 	  
-	  if (bpt->type == bp_hardware_watchpoint ||
-	      bpt->type == bp_read_watchpoint ||
-	      bpt->type == bp_access_watchpoint)
+	  /* Hack around 'unused var' error for some targets here */
+	  (void) mem_cnt, (void) i;
+	  target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
+								    bpt->type, i + mem_cnt, other_type_used);
+	  /* we can consider of type is bp_hardware_watchpoint, convert to 
+	     bp_watchpoint in the following condition */
+	  if (target_resources_ok < 0)
 	    {
-	      int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
-	      int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-	      
-	      /* Hack around 'unused var' error for some targets here */
-	      (void) mem_cnt, (void) i;
-	      target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
-									bpt->type, i + mem_cnt, other_type_used);
-	      /* we can consider of type is bp_hardware_watchpoint, convert to 
-		 bp_watchpoint in the following condition */
-	      if (target_resources_ok < 0)
-		{
-		  printf_filtered (_("\
+	      printf_filtered (_("\
 Cannot enable watchpoint %d because target watch resources\n\
 have been allocated for other watchpoints.\n"), bpt->number);
-		  bpt->enable_state = bp_disabled;
-		  value_free_to_mark (mark);
-		  return;
-		}
+	      bpt->enable_state = bp_disabled;
+	      value_free_to_mark (mark);
+	      return;
 	    }
-	  
-	  select_frame (frame_find_by_id (saved_frame_id));
-	  value_free_to_mark (mark);
 	}
+      
+      select_frame (frame_find_by_id (saved_frame_id));
+      value_free_to_mark (mark);
     }
 
   if (deprecated_modify_breakpoint_hook)
@@ -7724,6 +7671,7 @@
   breakpoint_modify_event (bpt->number);
 }
 
+
 void
 enable_breakpoint (struct breakpoint *bpt)
 {
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- src/gdb/breakpoint.h	2007/09/22 19:06:59	1.49
+++ src/gdb/breakpoint.h	2007/09/22 19:33:31	1.50
@@ -799,8 +799,6 @@
 
 extern void disable_breakpoints_in_shlibs (void);
 
-extern void re_enable_breakpoints_in_shlibs (void);
-
 extern void create_solib_load_event_breakpoint (char *, int, char *, char *);
 
 extern void create_solib_unload_event_breakpoint (char *, int,
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.158
retrieving revision 1.159
diff -u -r1.158 -r1.159
--- src/gdb/infcmd.c	2007/09/04 01:38:07	1.158
+++ src/gdb/infcmd.c	2007/09/22 19:33:31	1.159
@@ -433,10 +433,6 @@
 #else
       solib_create_inferior_hook ();
 #endif
-
-      /* Enable any breakpoints which were disabled when the
-	 underlying shared library was deleted.  */
-      re_enable_breakpoints_in_shlibs ();
     }
 
   observer_notify_inferior_created (target, from_tty);
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.247
retrieving revision 1.248
diff -u -r1.247 -r1.248
--- src/gdb/infrun.c	2007/09/17 19:44:20	1.247
+++ src/gdb/infrun.c	2007/09/22 19:33:31	1.248
@@ -1337,10 +1337,6 @@
 #endif
 	  target_terminal_inferior ();
 
-	  /* Try to reenable shared library breakpoints, additional
-	     code segments in shared libraries might be mapped in now. */
-	  re_enable_breakpoints_in_shlibs ();
-
 	  /* If requested, stop when the dynamic linker notifies
 	     gdb of events.  This allows the user to get control
 	     and place breakpoints in initializer routines for
@@ -2276,10 +2272,6 @@
 #endif
 	  target_terminal_inferior ();
 
-	  /* Try to reenable shared library breakpoints, additional
-	     code segments in shared libraries might be mapped in now. */
-	  re_enable_breakpoints_in_shlibs ();
-
 	  /* If requested, stop when the dynamic linker notifies
 	     gdb of events.  This allows the user to get control
 	     and place breakpoints in initializer routines for
===================================================================
RCS file: /cvs/src/src/gdb/solib-irix.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- src/gdb/solib-irix.c	2007/08/23 18:08:38	1.14
+++ src/gdb/solib-irix.c	2007/09/22 19:33:31	1.15
@@ -457,7 +457,6 @@
      suppresses the warning.  */
   solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
   stop_soon = NO_STOP_QUIETLY;
-  re_enable_breakpoints_in_shlibs ();
 }
 
 /* LOCAL FUNCTION
===================================================================
RCS file: /cvs/src/src/gdb/solib-osf.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/solib-osf.c	2007/08/23 18:08:38	1.11
+++ src/gdb/solib-osf.c	2007/09/22 19:33:31	1.12
@@ -336,9 +336,6 @@
      suppresses the warning.  */
   solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
   stop_soon = NO_STOP_QUIETLY;
-
-  /* Enable breakpoints disabled (unnecessarily) by clear_solib().  */
-  re_enable_breakpoints_in_shlibs ();
 }
 
 /* target_so_ops callback.  Do additional symbol handling, lookup, etc. after

2007-09-22  Vladimir Prus  <vladimir@codesourcery.com>

	* gdb.base/pending.exp: No longer expect "Pending breakpoint resolved"
	messages.
	* gdb.base/chng-syms.exp: Likewise.
	* gdb.base/unload.exp: Likewise.

===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/chng-syms.exp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- src/gdb/testsuite/gdb.base/chng-syms.exp	2007/08/23 18:14:16	1.8
+++ src/gdb/testsuite/gdb.base/chng-syms.exp	2007/09/22 19:33:32	1.9
@@ -105,10 +105,10 @@
 
     gdb_run_cmd
     gdb_expect {
-	-re "Error in re-setting .*No symbol .var1..*Program exited normally.*$gdb_prompt $" {
+	-re ".*No symbol .var1..*Program exited normally.*$gdb_prompt $" {
 	    pass "running with invalidated bpt condition after executable changes" 
 	}
-	-re "Error in re-setting .*No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" {
+	-re "No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" {
 	    pass "running with invalidated bpt condition after executable changes" 
 	}
 	-re "$gdb_prompt $" { 
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- src/gdb/testsuite/gdb.base/pending.exp	2007/08/23 18:14:17	1.10
+++ src/gdb/testsuite/gdb.base/pending.exp	2007/09/22 19:33:32	1.11
@@ -194,9 +194,7 @@
 
 gdb_run_cmd
 gdb_test "" \
-"Breakpoint.*at.*
-Pending breakpoint \"pendshr.c:$bp2_loc if x > 3\" resolved.*
-Breakpoint.*, main.*$mainline.*" \
+".*Breakpoint.*, main.*$mainline.*" \
 "running to main"
 
 #
@@ -204,8 +202,7 @@
 #
 
 gdb_test "enable 1" \
-"Breakpoint.*at.*
-Pending breakpoint \"pendfunc1.* resolved.*" \
+"" \
 "re-enabling pending breakpoint that can resolve instantly"
 
 #
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/testsuite/gdb.base/unload.exp	2007/08/23 18:14:17	1.11
+++ src/gdb/testsuite/gdb.base/unload.exp	2007/09/22 19:33:32	1.12
@@ -89,9 +89,7 @@
 
 gdb_run_cmd
 gdb_test "" \
-"Breakpoint.*at.*
-Pending breakpoint \"shrfunc1\" resolved.*
-Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \
+".*Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \
 "running program"
 
 gdb_test "continue" \

2007-09-23  Vladimir Prus  <vladimir@codesourcery.com>

	Allow a code breakpoint to have several locations
	associated with it.
	* breakpoint.h (enum enable_state): Remove the
	bp_shlib_disabled enumerator. 
	(struct bp_location): New members shlib_disabled,
	global_next, enabled and function_name.
	Rename pending to condition_not_parsed.

	* breakpoint.c (ALL_BP_LOCATIONS): Iterate over global_next.
	(ALL_BP_LOCATIONS_SAFE): Likewise.
	(breakpoint_enabled): Don't check for pending.
	(condition_command): Free and update all locations of
	a breakpoint.
	(insert_bp_location): Adjust.
	(software_breakpoint_inserted_here_p): Don't care
	if breakpoint is enabled, as soon as it's inserted.
	(print_it_typical): Print bpstat's location, not
	bpstat's breakpoint's location.
	(bpstat_stop_status): Iterate over all locations, not
	all breakpoints.
	(print_breakpoint_location): New.
	(print_one_breakpoint): Renamed to
	(print_one_breakpoint_location): ...this. Take
	parameters to describe which location is being
	printed. Modify code to properly print header
	for several locations and individual locations.
	(print_one_breakpoint): Print all locations.
	(breakpoint_has_pc): New.
	(describe_other_breakpoints): Use the above.
	(check_duplicates): Renamed to...
	(check_duplicates_for): .. this.
	(check_duplicates): Use check_duplicates_for.
	(allocate_bp_location): Adjust.
	(set_raw_breakpoint_without_location): New,
	extracted from set_raw_breakpoint.
	(set_breakpoint_location_function): New.
	(set_raw_breakpoint): Use 
	set_raw_breakpoint_without_location.
	(make_breakpoint_permanent): Mark all locations
	as inserted.
	(disable_breakpoints_in_shlibs): Iterate over
	locations.
	(disable_breakpoints_in_unloaded_shlib): Likewise.
	(re_enable_breakpoints_in_shlibs): Likewise.
	(mention): Say "pending" when breakpoint has
	zero locations.  If breakpoint has more than one
	location, say so.
	(add_location_to_breakpoint): New.
	(create_breakpoint): Accept symtabs_and_lines, not
	symtab_and_line. Pass extra sals to 
	add_location_to_breakpoint.
	(create_breakpoints): Pass symtabs_and_lines to
	create_breakpoints.
	(break_command_1): Make pending breakpoints
	have zero locations.
	(do_captured_breakpoint): Remove wrong allocation.
	(clear_command): Iterate over all locations.
	(unlink_locations_from_global_list): Renamed
	from unlink_location_from_global_list. Remove
	all locations.
	(delete_breakpoint): Remove all locations.
	Iterate over all locations when deciding which
	other location to re-enable.
	(all_locations_are_pending): New.
	(update_breakpoint_locations): Renamed from
	update_breakpoint_location. Try to match old
	and new locations using names of containing
	functions.
	(breakpoint_re_set_one): Adjust.
	(find_location_by_number): New.
	(disable_command): Allow disabling individual location.
	(enable_command): Allow enabling individual location.
	* breakpoint.c: Adjust all uses of breakpoint's
	enable state to for bp_shlib_disabled change.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.267
retrieving revision 1.268
diff -u -r1.267 -r1.268
--- src/gdb/breakpoint.c	2007/09/22 19:33:31	1.267
+++ src/gdb/breakpoint.c	2007/09/23 07:56:22	1.268
@@ -275,11 +275,11 @@
 
 /* Similar iterators for the low-level breakpoints.  */
 
-#define ALL_BP_LOCATIONS(B)  for (B = bp_location_chain; B; B = B->next)
+#define ALL_BP_LOCATIONS(B)  for (B = bp_location_chain; B; B = B->global_next)
 
 #define ALL_BP_LOCATIONS_SAFE(B,TMP)	\
 	for (B = bp_location_chain;	\
-	     B ? (TMP=B->next, 1): 0;	\
+	     B ? (TMP=B->global_next, 1): 0;	\
 	     B = TMP)
 
 /* True if breakpoint hit counts should be displayed in breakpoint info.  */
@@ -356,7 +356,7 @@
 static int
 breakpoint_enabled (struct breakpoint *b)
 {
-  return (b->enable_state == bp_enabled && !b->pending);
+  return (b->enable_state == bp_enabled);
 }
 
 /* Set breakpoint count to NUM.  */
@@ -572,10 +572,13 @@
     if (b->number == bnum)
     {
       struct bp_location *loc = b->loc;
-      if (loc->cond)
+      for (; loc; loc = loc->next)
 	{
-	  xfree (loc->cond);
-	  loc->cond = 0;
+	  if (loc->cond)
+	    {
+	      xfree (loc->cond);
+	      loc->cond = 0;
+	    }
 	}
       if (b->cond_string != NULL)
 	xfree (b->cond_string);
@@ -592,10 +595,11 @@
 	  /* I don't know if it matters whether this is the string the user
 	     typed in or the decompiled expression.  */
 	  b->cond_string = savestring (arg, strlen (arg));
-	  if (!b->pending)
+	  b->condition_not_parsed = 0;
+	  for (loc = b->loc; loc; loc = loc->next)
 	    {
-	      b->loc->cond = parse_exp_1 (&arg, 
-					  block_for_pc (b->loc->address), 0);
+	      arg = p;
+	      loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
 	      if (*arg)
 		error (_("Junk at end of expression"));
 	    }
@@ -846,7 +850,7 @@
   if (!breakpoint_enabled (bpt->owner))
     return 0;
 
-  if (bpt->inserted || bpt->duplicate)
+  if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
     return 0;
 
   /* Initialize the target-specific information.  */
@@ -969,7 +973,7 @@
 	    {
 	      /* See also: disable_breakpoints_in_shlibs. */
 	      val = 0;
-	      bpt->owner->enable_state = bp_shlib_disabled;
+	      bpt->shlib_disabled = 1;
 	      if (!*disabled_breaks)
 		{
 		  fprintf_unfiltered (tmp_error_stream, 
@@ -1808,9 +1812,7 @@
       if (bpt->loc_type != bp_loc_software_breakpoint)
 	continue;
 
-      if ((breakpoint_enabled (bpt->owner)
-	   || bpt->owner->enable_state == bp_permanent)
-	  && bpt->inserted
+      if (bpt->inserted
 	  && bpt->address == pc)	/* bp is enabled and matches pc */
 	{
 	  if (overlay_debugging 
@@ -2160,6 +2162,7 @@
 {
   struct cleanup *old_chain, *ui_out_chain;
   struct breakpoint *b;
+  struct bp_location *bl;
   struct ui_stream *stb;
   stb = ui_out_stream_new (uiout);
   old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2167,15 +2170,16 @@
      which has since been deleted.  */
   if (bs->breakpoint_at == NULL)
     return PRINT_UNKNOWN;
-  b = bs->breakpoint_at->owner;
+  bl = bs->breakpoint_at;
+  b = bl->owner;
 
   switch (b->type)
     {
     case bp_breakpoint:
     case bp_hardware_breakpoint:
-      if (b->loc->address != b->loc->requested_address)
-	breakpoint_adjustment_warning (b->loc->requested_address,
-	                               b->loc->address,
+      if (bl->address != bl->requested_address)
+	breakpoint_adjustment_warning (bl->requested_address,
+	                               bl->address,
 				       b->number, 1);
       annotate_breakpoint (b->number);
       ui_out_text (uiout, "\nBreakpoint ");
@@ -2672,7 +2676,8 @@
 bpstat
 bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint)
 {
-  struct breakpoint *b, *temp;
+  struct breakpoint *b = NULL;
+  struct bp_location *bl;
   /* True if we've hit a breakpoint (as opposed to a watchpoint).  */
   int real_breakpoint = 0;
   /* Root of the chain of bpstat's */
@@ -2681,8 +2686,10 @@
   bpstat bs = root_bs;
   int thread_id = pid_to_thread_id (ptid);
 
-  ALL_BREAKPOINTS_SAFE (b, temp)
+  ALL_BP_LOCATIONS (bl)
   {
+    b = bl->owner;
+    gdb_assert (b);
     if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
       continue;
 
@@ -2697,11 +2704,11 @@
 	&& b->type != bp_catch_catch
 	&& b->type != bp_catch_throw)	/* a non-watchpoint bp */
       {
-	if (b->loc->address != bp_addr) 	/* address doesn't match */
+	if (bl->address != bp_addr) 	/* address doesn't match */
 	  continue;
 	if (overlay_debugging		/* unmapped overlay section */
-	    && section_is_overlay (b->loc->section) 
-	    && !section_is_mapped (b->loc->section))
+	    && section_is_overlay (bl->section) 
+	    && !section_is_mapped (bl->section))
 	  continue;
       }
 
@@ -2719,11 +2726,11 @@
 
     if (b->type == bp_hardware_breakpoint)
       {
-	if (b->loc->address != bp_addr)
+	if (bl->address != bp_addr)
 	  continue;
 	if (overlay_debugging		/* unmapped overlay section */
-	    && section_is_overlay (b->loc->section) 
-	    && !section_is_mapped (b->loc->section))
+	    && section_is_overlay (bl->section) 
+	    && !section_is_mapped (bl->section))
 	  continue;
       }
 
@@ -2774,7 +2781,7 @@
 
     /* Come here if it's a watchpoint, or if the break address matches */
 
-    bs = bpstat_alloc (b->loc, bs);	/* Alloc a bpstat to explain stop */
+    bs = bpstat_alloc (bl, bs);	/* Alloc a bpstat to explain stop */
 
     /* Watchpoints may change this, if not found to have triggered. */
     bs->stop = 1;
@@ -2926,19 +2933,19 @@
       {
 	int value_is_zero = 0;
 
-	if (b->loc->cond)
+	if (bl->cond)
 	  {
 	    /* Need to select the frame, with all that implies
 	       so that the conditions will have the right context.  */
 	    select_frame (get_current_frame ());
 	    value_is_zero
-	      = catch_errors (breakpoint_cond_eval, (b->loc->cond),
+	      = catch_errors (breakpoint_cond_eval, (bl->cond),
 			      "Error in testing breakpoint condition:\n",
 			      RETURN_MASK_ALL);
 	    /* FIXME-someday, should give breakpoint # */
 	    free_all_values ();
 	  }
-	if (b->loc->cond && value_is_zero)
+	if (bl->cond && value_is_zero)
 	  {
 	    bs->stop = 0;
 	    /* Don't consider this a hit.  */
@@ -2985,9 +2992,9 @@
   /* The value of a hardware watchpoint hasn't changed, but the
      intermediate memory locations we are watching may have.  */
   if (bs && !bs->stop &&
-      (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
-       bs->breakpoint_at->owner->type == bp_read_watchpoint ||
-       bs->breakpoint_at->owner->type == bp_access_watchpoint))
+      (b->type == bp_hardware_watchpoint ||
+       b->type == bp_read_watchpoint ||
+       b->type == bp_access_watchpoint))
     {
       remove_breakpoints ();
       insert_breakpoints ();
@@ -3349,10 +3356,54 @@
   *cp_list = bs;
 }
 
+static void print_breakpoint_location (struct breakpoint *b,
+				       struct bp_location *loc,
+				       char *wrap_indent,
+				       struct ui_stream *stb)
+{
+  if (b->source_file)
+    {
+      struct symbol *sym 
+	= find_pc_sect_function (loc->address, loc->section);
+      if (sym)
+	{
+	  ui_out_text (uiout, "in ");
+	  ui_out_field_string (uiout, "func",
+			       SYMBOL_PRINT_NAME (sym));
+	  ui_out_wrap_hint (uiout, wrap_indent);
+	  ui_out_text (uiout, " at ");
+	}
+      ui_out_field_string (uiout, "file", b->source_file);
+      ui_out_text (uiout, ":");
+      
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  struct symtab_and_line sal = find_pc_line (loc->address, 0);
+	  char *fullname = symtab_to_fullname (sal.symtab);
+	  
+	  if (fullname)
+	    ui_out_field_string (uiout, "fullname", fullname);
+	}
+      
+      ui_out_field_int (uiout, "line", b->line_number);
+    }
+  else if (!b->loc)
+    {
+      ui_out_field_string (uiout, "pending", b->addr_string);
+    }
+  else
+    {
+      print_address_symbolic (loc->address, stb->stream, demangle, "");
+      ui_out_field_stream (uiout, "at", stb);
+    }
+}
+
 /* Print B to gdb_stdout. */
 static void
-print_one_breakpoint (struct breakpoint *b,
-		      CORE_ADDR *last_addr)
+print_one_breakpoint_location (struct breakpoint *b,
+			       struct bp_location *loc,
+			       int loc_number,
+			       CORE_ADDR *last_addr)
 {
   struct command_line *l;
   struct symbol *sym;
@@ -3397,30 +3448,80 @@
   struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
   struct cleanup *bkpt_chain;
 
+  int header_of_multiple = 0;
+  int part_of_multiple = (loc != NULL);
+
+  gdb_assert (!loc || loc_number != 0);
+  /* See comment in print_one_breakpoint concerning
+     treatment of breakpoints with single disabled
+     location.  */
+  if (loc == NULL 
+      && (b->loc != NULL 
+	  && (b->loc->next != NULL || !b->loc->enabled)))
+    header_of_multiple = 1;
+  if (loc == NULL)
+    loc = b->loc;
+
   annotate_record ();
   bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
 
   /* 1 */
   annotate_field (0);
-  ui_out_field_int (uiout, "number", b->number);
+  if (part_of_multiple)
+    {
+      char *formatted;
+      asprintf (&formatted, "%d.%d", b->number, loc_number);
+      ui_out_field_string (uiout, "number", formatted);
+      xfree (formatted);
+    }
+  else
+    {
+      ui_out_field_int (uiout, "number", b->number);
+    }
 
   /* 2 */
   annotate_field (1);
-  if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
-      || ((int) b->type != bptypes[(int) b->type].type))
-    internal_error (__FILE__, __LINE__,
-		    _("bptypes table does not describe type #%d."),
-		    (int) b->type);
-  ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+  if (part_of_multiple)
+    ui_out_field_skip (uiout, "type");
+  else 
+    {
+      if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
+	  || ((int) b->type != bptypes[(int) b->type].type))
+	internal_error (__FILE__, __LINE__,
+			_("bptypes table does not describe type #%d."),
+			(int) b->type);
+      ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+    }
 
   /* 3 */
   annotate_field (2);
-  ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+  if (part_of_multiple)
+    ui_out_field_skip (uiout, "disp");
+  else
+    ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+
 
   /* 4 */
   annotate_field (3);
-  ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
-  ui_out_spaces (uiout, 2);
+  if (part_of_multiple)
+    ui_out_field_string (uiout, "enabled", 
+			 loc->shlib_disabled 
+			 ? (loc->enabled ? "y(p)" : "n(p)")
+			 : (loc->enabled ? "y" : "n"));
+  else
+    {
+      int pending = (b->loc == NULL || b->loc->shlib_disabled);
+      /* For header of multiple, there's no point showing pending
+	 state -- it will be apparent from the locations.  */
+      if (header_of_multiple)
+	pending = 0;
+      ui_out_field_fmt (uiout, "enabled", "%c%s", 
+			bpenables[(int) b->enable_state],
+			pending ? "(p)" : "");
+      if (!pending)
+	ui_out_spaces (uiout, 3);
+    }
+
   
   /* 5 and 6 */
   strcpy (wrap_indent, "                           ");
@@ -3433,7 +3534,14 @@
     }
 
   if (b->ops != NULL && b->ops->print_one != NULL)
-    b->ops->print_one (b, last_addr);
+    {
+      /* Although the print_one can possibly print
+	 all locations,  calling it here is not likely
+	 to get any nice result.  So, make sure there's
+	 just one location.  */
+      gdb_assert (b->loc == NULL || b->loc->next == NULL);
+      b->ops->print_one (b, last_addr);
+    }
   else
     switch (b->type)
       {
@@ -3545,51 +3653,22 @@
 	if (addressprint)
 	  {
 	    annotate_field (4);
-	    if (b->pending)
+	    if (b->loc == NULL)
 	      ui_out_field_string (uiout, "addr", "<PENDING>");
+	    else if (header_of_multiple)
+	      ui_out_field_string (uiout, "addr", "<MULTIPLE>");
 	    else
-	      ui_out_field_core_addr (uiout, "addr", b->loc->address);
+	      ui_out_field_core_addr (uiout, "addr", loc->address);
 	  }
 	annotate_field (5);
-	*last_addr = b->loc->address;
-	if (b->source_file)
-	  {
-	    sym = find_pc_sect_function (b->loc->address, b->loc->section);
-	    if (sym)
-	      {
-		ui_out_text (uiout, "in ");
-		ui_out_field_string (uiout, "func",
-				     SYMBOL_PRINT_NAME (sym));
-		ui_out_wrap_hint (uiout, wrap_indent);
-		ui_out_text (uiout, " at ");
-	      }
-	    ui_out_field_string (uiout, "file", b->source_file);
-	    ui_out_text (uiout, ":");
-
-            if (ui_out_is_mi_like_p (uiout))
-              {
-                struct symtab_and_line sal = find_pc_line (b->loc->address, 0);
-                char *fullname = symtab_to_fullname (sal.symtab);
-
-                if (fullname)
-                  ui_out_field_string (uiout, "fullname", fullname);
-              }
-
-	    ui_out_field_int (uiout, "line", b->line_number);
-	  }
-	else if (b->pending)
-	  {
-	    ui_out_field_string (uiout, "pending", b->addr_string);
-	  }
-	else
-	  {
-	    print_address_symbolic (b->loc->address, stb->stream, demangle, "");
-	    ui_out_field_stream (uiout, "at", stb);
-	  }
+	if (!header_of_multiple)
+	  print_breakpoint_location (b, loc, wrap_indent, stb);
+	if (b->loc)
+	  *last_addr = b->loc->address;
 	break;
       }
 
-  if (b->thread != -1)
+  if (!part_of_multiple && b->thread != -1)
     {
       /* FIXME: This seems to be redundant and lost here; see the
 	 "stop only in" line a little further down. */
@@ -3599,7 +3678,7 @@
   
   ui_out_text (uiout, "\n");
   
-  if (frame_id_p (b->frame_id))
+  if (part_of_multiple && frame_id_p (b->frame_id))
     {
       annotate_field (6);
       ui_out_text (uiout, "\tstop only in stack frame at ");
@@ -3609,27 +3688,18 @@
       ui_out_text (uiout, "\n");
     }
   
-  if (b->loc->cond && !ada_exception_catchpoint_p (b))
+  if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
     {
       /* We do not print the condition for Ada exception catchpoints
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
       ui_out_text (uiout, "\tstop only if ");
-      print_expression (b->loc->cond, stb->stream);
-      ui_out_field_stream (uiout, "cond", stb);
-      ui_out_text (uiout, "\n");
-    }
-
-  if (b->pending && b->cond_string)
-    {
-      annotate_field (7);
-      ui_out_text (uiout, "\tstop only if ");
       ui_out_field_string (uiout, "cond", b->cond_string);
       ui_out_text (uiout, "\n");
     }
 
-  if (b->thread != -1)
+  if (!part_of_multiple && b->thread != -1)
     {
       /* FIXME should make an annotation for this */
       ui_out_text (uiout, "\tstop only in thread ");
@@ -3637,7 +3707,7 @@
       ui_out_text (uiout, "\n");
     }
   
-  if (show_breakpoint_hit_counts && b->hit_count)
+  if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
     {
       /* FIXME should make an annotation for this */
       if (ep_is_catchpoint (b))
@@ -3655,10 +3725,10 @@
   /* Output the count also if it is zero, but only if this is
      mi. FIXME: Should have a better test for this. */
   if (ui_out_is_mi_like_p (uiout))
-    if (show_breakpoint_hit_counts && b->hit_count == 0)
+    if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
       ui_out_field_int (uiout, "times", b->hit_count);
 
-  if (b->ignore_count)
+  if (!part_of_multiple && b->ignore_count)
     {
       annotate_field (8);
       ui_out_text (uiout, "\tignore next ");
@@ -3666,7 +3736,7 @@
       ui_out_text (uiout, " hits\n");
     }
   
-  if ((l = b->commands))
+  if (!part_of_multiple && (l = b->commands))
     {
       struct cleanup *script_chain;
 
@@ -3679,6 +3749,35 @@
   do_cleanups (old_chain);
 }
 
+static void
+print_one_breakpoint (struct breakpoint *b,
+		      CORE_ADDR *last_addr)
+{
+  print_one_breakpoint_location (b, NULL, 0, last_addr);
+
+  /* If this breakpoint has custom print function,
+     it's already printed.  Otherwise, print individual
+     locations, if any.  */
+  if (b->ops == NULL || b->ops->print_one == NULL)
+    {
+      /* If breakpoint has a single location that is
+	 disabled, we print it as if it had
+	 several locations, since otherwise it's hard to
+	 represent "breakpoint enabled, location disabled"
+	 situation.  */	 
+      if (b->loc 
+	  && (b->loc->next || !b->loc->enabled)
+	  && !ui_out_is_mi_like_p (uiout))
+	{
+	  struct bp_location *loc;
+	  int n = 1;
+	  for (loc = b->loc; loc; loc = loc->next, ++n)
+	    print_one_breakpoint_location (b, loc, n, last_addr);
+	}
+    }
+}
+
+
 struct captured_breakpoint_query_args
   {
     int bnum;
@@ -3771,7 +3870,7 @@
     annotate_breakpoints_headers ();
   if (nr_printable_breakpoints > 0)
     annotate_field (0);
-  ui_out_table_header (uiout, 3, ui_left, "number", "Num");		/* 1 */
+  ui_out_table_header (uiout, 7, ui_left, "number", "Num");		/* 1 */
   if (nr_printable_breakpoints > 0)
     annotate_field (1);
   ui_out_table_header (uiout, 14, ui_left, "type", "Type");		/* 2 */
@@ -3780,7 +3879,7 @@
   ui_out_table_header (uiout, 4, ui_left, "disp", "Disp");		/* 3 */
   if (nr_printable_breakpoints > 0)
     annotate_field (3);
-  ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");	/* 4 */
+  ui_out_table_header (uiout, 4, ui_left, "enabled", "Enb");	/* 4 */
   if (addressprint)
 	{
 	  if (nr_printable_breakpoints > 0)
@@ -3852,6 +3951,19 @@
   breakpoint_1 (bnum, 1);
 }
 
+static int
+breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
+{
+  struct bp_location *bl = b->loc;
+  for (; bl; bl = bl->next)
+    {
+      if (bl->address == pc
+	  && (!overlay_debugging || bl->section == section))
+	return 1;	  
+    }
+  return 0;
+}
+
 /* Print a message describing any breakpoints set at PC.  */
 
 static void
@@ -3861,9 +3973,7 @@
   struct breakpoint *b;
 
   ALL_BREAKPOINTS (b)
-    if (b->loc->address == pc)	/* address match / overlay match */
-      if (!b->pending && (!overlay_debugging || b->loc->section == section))
-	others++;
+    others += breakpoint_has_pc (b, pc, section);
   if (others > 0)
     {
       if (others == 1)
@@ -3871,26 +3981,24 @@
       else /* if (others == ???) */
 	printf_filtered (_("Note: breakpoints "));
       ALL_BREAKPOINTS (b)
-	if (b->loc->address == pc)	/* address match / overlay match */
-	  if (!b->pending && (!overlay_debugging || b->loc->section == section))
-	    {
-	      others--;
-	      printf_filtered ("%d", b->number);
-	      if (b->thread == -1 && thread != -1)
-		printf_filtered (" (all threads)");
-	      else if (b->thread != -1)
-		printf_filtered (" (thread %d)", b->thread);
-	      printf_filtered ("%s%s ",
-			       ((b->enable_state == bp_disabled || 
-				 b->enable_state == bp_shlib_disabled || 
-				 b->enable_state == bp_call_disabled) 
-				? " (disabled)"
-				: b->enable_state == bp_permanent 
-				? " (permanent)"
-				: ""),
-			       (others > 1) ? "," 
-			       : ((others == 1) ? " and" : ""));
-	    }
+	if (breakpoint_has_pc (b, pc, section))
+	  {
+	    others--;
+	    printf_filtered ("%d", b->number);
+	    if (b->thread == -1 && thread != -1)
+	      printf_filtered (" (all threads)");
+	    else if (b->thread != -1)
+	      printf_filtered (" (thread %d)", b->thread);
+	    printf_filtered ("%s%s ",
+			     ((b->enable_state == bp_disabled || 
+			       b->enable_state == bp_call_disabled) 
+			      ? " (disabled)"
+			      : b->enable_state == bp_permanent 
+			      ? " (permanent)"
+			      : ""),
+			     (others > 1) ? "," 
+			     : ((others == 1) ? " and" : ""));
+	  }
       printf_filtered (_("also set at pc "));
       deprecated_print_address_numeric (pc, 1, gdb_stdout);
       printf_filtered (".\n");
@@ -3951,22 +4059,17 @@
    that one the official one, and the rest as duplicates.  */
 
 static void
-check_duplicates (struct breakpoint *bpt)
+check_duplicates_for (CORE_ADDR address, asection *section)
 {
   struct bp_location *b;
   int count = 0;
   struct bp_location *perm_bp = 0;
-  CORE_ADDR address = bpt->loc->address;
-  asection *section = bpt->loc->section;
-
-  if (! breakpoint_address_is_meaningful (bpt))
-    return;
 
   ALL_BP_LOCATIONS (b)
     if (b->owner->enable_state != bp_disabled
-	&& b->owner->enable_state != bp_shlib_disabled
-	&& !b->owner->pending
 	&& b->owner->enable_state != bp_call_disabled
+	&& b->enabled
+	&& !b->shlib_disabled
 	&& b->address == address	/* address / overlay match */
 	&& (!overlay_debugging || b->section == section)
 	&& breakpoint_address_is_meaningful (b->owner))
@@ -3999,9 +4102,8 @@
 	if (b != perm_bp)
 	  {
 	    if (b->owner->enable_state != bp_disabled
-		&& b->owner->enable_state != bp_shlib_disabled
-		&& !b->owner->pending
 		&& b->owner->enable_state != bp_call_disabled
+		&& b->enabled && !b->shlib_disabled		
 		&& b->address == address	/* address / overlay match */
 		&& (!overlay_debugging || b->section == section)
 		&& breakpoint_address_is_meaningful (b->owner))
@@ -4018,6 +4120,18 @@
 }
 
 static void
+check_duplicates (struct breakpoint *bpt)
+{
+  struct bp_location *bl = bpt->loc;
+
+  if (! breakpoint_address_is_meaningful (bpt))
+    return;
+
+  for (; bl; bl = bl->next)
+    check_duplicates_for (bl->address, bl->section);    
+}
+
+static void
 breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
                                int bnum, int have_bnum)
 {
@@ -4089,6 +4203,8 @@
 
   loc->owner = bpt;
   loc->cond = NULL;
+  loc->shlib_disabled = 0;
+  loc->enabled = 1;
 
   switch (bp_type)
     {
@@ -4134,9 +4250,9 @@
     bp_location_chain = loc;
   else
     {
-      while (loc_p->next)
-	loc_p = loc_p->next;
-      loc_p->next = loc;
+      while (loc_p->global_next)
+	loc_p = loc_p->global_next;
+      loc_p->global_next = loc;
     }
 
   return loc;
@@ -4149,53 +4265,21 @@
   xfree (loc);
 }
 
-/* set_raw_breakpoint() is a low level routine for allocating and
-   partially initializing a breakpoint of type BPTYPE.  The newly
-   created breakpoint's address, section, source file name, and line
-   number are provided by SAL.  The newly created and partially
-   initialized breakpoint is added to the breakpoint chain and
-   is also returned as the value of this function.
-
-   It is expected that the caller will complete the initialization of
-   the newly created breakpoint struct as well as output any status
-   information regarding the creation of a new breakpoint.  In
-   particular, set_raw_breakpoint() does NOT set the breakpoint
-   number!  Care should be taken to not allow an error() to occur
-   prior to completing the initialization of the breakpoint.  If this
-   should happen, a bogus breakpoint will be left on the chain.  */
+/* Helper to set_raw_breakpoint below.  Creates a breakpoint
+   that has type BPTYPE and has no locations as yet.  */
 
 struct breakpoint *
-set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+set_raw_breakpoint_without_location (enum bptype bptype)
 {
   struct breakpoint *b, *b1;
-  CORE_ADDR adjusted_address;
 
   b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
   memset (b, 0, sizeof (*b));
 
-  /* Adjust the breakpoint's address prior to allocating a location.
-     Once we call allocate_bp_location(), that mostly uninitialized
-     location will be placed on the location chain.  Adjustment of the
-     breakpoint may cause read_memory_nobpt() to be called and we do
-     not want its scan of the location chain to find a breakpoint and
-     location that's only been partially initialized.  */
-  adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
-
-  b->loc = allocate_bp_location (b, bptype);
-  b->loc->requested_address = sal.pc;
-  b->loc->address = adjusted_address;
-
-  if (sal.symtab == NULL)
-    b->source_file = NULL;
-  else
-    b->source_file = savestring (sal.symtab->filename,
-				 strlen (sal.symtab->filename));
-  b->loc->section = sal.section;
   b->type = bptype;
   b->language = current_language->la_language;
   b->input_radix = input_radix;
   b->thread = -1;
-  b->line_number = sal.line;
   b->enable_state = bp_enabled;
   b->next = 0;
   b->silent = 0;
@@ -4207,7 +4291,7 @@
   b->forked_inferior_pid = 0;
   b->exec_pathname = NULL;
   b->ops = NULL;
-  b->pending = 0;
+  b->condition_not_parsed = 0;
 
   /* Add this breakpoint to the end of the chain
      so that a list of breakpoints will come out in order
@@ -4222,6 +4306,65 @@
 	b1 = b1->next;
       b1->next = b;
     }
+  return b;
+}
+
+/* Initialize loc->function_name.  */
+static void
+set_breakpoint_location_function (struct bp_location *loc)
+{
+  if (loc->owner->type == bp_breakpoint
+      || loc->owner->type == bp_hardware_breakpoint)
+    {
+      find_pc_partial_function (loc->address, &(loc->function_name), 
+				NULL, NULL);
+      if (loc->function_name)
+	loc->function_name = xstrdup (loc->function_name);
+    }
+}
+
+/* set_raw_breakpoint is a low level routine for allocating and
+   partially initializing a breakpoint of type BPTYPE.  The newly
+   created breakpoint's address, section, source file name, and line
+   number are provided by SAL.  The newly created and partially
+   initialized breakpoint is added to the breakpoint chain and
+   is also returned as the value of this function.
+
+   It is expected that the caller will complete the initialization of
+   the newly created breakpoint struct as well as output any status
+   information regarding the creation of a new breakpoint.  In
+   particular, set_raw_breakpoint does NOT set the breakpoint
+   number!  Care should be taken to not allow an error to occur
+   prior to completing the initialization of the breakpoint.  If this
+   should happen, a bogus breakpoint will be left on the chain.  */
+
+struct breakpoint *
+set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+{
+  struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
+  CORE_ADDR adjusted_address;
+
+  /* Adjust the breakpoint's address prior to allocating a location.
+     Once we call allocate_bp_location(), that mostly uninitialized
+     location will be placed on the location chain.  Adjustment of the
+     breakpoint may cause read_memory_nobpt() to be called and we do
+     not want its scan of the location chain to find a breakpoint and
+     location that's only been partially initialized.  */
+  adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+
+  b->loc = allocate_bp_location (b, bptype);
+  b->loc->requested_address = sal.pc;
+  b->loc->address = adjusted_address;
+
+  if (sal.symtab == NULL)
+    b->source_file = NULL;
+  else
+    b->source_file = savestring (sal.symtab->filename,
+				 strlen (sal.symtab->filename));
+  b->loc->section = sal.section;
+  b->line_number = sal.line;
+
+  set_breakpoint_location_function (b->loc);
 
   check_duplicates (b);
   breakpoints_changed ();
@@ -4235,10 +4378,16 @@
 void
 make_breakpoint_permanent (struct breakpoint *b)
 {
+  struct bp_location *bl;
   b->enable_state = bp_permanent;
 
-  /* By definition, permanent breakpoints are already present in the code.  */
-  b->loc->inserted = 1;
+  /* By definition, permanent breakpoints are already present in the code. 
+     Mark all locations as inserted.  For now, make_breakpoint_permanent
+     is called in just one place, so it's hard to say if it's reasonable
+     to have permanent breakpoint with multiple locations or not,
+     but it's easy to implmement.  */
+  for (bl = b->loc; bl; bl = bl->next)
+    bl->inserted = 1;
 }
 
 static struct breakpoint *
@@ -4431,20 +4580,28 @@
 void
 disable_breakpoints_in_shlibs (void)
 {
-  struct breakpoint *b;
+  struct bp_location *loc;
   int disabled_shlib_breaks = 0;
 
-  ALL_BREAKPOINTS (b)
+  ALL_BP_LOCATIONS (loc)
   {
+    struct breakpoint *b = loc->owner;
+    /* We apply the check to all breakpoints, including disabled
+       for those with loc->duplicate set.  This is so that when breakpoint
+       becomes enabled, or the duplicate is removed, gdb will try to insert
+       all breakpoints.  If we don't set shlib_disabled here, we'll try
+       to insert those breakpoints and fail.  */
     if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
-	&& breakpoint_enabled (b) && !b->loc->duplicate
+	&& !loc->shlib_disabled
 #ifdef PC_SOLIB
-	&& PC_SOLIB (b->loc->address)
+	&& PC_SOLIB (loc->address)
 #else
-	&& solib_address (b->loc->address)
+	&& solib_address (loc->address)
 #endif
 	)
-	b->enable_state = bp_shlib_disabled;
+      {
+	loc->shlib_disabled = 1;
+      }
   }
 }
 
@@ -4454,27 +4611,28 @@
 void
 disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 {
-  struct breakpoint *b;
+  struct bp_location *loc;
   int disabled_shlib_breaks = 0;
 
-  ALL_BREAKPOINTS (b)
+  ALL_BP_LOCATIONS (loc)
   {
-    if ((b->loc->loc_type == bp_loc_hardware_breakpoint
-	|| b->loc->loc_type == bp_loc_software_breakpoint)
-	&& breakpoint_enabled (b) && !b->loc->duplicate)
+    struct breakpoint *b = loc->owner;
+    if ((loc->loc_type == bp_loc_hardware_breakpoint
+	 || loc->loc_type == bp_loc_software_breakpoint)
+	&& !loc->shlib_disabled)
       {
 #ifdef PC_SOLIB
-	char *so_name = PC_SOLIB (b->loc->address);
+	char *so_name = PC_SOLIB (loc->address);
 #else
-	char *so_name = solib_address (b->loc->address);
+	char *so_name = solib_address (loc->address);
 #endif
 	if (so_name && !strcmp (so_name, solib->so_name))
           {
-	    b->enable_state = bp_shlib_disabled;
+	    loc->shlib_disabled = 1;
 	    /* At this point, we cannot rely on remove_breakpoint
 	       succeeding so we must mark the breakpoint as not inserted
 	       to prevent future errors occurring in remove_breakpoints.  */
-	    b->loc->inserted = 0;
+	    loc->inserted = 0;
 	    if (!disabled_shlib_breaks)
 	      {
 		target_terminal_ours_for_output ();
@@ -4894,7 +5052,7 @@
     {
       /* i18n: cagney/2005-02-11: Below needs to be merged into a
 	 single string.  */
-      if (b->pending)
+      if (b->loc == NULL)
 	{
 	  printf_filtered (_(" (%s) pending."), b->addr_string);
 	}
@@ -4908,6 +5066,16 @@
 	  if (b->source_file)
 	    printf_filtered (": file %s, line %d.",
 			     b->source_file, b->line_number);
+	  
+	  if (b->loc->next)
+	    {
+	      struct bp_location *loc = b->loc;
+	      int n = 0;
+	      for (; loc; loc = loc->next)
+		++n;
+	      printf_filtered (" (%d locations)", n);		
+	    }
+
 	}
     }
   do_cleanups (old_chain);
@@ -4917,6 +5085,24 @@
 }
 
 
+static struct bp_location *
+add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+			    const struct symtab_and_line *sal)
+{
+  struct bp_location *loc, **tmp;
+
+  loc = allocate_bp_location (b, bptype);
+  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
+    ;
+  *tmp = loc;
+  loc->requested_address = sal->pc;
+  loc->address = adjust_breakpoint_address (loc->requested_address,
+					    bptype);
+  loc->section = sal->section;
+
+  set_breakpoint_location_function (loc);
+  return loc;
+}
 
 /* Create a breakpoint with SAL as location.  Use ADDR_STRING
    as textual description of the location, and COND_STRING
@@ -4926,13 +5112,14 @@
    create_breakpoints function.  */
 
 static void
-create_breakpoint (struct symtab_and_line sal, char *addr_string,
+create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
 		   char *cond_string,
 		   enum bptype type, enum bpdisp disposition,
 		   int thread, int ignore_count, int from_tty,
 		   struct breakpoint *pending_bp)
 {
-  struct breakpoint *b;
+  struct breakpoint *b = NULL;
+  int i;
 
   if (type == bp_hardware_breakpoint)
     {
@@ -4946,50 +5133,46 @@
 	error (_("Hardware breakpoints used exceeds limit."));
     }
 
-  if (from_tty)
-    describe_other_breakpoints (sal.pc, sal.section, thread);
-  
-  b = set_raw_breakpoint (sal, type);
-  set_breakpoint_count (breakpoint_count + 1);
-  b->number = breakpoint_count;
-  b->thread = thread;
+  for (i = 0; i < sals.nelts; ++i)
+    {
+      struct symtab_and_line sal = sals.sals[i];
+      struct bp_location *loc;
+
+      if (from_tty)
+	describe_other_breakpoints (sal.pc, sal.section, thread);
+
+      if (i == 0)
+	{
+	  b = set_raw_breakpoint (sal, type);
+	  set_breakpoint_count (breakpoint_count + 1);
+	  b->number = breakpoint_count;
+	  b->thread = thread;
   
-  b->cond_string = cond_string;
-  b->ignore_count = ignore_count;
-  b->enable_state = bp_enabled;
-  b->disposition = disposition;
-  /* If resolving a pending breakpoint, a check must be made to see if
-     the user has specified a new condition or commands for the 
-     breakpoint.  A new condition will override any condition that was 
-     initially specified with the initial breakpoint command.  */
-  if (pending_bp)
-    {
-      if (pending_bp->cond_string)
-	b->cond_string = savestring (pending_bp->cond_string, 
-				     strlen (pending_bp->cond_string));
-      
-      /* If there are commands associated with the breakpoint, they should 
-	 be copied too.  */
-      if (pending_bp->commands)
-	b->commands = copy_command_lines (pending_bp->commands);
-	    
-      /* We have to copy over the ignore_count and thread as well.  */
-      b->ignore_count = pending_bp->ignore_count;
-      b->thread = pending_bp->thread;
-    }
+	  b->cond_string = cond_string;
+	  b->ignore_count = ignore_count;
+	  b->enable_state = bp_enabled;
+	  b->disposition = disposition;
 
-  if (b->cond_string)
-    {
-      char *arg = b->cond_string;
-      b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
-      if (*arg)
+	  loc = b->loc;
+	}
+      else
 	{
-	  if (pending_bp)
-	    error (_("Junk at end of pending breakpoint condition expression"));
-	  else
-	    error (_("Garbage %s follows condition"), arg);
+	  loc = add_location_to_breakpoint (b, type, &sal);
 	}
-    }	    
+
+      if (b->cond_string)
+	{
+	  char *arg = b->cond_string;
+	  b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+	  if (*arg)
+	    {
+	      if (pending_bp)
+		error (_("Junk at end of pending breakpoint condition expression"));
+	      else
+		error (_("Garbage %s follows condition"), arg);
+	    }
+	}
+    }   
 
   if (addr_string)
     b->addr_string = addr_string;
@@ -5031,7 +5214,11 @@
   int i;
   for (i = 0; i < sals.nelts; ++i)
     {
-      create_breakpoint (sals.sals[i], addr_string[i],
+      struct symtabs_and_lines sals2;
+      sals2.sals = sals.sals + i;
+      sals2.nelts = 1;
+
+      create_breakpoint (sals2, addr_string[i],
 			 cond_string, type, disposition,
 			 thread, ignore_count, from_tty,
 			 pending_bp);
@@ -5360,19 +5547,19 @@
 
       make_cleanup (xfree, copy_arg);
 
-      b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint 
-		              : bp_breakpoint);
+      b = set_raw_breakpoint_without_location (hardwareflag 
+					       ? bp_hardware_breakpoint 
+					       : bp_breakpoint);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
-      b->loc->cond = NULL;
       b->thread = thread;
       b->addr_string = addr_string[0];
       b->cond_string = cond_string;
       b->ignore_count = ignore_count;
-      b->pending = 1;
       b->disposition = tempflag ? disp_del : disp_donttouch;
       b->from_tty = from_tty;
       b->flag = flag;
+      b->condition_not_parsed = 1;
       mention (b);
     }
   
@@ -5411,7 +5598,7 @@
   struct cleanup *breakpoint_chain = NULL;
   int i;
   char **addr_string;
-  char *cond_string;
+  char *cond_string = 0;
 
   char *address_end;
 
@@ -5440,10 +5627,6 @@
   cond = xcalloc (sals.nelts, sizeof (struct expression *));
   make_cleanup (xfree, cond);
 
-  /* Allocate space for all the cond strings. */
-  cond_string = xcalloc (sals.nelts, sizeof (char **));
-  make_cleanup (xfree, cond_string);
-
   /* ----------------------------- SNIP -----------------------------
      Anything added to the cleanup chain beyond this point is assumed
      to be part of a breakpoint.  If the breakpoint create goes
@@ -6733,23 +6916,35 @@
 	 breakpoint chain, and add them to the 'found' chain.  */
       ALL_BREAKPOINTS_SAFE (b, tmp)
 	{
+	  int match = 0;
 	  /* Are we going to delete b? */
 	  if (b->type != bp_none
 	      && b->type != bp_watchpoint
 	      && b->type != bp_hardware_watchpoint
 	      && b->type != bp_read_watchpoint
-	      && b->type != bp_access_watchpoint
-	      /* Not if b is a watchpoint of any sort... */
-	      && (((sal.pc && (b->loc->address == sal.pc)) 
-		   && (!section_is_overlay (b->loc->section)
-		       || b->loc->section == sal.section))
-		  /* Yes, if sal.pc matches b (modulo overlays).  */
-		  || ((default_match || (0 == sal.pc))
-		      && b->source_file != NULL
-		      && sal.symtab != NULL
-		      && strcmp (b->source_file, sal.symtab->filename) == 0
-		      && b->line_number == sal.line)))
-	    /* Yes, if sal source file and line matches b.  */
+	      && b->type != bp_access_watchpoint)
+	    {
+	      struct bp_location *loc = b->loc;
+	      for (; loc; loc = loc->next)
+		{
+		  int pc_match = sal.pc 
+		    && (loc->address == sal.pc)
+		    && (!section_is_overlay (loc->section)
+			|| loc->section == sal.section);
+		  int line_match = ((default_match || (0 == sal.pc))
+				    && b->source_file != NULL
+				    && sal.symtab != NULL
+				    && strcmp (b->source_file, sal.symtab->filename) == 0
+				    && b->line_number == sal.line);
+		  if (pc_match || line_match)
+		    {
+		      match = 1;
+		      break;
+		    }
+		}
+	    }
+
+	  if (match)
 	    {
 	      /* Remove it from breakpoint_chain...  */
 	      if (b == breakpoint_chain)
@@ -6824,6 +7019,35 @@
   }
 }
 
+/* Remove locations of breakpoint BPT from
+   the global list of breakpoint locations.  */
+
+static void
+unlink_locations_from_global_list (struct breakpoint *bpt)
+{
+  /* This code assumes that the locations
+     of a breakpoint are found in the global list
+     in the same order,  but not necessary adjacent.  */
+  struct bp_location **tmp = &bp_location_chain;
+  struct bp_location *here = bpt->loc;
+
+  if (here == NULL)
+    return;
+
+  for (; *tmp && here;)
+    {
+      if (*tmp == here)
+	{
+	  *tmp = here->global_next;
+	  here = here->next;
+	}
+      else
+	{
+	  tmp = &((*tmp)->global_next);
+	}
+    }
+}
+
 /* Delete a breakpoint and clean up all traces of it in the data
    structures. */
 
@@ -6856,17 +7080,23 @@
     deprecated_delete_breakpoint_hook (bpt);
   breakpoint_delete_event (bpt->number);
 
-  if (bpt->loc->inserted)
-    remove_breakpoint (bpt->loc, mark_inserted);
+  for (loc = bpt->loc; loc; loc = loc->next)
+    {
+      if (loc->inserted)
+	remove_breakpoint (loc, mark_inserted);
+
+      free_valchain (loc);
 
-  free_valchain (bpt->loc);
+      if (loc->cond)
+	xfree (loc->cond);
+
+      if (loc->function_name)
+	xfree (loc->function_name);
+    }
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;
 
-  if (bp_location_chain == bpt->loc)
-    bp_location_chain = bpt->loc->next;
-
   /* If we have callback-style exception catchpoints, don't go through
      the adjustments to the C++ runtime library etc. if the inferior
      isn't actually running.  target_enable_exception_callback for a
@@ -6896,82 +7126,83 @@
       break;
     }
 
-  ALL_BP_LOCATIONS (loc)
-    if (loc->next == bpt->loc)
-      {
-	loc->next = bpt->loc->next;
-	break;
-      }
+  unlink_locations_from_global_list (bpt);
 
   check_duplicates (bpt);
-  /* If this breakpoint was inserted, and there is another breakpoint
-     at the same address, we need to insert the other breakpoint.  */
-  if (bpt->loc->inserted
-      && bpt->type != bp_hardware_watchpoint
+
+  if (bpt->type != bp_hardware_watchpoint
       && bpt->type != bp_read_watchpoint
       && bpt->type != bp_access_watchpoint
       && bpt->type != bp_catch_fork
       && bpt->type != bp_catch_vfork
       && bpt->type != bp_catch_exec)
-    {
-      ALL_BREAKPOINTS (b)
-	if (b->loc->address == bpt->loc->address
-	    && b->loc->section == bpt->loc->section
-	    && !b->loc->duplicate
-	    && b->enable_state != bp_disabled
-	    && b->enable_state != bp_shlib_disabled
-	    && !b->pending
-	    && b->enable_state != bp_call_disabled)
-	{
-	  int val;
-
-	  /* We should never reach this point if there is a permanent
-	     breakpoint at the same address as the one being deleted.
-	     If there is a permanent breakpoint somewhere, it should
-	     always be the only one inserted.  */
-	  if (b->enable_state == bp_permanent)
-	    internal_error (__FILE__, __LINE__,
-			    _("another breakpoint was inserted on top of "
-			    "a permanent breakpoint"));
-
-	  memset (&b->loc->target_info, 0, sizeof (b->loc->target_info));
-	  b->loc->target_info.placed_address = b->loc->address;
-	  if (b->type == bp_hardware_breakpoint)
-	    val = target_insert_hw_breakpoint (&b->loc->target_info);
-	  else
-	    val = target_insert_breakpoint (&b->loc->target_info);
+    for (loc = bpt->loc; loc; loc = loc->next)
+      {
+	/* If this breakpoint location was inserted, and there is 
+	   another breakpoint at the same address, we need to 
+	   insert the other breakpoint.  */
+	if (loc->inserted)
+	  {
+	    struct bp_location *loc2;
+	    ALL_BP_LOCATIONS (loc2)
+	      if (loc2->address == loc->address
+		  && loc2->section == loc->section
+		  && !loc->duplicate
+		  && loc2->owner->enable_state != bp_disabled
+		  && loc2->enabled 
+		  && !loc2->shlib_disabled
+		  && loc2->owner->enable_state != bp_call_disabled)
+		{
+		  int val;
 
-	  /* If there was an error in the insert, print a message, then stop execution.  */
-	  if (val != 0)
-	    {
-	      struct ui_file *tmp_error_stream = mem_fileopen ();
-	      make_cleanup_ui_file_delete (tmp_error_stream);
-	     
+		  /* We should never reach this point if there is a permanent
+		     breakpoint at the same address as the one being deleted.
+		     If there is a permanent breakpoint somewhere, it should
+		     always be the only one inserted.  */
+		  if (loc2->owner->enable_state == bp_permanent)
+		    internal_error (__FILE__, __LINE__,
+				    _("another breakpoint was inserted on top of "
+				      "a permanent breakpoint"));
+
+		  memset (&loc2->target_info, 0, sizeof (loc2->target_info));
+		  loc2->target_info.placed_address = loc2->address;
+		  if (b->type == bp_hardware_breakpoint)
+		    val = target_insert_hw_breakpoint (&loc2->target_info);
+		  else
+		    val = target_insert_breakpoint (&loc2->target_info);
 
-	      if (b->type == bp_hardware_breakpoint)
-		{
-		  fprintf_unfiltered (tmp_error_stream, 
-					"Cannot insert hardware breakpoint %d.\n"
-				      "You may have requested too many hardware breakpoints.\n",
-					b->number);
-		  }
-		else
-		  {
-		    fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
-		    fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
-		    deprecated_print_address_numeric (b->loc->address, 1, tmp_error_stream);
-		    fprintf_filtered (tmp_error_stream, ": %s.\n",
-				      safe_strerror (val));
-		  }
-	      
-	      fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
-	      target_terminal_ours_for_output ();
-	      error_stream(tmp_error_stream); 
-	    }
-	  else
-	    b->loc->inserted = 1;
-	}
-    }
+		  /* If there was an error in the insert, print a message, then stop execution.  */
+		  if (val != 0)
+		    {
+		      struct ui_file *tmp_error_stream = mem_fileopen ();
+		      make_cleanup_ui_file_delete (tmp_error_stream);
+		      
+		      
+		      if (b->type == bp_hardware_breakpoint)
+			{
+			  fprintf_unfiltered (tmp_error_stream, 
+					      "Cannot insert hardware breakpoint %d.\n"
+					      "You may have requested too many hardware breakpoints.\n",
+					      b->number);
+			}
+		      else
+			{
+			  fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
+			  fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
+			  deprecated_print_address_numeric (loc2->address, 1, tmp_error_stream);
+			  fprintf_filtered (tmp_error_stream, ": %s.\n",
+					    safe_strerror (val));
+			}
+		      
+		      fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
+		      target_terminal_ours_for_output ();
+		      error_stream(tmp_error_stream); 
+		    }
+		  else
+		    loc2->inserted = 1;
+		}
+	  }
+      }
 
   free_command_lines (&bpt->commands);
   if (bpt->cond_string != NULL)
@@ -7013,9 +7244,12 @@
      bp, we mark it as deleted before freeing its storage. */
   bpt->type = bp_none;
 
-  if (bpt->loc->cond)
-    xfree (bpt->loc->cond);
-  xfree (bpt->loc);
+  for (loc = bpt->loc; loc;)
+    {
+      struct bp_location *loc_next = loc->next;
+      xfree (loc);
+      loc = loc_next;
+    }
   xfree (bpt);
 }
 
@@ -7083,94 +7317,95 @@
     map_breakpoint_numbers (arg, delete_breakpoint);
 }
 
-static void
-unlink_locations_from_global_list (struct breakpoint *bpt)
-  /* Remove locations of this breakpoint from the list of
-     all breakpoint locations.  */
+static int
+all_locations_are_pending (struct bp_location *loc)
 {
-  struct bp_location **tmp = &bp_location_chain;
-  struct bp_location *here = bpt->loc;
-
-  if (here == NULL)
-    return;
-
-  for (; *tmp && *tmp != here; tmp = &((*tmp)->next));
-  gdb_assert (*tmp);
-       
-  *tmp = here->next;	
+  for (; loc; loc = loc->next)
+    if (!loc->shlib_disabled)
+      return 0;
+  return 1;
 }
 
-
 static void
-update_breakpoint_location (struct breakpoint *b,
-			    struct symtabs_and_lines sals)
+update_breakpoint_locations (struct breakpoint *b,
+			     struct symtabs_and_lines sals)
 {
   int i;
   char *s;
-  /* FIXME: memleak.  */
-  struct bp_location *existing = b->loc;
-  struct bp_location *loc;
-  struct symtab_and_line sal;
-  
-  if (b->enable_state == bp_shlib_disabled && sals.nelts == 0)
+  struct bp_location *existing_locations = b->loc;
+
+  /* If there's no new locations, and all existing locations
+     are pending, don't do anything.  This optimizes
+     the common case where all locations are in the same
+     shared library, that was unloaded. We'd like to
+     retain the location, so that when the library
+     is loaded again, we don't loose the enabled/disabled
+     status of the individual locations.  */
+  if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
     return;
 
   unlink_locations_from_global_list (b);
   b->loc = NULL;
 
-  gdb_assert (sals.nelts == 0 || sals.nelts == 1);
-  if (sals.nelts == 0)
-    return;
-  sal = sals.sals[0];
-
-  loc = allocate_bp_location (b, b->type);
-  loc->requested_address = sal.pc;
-  loc->address = adjust_breakpoint_address (loc->requested_address,
-					    b->type);
-  loc->section = sal.section;
-  b->loc = loc;
-
-  /* Reparse conditions, they might contain references to the
-     old symtab.  */
-  if (b->cond_string != NULL)
+  for (i = 0; i < sals.nelts; ++i)
     {
-      struct gdb_exception e;
-      
-      s = b->cond_string;
-      TRY_CATCH (e, RETURN_MASK_ERROR)
-	{
-	  loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc), 
-				   0);
-	}
-      if (e.reason < 0)
-	{
-	  warning (_("failed to reevaluate condition for breakpoint %d: %s"), 
-		   b->number, e.message);
-	  b->enable_state = bp_disabled;
-	}
-    }
+      struct bp_location *new_loc = 
+	add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
 
-  if (b->source_file != NULL)
-    xfree (b->source_file);
-  if (sal.symtab == NULL)
-    b->source_file = NULL;
-  else
-    b->source_file =
-      savestring (sal.symtab->filename,
-		  strlen (sal.symtab->filename));
+      /* Reparse conditions, they might contain references to the
+	 old symtab.  */
+      if (b->cond_string != NULL)
+	{
+	  struct gdb_exception e;
 
-  if (b->line_number == 0)
-    b->line_number = sal.line;
+	  s = b->cond_string;
+	  TRY_CATCH (e, RETURN_MASK_ERROR)
+	    {
+	      new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 
+					   0);
+	    }
+	  if (e.reason < 0)
+	    {
+	      warning (_("failed to reevaluate condition for breakpoint %d: %s"), 
+		       b->number, e.message);
+	      new_loc->enabled = 0;
+	    }
+	}
 
-  if (b->enable_state == bp_shlib_disabled)
-    b->enable_state = bp_enabled;
+      if (b->source_file != NULL)
+	xfree (b->source_file);
+      if (sals.sals[i].symtab == NULL)
+	b->source_file = NULL;
+      else
+	b->source_file =
+	  savestring (sals.sals[i].symtab->filename,
+		      strlen (sals.sals[i].symtab->filename));
 
-  b->pending = 0;
+      if (b->line_number == 0)
+	b->line_number = sals.sals[i].line;
+    }
 
-  check_duplicates (b);
+  /* If possible, carry over 'disable' status from existing breakpoints.  */
+  {
+    struct bp_location *e = existing_locations;
+    for (; e; e = e->next)
+      {
+	if (!e->enabled && e->function_name)
+	  {
+	    struct bp_location *l = b->loc;
+	    for (; l; l = l->next)
+	      if (l->function_name 
+		  && strcmp (e->function_name, l->function_name) == 0)
+		{
+		  l->enabled = 0;
+		  break;
+		}
+	  }
+      }
+  }
 
-  if (existing)
-    free_bp_location (existing);
+  if (existing_locations)
+    free_bp_location (existing_locations);
 }
 
 
@@ -7227,8 +7462,10 @@
 	     don't need extra messages.  If breakpoint is in bp_shlib_disabled
 	     state, then user already saw the message about that breakpoint
 	     being disabled, and don't want to see more errors.  */
-	  if (not_found && (b->pending || b->enable_state == bp_shlib_disabled
-			    || b->enable_state == bp_disabled))
+	  if (not_found 
+	      && (b->condition_not_parsed 
+		  || (b->loc && b->loc->shlib_disabled)
+		  || b->enable_state == bp_disabled))
 	    not_found_and_ok = 1;
 
 	  if (!not_found_and_ok)
@@ -7249,7 +7486,7 @@
       
       gdb_assert (sals.nelts == 1);
       resolve_sal_pc (&sals.sals[0]);
-      if (b->pending && s && s[0])
+      if (b->condition_not_parsed && s && s[0])
 	{
 	  char *cond_string = 0;
 	  int thread = -1;
@@ -7258,9 +7495,14 @@
 	  if (cond_string)
 	    b->cond_string = cond_string;
 	  b->thread = thread;
+	  b->condition_not_parsed = 0;
 	}
 
-      update_breakpoint_location (b, sals);
+      update_breakpoint_locations (b, sals);
+
+      /* Now that this is re-enabled, check_duplicates
+	 can be used. */
+      check_duplicates (b);
 
       xfree (sals.sals);
       break;
@@ -7524,6 +7766,48 @@
     }
 }
 
+static struct bp_location *
+find_location_by_number (char *number)
+{
+  char *dot = strchr (number, '.');
+  char *p1;
+  int bp_num;
+  int loc_num;
+  struct breakpoint *b;
+  struct bp_location *loc;  
+
+  *dot = '\0';
+
+  p1 = number;
+  bp_num = get_number_or_range (&p1);
+  if (bp_num == 0)
+    error (_("Bad breakpoint number '%s'"), number);
+
+  ALL_BREAKPOINTS (b)
+    if (b->number == bp_num)
+      {
+	break;
+      }
+
+  if (!b || b->number != bp_num)
+    error (_("Bad breakpoint number '%s'"), number);
+  
+  p1 = dot+1;
+  loc_num = get_number_or_range (&p1);
+  if (loc_num == 0)
+    error (_("Bad breakpoint location number '%s'"), number);
+
+  --loc_num;
+  loc = b->loc;
+  for (;loc_num && loc; --loc_num, loc = loc->next)
+    ;
+  if (!loc)
+    error (_("Bad breakpoint location number '%s'"), dot+1);
+    
+  return loc;  
+}
+
+
 /* Set ignore-count of breakpoint number BPTNUM to COUNT.
    If from_tty is nonzero, it prints a message to that effect,
    which ends with a period (no newline).  */
@@ -7579,6 +7863,13 @@
       default:
 	continue;
       }
+  else if (strchr (args, '.'))
+    {
+      struct bp_location *loc = find_location_by_number (args);
+      if (loc)
+	loc->enabled = 0;
+      check_duplicates (loc->owner);
+    }
   else
     map_breakpoint_numbers (args, disable_breakpoint);
 }
@@ -7711,6 +8002,13 @@
       default:
 	continue;
       }
+  else if (strchr (args, '.'))
+    {
+      struct bp_location *loc = find_location_by_number (args);
+      if (loc)
+	loc->enabled = 1;
+      check_duplicates (loc->owner);
+    }
   else
     map_breakpoint_numbers (args, enable_breakpoint);
 }
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -r1.50 -r1.51
--- src/gdb/breakpoint.h	2007/09/22 19:33:31	1.50
+++ src/gdb/breakpoint.h	2007/09/23 07:56:22	1.51
@@ -143,9 +143,6 @@
   {
     bp_disabled,	/* The eventpoint is inactive, and cannot trigger. */
     bp_enabled,		/* The eventpoint is active, and can trigger. */
-    bp_shlib_disabled,	/* The eventpoint's address is in an unloaded solib.
-			   The eventpoint will be automatically enabled 
-			   and reset when that solib is loaded. */
     bp_call_disabled,	/* The eventpoint has been disabled while a call 
 			   into the inferior is "in flight", because some 
 			   eventpoints interfere with the implementation of 
@@ -232,9 +229,14 @@
 
 struct bp_location
 {
-  /* Chain pointer to the next breakpoint location.  */
+  /* Chain pointer to the next breakpoint location for
+     the same parent breakpoint.  */
   struct bp_location *next;
 
+  /* Pointer to the next breakpoint location, in a global
+     list of all breakpoint locations.  */
+  struct bp_location *global_next;
+ 
   /* Type of this breakpoint location.  */
   enum bp_loc_type loc_type;
 
@@ -249,6 +251,14 @@
      locations,  the evaluation of expression can be different for
      different locations.  */
   struct expression *cond;
+
+  /* This location's address is in an unloaded solib, and so this
+     location should not be inserted.  It will be automatically
+     enabled when that solib is loaded.  */
+  char shlib_disabled; 
+
+  /* Is this particular location enabled.  */
+  char enabled;
   
   /* Nonzero if this breakpoint is now inserted.  */
   char inserted;
@@ -281,6 +291,8 @@
      processor's architectual constraints.  */
   CORE_ADDR requested_address;
 
+  char *function_name;
+
   /* Details of the placed breakpoint, when inserted.  */
   struct bp_target_info target_info;
 
@@ -423,8 +435,10 @@
        second bit : 0 normal breakpoint, 1 hardware breakpoint. */
     int flag;
 
-    /* Is breakpoint pending on shlib loads?  */
-    int pending;
+    /* Is breakpoint's condition not yet parsed because we found
+       no location initially so had no context to parse
+       the condition in.  */
+    int condition_not_parsed;
   };
 
 /* The following stuff is an abstract data type "bpstat" ("breakpoint

2007-09-23  Vladimir Prus  <vladimir@codesourcery.com>
	
	* gdb.base/annota1.exp: Adjust for 'info break'
	format changes.
	* gdb.base/annota3.exp: Likewise.
	* gdb.base/break.exp: Likewise.
	* gdb.base/condbreak.exp: Likewise.
	* gdb.base/pending.exp: Likewise.
	* gdb.base/sepdebug.exp: Likewise.
	* gdb.base/unload.exp: Likewise.
	* gdb.base/ovldbreak.exp: Likewise.
	
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota1.exp,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- src/gdb/testsuite/gdb.base/annota1.exp	2007/08/23 18:14:16	1.24
+++ src/gdb/testsuite/gdb.base/annota1.exp	2007/09/23 07:56:22	1.25
@@ -117,9 +117,9 @@
 #
 send_gdb "info break\n" 
 gdb_expect {
-    -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType           \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress    +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1   \r\n\032\032field 1\r\nbreakpoint     \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny   \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+    -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum     \r\n\032\032field 1\r\nType           \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb  \r\n\032\032field 4\r\nAddress    +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1       \r\n\032\032field 1\r\nbreakpoint     \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny    \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
 	{pass "breakpoint info"}
-    -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType           \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress    +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1   \r\n\032\032field 1\r\nbreakpoint     \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny   \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+    -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum     \r\n\032\032field 1\r\nType           \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb  \r\n\032\032field 4\r\nAddress    +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1       \r\n\032\032field 1\r\nbreakpoint     \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny    \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
 	{ setup_xfail "*-*-*" 1270
           fail "breakpoint info"}
    -re ".*$gdb_prompt$" { fail "breakpoint info" }
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota3.exp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- src/gdb/testsuite/gdb.base/annota3.exp	2007/08/23 18:14:16	1.14
+++ src/gdb/testsuite/gdb.base/annota3.exp	2007/09/23 07:56:22	1.15
@@ -127,8 +127,8 @@
 send_gdb "info break\n" 
 gdb_expect_list "breakpoint info" "$gdb_prompt$" {
     "\r\n\032\032post-prompt\r\n"
-    "Num Type           Disp Enb Address    +What\r\n"
-    "1   breakpoint     keep y   0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
+    "Num     Type           Disp Enb  Address    +What\r\n"
+    "1       breakpoint     keep y    0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
 }
 
 
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/break.exp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- src/gdb/testsuite/gdb.base/break.exp	2007/08/23 18:14:16	1.29
+++ src/gdb/testsuite/gdb.base/break.exp	2007/09/23 07:56:22	1.30
@@ -179,7 +179,7 @@
 set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1]
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$main_line.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in factorial$proto at .*$srcfile:$bp_location7.*
@@ -309,7 +309,7 @@
 #
 # check to see what breakpoints are set (temporary this time)
 #
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num     Type.*Disp Enb  Address.*What.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/condbreak.exp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- src/gdb/testsuite/gdb.base/condbreak.exp	2007/08/23 18:14:16	1.8
+++ src/gdb/testsuite/gdb.base/condbreak.exp	2007/09/23 07:56:22	1.9
@@ -125,14 +125,14 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$bp_location6.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in marker1$marker1_proto at .*$srcfile1:($bp_location15|$bp_location16).*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$bp_location1.*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).*
-\[\t \]+stop only if a == 43.*" \
+\[\t \]+stop only if \\(a==43\\).*" \
     "breakpoint info"
 
 
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/testsuite/gdb.base/pending.exp	2007/09/22 19:33:32	1.11
+++ src/gdb/testsuite/gdb.base/pending.exp	2007/09/23 07:56:22	1.12
@@ -71,8 +71,8 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*" \
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendfunc1.*" \
 "single pending breakpoint info"
 
 #
@@ -86,8 +86,8 @@
     "breakpoint function"
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendfunc1.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
 "pending plus real breakpoint info"
 
@@ -108,8 +108,8 @@
 gdb_test "condition 1 k == 1" ""
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendfunc1.*
 \[\t \]+stop only if k == 1.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
 "pending plus condition"
@@ -121,8 +121,8 @@
 gdb_test "disable 1" ""
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n\\(p\\).*PENDING.*pendfunc1.*
 \[\t \]+stop only if k == 1.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
 "pending disabled"
@@ -134,8 +134,8 @@
         "Set commands for pending breakpoint"
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n\\(p\\).*PENDING.*pendfunc1.*
 \[\t \]+stop only if k == 1.*
 \[\t \]+print k.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline" \
@@ -154,12 +154,12 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n\\(p\\).*PENDING.*pendfunc1.*
 \[\t \]+stop only if k == 1.*
 \[\t \]+print k.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
 "multiple pending breakpoints"
 
 
@@ -179,13 +179,13 @@
     "set ignore count on pending breakpoint 3"
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep n.*PENDING.*pendfunc1.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep n\\(p\\).*PENDING.*pendfunc1.*
 \[\t \]+stop only if k == 1.*
 \[\t \]+print k.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
 "multiple pending breakpoints 2"
 
 #
@@ -253,7 +253,7 @@
 rerun_to_main
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*imaginary.*" \
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*imaginary.*" \
 "verify pending breakpoint after restart"
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- src/gdb/testsuite/gdb.base/sepdebug.exp	2007/09/21 22:42:52	1.10
+++ src/gdb/testsuite/gdb.base/sepdebug.exp	2007/09/23 07:56:22	1.11
@@ -179,7 +179,7 @@
 set bp_location9 [gdb_get_line_number "set breakpoint 9 here"]
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in main at .*$srcfile:$main_line.*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in marker2 at .*$srcfile:($bp_location8|$bp_location9).*
 \[0-9\]+\[\t \]+breakpoint     keep y.* in factorial at .*$srcfile:$bp_location7.*
@@ -298,7 +298,7 @@
 #
 # check to see what breakpoints are set (temporary this time)
 #
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num     Type.*Disp Enb  Address.*What.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in factorial at .*$srcfile:$bp_location7.*\[\r\n\]
 \[0-9\]+\[\t \]+breakpoint     del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- src/gdb/testsuite/gdb.base/unload.exp	2007/09/22 19:33:32	1.12
+++ src/gdb/testsuite/gdb.base/unload.exp	2007/09/23 07:56:22	1.13
@@ -81,8 +81,8 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*shrfunc1.*" \
+    "Num     Type\[ \]+Disp Enb  Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint     keep y\\(p\\).*PENDING.*shrfunc1.*" \
 "single pending breakpoint info"
 
 set unloadshr_line [gdb_get_line_number "unloadshr break" ${libsrcfile}]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/ovldbreak.exp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- src/gdb/testsuite/gdb.cp/ovldbreak.exp	2007/08/23 18:14:17	1.6
+++ src/gdb/testsuite/gdb.cp/ovldbreak.exp	2007/09/23 07:56:22	1.7
@@ -153,7 +153,7 @@
 # Verify the breakpoints.
 
 gdb_test "info break" \
-    "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+    "Num     Type\[\t \]+Disp Enb  Address\[\t \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
 \[\t \]+breakpoint already hit 1 time\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -211,7 +211,7 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+    "Num     Type\[\t \]+Disp Enb  Address\[\t \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
 \[\t \]+breakpoint already hit 1 time\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -290,7 +290,7 @@
 }
 
 gdb_test "info break" \
-    "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+    "Num     Type\[\t \]+Disp Enb  Address\[\t \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r

2007-09-24  Vladimir Prus  <vladimir@codesourcery.com>
	
	* breakpoint.c (remove_sal): New.
	(expand_line_sal_maybe): New.
	(create_breakpoints): Call expand_line_sal_maybe.
	(clear_command): Add comment.
	(breakpoint_re_set_one): Call expand_line_sal_maybe.
	* linespec.c (decode_indirect): Set explicit_pc to 1.
	(decode_all_digits): Set explicit_line to 1.
	(append_expanded_sal): New.
	(expand_line_sal): New.
	* linespec.h (expand_line_sal): Declare.
	* symtab.c (init_sal): Initialize explicit_pc 
	and explicit_line.
	* symtab.h (struct symtab_and_line): New fields
	explicit_pc and explicit_line.	

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.268
retrieving revision 1.269
diff -u -r1.268 -r1.269
--- src/gdb/breakpoint.c	2007/09/23 07:56:22	1.268
+++ src/gdb/breakpoint.c	2007/09/24 07:40:32	1.269
@@ -5184,6 +5184,128 @@
   mention (b);
 }
 
+/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
+   elements to fill the void space.  */
+static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
+{
+  int i = index_to_remove+1;
+  int last_index = sal->nelts-1;
+
+  for (;i <= last_index; ++i)
+    sal->sals[i-1] = sal->sals[i];
+
+  --(sal->nelts);
+}
+
+/* If appropriate, obtains all sals that correspond
+   to the same file and line as SAL.  This is done
+   only if SAL does not have explicit PC and has
+   line and file information.  If we got just a single
+   expanded sal, return the original.
+
+   Otherwise, if SAL.explicit_line is not set, filter out 
+   all sals for which the name of enclosing function 
+   is different from SAL. This makes sure that if we have
+   breakpoint originally set in template instantiation, say
+   foo<int>(), we won't expand SAL to locations at the same
+   line in all existing instantiations of 'foo'.
+
+*/
+struct symtabs_and_lines
+expand_line_sal_maybe (struct symtab_and_line sal)
+{
+  struct symtabs_and_lines expanded;
+  CORE_ADDR original_pc = sal.pc;
+  char *original_function = NULL;
+  int found;
+  int i;
+
+  /* If we have explicit pc, don't expand.
+     If we have no line number, we can't expand.  */
+  if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL)
+    {
+      expanded.nelts = 1;
+      expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+      expanded.sals[0] = sal;
+      return expanded;
+    }
+
+  sal.pc = 0;
+  find_pc_partial_function (original_pc, &original_function, NULL, NULL);
+  
+  expanded = expand_line_sal (sal);
+  if (expanded.nelts == 1)
+    {
+      /* We had one sal, we got one sal.  Without futher
+	 processing, just return the original sal.  */
+      xfree (expanded.sals);
+      expanded.nelts = 1;
+      expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+      sal.pc = original_pc;
+      expanded.sals[0] = sal;
+      return expanded;      
+    }
+
+  if (!sal.explicit_line)
+    {
+      CORE_ADDR func_addr, func_end;
+      for (i = 0; i < expanded.nelts; ++i)
+	{
+	  CORE_ADDR pc = expanded.sals[i].pc;
+	  char *this_function;
+	  if (find_pc_partial_function (pc, &this_function, 
+					&func_addr, &func_end))
+	    {
+	      if (this_function && 
+		  strcmp (this_function, original_function) != 0)
+		{
+		  remove_sal (&expanded, i);
+		  --i;
+		}
+	      else if (func_addr == pc)	    
+		{	     
+		  /* We're at beginning of a function, and should
+		     skip prologue.  */
+		  struct symbol *sym = find_pc_function (pc);
+		  if (sym)
+		    expanded.sals[i] = find_function_start_sal (sym, 1);
+		  else
+		    expanded.sals[i].pc 
+		      = gdbarch_skip_prologue (current_gdbarch, pc);
+		}
+	    }
+	}
+    }
+
+  
+  if (expanded.nelts <= 1)
+    {
+      /* This is un ugly workaround. If we get zero
+       expanded sals then something is really wrong.
+      Fix that by returnign the original sal. */
+      xfree (expanded.sals);
+      expanded.nelts = 1;
+      expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+      sal.pc = original_pc;
+      expanded.sals[0] = sal;
+      return expanded;      
+    }
+
+  if (original_pc)
+    {
+      found = 0;
+      for (i = 0; i < expanded.nelts; ++i)
+	if (expanded.sals[i].pc == original_pc)
+	  {
+	    found = 1;
+	    break;
+	  }
+      gdb_assert (found);
+    }
+
+  return expanded;
+}
+
 /* Add SALS.nelts breakpoints to the breakpoint table.  For each
    SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
    value.  COND_STRING, if not NULL, specified the condition to be
@@ -5214,11 +5336,10 @@
   int i;
   for (i = 0; i < sals.nelts; ++i)
     {
-      struct symtabs_and_lines sals2;
-      sals2.sals = sals.sals + i;
-      sals2.nelts = 1;
+      struct symtabs_and_lines expanded = 
+	expand_line_sal_maybe (sals.sals[i]);
 
-      create_breakpoint (sals2, addr_string[i],
+      create_breakpoint (expanded, addr_string[i],
 			 cond_string, type, disposition,
 			 thread, ignore_count, from_tty,
 			 pending_bp);
@@ -6889,6 +7010,23 @@
       default_match = 1;
     }
 
+  /* We don't call resolve_sal_pc here. That's not
+     as bad as it seems, because all existing breakpoints
+     typically have both file/line and pc set.  So, if
+     clear is given file/line, we can match this to existing
+     breakpoint without obtaining pc at all.
+
+     We only support clearing given the address explicitly 
+     present in breakpoint table.  Say, we've set breakpoint 
+     at file:line. There were several PC values for that file:line,
+     due to optimization, all in one block.
+     We've picked one PC value. If "clear" is issued with another
+     PC corresponding to the same file:line, the breakpoint won't
+     be cleared.  We probably can still clear the breakpoint, but 
+     since the other PC value is never presented to user, user
+     can only find it by guessing, and it does not seem important
+     to support that.  */
+
   /* For each line spec given, delete bps which correspond
      to it.  Do it in two passes, solely to preserve the current
      behavior that from_tty is forced true if we delete more than
@@ -7404,8 +7542,12 @@
       }
   }
 
-  if (existing_locations)
-    free_bp_location (existing_locations);
+  while (existing_locations)
+    {
+      struct bp_location *next = existing_locations->next;
+      free_bp_location (existing_locations);
+      existing_locations = next;
+    }
 }
 
 
@@ -7423,6 +7565,7 @@
   int not_found = 0;
   int *not_found_ptr = &not_found;
   struct symtabs_and_lines sals = {};
+  struct symtabs_and_lines expanded;
   char *s;
   enum enable_state save_enable;
   struct gdb_exception e;
@@ -7497,8 +7640,8 @@
 	  b->thread = thread;
 	  b->condition_not_parsed = 0;
 	}
-
-      update_breakpoint_locations (b, sals);
+      expanded = expand_line_sal_maybe (sals.sals[0]);
+      update_breakpoint_locations (b, expanded);
 
       /* Now that this is re-enabled, check_duplicates
 	 can be used. */
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- src/gdb/linespec.c	2007/08/23 18:08:35	1.72
+++ src/gdb/linespec.c	2007/09/24 07:40:32	1.73
@@ -963,6 +963,7 @@
   values.sals[0] = find_pc_line (pc, 0);
   values.sals[0].pc = pc;
   values.sals[0].section = find_pc_overlay (pc);
+  values.sals[0].explicit_pc = 1;
 
   return values;
 }
@@ -1633,6 +1634,7 @@
   values.nelts = 1;
   if (need_canonical)
     build_canonical_line_spec (values.sals, NULL, canonical);
+  values.sals[0].explicit_line = 1;
   return values;
 }
 
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -r1.164 -r1.165
--- src/gdb/symtab.c	2007/08/29 18:34:46	1.164
+++ src/gdb/symtab.c	2007/09/24 07:40:32	1.165
@@ -691,6 +691,8 @@
   sal->line = 0;
   sal->pc = 0;
   sal->end = 0;
+  sal->explicit_pc = 0;
+  sal->explicit_line = 0;
 }
 
 
@@ -4172,6 +4174,166 @@
   set_main_name (NULL);
 }
 
+/* Helper to expand_line_sal below.  Appends new sal to SAL,
+   initializing it from SYMTAB, LINENO and PC.  */
+static void
+append_expanded_sal (struct symtabs_and_lines *sal,
+		     struct symtab *symtab,
+		     int lineno, CORE_ADDR pc)
+{
+  CORE_ADDR func_addr, func_end;
+  
+  sal->sals = xrealloc (sal->sals, 
+			sizeof (sal->sals[0]) 
+			* (sal->nelts + 1));
+  init_sal (sal->sals + sal->nelts);
+  sal->sals[sal->nelts].symtab = symtab;
+  sal->sals[sal->nelts].section = NULL;
+  sal->sals[sal->nelts].end = 0;
+  sal->sals[sal->nelts].line = lineno;  
+  sal->sals[sal->nelts].pc = pc;
+  ++sal->nelts;      
+}
+
+/* Compute a set of all sals in
+   the entire program that correspond to same file
+   and line as SAL and return those.  If there
+   are several sals that belong to the same block,
+   only one sal for the block is included in results.  */
+   
+struct symtabs_and_lines
+expand_line_sal (struct symtab_and_line sal)
+{
+  struct symtabs_and_lines ret, this_line;
+  int i, j;
+  struct objfile *objfile;
+  struct partial_symtab *psymtab;
+  struct symtab *symtab;
+  int lineno;
+  int deleted = 0;
+  struct block **blocks = NULL;
+  int *filter;
+
+  ret.nelts = 0;
+  ret.sals = NULL;
+
+  if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
+    {
+      ret.sals = xmalloc (sizeof (struct symtab_and_line));
+      ret.sals[0] = sal;
+      ret.nelts = 1;
+      return ret;
+    }
+  else
+    {
+      struct linetable_entry *best_item = 0;
+      struct symtab *best_symtab = 0;
+      int exact = 0;
+
+      lineno = sal.line;
+
+      /* We meed to find all symtabs for a file which name
+	 is described by sal. We cannot just directly 
+	 iterate over symtabs, since a symtab might not be
+	 yet created. We also cannot iterate over psymtabs,
+	 calling PSYMTAB_TO_SYMTAB and working on that symtab,
+	 since PSYMTAB_TO_SYMTAB will return NULL for psymtab
+	 corresponding to an included file. Therefore, we do
+	 first pass over psymtabs, reading in those with
+	 the right name.  Then, we iterate over symtabs, knowing
+	 that all symtabs we're interested in are loaded.  */
+
+      ALL_PSYMTABS (objfile, psymtab)
+	{
+	  if (strcmp (sal.symtab->filename,
+		      psymtab->filename) == 0)
+	    PSYMTAB_TO_SYMTAB (psymtab);
+	}
+
+	 
+      /* For each symtab, we add all pcs to ret.sals. I'm actually
+	 not sure what to do if we have exact match in one symtab,
+	 and non-exact match on another symtab.
+      */
+      ALL_SYMTABS (objfile, symtab)
+	{
+	  if (strcmp (sal.symtab->filename,
+		      symtab->filename) == 0)
+	    {
+	      struct linetable *l;
+	      int len;
+	      l = LINETABLE (symtab);
+	      if (!l)
+		continue;
+	      len = l->nitems;
+
+	      for (j = 0; j < len; j++)
+		{
+		  struct linetable_entry *item = &(l->item[j]);
+
+		  if (item->line == lineno)
+		    {
+		      exact = 1;
+		      append_expanded_sal (&ret, symtab, lineno, item->pc);
+		    }      
+		  else if (!exact && item->line > lineno
+			   && (best_item == NULL || item->line < best_item->line))
+		  
+		    {
+		      best_item = item;
+		      best_symtab = symtab;
+		    }
+		}
+	    }
+	}
+      if (!exact && best_item)
+	append_expanded_sal (&ret, best_symtab, lineno, best_item->pc);
+    }
+
+  /* For optimized code, compiler can scatter one source line accross
+     disjoint ranges of PC values, even when no duplicate functions
+     or inline functions are involved.  For example, 'for (;;)' inside
+     non-template non-inline non-ctor-or-dtor function can result
+     in two PC ranges.  In this case, we don't want to set breakpoint
+     on first PC of each range.  To filter such cases, we use containing
+     blocks -- for each PC found above we see if there are other PCs
+     that are in the same block.  If yes, the other PCs are filtered out.  */  
+
+  filter = xmalloc (ret.nelts * sizeof (int));
+  blocks = xmalloc (ret.nelts * sizeof (struct block *));
+  for (i = 0; i < ret.nelts; ++i)
+    {
+      filter[i] = 1;
+      blocks[i] = block_for_pc (ret.sals[i].pc);
+    }
+
+  for (i = 0; i < ret.nelts; ++i)
+    if (blocks[i] != NULL)
+      for (j = i+1; j < ret.nelts; ++j)
+	if (blocks[j] == blocks[i])
+	  {
+	    filter[j] = 0;
+	    ++deleted;
+	    break;
+	  }
+  
+  {
+    struct symtab_and_line *final = 
+      xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
+    
+    for (i = 0, j = 0; i < ret.nelts; ++i)
+      if (filter[i])
+	final[j++] = ret.sals[i];
+    
+    ret.nelts -= deleted;
+    xfree (ret.sals);
+    ret.sals = final;
+  }
+
+  return ret;
+}
+
+
 void
 _initialize_symtab (void)
 {
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -r1.106 -r1.107
--- src/gdb/symtab.h	2007/08/23 18:08:45	1.106
+++ src/gdb/symtab.h	2007/09/24 07:40:32	1.107
@@ -1213,6 +1213,8 @@
 
   CORE_ADDR pc;
   CORE_ADDR end;
+  int explicit_pc;
+  int explicit_line;
 };
 
 extern void init_sal (struct symtab_and_line *sal);
@@ -1404,5 +1406,7 @@
 						  const domain_enum domain,
 						  struct symtab **symtab);
 
+extern struct symtabs_and_lines
+expand_line_sal (struct symtab_and_line sal);
 
 #endif /* !defined(SYMTAB_H) */

2007-09-24  Vladimir Prus  <vladimir@codesourcery.com>

	* gdb.cp/mb-ctor.cc: New.
	* gdb.cp/mb-ctor.exp: New.
	* gdb.cp/mb-templates.cc: New.
	* gdb.cp/mb-templates.exp: New.

/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.cc,v  -->  standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-ctor.cc
+++ -	2007-11-01 22:04:53.928594000 +0000
@@ -0,0 +1,58 @@
+
+#include <stdio.h>
+
+class Base 
+{
+public:
+  Base(int k);
+  ~Base();
+  virtual void foo() {}
+private:
+  int k;
+};
+
+Base::Base(int k)
+{
+  this->k = k;
+}
+
+Base::~Base()
+{
+    printf("~Base\n");
+}
+
+class Derived : public virtual Base
+{
+public:
+  Derived(int i);
+  ~Derived();
+private:
+  int i;
+};
+
+Derived::Derived(int i) : Base(i)
+{
+  this->i = i;
+}
+
+Derived::~Derived()
+{
+    printf("~Derived\n");
+}
+
+class DeeplyDerived : public Derived
+{
+public:
+  DeeplyDerived(int i) : Base(i), Derived(i) {}
+};
+
+int main()
+{
+  /* Invokes the Derived ctor that constructs both
+     Derived and Base.  */
+  Derived d(7);
+  /* Invokes the Derived ctor that constructs only
+     Derived. Base is constructed separately by
+     DeeplyDerived's ctor.  */
+  DeeplyDerived dd(15);
+}
/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.exp,v  -->  standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-ctor.exp
+++ -	2007-11-01 22:04:54.490054000 +0000
@@ -0,0 +1,86 @@
+# Copyright 2007
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that breakpoints on C++ constructors work, despite the
+# fact that gcc generates several versions of constructor function.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "mb-ctor"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+     untested mb-ctor.exp
+     return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Set a breakpoint with multiple locations
+# and a condition.
+
+gdb_test "break 'Derived::Derived(int)'" \
+    "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+    "set-breakpoint at ctor"
+
+gdb_test "break 'Derived::~Derived()'" \
+    "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+    "set-breakpoint at ctor"
+
+gdb_run_cmd
+gdb_expect {
+    -re "Breakpoint \[0-9\]+,.*Derived.*i=7.*$gdb_prompt $" {
+	pass "run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "run to breakpoint"
+    }
+    timeout {
+	fail "run to breakpoint (timeout)"
+    }
+}
+
+gdb_test "continue" \
+    ".*Breakpoint.*Derived.*i=15.*" \
+    "run to breakpoint 2"
+
+gdb_test "continue" \
+    ".*Breakpoint.*~Derived.*" \
+    "run to breakpoint 3"
+
+gdb_test "continue" \
+    ".*Breakpoint.*~Derived.*" \
+    "run to breakpoint 4"
+
+gdb_test "continue" \
+    ".*exited normally.*" \
+    "run to exit"
+
+
+
/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.cc,v  -->  standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-templates.cc
+++ -	2007-11-01 22:04:55.064722000 +0000
@@ -0,0 +1,19 @@
+
+#include <iostream>
+using namespace std;
+
+template<class T>
+void foo(T i)
+{
+  std::cout << "hi\n"; // set breakpoint here
+}
+
+int main()
+{
+    foo<int>(0);
+    foo<double>(0);
+    foo<int>(1);
+    foo<double>(1);
+    foo<int>(2);
+    foo<double>(2);
+}
/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.exp,v  -->  standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-templates.exp
+++ -	2007-11-01 22:04:55.647560000 +0000
@@ -0,0 +1,161 @@
+# Copyright 2007
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This test verifies that setting breakpoint on line in template
+# function will fire in all instantiations of that template.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "mb-templates"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+     untested mb-templates.exp
+     return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set bp_location [gdb_get_line_number "set breakpoint here"]
+
+# Set a breakpoint with multiple locations
+# and a condition.
+
+gdb_test "break $srcfile:$bp_location if i==1" \
+    "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+    "initial condition: set breakpoint"
+
+gdb_run_cmd
+gdb_expect {
+    -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
+	pass "initial condition: run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "initial condition: run to breakpoint"
+    }
+    timeout {
+	fail "initial condition: run to breakpoint (timeout)"
+    }
+}
+
+gdb_test "continue" \
+    ".*Breakpoint.*foo<double> \\(i=1\\).*" \
+    "initial condition: run to breakpoint 2"
+
+# Set breakpoint with multiple locations.
+# Separately set the condition.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break $srcfile:$bp_location" \
+    "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+    "separate condition: set breakpoint"
+
+gdb_test "condition 1 i==1" "" \
+    "separate condition: set condition"
+    
+gdb_run_cmd
+gdb_expect {
+    -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
+	pass "separate condition: run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "separate condition: run to breakpoint"
+    }
+    timeout {
+	fail "separate condition: run to breakpoint (timeout)"
+    }
+}
+
+gdb_test "continue" \
+    ".*Breakpoint.*foo<double> \\(i=1\\).*" \
+    "separate condition: run to breakpoint 2"
+
+# Try disabling a single location. We also test
+# that at least in simple cases, the enable/disable
+# state of locations surive "run".
+gdb_test "disable 1.1" "" "disabling location: disable"
+
+gdb_run_cmd
+gdb_expect {
+    -re "Breakpoint \[0-9\]+,.*foo<double> \\(i=1\\).*$gdb_prompt $" {
+	pass "disabling location: run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "disabling location: run to breakpoint"
+    }
+    timeout {
+	fail "disabling location: run to breakpoint (timeout)"
+    }
+}
+
+# Try disabling entire breakpoint
+gdb_test "enable 1.1" "" "disabling location: enable"
+
+
+gdb_test "disable 1" "" "disable breakpoint: disable"
+
+gdb_run_cmd
+gdb_expect {
+    -re "Program exited normally.*$gdb_prompt $" {
+	pass "disable breakpoint: run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "disable breakpoint: run to breakpoint"
+    }
+    timeout {
+	fail "disable breakpoint: run to breakpoint (timeout)"
+    }
+}
+
+# Make sure breakpoint can be set on a specific instantion.
+delete_breakpoints
+gdb_test "break 'void foo<int>(int)'" ".*" \
+    "instantiation: set breakpoint"
+
+
+gdb_run_cmd
+gdb_expect {
+    -re ".*Breakpoint \[0-9\]+,.*foo<int> \\(i=0\\).*$gdb_prompt $" {
+	pass "instantiation: run to breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "instantiation: run to breakpoint"
+    }
+    timeout {
+	fail "instantiation: run to breakpoint (timeout)"
+    }
+}
+
+gdb_test "continue" \
+    ".*Breakpoint.*foo<int> \\(i=1\\).*" \
+    "instantiation: run to breakpoint 2"
+

2007-09-26  Vladimir Prus  <vladimir@codesourcery.com>

	* breakpoint.c (create_breakpoint): Set
	condition on each location, not on the first
	location of breakpoint.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.269
retrieving revision 1.270
diff -u -r1.269 -r1.270
--- src/gdb/breakpoint.c	2007/09/24 07:40:32	1.269
+++ src/gdb/breakpoint.c	2007/09/26 18:44:55	1.270
@@ -5163,7 +5163,7 @@
       if (b->cond_string)
 	{
 	  char *arg = b->cond_string;
-	  b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+	  loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
 	  if (*arg)
 	    {
 	      if (pending_bp)

2007-09-28  Vladimir Prus  <vladimir@codesourcery.com>

	* NEW: Mention pending breakpoint changes and
	support for breakpoints at multiple locations.

===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.239
retrieving revision 1.240
diff -u -r1.239 -r1.240
--- src/gdb/NEWS	2007/09/17 19:30:05	1.239
+++ src/gdb/NEWS	2007/09/28 06:24:20	1.240
@@ -3,6 +3,13 @@
 
 *** Changes since GDB 6.7
 
+* Pending breakpoints no longer change their number when their address
+  is resolved.
+
+* GDB now supports breakpoints with multiple locations,
+  including breakpoints on C++ constructors, inside C++ templates,
+  and in inlined functions.
+
 *** Changes in GDB 6.6
 
 * Resolved 101 resource leaks, null pointer dereferences, etc. in gdb, 

2007-09-28  Vladimir Prus  <vladimir@codesourcery.com>

	* gdb.texinfo (Setting Breakpoints): Revise
	documentation for pending breakpoints.  Document
	breakpoints with multiple locations.

===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.432
retrieving revision 1.433
diff -u -r1.432 -r1.433
--- src/gdb/doc/gdb.texinfo	2007/09/16 14:59:30	1.432
+++ src/gdb/doc/gdb.texinfo	2007/09/28 06:24:20	1.433
@@ -2991,11 +2991,17 @@
 Whether the breakpoint is marked to be disabled or deleted when hit.
 @item Enabled or Disabled
 Enabled breakpoints are marked with @samp{y}.  @samp{n} marks breakpoints
-that are not enabled.
+that are not enabled.  An optional @samp{(p)} suffix marks pending
+breakpoints --- breakpoints for which address is either not yet
+resolved, pending load of a shared library, or for which address was
+in a shared library that was since unloaded.  Such breakpoint won't
+fire until a shared library that has the symbol or line referred by
+breakpoint is loaded.  See below for details.
 @item Address
-Where the breakpoint is in your program, as a memory address.  If the
-breakpoint is pending (see below for details) on a future load of a shared library, the address
-will be listed as @samp{<PENDING>}.
+Where the breakpoint is in your program, as a memory address.  For a
+pending breakpoint whose address is not yet known,  this field will
+contain @samp{<PENDING>}.  A breakpoint with several locations will
+have @samp{<MULTIPLE>} in this field --- see below for details.
 @item What
 Where the breakpoint is in the source for your program, as a file and
 line number.  For a pending breakpoint, the original string passed to
@@ -3032,23 +3038,83 @@
 the breakpoints are conditional, this is even useful
 (@pxref{Conditions, ,Break Conditions}).
 
-@cindex pending breakpoints
-If a specified breakpoint location cannot be found, it may be due to the fact
-that the location is in a shared library that is yet to be loaded.  In such
-a case, you may want @value{GDBN} to create a special breakpoint (known as
-a @dfn{pending breakpoint}) that
-attempts to resolve itself in the future when an appropriate shared library
-gets loaded.
-
-Pending breakpoints are useful to set at the start of your
-@value{GDBN} session for locations that you know will be dynamically loaded
-later by the program being debugged.  When shared libraries are loaded,
-a check is made to see if the load resolves any pending breakpoint locations.
-If a pending breakpoint location gets resolved,
-a regular breakpoint is created and the original pending breakpoint is removed.
+It is possible that a breakpoint correspond to several locations 
+in your program.  Examples of this situation are:
+
+@itemize @bullet
+
+@item
+For a C@t{++} constructor, the @value{NGCC} compiler generates several
+instances of the function body, used in different cases.
 
-@value{GDBN} provides some additional commands for controlling pending
-breakpoint support:
+@item
+For a C@t{++} template function, a given line in the function can
+correspond to any number of instantiations.
+
+@item
+For an inlined function, a given source line can correspond to
+several places where that function is inlined.
+
+@end itemize
+
+In all those cases, @value{GDBN} will insert a breakpoint at all
+the relevant locations.
+
+A breakpoint with multiple locations is displayed in the
+breakpoint table using several rows --- one header row, followed
+by one row for each breakpoint location.  The header row
+has @samp{<MULTIPLE>} in the address column.  The rows for
+individual locations contain the actual addresses for locations,
+and say what functions those locations are in.  The number
+column for a location has number in the format 
+@var{breakpoint-number}.@var{location-number}.
+
+For example:
+@smallexample
+Num     Type           Disp Enb  Address    What
+1       breakpoint     keep y    <MULTIPLE>
+        stop only if i==1
+        breakpoint already hit 1 time
+1.1                         y    0x080486a2 in void foo<int>() at t.cc:8
+1.2                         y    0x080486ca in void foo<double>() at t.cc:8
+@end smallexample
+
+Each location can be individually enabled or disabled by passing
+@var{breakpoint-number}.@var{location-number} as argument to the
+@code{enable} and @code{disable} commands.
+
+@cindex pending breakpoints
+It's quite common to have a breakpoint inside a shared library.
+The shared library may be loaded and unloaded explicitly,
+and possibly repeatedly, as the program is executed.  To support
+this use case, @value{GDBN} updates breakpoint locations whenever
+any shared library is loaded or unloaded.  Typically, you would
+set a breakpoint in a shared library at the beginning of your 
+debugging session, when the library is not loaded, and when the
+symbols from the library are not available.  When you try to set
+breakpoint, @value{GDBN} will ask you if you want to set
+a so called @dfn{pending breakpoint} --- breakpoint whose address 
+is not yet resolved.
+
+After the program is run, whenever a new shared library is loaded,
+@value{GDBN} reevaluates all the breakpoints.  When a newly loaded
+shared library contains the symbol or line referred to by some
+pending breakpoint, that breakpoint is resolved and becomes an
+ordinary breakpoint.  When a library is unloaded, all breakpoints
+that refer to its symbols or source lines become pending again.
+
+This logic works for breakpoints with multiple locations, too.  For
+example, if you have a breakpoint in a C@t{++} template function, and
+a newly loaded shared library has an instantiation of that template,
+a new location is added to the list of locations for the breakpoint.
+
+Except for having unresolved address, pending breakpoints do not
+differ from regular breakpoints.  You can set conditions or commands,
+enable and disable them and perform other breakpoint operations.
+
+@value{GDBN} provides some additional commands for controlling what
+happens when the @samp{break} command cannot resolve breakpoint
+address specification to an address:
 
 @kindex set breakpoint pending
 @kindex show breakpoint pending
@@ -3070,19 +3136,9 @@
 Show the current behavior setting for creating pending breakpoints.
 @end table
 
-@cindex operations allowed on pending breakpoints
-Normal breakpoint operations apply to pending breakpoints as well.  You may
-specify a condition for a pending breakpoint and/or commands to run when the
-breakpoint is reached.  You can also enable or disable
-the pending breakpoint.  When you specify a condition for a pending breakpoint,
-the parsing of the condition will be deferred until the point where the
-pending breakpoint location is resolved.  Disabling a pending breakpoint
-tells @value{GDBN} to not attempt to resolve the breakpoint on any subsequent
-shared library load.  When a pending breakpoint is re-enabled,
-@value{GDBN} checks to see if the location is already resolved.
-This is done because any number of shared library loads could have
-occurred since the time the breakpoint was disabled and one or more
-of these loads could resolve the location.
+The settings above only affect the @code{break} command and its
+variants.  Once breakpoint is set, it will be automatically updated
+as shared libraries are loaded and unloaded.
 
 @cindex automatic hardware breakpoints
 For some targets, @value{GDBN} can automatically decide if hardware or

2007-10-08  Pierre Muller  <muller@ics.u-strasbg.fr>

	* breakpoint.c (print_one_breakpoint_location): ARI fix: 
	Replace asprintf by xstrprintf.

===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.271
retrieving revision 1.272
diff -u -r1.271 -r1.272
--- src/gdb/breakpoint.c	2007/10/01 00:17:57	1.271
+++ src/gdb/breakpoint.c	2007/10/08 15:23:42	1.272
@@ -3526,7 +3526,7 @@
   if (part_of_multiple)
     {
       char *formatted;
-      asprintf (&formatted, "%d.%d", b->number, loc_number);
+      formatted = xstrprintf ("%d.%d", b->number, loc_number);
       ui_out_field_string (uiout, "number", formatted);
       xfree (formatted);
     }

2007-09-17  Daniel Jacobowitz  <dan@codesourcery.com>

	* schedlock.c (NUM): Change to 1.
	(main): Use args[0] for the main thread.
	* schedlock.exp: Only expect two threads.  Only issue one pass or fail
	regardless of the number of threads.

--- ./gdb/testsuite/gdb.threads/schedlock.exp	23 Aug 2007 18:14:19 -0000	1.6
+++ ./gdb/testsuite/gdb.threads/schedlock.exp	17 Sep 2007 15:38:05 -0000	1.7
@@ -32,6 +32,9 @@ set testfile "schedlock"
 set srcfile ${testfile}.c
 set binfile ${objdir}/${subdir}/${testfile}
 
+# The number of threads, including the main thread.
+set NUM 2
+
 if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
     return -1
 }
@@ -44,11 +47,11 @@ proc get_args { } {
 
   send_gdb "print args\n"
   gdb_expect {
-    -re "\\\$\[0-9\]+ = {(\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+)}.*$gdb_prompt"
+    -re "\\\$\[0-9\]+ = {(\[0-9\]+), (\[0-9\]+)}.*$gdb_prompt"
       {
 	set list_count [expr $list_count + 1]
 	pass "listed args ($list_count)"
-	return [list $expect_out(1,string) $expect_out(2,string) $expect_out(3,string) $expect_out(4,string) $expect_out(5,string) $expect_out(6,string)]
+	return [list $expect_out(1,string) $expect_out(2,string)]
       }
     -re "$gdb_prompt"
       {
@@ -112,7 +115,7 @@ proc my_continue { msg } {
   stop_process "stop all threads ($msg)"
 
   # Make sure we're in one of the non-main looping threads.
-  gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 5"]
+  gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
   gdb_continue_to_breakpoint "return to loop ($msg)"
   delete_breakpoints
 }
@@ -198,13 +201,17 @@ my_continue "initial"
 
 set cont_args [get_args]
 
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
+set ok 1
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
   if {[lindex $start_args $i] == [lindex $cont_args $i]} {
-    fail "thread $i ran (didn't run)"
-  } else {
-    pass "thread $i ran"
+    set ok 0
   }
 }
+if { $ok } {
+  pass "all threads alive"
+} else {
+  fail "all threads alive"
+}
 
 # We can't change threads, unfortunately, in current GDB.  Use
 # whichever we stopped in.
@@ -230,7 +237,7 @@ set start_args $cont_args
 set cont_args [get_args]
 
 set num_other_threads 0
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
   if {[lindex $start_args $i] == [lindex $cont_args $i]} {
     if {$i == $curthread} {
       fail "current thread stepped (didn't run)"
@@ -248,9 +255,9 @@ for {set i 0} {[expr $i < 6]} {set i [ex
   }
 }
 if {$num_other_threads > 0} {
-  pass "other threads ran (1)"
+  pass "other threads ran - unlocked"
 } else {
-  fail "other threads ran (no other threads ran) (1)"
+  fail "other threads ran - unlocked"
 }
 
 # Test continue with scheduler locking
@@ -269,21 +276,25 @@ if {$curthread == $newthread} {
 set start_args $cont_args
 set cont_args [get_args]
 
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
+set num_other_threads 0
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
   if {[lindex $start_args $i] == [lindex $cont_args $i]} {
     if {$i == $curthread} {
       fail "current thread ran (didn't run)"
-    } else {
-      pass "other thread $i didn't run"
     }
   } else {
     if {$i == $curthread} {
       pass "current thread ran"
     } else {
-      fail "other thread $i didn't run (ran)"
+      incr num_other_threads
     }
   }
 }
+if {$num_other_threads > 0} {
+  fail "other threads didn't run - locked"
+} else {
+  pass "other threads didn't run - locked"
+}
 
 # Test stepping with scheduler locking
 step_ten_loops "locked"
@@ -299,12 +310,11 @@ if {$curthread == $newthread} {
 set start_args $cont_args
 set cont_args [get_args]
 
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
+set num_other_threads 0
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
   if {[lindex $start_args $i] == [lindex $cont_args $i]} {
     if {$i == $curthread} {
       fail "current thread stepped locked (didn't run)"
-    } else {
-      pass "other thread $i didn't run (stepping)"
     }
   } else {
     if {$i == $curthread} {
@@ -314,9 +324,14 @@ for {set i 0} {[expr $i < 6]} {set i [ex
 	    fail "current thread stepped locked (wrong amount)"
 	}
     } else {
-      fail "other thread $i didn't run (stepping) (ran)"
+      incr num_other_threads
     }
   }
 }
+if {$num_other_threads > 0} {
+  fail "other threads didn't run - step locked"
+} else {
+  pass "other threads didn't run - step locked"
+}
 
 return 0
--- ./gdb/testsuite/gdb.threads/schedlock.c	23 Aug 2007 18:08:50 -0000	1.7
+++ ./gdb/testsuite/gdb.threads/schedlock.c	17 Sep 2007 15:38:05 -0000	1.8
@@ -22,7 +22,7 @@
 
 void *thread_function(void *arg); /* Pointer to function executed by each thread */
 
-#define NUM 5
+#define NUM 1
 
 unsigned int args[NUM+1];
 
@@ -32,7 +32,7 @@ int main() {
     void *thread_result;
     long i;
 
-    for (i = 0; i < NUM; i++)
+    for (i = 1; i <= NUM; i++)
       {
 	args[i] = 1;
 	res = pthread_create(&threads[i],
@@ -42,8 +42,8 @@ int main() {
       }
 
     /* schedlock.exp: last thread start.  */
-    args[i] = 1;
-    thread_function ((void *) i);
+    args[0] = 1;
+    thread_function ((void *) 0);
 
     exit(EXIT_SUCCESS);
 }

2007-12-10  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* lib/gdb.exp (build_id_debug_filename_get): OBJCOPY pipe being read
	must be set to binary.

--- ./gdb/testsuite/lib/gdb.exp	9 Dec 2007 11:21:21 -0000	1.93
+++ ./gdb/testsuite/lib/gdb.exp	10 Dec 2007 00:14:55 -0000
@@ -2500,6 +2500,7 @@ proc build_id_debug_filename_get { exec 
 	return ""
     }
     set fi [open $tmp]
+    fconfigure $fi -translation binary
     # Skip the NOTE header.
     read $fi 16
     set data [read $fi]