This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] target defined breakpoints


Hui,

On Tue, Feb 05, 2013 at 12:28:59PM +0800, Hui Zhu wrote:
> Hi,
> 
> According to the discussion with Yao in meeting.  We want to merge all
> this function to breakpoint event function.
> He still want use the pkg handler inside the target defined
> breakpoints and pkg format.  So I post the new version of it.
> 
> According to the comments from Stan, I merge
> parse_tracepoint_definition function together with the parser of
> target defined breakpoints and name it to
> parse_tracepoint_breakpoint_definition.
> And I update the pkg format to make it more easy support by
> parse_tracepoint_breakpoint_definition.  Please got it from
> target-defined-breakpoints-doc.txt.
> 
> Thanks,
> Hui

This isn't my domain, so cannot review, but after scanning the patch,
I noticed that you are introducing a number of new structures and
functions. I would like us to make sure that every new function,
structure, variable, constant, etc, gets properly documented. For
structures, this includes documenting each field. Would you mind
updating your patch accordingly? Just a reminder, also, that for
functions destined to be used as callbacks (Eg: gdbarch methods),
the callback itself should already be documented, so it's ok to
just say "Implements the "bla bla" gdbarch method." for instance.

Thank you.

> --- a/breakpoint.c
> +++ b/breakpoint.c
> @@ -82,6 +82,9 @@
>  #include "mi/mi-common.h"
>  #include "python/python.h"
>  
> +extern int hex2bin (const char *hex, gdb_byte *bin, int count);
> +extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
> +
>  /* Prototypes for local functions.  */
>  
>  static void enable_delete_command (char *, int);
> @@ -512,6 +515,19 @@ gdb_evaluates_breakpoint_condition_p (vo
>    return (mode == condition_evaluation_host);
>  }
>  
> +const char target_defined_breakpoints_query[] = "query";
> +const char target_defined_breakpoints_merge[] = "merge";
> +const char target_defined_breakpoints_gdb[] = "gdb";
> +const char target_defined_breakpoints_target[] = "target";
> +const char *const target_defined_breakpoints_enums[] = {
> +  target_defined_breakpoints_query,
> +  target_defined_breakpoints_merge,
> +  target_defined_breakpoints_gdb,
> +  target_defined_breakpoints_target,
> +  NULL
> +};
> +const char *target_defined_breakpoints_mode = target_defined_breakpoints_query;
> +
>  void _initialize_breakpoint (void);
>  
>  /* Are we executing breakpoint commands?  */
> @@ -1219,6 +1235,15 @@ breakpoint_set_commands (struct breakpoi
>    observer_notify_breakpoint_modified (b);
>  }
>  
> +struct command_line *
> +breakpoint_get_commands (struct breakpoint *b)
> +{
> +  if (b->commands && b->commands->commands)
> +    return b->commands->commands;
> +
> +  return NULL;
> +}
> +
>  /* Set the internal `silent' flag on the breakpoint.  Note that this
>     is not the same as the "silent" that may appear in the breakpoint's
>     commands.  */
> @@ -6195,6 +6220,14 @@ print_one_breakpoint (struct breakpoint
>  	    }
>  	}
>      }
> +
> +    if (b->target_defined_id)
> +      {
> +	annotate_field (7);
> +	ui_out_text (uiout, "\ttarget-defined-breakpoint ");
> +	ui_out_field_int (uiout, "id", b->target_defined_id);
> +	ui_out_text (uiout, "\n");
> +      }
>  }
>  
>  static int
> @@ -6914,6 +6947,8 @@ init_raw_breakpoint_without_location (st
>    b->condition_not_parsed = 0;
>    b->py_bp_object = NULL;
>    b->related_breakpoint = b;
> +  b->target_defined_id = 0;
> +  b->target_defined_inserted = 0;
>  }
>  
>  /* Helper to set_raw_breakpoint below.  Creates a breakpoint
> @@ -15722,6 +15757,515 @@ pc_at_non_inline_function (struct addres
>    return 0;
>  }
>  
> +static int
> +target_defined_breakpoints_get_id (void)
> +{
> +  struct breakpoint *b;
> +  int id = 1;
> +
> +  while (1)
> +    {
> +      ALL_BREAKPOINTS (b)
> +	{
> +	  if (b->target_defined_id == id)
> +	    break;
> +	}
> +      if (b)
> +	id ++;
> +      else
> +	break;
> +    }
> +
> +  return id;
> +}
> +
> +static void
> +uploaded_bp_commands_clean (struct uploaded_bp *ubp)
> +{
> +  struct uploaded_bpcmd *cmd, *cmd_tmp;
> +
> +  for (cmd = ubp->commands; cmd ? (cmd_tmp = cmd->next, 1): 0; cmd = cmd_tmp)
> +    xfree (cmd);
> +  ubp->commands = NULL;
> +}
> +
> +static void
> +uploaded_bp_commands_add (struct uploaded_bp *ubp, char *buf)
> +{
> +  struct uploaded_bpcmd *new_cmd, *cmd;
> +
> +  new_cmd = xzalloc (sizeof (struct uploaded_bpcmd));
> +  new_cmd->str = xstrdup (buf);
> +
> +  for (cmd = ubp->commands; cmd && cmd->next; cmd = cmd->next)
> +    ;
> +  if (cmd)
> +    cmd->next = new_cmd;
> +  else
> +    ubp->commands = new_cmd;
> +}
> +
> +static void
> +handle_target_defined_breakpoint_cmd (char cmd, struct uploaded_bp *ubp)
> +{
> +  switch (cmd)
> +    {
> +    case 'E':
> +      ubp->enable = 1;
> +      break;
> +    case 'D':
> +      ubp->enable = 0;
> +      break;
> +    case 'R':
> +      ubp->removed = 1;
> +      break;
> +    }
> +}
> +
> +/* Given a line of text defining a part of a tracepoint
> +   or a target-defined breakpoint, parse it into UP.  */
> +
> +int
> +parse_tracepoint_breakpoint_definition (char *line, void *up,
> +					int is_tracepoint)
> +{
> +  char *p;
> +  char piece;
> +  ULONGEST num;
> +
> +  p = line;
> +  /* Both tracepoint and action definitions start with the same number
> +     and address sequence.  */
> +  piece = *p++;
> +  p = unpack_varlen_hex (p, &num);
> +  p++;  /* skip a colon */
> +
> +  if (is_tracepoint)
> +    {
> +      ULONGEST addr, step, pass, orig_size, xlen, start;
> +      int enabled, end;
> +      enum bptype type;
> +      char *cond, *srctype, *buf;
> +      struct uploaded_tp **utpp = up;
> +      struct uploaded_tp *utp = NULL;
> +
> +      p = unpack_varlen_hex (p, &addr);
> +      p++;  /* skip a colon */
> +
> +      if (piece == 'T')
> +	{
> +	  enabled = (*p++ == 'E');
> +	  p++;  /* skip a colon */
> +	  p = unpack_varlen_hex (p, &step);
> +	  p++;  /* skip a colon */
> +	  p = unpack_varlen_hex (p, &pass);
> +	  type = bp_tracepoint;
> +	  cond = NULL;
> +	  /* Thumb through optional fields.  */
> +	  while (*p == ':')
> +	   {
> +	      p++;  /* skip a colon */
> +	      if (*p == 'F')
> +		{
> +		  type = bp_fast_tracepoint;
> +		  p++;
> +		  p = unpack_varlen_hex (p, &orig_size);
> +		}
> +	      else if (*p == 'S')
> +		{
> +		  type = bp_static_tracepoint;
> +		  p++;
> +		}
> +	      else if (*p == 'X')
> +		{
> +		  p++;
> +		  p = unpack_varlen_hex (p, &xlen);
> +		  p++;  /* skip a comma */
> +		  cond = (char *) xmalloc (2 * xlen + 1);
> +		  strncpy (cond, p, 2 * xlen);
> +		  cond[2 * xlen] = '\0';
> +		  p += 2 * xlen;
> +		}
> +	      else
> +		warning (_("Unrecognized char '%c' in tracepoint "
> +			   "definition, skipping rest"), *p);
> +	    }
> +	  utp = get_uploaded_tp (num, addr, utpp);
> +	  utp->type = type;
> +	  utp->enabled = enabled;
> +	  utp->step = step;
> +	  utp->pass = pass;
> +	  utp->cond = cond;
> +	}
> +      else if (piece == 'A')
> +	{
> +	  utp = get_uploaded_tp (num, addr, utpp);
> +	  VEC_safe_push (char_ptr, utp->actions, xstrdup (p));
> +	}
> +      else if (piece == 'S')
> +	{
> +	  utp = get_uploaded_tp (num, addr, utpp);
> +	  VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p));
> +	}
> +      else if (piece == 'Z')
> +	{
> +	  /* Parse a chunk of source form definition.  */
> +	  utp = get_uploaded_tp (num, addr, utpp);
> +	  srctype = p;
> +	  p = strchr (p, ':');
> +	  p++;  /* skip a colon */
> +	  p = unpack_varlen_hex (p, &start);
> +	  p++;  /* skip a colon */
> +	  p = unpack_varlen_hex (p, &xlen);
> +	  p++;  /* skip a colon */
> +
> +	  buf = alloca (strlen (line));
> +
> +	  end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
> +	  buf[end] = '\0';
> +
> +	  if (strncmp (srctype, "at:", strlen ("at:")) == 0)
> +	    utp->at_string = xstrdup (buf);
> +	  else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
> +	    utp->cond_string = xstrdup (buf);
> +	  else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
> +	    VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
> +	}
> +      else if (piece == 'V')
> +	{
> +	  utp = get_uploaded_tp (num, addr, utpp);
> +
> +	  parse_tracepoint_status (p, NULL, utp);
> +	}
> +      else
> +	{
> +	  /* Don't error out, the target might be sending us optional
> +	     info that we don't care about.  */
> +	  warning (_("Unrecognized tracepoint piece '%c', ignoring"), piece);
> +	}
> +    }
> +  else
> +    {
> +      struct uploaded_bp **ubpp = up;
> +      struct uploaded_bp *ubp, *ubp_tmp;
> +
> +      if ((piece == 'C' || piece == 'O') && num == 0)
> +        return -1;
> +
> +      for (ubp = *ubpp; ubp ? (ubp_tmp = ubp->next, 1): 0; ubp = ubp_tmp)
> +	{
> +	  int loop_stop = 0;
> +
> +	  if (ubp->removed)
> +	    continue;
> +
> +	  switch (piece)
> +	    {
> +	    case 'E':
> +	    case 'D':
> +	    case 'R':
> +	      if (num == 0)
> +		handle_target_defined_breakpoint_cmd (piece, ubp);
> +	      else if (ubp->id == (int) num)
> +		{
> +		  if (p[0] != '\0' && piece != 'R')
> +		    {
> +		      /* Get the ubp that same with the id,
> +			 change it to new value.  */
> +		      loop_stop = 1;
> +		    }
> +		  else
> +		    {
> +		      handle_target_defined_breakpoint_cmd (piece, ubp);
> +		      return 0;
> +		    }
> +		}
> +	      break;
> +	    case 'C':
> +	    case 'O':
> +	      if (ubp->id == (int)num)
> +		loop_stop = 1;
> +	      break;
> +	    default:
> +	      return -1;
> +	      break;
> +	    }
> +
> +	  if (loop_stop)
> +	    break;
> +	}
> +
> +      if (num == 0)
> +	return 0;
> +
> +      switch (piece)
> +	{
> +	case 'E':
> +	case 'D':
> +	  {
> +	    char *b_addr_hex;
> +	    char *b_addr;
> +	    enum bptype b_type;
> +	    ULONGEST ignore_num;
> +	    int end;
> +
> +	    b_addr_hex = p;
> +	    p = strchr (p, ':');
> +	    if (!p)
> +	      return -1;
> +	    p[0] = '\0';
> +	    p += 1;
> +	    b_addr = alloca (strlen (b_addr_hex) / 2);
> +	    end = hex2bin (b_addr_hex, (gdb_byte *) b_addr,
> +			   strlen (b_addr_hex) / 2);
> +	    b_addr[end] = '\0';
> +
> +	    if (p[0] == 'S')
> +	      b_type = bp_breakpoint;
> +	    else if (p[0] == 'H')
> +	      b_type = bp_hardware_breakpoint;
> +	    else
> +	      return -1;
> +	    if (p[1] != ':' || p[2] == '\0')
> +	      return -1;
> +	    p += 2;
> +
> +	    unpack_varlen_hex (p, &ignore_num);
> +
> +	    if (ubp)
> +	      ubp->removed = 1;
> +	    ubp = xzalloc (sizeof (struct uploaded_bp));
> +
> +            ubp->id = (int) num;
> +	    ubp->enable = (piece == 'E') ? 1 : 0;
> +	    ubp->addr_string = xstrdup (b_addr);
> +	    ubp->type = b_type;
> +	    ubp->ignore_count = (int) ignore_num;
> +
> +	    for (ubp_tmp = *ubpp; ubp_tmp && ubp_tmp->next;
> +		 ubp_tmp = ubp_tmp->next)
> +	      ;
> +	    if (ubp_tmp)
> +	      ubp_tmp->next = ubp;
> +	    else
> +	      *ubpp = ubp;
> +	  }
> +	  break;
> +        case 'R':
> +	  return -1;
> +	  break;
> +	case 'C':
> +	case 'O':
> +	  if (!ubp)
> +	    return -1;
> +	  {
> +	    char *buf;
> +	    int end;
> +
> +	    buf = alloca (strlen (p)/2 + 1);
> +	    end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
> +	    buf[end] = '\0';
> +	    if (piece == 'O')
> +	      {
> +		if (ubp->condition)
> +		  {
> +		    xfree (ubp->condition);
> +		    ubp->condition = NULL;
> +		  }
> +		if (end)
> +		  ubp->condition = xstrdup (buf);
> +	      }
> +	    else
> +	      {
> +		if (end == 0)
> +		  uploaded_bp_commands_clean (ubp);
> +		else
> +		  uploaded_bp_commands_add (ubp, buf);
> +	      }
> +	  }
> +	  break;
> +	}
> +    }
> +
> +  return 0;
> +}
> +
> +void
> +clean_upload_target_defined_breakpoints (void *p)
> +{
> +  struct uploaded_bp **ubpp = p;
> +  struct uploaded_bp *ubp, *ubp_tmp;
> +
> +  for (ubp = *ubpp; ubp ? (ubp_tmp = ubp->next, 1): 0; ubp = ubp_tmp)
> +    {
> +      uploaded_bp_commands_clean (ubp);
> +      xfree (ubp);
> +    }
> +  *ubpp = NULL;
> +}
> +
> +void
> +show_upload_target_defined_breakpoints (struct uploaded_bp *ubp)
> +{
> +  struct uploaded_bp *tmp;
> +  int number = 0;
> +
> +  for (tmp = ubp; tmp; tmp = tmp->next)
> +    {
> +      if (!tmp->removed)
> +        number ++;
> +    }
> +  if (number)
> +    printf_filtered (_("Got %d target-defined-breakpoints from target\n"), number);
> +  else
> +    return;
> +
> +  for (tmp = ubp; tmp; tmp = tmp->next)
> +    {
> +      if (tmp->removed)
> +	continue;
> +      printf_filtered (_("Id %d in %s"), tmp->id, tmp->addr_string);
> +      if (tmp->condition)
> +	printf_filtered (_(" stop only if %s"), tmp->condition);
> +      if (tmp->ignore_count)
> +	printf_filtered (_(" ignore next %d hits"), tmp->ignore_count);
> +      printf_filtered (_("\n"));
> +      if (tmp->commands)
> +        {
> +	  struct uploaded_bpcmd *cmd;
> +
> +	  for (cmd = ubp->commands; cmd; cmd = cmd->next)
> +	    printf_filtered (_("    %s\n"), cmd->str);
> +	}
> +    }
> +}
> +
> +struct uploaded_bpcmd *this_ubpcmd = NULL;
> +
> +static char *
> +read_target_defined_breakpoints_action (void)
> +{
> +  char *ret = NULL;
> +
> +  if (this_ubpcmd)
> +    {
> +      ret = this_ubpcmd->str;
> +      this_ubpcmd = this_ubpcmd->next;
> +    }
> +
> +  return ret;
> +}
> +
> +void
> +merge_uploaded_target_defined_breakpoints (struct uploaded_bp *ubp)
> +{
> +  for (; ubp; ubp = ubp->next)
> +    {
> +      struct breakpoint *b;
> +
> +      if (ubp->removed)
> +	continue;
> +
> +      ALL_BREAKPOINTS(b)
> +        {
> +	  if (b->target_defined_inserted)
> +	    continue;
> +
> +	  if (b->target_defined_id == ubp->id)
> +	    {
> +	      if (strcmp (b->addr_string, ubp->addr_string) == 0)
> +		{
> +		  printf_filtered (_("\
> +Assuming target_defined-breakpoints %d in GDB is same as target's\n\
> +target_defined-breakpoints %d at %s.\n"),
> +				   b->number, ubp->id, ubp->addr_string);
> +		  b->target_defined_inserted = 1;
> +		  break;
> +		}
> +	       else
> +		{
> +		  b->target_defined_id = target_defined_breakpoints_get_id ();
> +		  printf_filtered (_("\
> +Change breakpoint %d's target-defined-breakpoints id to %d.\n"),
> +				   b->number, b->target_defined_id);
> +		}
> +	    }
> +	}
> +
> +      if (!b)
> +        {
> +          /* Create new breakpoint.  */
> +          if (!create_breakpoint (get_current_arch (),
> +				  ubp->addr_string,
> +				  ubp->condition, -1, 0, 0, 0,
> +				  ubp->type,
> +				  ubp->ignore_count,
> +				  pending_break_support,
> +				  &bkpt_breakpoint_ops,
> +				  0,
> +				  ubp->enable,
> +				  0, CREATE_BREAKPOINT_FLAGS_INSERTED))
> +	    {
> +	      printf_filtered (_("\
> +Create breakpoint for target-defined-breakpoint %d got error.\n"),
> +			       ubp->id);
> +	      continue;
> +	    }
> +	  b = get_breakpoint (breakpoint_count);
> +	  b->target_defined_id = ubp->id;
> +	  b->target_defined_inserted = 1;
> +	  if (ubp->commands)
> +	    {
> +	      struct command_line *cmd_list;
> +
> +	      this_ubpcmd = ubp->commands;
> +	      cmd_list = read_command_lines_1 (read_target_defined_breakpoints_action,
> +					       1, NULL, NULL);
> +	      breakpoint_set_commands (b, cmd_list);
> +	    }
> +	  printf_filtered (_("\
> +Create breakpoint %d for target-defined-breakpoint %d.\n"),
> +			   b->number, b->target_defined_id);
> +	}
> +    }
> +}
> +
> +void
> +target_defined_breakpoints_reset (void)
> +{
> +  struct breakpoint *b;
> +
> +  ALL_BREAKPOINTS(b)
> +    b->target_defined_inserted = 0;
> +}
> +
> +void
> +target_defined_breakpoints_clean (void)
> +{
> +  struct breakpoint *b, *btmp;
> +
> +  ALL_BREAKPOINTS_SAFE (b, btmp)
> +    {
> +      if (b->target_defined_id)
> +        delete_breakpoint (b);
> +    }
> +}
> +
> +int
> +target_defined_breakpoints_number (void)
> +{
> +  int ret = 0;
> +  struct breakpoint *b;
> +
> +  ALL_BREAKPOINTS(b)
> +    {
> +      if (b->target_defined_id)
> +        ret ++;
> +    }
> +
> +  return ret;
> +}
> +
>  void
>  initialize_breakpoint_ops (void)
>  {
> @@ -16494,6 +17038,24 @@ be set to \"gdb\""),
>  			   &breakpoint_set_cmdlist,
>  			   &breakpoint_show_cmdlist);
>  
> +  add_setshow_enum_cmd ("target-defined", class_support,
> +			target_defined_breakpoints_enums, &target_defined_breakpoints_mode,
> +			_("\
> +Set mode for target-defined-breakpoints."), _("\
> +Show mode for target-defined-breakpoints."), _("\
> +When this mode is \"query\" (the default mode), will query when got the\n\
> +target-defined-breakpoints.\n\
> +When this mode is \"merge\", the target-defined-breakpoints\n\
> +of GDB and target will merge together when GDB connect to target.\n\
> +When this mode is \"gdb\", the target-defined-breakpoints of target will be removed\n\
> +when GDB connect to target.\n\
> +When this mode is \"target\", the target-defined-breakpoints of GDB will be removed\n\
> +when GDB connect to target."),
> +			   NULL,
> + 			   NULL,
> + 			   &breakpoint_set_cmdlist,
> + 			   &breakpoint_show_cmdlist);
> +
>    add_com ("break-range", class_breakpoint, break_range_command, _("\
>  Set a breakpoint for an address range.\n\
>  break-range START-LOCATION, END-LOCATION\n\
> --- a/breakpoint.h
> +++ b/breakpoint.h
> @@ -735,6 +735,9 @@ struct breakpoint
>         can sometimes be NULL for enabled GDBs as not all breakpoint
>         types are tracked by the Python scripting API.  */
>      struct breakpoint_object *py_bp_object;
> +
> +    int target_defined_id;
> +    int target_defined_inserted;
>    };
>  
>  /* An instance of this type is used to represent a watchpoint.  It
> @@ -1085,6 +1088,25 @@ struct bpstats
>      enum bp_print_how print_it;
>    };
>  
> +struct uploaded_bpcmd
> +  {
> +    struct uploaded_bpcmd *next;
> +    char *str;
> +  };
> +
> +struct uploaded_bp
> +  {
> +    int removed;
> +    struct uploaded_bp *next;
> +    int id;
> +    int enable;
> +    char *addr_string;
> +    enum bptype type;
> +    int ignore_count;
> +    char *condition;
> +    struct uploaded_bpcmd *commands;
> +  };
> +
>  enum inf_context
>    {
>      inf_starting,
> @@ -1101,8 +1123,14 @@ enum breakpoint_here
>      ordinary_breakpoint_here,
>      permanent_breakpoint_here
>    };
> -
>  
> +extern const char target_defined_breakpoints_query[];
> +extern const char target_defined_breakpoints_merge[];
> +extern const char target_defined_breakpoints_gdb[];
> +extern const char target_defined_breakpoints_target[];
> +extern const char *target_defined_breakpoints_mode;
> +
> +
>  /* Prototypes for breakpoint-related functions.  */
>  
>  extern enum breakpoint_here breakpoint_here_p (struct address_space *, 
> @@ -1374,6 +1402,8 @@ extern void enable_breakpoint (struct br
>  extern void breakpoint_set_commands (struct breakpoint *b, 
>  				     struct command_line *commands);
>  
> +extern struct command_line * breakpoint_get_commands (struct breakpoint *b);
> +
>  extern void breakpoint_set_silent (struct breakpoint *b, int silent);
>  
>  extern void breakpoint_set_thread (struct breakpoint *b, int thread);
> @@ -1523,4 +1553,19 @@ extern struct gdbarch *get_sal_arch (str
>  
>  extern void handle_solib_event (void);
>  
> +extern void target_defined_breakpoints_reset (void);
> +
> +extern void target_defined_breakpoints_clean (void);
> +
> +extern int target_defined_breakpoints_number (void);
> +
> +extern void clean_upload_target_defined_breakpoints (void *p);
> +
> +extern void show_upload_target_defined_breakpoints (struct uploaded_bp *ubp);
> +
> +extern void merge_uploaded_target_defined_breakpoints (struct uploaded_bp *ubp);
> +
> +extern int parse_tracepoint_breakpoint_definition (char *line, void *up,
> +						   int is_tracepoint);
> +
>  #endif /* !defined (BREAKPOINT_H) */
> --- a/remote.c
> +++ b/remote.c
> @@ -216,6 +216,10 @@ static int remote_get_trace_status (stru
>  static int remote_upload_tracepoints (struct uploaded_tp **utpp);
>  
>  static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp);
> +
> +static int remote_upload_target_defined_breakpoints (struct uploaded_bp **ubpp);
> +
> +static void remote_download_target_defined_breakpoints (void);
>    
>  static void remote_query_supported (void);
>  
> @@ -1284,6 +1288,7 @@ enum {
>    PACKET_qXfer_fdpic,
>    PACKET_QDisableRandomization,
>    PACKET_QAgent,
> +  PACKET_TargetDefinedBreakpoints,
>    PACKET_MAX
>  };
>  
> @@ -3521,6 +3526,52 @@ remote_start_remote (int from_tty, struc
>       up.  */
>    rs->starting_up = 0;
>  
> +  /* Get target-defined-breakpoints from target.  */
> +  if (remote_protocol_packets[PACKET_TargetDefinedBreakpoints].support
> +	!= PACKET_DISABLE)
> +    {
> +      static struct uploaded_bp *uploaded_bps = NULL;
> +      struct cleanup *old_chain = make_cleanup
> +					(clean_upload_target_defined_breakpoints,
> +					 &uploaded_bps);
> +      int num;
> +
> +      if ((target_defined_breakpoints_mode == target_defined_breakpoints_target)
> +	  || (target_defined_breakpoints_mode == target_defined_breakpoints_query
> +	      && (num = target_defined_breakpoints_number ())
> +	      && query (_("Remove %d target-defined-breakpoints in GDB?"), num)))
> +	target_defined_breakpoints_clean ();
> +      else
> +	target_defined_breakpoints_reset ();
> +
> +      if (target_defined_breakpoints_mode != target_defined_breakpoints_gdb)
> +        {
> +          remote_upload_target_defined_breakpoints (&uploaded_bps);
> +	  show_upload_target_defined_breakpoints (uploaded_bps);
> +	}
> +      else
> +        {
> +	  /* Remove all the target-defined-breakpoints in target part.  */
> +	  snprintf (rs->buf, rs->buf_size, "QBDP:0:R");
> +	  remote_send (&rs->buf, &rs->buf_size);
> +	}
> +
> +      if (target_defined_breakpoints_mode == target_defined_breakpoints_query)
> +        {
> +	  if (uploaded_bps)
> +	    {
> +	      if (!query (_("Add to GDB?")))
> +		clean_upload_target_defined_breakpoints (&uploaded_bps);
> +	    }
> +	}
> +
> +      merge_uploaded_target_defined_breakpoints (uploaded_bps);
> +
> +      do_cleanups (old_chain);
> +
> +      remote_download_target_defined_breakpoints ();
> +    }
> +
>    /* If breakpoints are global, insert them now.  */
>    if (gdbarch_has_global_breakpoints (target_gdbarch ())
>        && breakpoints_always_inserted_mode ())
> @@ -3929,6 +3980,8 @@ static struct protocol_feature remote_pr
>    { "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
>    { "tracenz", PACKET_DISABLE,
>      remote_string_tracing_feature, -1 },
> +  { "TargetDefinedBreakpoints", PACKET_DISABLE, remote_supported_packet,
> +    PACKET_TargetDefinedBreakpoints },
>  };
>  
>  static char *remote_support_xml;
> @@ -11311,7 +11364,7 @@ remote_upload_tracepoints (struct upload
>    p = rs->buf;
>    while (*p && *p != 'l')
>      {
> -      parse_tracepoint_definition (p, utpp);
> +      parse_tracepoint_breakpoint_definition (p, utpp, 1);
>        /* Ask for another packet of tracepoint definition.  */
>        putpkt ("qTsP");
>        getpkt (&rs->buf, &rs->buf_size, 0);
> @@ -11341,6 +11394,83 @@ remote_upload_trace_state_variables (str
>    return 0;
>  }
>  
> +static int
> +remote_upload_target_defined_breakpoints (struct uploaded_bp **ubpp)
> +{
> +  struct remote_state *rs = get_remote_state ();
> +  char *p;
> +
> +  /* Ask for a first packet of target-defined-breakpoints definition.  */
> +  putpkt ("qBfP");
> +  getpkt (&rs->buf, &rs->buf_size, 0);
> +  p = rs->buf;
> +  while (*p && *p != 'l')
> +    {
> +      parse_tracepoint_breakpoint_definition (p, ubpp, 0);
> +      /* Ask for another packet of target-defined-breakpoints definition.  */
> +      putpkt ("qBsP");
> +      getpkt (&rs->buf, &rs->buf_size, 0);
> +      p = rs->buf;
> +    }
> +  return 0;
> +}
> +
> +static void
> +remote_download_target_defined_breakpoints (void)
> +{
> +  struct remote_state *rs = get_remote_state ();
> +  struct breakpoint *b;
> +  extern struct breakpoint *breakpoint_chain;
> +
> +  for (b = breakpoint_chain;  b; b = b->next)
> +    {
> +      if (b->target_defined_id && !b->target_defined_inserted)
> +	{
> +	  struct command_line *cmd;
> +	  char *hex = alloca (strlen (b->addr_string) * 2);
> +	  int end = bin2hex (b->addr_string, hex, 0);
> +
> +	  hex[end * 2] = '\0';
> +	  snprintf (rs->buf, rs->buf_size, "QBDP:%x:%c:%s:%c:%x",
> +		    b->target_defined_id, (b->enable_state == bp_enabled) ? 'E' : 'D',
> +		    hex,
> +		    (b->type == bp_hardware_breakpoint) ? 'H' : 'S',
> +		    b->ignore_count);
> +	  remote_send (&rs->buf, &rs->buf_size);
> +
> +	  if (b->cond_string)
> +	    {
> +	      char *p = rs->buf;
> +	      int end;
> +
> +	      snprintf (rs->buf, rs->buf_size, "QBDP:%x:O:", b->target_defined_id);
> +	      p += strlen (p);
> +	      end = bin2hex (b->cond_string, p, strlen (b->cond_string));
> +	      p[end] = '\0';
> +	      remote_send (&rs->buf, &rs->buf_size);
> +	    }
> +
> +          for (cmd = breakpoint_get_commands (b); cmd; cmd = cmd->next)
> +	    {
> +	      char *p = rs->buf;
> +	      int end;
> +
> +	      snprintf (rs->buf, rs->buf_size, "QBDP:%x:C:", b->target_defined_id);
> +	      p += strlen (p);
> +	      end = bin2hex (cmd->line, p, strlen (cmd->line));
> +	      p[end] = '\0';
> +	      remote_send (&rs->buf, &rs->buf_size);
> +	    }
> +
> +          b->target_defined_inserted = 1;
> +
> +	  printf_filtered (_("\
> +Download breakpoint %d to target as target-defined-breakpoint %d.\n"),
> +			   b->number, b->target_defined_id);
> +	}
> +    }
> +}
> +
>  void
>  _initialize_remote (void)
>  {
> @@ -11682,6 +11812,9 @@ Show the maximum size of the address (in
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
>  			 "QAgent", "agent", 0);
>  
> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_TargetDefinedBreakpoints],
> +			 "TargetDefinedBreakpoints", "target-defined-breakpoints", 0);
> +
>    /* Keep the old ``set remote Z-packet ...'' working.  Each individual
>       Z sub-packet has its own set and show commands, but users may
>       have sets to this variable in their .gdbinit files (or in their
> --- a/tracepoint.c
> +++ b/tracepoint.c
> @@ -3835,7 +3835,7 @@ tfile_interp_line (char *line,
>    else if (strncmp (p, "tp ", strlen ("tp ")) == 0)
>      {
>        p += strlen ("tp ");
> -      parse_tracepoint_definition (p, utpp);
> +      parse_tracepoint_breakpoint_definition (p, utpp, 1);
>      }
>    else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0)
>      {
> @@ -4029,121 +4029,6 @@ parse_tracepoint_status (char *p, struct
>    /* Ignore any extra, allowing for future extensions.  */
>  }
>  
> -/* Given a line of text defining a part of a tracepoint, parse it into
> -   an "uploaded tracepoint".  */
> -
> -void
> -parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
> -{
> -  char *p;
> -  char piece;
> -  ULONGEST num, addr, step, pass, orig_size, xlen, start;
> -  int enabled, end;
> -  enum bptype type;
> -  char *cond, *srctype, *buf;
> -  struct uploaded_tp *utp = NULL;
> -
> -  p = line;
> -  /* Both tracepoint and action definitions start with the same number
> -     and address sequence.  */
> -  piece = *p++;
> -  p = unpack_varlen_hex (p, &num);
> -  p++;  /* skip a colon */
> -  p = unpack_varlen_hex (p, &addr);
> -  p++;  /* skip a colon */
> -  if (piece == 'T')
> -    {
> -      enabled = (*p++ == 'E');
> -      p++;  /* skip a colon */
> -      p = unpack_varlen_hex (p, &step);
> -      p++;  /* skip a colon */
> -      p = unpack_varlen_hex (p, &pass);
> -      type = bp_tracepoint;
> -      cond = NULL;
> -      /* Thumb through optional fields.  */
> -      while (*p == ':')
> -	{
> -	  p++;  /* skip a colon */
> -	  if (*p == 'F')
> -	    {
> -	      type = bp_fast_tracepoint;
> -	      p++;
> -	      p = unpack_varlen_hex (p, &orig_size);
> -	    }
> -	  else if (*p == 'S')
> -	    {
> -	      type = bp_static_tracepoint;
> -	      p++;
> -	    }
> -	  else if (*p == 'X')
> -	    {
> -	      p++;
> -	      p = unpack_varlen_hex (p, &xlen);
> -	      p++;  /* skip a comma */
> -	      cond = (char *) xmalloc (2 * xlen + 1);
> -	      strncpy (cond, p, 2 * xlen);
> -	      cond[2 * xlen] = '\0';
> -	      p += 2 * xlen;
> -	    }
> -	  else
> -	    warning (_("Unrecognized char '%c' in tracepoint "
> -		       "definition, skipping rest"), *p);
> -	}
> -      utp = get_uploaded_tp (num, addr, utpp);
> -      utp->type = type;
> -      utp->enabled = enabled;
> -      utp->step = step;
> -      utp->pass = pass;
> -      utp->cond = cond;
> -    }
> -  else if (piece == 'A')
> -    {
> -      utp = get_uploaded_tp (num, addr, utpp);
> -      VEC_safe_push (char_ptr, utp->actions, xstrdup (p));
> -    }
> -  else if (piece == 'S')
> -    {
> -      utp = get_uploaded_tp (num, addr, utpp);
> -      VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p));
> -    }
> -  else if (piece == 'Z')
> -    {
> -      /* Parse a chunk of source form definition.  */
> -      utp = get_uploaded_tp (num, addr, utpp);
> -      srctype = p;
> -      p = strchr (p, ':');
> -      p++;  /* skip a colon */
> -      p = unpack_varlen_hex (p, &start);
> -      p++;  /* skip a colon */
> -      p = unpack_varlen_hex (p, &xlen);
> -      p++;  /* skip a colon */
> -
> -      buf = alloca (strlen (line));
> -
> -      end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
> -      buf[end] = '\0';
> -
> -      if (strncmp (srctype, "at:", strlen ("at:")) == 0)
> -	utp->at_string = xstrdup (buf);
> -      else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
> -	utp->cond_string = xstrdup (buf);
> -      else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
> -	VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
> -    }
> -  else if (piece == 'V')
> -    {
> -      utp = get_uploaded_tp (num, addr, utpp);
> -
> -      parse_tracepoint_status (p, NULL, utp);
> -    }
> -  else
> -    {
> -      /* Don't error out, the target might be sending us optional
> -	 info that we don't care about.  */
> -      warning (_("Unrecognized tracepoint piece '%c', ignoring"), piece);
> -    }
> -}
> -
>  /* Convert a textual description of a trace state variable into an
>     uploaded object.  */
>  
> --- a/tracepoint.h
> +++ b/tracepoint.h
> @@ -259,8 +259,6 @@ extern void parse_trace_status (char *li
>  extern void parse_tracepoint_status (char *p, struct breakpoint *tp,
>  				     struct uploaded_tp *utp);
>  
> -extern void parse_tracepoint_definition (char *line,
> -					 struct uploaded_tp **utpp);
>  extern void parse_tsv_definition (char *line, struct uploaded_tsv **utsvp);
>  
>  extern struct uploaded_tp *get_uploaded_tp (int num, ULONGEST addr,

> --- a/doc/gdb.texinfo
> +++ b/doc/gdb.texinfo
> @@ -3805,6 +3805,34 @@ not support breakpoint condition evaluat
>  to evaluating all these conditions on the host's side.
>  @end table
>  
> +Prior to @value{GDBN} connects to remote target, some breakpoints might
> +have been already set in target, either by a prior @value{GDBN} session or
> +by the program itself through some special system API.  When @value{GDBN}
> +connects to target, it should handle these existing breakpoints from
> +remote target.  We call these breakpoints @dfn{target-defined-breakpoints}.
> +
> +This feature can be controlled via the following commands:
> +
> +@kindex set breakpoint target-defined
> +@kindex show breakpoint target-defined
> +@table @code
> +@item set breakpoint target-defined query
> +If this option is @samp{query} (the default), @value{GDBN} will query the user
> +how to handle the target-defined-breakpoints when @value{GDBN} connects to the target.
> +
> +@item set breakpoint target-defined merge
> +If this option is @samp{merge}, the target-defined-breakpoints of both @value{GDBN}
> +and of the target will be kept.
> +
> +@item set breakpoint target-defined gdb
> +If this option is @samp{gdb}, the target-defined-breakpoints of target will be removed
> +when @value{GDBN} connects to target.
> +
> +@item set breakpoint target-defined target
> +If this option is @samp{target}, the target-defined-breakpoints of @value{GDBN} will
> +be removed when @value{GDBN} connects to target.
> +@end table
> +
>  
>  @cindex negative breakpoint numbers
>  @cindex internal @value{GDBN} breakpoints
> @@ -35422,6 +35450,7 @@ Show the current setting of the target w
>  * Memory Map Format::
>  * Thread List Format::
>  * Traceframe Info Format::
> +* Target-defined-breakpoints Format::
>  @end menu
>  
>  @node Overview
> @@ -40115,6 +40144,77 @@ The formal DTD for the traceframe info f
>                          length  CDATA   #REQUIRED>
>  @end smallexample
>  
> +@node Target-defined-breakpoints Format
> +@section Target-defined-breakpoints Format
> +@cindex target-defined-breakpoints format
> +
> +@table @samp
> +@item qBfP
> +@itemx qBsP
> +These packets request data in target-defined-breakpoints base format
> +about target-defined-breakpoints from the target.
> +@value{GDBN} sends @code{qBfP} to get the first piece
> +of data, and multiple @code{qTsP} to get additional pieces.
> +
> +@item @samp{QBDP}:@var{target-defined-breakpoints base format}
> +@value{GDBN} uses this packet to control the target-defined-breakpoints in the remote.
> +@end table
> +
> +Target-defined-breakpoints base format describes the operation of
> +the target-defined-breakpoints in @value{GDBN} and the target.
> +
> +@table @samp
> +
> +@item @var{command}:@var{id}:@var{addr_string}:@var{type}:@var{ignore_num}
> +@table @samp
> +@item @var{command}
> +This is the command character, either @samp{E} (for ``enable'') or
> +@samp{D} (for ``disable'').
> +If the target-defined-breakpoint @var{id} does not exist, create one and
> +enable or disable it.  @value{GDBN} will assume the breakpoint already
> +exists and is inserted in the remote, so the target needs to insert
> +the breakpoint when it creates it.
> +If the target-defined-breakpoint @var{id} does exist, the following items
> +will be ignored, and the target-defined-breakpoint will be enabled or
> +disabled as specified by @var{command}.
> +@item @var{id}
> +This is the id in hex string format of the breakpoint to which to
> +apply this command.
> +0 means all target-defined-breakpoints.
> +@item @var{addr_string}
> +This is the address of an target-defined-breakpoint to create, encoded
> +as a hex string.
> +@item @var{type}
> +This is the type of the target-defined-breakpoint to create, either
> +@samp{H} (for ``hardware'') or @samp{S} (for ``software'').
> +@item @var{ignore_num}
> +This is the ignore count of the target-defined-breakpoint to create,
> +encoded as a hex string.
> +@end table
> +
> +@item R:@var{id}
> +This is the remove packet.
> +@var{id} is the number of the target-defined-breakpoint that this command
> +wants to remove, encoded as a hex string.
> +0 means all target-defined-breakpoints.
> +When @value{GDBN} or the target get this packet, they will delete
> +the target-defined-breakpoint @var{id}.
> +
> +@item C:@var{id}:@var{cmd_str}
> +This packet adds commands in @var{cmd_list} to the command list
> +of the target-defined-breakpoint whose number is @var{id}.
> +If @var{cmd_str} is empty, the command list will be emptied.
> +@var{cmd_str} is encoded as hex string.
> +
> +@item O:@var{id}:@var{condition_str}
> +This packet sets the condition of the target-defined-breakpoint @var{id} to
> +be as specified by @var{condition_str}.
> +If @var{condition_str} is empty, the target-defined-breakpoint becomes
> +unconditional.
> +@var{condition_str} is encoded as hex string.
> +
> +@end table
> +
>  @include agentexpr.texi
>  
>  @node Target Descriptions


-- 
Joel


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]