[RFC stub-side break conditions 3/5] GDB-side changes

Pedro Alves alves.ped@gmail.com
Fri Jan 6 16:23:00 GMT 2012


On 01/05/2012 02:56 PM, Luis Machado wrote:

> Regarding always-inserted mode, if it is "on" we must send condition changes right away, or else the target will potentially miss breakpoint hits.

Could you elaborate a bit more on how will it miss breakpoint hits?

 > I'd like to hear about the change to "info break"

As they say, a picture is worth a thousand words.  How does the new output look like?  What about MI?

 > and also the way we should pass conditions down to the stub.  Currently i'm adding the agent expressions to a condition list in the target info field of bp locations.

Sounds good at first sight.


I'm mostly wondering whether the assumption that we can re-insert
a breakpoint at the same address is solid.



 > +static int
 > +gdb_evaluates_breakpoint_condition_p (void)
 > +{
 > +  const char *mode = breakpoint_condition_evaluation_mode ();
 > +
 > +  return (mode == condition_evaluation_gdb? 1 : 0);

Missing space before `?'.  Or just write

   return (mode == condition_evaluation_gdb);

Same thing.

 > +}


 > +/* Iterates through locations with address ADDRESS.  BP_LOCP_TMP points to
 > +   each object.  BP_LOCP_START points to where the loop should start from.
 > +   If BP_LOCP_START is a NULL pointer, the macro automatically seeks the
 > +   appropriate location to start with.  */
 > +
 > +#define ALL_BP_LOCATIONS_AT_ADDR(BP_LOCP_TMP, BP_LOCP_START, ADDRESS)	\
 > +	if (!BP_LOCP_START)						\
 > +	  BP_LOCP_START = get_first_locp_gte_addr (ADDRESS);		\
 > +	for (BP_LOCP_TMP = BP_LOCP_START;				\
 > +	     (BP_LOCP_TMP<  bp_location + bp_location_count		\
 > +	&&  (*BP_LOCP_TMP)->address == ADDRESS);			\
 > +	     BP_LOCP_TMP++)
 > +

The address alone is not enough when you consider multi-process.
The users of this macro aren't considering that.  Several instances of
this problem.


 > +/* Based on location BL, create a list of breakpoint conditions to be
 > +   passed on to the target.  If we have duplicated locations with different
 > +   conditions, we will add such conditions to the list.  The idea is that the
 > +   target will evaluate the list of conditions and will only notify GDB when
 > +   one of them is true.  */

What does the return code mean?

 > +
 > +static int
 > +build_target_condition_list (struct bp_location *bl)
 > +{



On 01/05/2012 02:56 PM, Luis Machado wrote:
 > +	}
 > +      /* We will never reach this point.  */
 > +    }

Then by all means gdb_assert.  :-)




 > +  /* Even if the target evaluated the condition on its end and notified GDB, we
 > +     need to do so again since GDB does not know if we stopped due to a
 > +     breakpoint or a single step.

 > + This will only be done when we single step straight to a conditional breakpoint.  */

Where is the code that makes this true?

 > +
 >     if (frame_id_p (b->frame_id)
 >         &&  !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
 >       bs->stop = 0;
 > @@ -4905,6 +5219,19 @@ print_one_breakpoint_location (struct br
 >         else
 >   	ui_out_text (uiout, "\tstop only if ");
 >         ui_out_field_string (uiout, "cond", b->cond_string);
 > +
 > +      /* Print whether the remote stub is doing the breakpoint's condition
 > +	 evaluation.  If GDB is doing the evaluation, don't print anything.  */
 > +      if (loc&&  is_breakpoint (b)&&  loc->cond_bytecode
 > +	&&  breakpoint_condition_evaluation_mode ()
 > +	  != condition_evaluation_gdb)

What if you set a conditional breakpoint, have it evaluate the in target,
and then, flip the setting to gdb-side, while the breakpoint's condition is
still being evaluated on the target side?  Shouldn't this always
print "target"/"stub" when loc->cond_bytecode is non-NULL?

 > +	{
 > +	  ui_out_text (uiout, " (");
 > +	  ui_out_field_string (uiout, "condeval",
 > +			       breakpoint_condition_evaluation_mode ());
 > +	  ui_out_text (uiout, ")");
 > +	}
 > +
 >         ui_out_text (uiout, "\n");
 >       }




 > @@ -10366,12 +10696,56 @@ swap_insertion (struct bp_location *left
 >
 >     left->inserted = right->inserted;
 >     left->duplicate = right->duplicate;
 > +  left->needs_update = right->needs_update;
 >     left->target_info = right->target_info;
 >     right->inserted = left_inserted;
 >     right->duplicate = left_duplicate;
 > +  left->needs_update = right->needs_update;

Doesn't look right.  Should probably be

   const int left_needs_update = left->needs_update;
   ...
   left->needs_update = right->needs_update;
   ...
   right->needs_update = left_needs_update;



 > +	  modified = modified? 1 : (*loc2p)->condition_changed;

Space before `?'.  Perhaps clearer alternatives are:

   modified = modified || (*loc2p)->condition_changed;

or even the common:

   if (!modified)
     modified = (*loc2p)->condition_changed;




 > +      /* Check if this is a new/deleted duplicated location or a duplicated
 > +	 location that had its condition modified.  If so,  we want to send its

Spurious space.


 > @@ -11387,7 +11810,10 @@ delete_breakpoint (struct breakpoint *bp
 >        itself, since remove_breakpoint looks at location's owner.  It
 >        might be better design to have location completely
 >        self-contained, but it's not the case now.  */
 > -  update_global_location_list (0);
 > +  if (is_breakpoint (bpt))
 > +    update_global_location_list (1);

The whole point of the update_global_location_list parameter is being able
to say "don't insert locations new locations because I'm just deleting a
breakpoint".  This was necessary for situations like following an exec, IIRC.

 > +  else
 > +    update_global_location_list (0);
 >


 > +/* List of conditions used to pass conditions down to the target.  */
 > +struct condition_list
 > +{
 > +  /* Breakpoint condition.  */
 > +  struct agent_expr *expr;
 > +  /* Pointer to the next condition.  */
 > +  struct condition_list *next;
 > +};

Can this be a VEC of `struct agent_expr *' instead?



More information about the Gdb-patches mailing list