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]

[PATCH 1/4] Fix PR breakpoints/16494: add dprintf-style "agent-call"(gdb)


Because current GDB rsp packet already has the support to put the function
address and channel to gdbserver:
printf (0x34) numargs string â
Do a formatted print, in the style of the C function printf). The value of numargs is the number of arguments to expect on the stack, while string is the format string, prefixed with a two-byte length. The last byte of the string must be zero, and is included in the length. The format string includes escaped sequences just as it appears in C source, so for instance the format string "\t%d\n" is six characters long, and the output will consist of a tab character, a decimal number, and a newline. At the top of the stack, above the values to be printed, this bytecode will pop a âfunctionâ and âchannelâ. If the function is nonzero, then the target may treat it as a function and call it, passing the channel as a first argument, as with the C function fprintf. If the function is zero, then the target may simply call a standard formatted print function of its choice. In all, this bytecode pops 2 + numargs stack elements, and pushes nothing.
This patch doesn't need add anything to this part but a feature support packet "DprintfAgentCall" to make sure if gdbserver support agent-call or not.

I add a new style "agent-call" to GDB send function address and channel
to gdbserver when it send dprintf to gdbserver.

Thanks,
Hui
2014-03-04  Hui Zhu  <hui@codesourcery.com>

	PR breakpoint/16494
	* breakpoint.c (infcall.h): New.
	(dprintf_style_agent_call): New.
	(dprintf_style_enums): Add dprintf_style_agent_call.
	(parse_cmd_to_aexpr): Update comments and arguments.
	(build_target_command_list): Add "dprintf_style_agent_call".
	(update_dprintf_command_list): Ditto.
	* remote.c (remote_state): Add dprintf_agent_call.
	(PACKET_DprintfAgentCall): New.
	(remote_dprintf_agent_call_feature): New.
	(remote_protocol_features): Add "DprintfAgentCall".
	(remote_can_run_dprintf_agent_call): New.
	(init_remote_ops): Add remote_can_run_dprintf_agent_call.
	(_initialize_remote): Add "dprintf-agent-call".
	* target-delegates.c: Rebuild.
	* target.h (target_ops): Add "to_can_run_dprintf_agent_call".
	(target_can_run_dprintf_agent_call): New.

--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -68,6 +68,7 @@
 #include "skip.h"
 #include "ax-gdb.h"
 #include "dummy-frame.h"
+#include "infcall.h"
#include "format.h" @@ -311,10 +312,12 @@ struct breakpoint_ops dprintf_breakpoint
 static const char dprintf_style_gdb[] = "gdb";
 static const char dprintf_style_call[] = "call";
 static const char dprintf_style_agent[] = "agent";
+static const char dprintf_style_agent_call[] = "agent-call";
 static const char *const dprintf_style_enums[] = {
   dprintf_style_gdb,
   dprintf_style_call,
   dprintf_style_agent,
+  dprintf_style_agent_call,
   NULL
 };
 static const char *dprintf_style = dprintf_style_gdb;
@@ -2193,10 +2196,11 @@ build_target_condition_list (struct bp_l
/* Parses a command described by string CMD into an agent expression
    bytecode suitable for evaluation by the bytecode interpreter.
+   FUNCTION and CHANNEL is for the dprintf.
    Return NULL if there was any error during parsing.  */
static struct agent_expr *
-parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
+parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd, char *function, char *channel)
 {
   struct cleanup *old_cleanups = 0;
   struct expression *expr, **argvec;
@@ -2206,6 +2210,9 @@ parse_cmd_to_aexpr (CORE_ADDR scope, cha
   const char *format_start, *format_end;
   struct format_piece *fpieces;
   int nargs;
+  CORE_ADDR function_addr = 0;
+  LONGEST channel_val = 0;
+  struct value *val;
   struct gdbarch *gdbarch = get_current_arch ();
if (!cmd)
@@ -2258,11 +2265,29 @@ parse_cmd_to_aexpr (CORE_ADDR scope, cha
 	++cmdrest;
     }
+ /* Get address of FUNCTION . */
+  if (function != NULL  && strlen (function) > 0)
+    {
+      expr = parse_expression (function);
+      make_cleanup (free_current_contents, &expr);
+      val = evaluate_expression (expr);
+      function_addr = find_function_addr(val, NULL);
+    }
+
+  /* Get value of channel.  */
+  if (channel != NULL && strlen (channel) > 0)
+    {
+      expr = parse_expression (channel);
+      make_cleanup (free_current_contents, &expr);
+      val = evaluate_expression (expr);
+      channel_val = value_as_long(val);
+    }
+
   /* We don't want to stop processing, so catch any errors
      that may show up.  */
   TRY_CATCH (ex, RETURN_MASK_ERROR)
     {
-      aexpr = gen_printf (scope, gdbarch, 0, 0,
+      aexpr = gen_printf (scope, gdbarch, function_addr, channel_val,
 			  format_start, format_end - format_start,
 			  fpieces, nargs, argvec);
     }
@@ -2298,12 +2323,17 @@ build_target_command_list (struct bp_loc
/* For now, limit to agent-style dprintf breakpoints. */
   if (bl->owner->type != bp_dprintf
-      || strcmp (dprintf_style, dprintf_style_agent) != 0)
+      || (strcmp (dprintf_style, dprintf_style_agent) != 0
+	  && strcmp (dprintf_style, dprintf_style_agent_call) != 0))
     return;
if (!target_can_run_breakpoint_commands ())
     return;
+ if (strcmp (dprintf_style, dprintf_style_agent_call) == 0
+      && !target_can_run_dprintf_agent_call ())
+    error (_("Target cannot run dprintf agent call."));
+
   /* Do a first pass to check for locations with no assigned
      conditions or conditions that fail to parse to a valid agent expression
      bytecode.  If any of these happen, then it's no use to send conditions
@@ -2322,8 +2352,15 @@ build_target_command_list (struct bp_loc
 		 case we already freed the command bytecodes (see
 		 force_breakpoint_reinsertion).  We just
 		 need to parse the command to bytecodes again.  */
-	      aexpr = parse_cmd_to_aexpr (bl->address,
-					  loc->owner->extra_string);
+	      if (strcmp (dprintf_style, dprintf_style_agent_call) == 0)
+		aexpr = parse_cmd_to_aexpr (bl->address,
+					    loc->owner->extra_string,
+					    dprintf_function,
+					    dprintf_channel);
+	      else
+		aexpr = parse_cmd_to_aexpr (bl->address,
+					    loc->owner->extra_string,
+					    NULL, NULL);
 	      loc->cmd_bytecode = aexpr;
if (!aexpr)
@@ -9127,6 +9164,16 @@ update_dprintf_command_list (struct brea
 	  printf_line = xstrprintf ("printf %s", dprintf_args);
 	}
     }
+  else if (strcmp (dprintf_style, dprintf_style_agent_call) == 0)
+    {
+      if (target_can_run_dprintf_agent_call ())
+	printf_line = xstrprintf ("agent-printf %s", dprintf_args);
+      else
+	{
+	  warning (_("Target cannot run dprintf agent call, falling back to GDB printf"));
+	  printf_line = xstrprintf ("printf %s", dprintf_args);
+	}
+    }
   else
     internal_error (__FILE__, __LINE__,
 		    _("Invalid dprintf style."));
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -340,6 +340,9 @@ struct remote_state
      commands.  */
   int breakpoint_commands;
+ /* True if the stub reports support for dprintf agent call. */
+  int dprintf_agent_call;
+
   /* True if the stub reports support for fast tracepoints.  */
   int fast_tracepoints;
@@ -1353,6 +1356,7 @@ enum {
   PACKET_ConditionalTracepoints,
   PACKET_ConditionalBreakpoints,
   PACKET_BreakpointCommands,
+  PACKET_DprintfAgentCall,
   PACKET_FastTracepoints,
   PACKET_StaticTracepoints,
   PACKET_InstallInTrace,
@@ -3912,6 +3916,16 @@ remote_breakpoint_commands_feature (cons
 }
static void
+remote_dprintf_agent_call_feature (const struct protocol_feature *feature,
+				   enum packet_support support,
+				   const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  rs->dprintf_agent_call = (support == PACKET_ENABLE);
+}
+
+static void
 remote_fast_tracepoint_feature (const struct protocol_feature *feature,
 				enum packet_support support,
 				const char *value)
@@ -4023,6 +4037,8 @@ static const struct protocol_feature rem
     PACKET_ConditionalBreakpoints },
   { "BreakpointCommands", PACKET_DISABLE, remote_breakpoint_commands_feature,
     PACKET_BreakpointCommands },
+  { "DprintfAgentCall", PACKET_DISABLE, remote_dprintf_agent_call_feature,
+    PACKET_DprintfAgentCall },
   { "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
     PACKET_FastTracepoints },
   { "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature,
@@ -10402,6 +10418,14 @@ remote_download_command_source (int num,
     }
 }
+static int
+remote_can_run_dprintf_agent_call (struct target_ops *self)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return rs->dprintf_agent_call;
+}
+
 static void
 remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
 {
@@ -11462,6 +11486,8 @@ Specify the serial device it is connecte
   remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
   remote_ops.to_supports_evaluation_of_breakpoint_conditions = remote_supports_cond_breakpoints;
   remote_ops.to_can_run_breakpoint_commands = remote_can_run_breakpoint_commands;
+  remote_ops.to_can_run_dprintf_agent_call
+    = remote_can_run_dprintf_agent_call;
   remote_ops.to_trace_init = remote_trace_init;
   remote_ops.to_download_tracepoint = remote_download_tracepoint;
   remote_ops.to_can_download_tracepoint = remote_can_download_tracepoint;
@@ -12050,6 +12076,10 @@ Show the maximum size of the address (in
 			 "BreakpointCommands",
 			 "breakpoint-commands", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_DprintfAgentCall],
+			 "DprintfAgentCall",
+			 "dprintf-agent-call", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_FastTracepoints],
 			 "FastTracepoints", "fast-tracepoints", 0);
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -920,6 +920,19 @@ tdefault_can_run_breakpoint_commands (st
   return 0;
 }
+static int
+delegate_can_run_dprintf_agent_call (struct target_ops *self)
+{
+  self = self->beneath;
+  return self->to_can_run_dprintf_agent_call (self);
+}
+
+static int
+tdefault_can_run_dprintf_agent_call (struct target_ops *self)
+{
+  return 0;
+}
+
 static struct gdbarch *
 delegate_thread_architecture (struct target_ops *self, ptid_t arg1)
 {
@@ -1768,6 +1781,8 @@ install_delegators (struct target_ops *o
     ops->to_supports_evaluation_of_breakpoint_conditions = delegate_supports_evaluation_of_breakpoint_conditions;
   if (ops->to_can_run_breakpoint_commands == NULL)
     ops->to_can_run_breakpoint_commands = delegate_can_run_breakpoint_commands;
+  if (ops->to_can_run_dprintf_agent_call == NULL)
+    ops->to_can_run_dprintf_agent_call = delegate_can_run_dprintf_agent_call;
   if (ops->to_thread_architecture == NULL)
     ops->to_thread_architecture = delegate_thread_architecture;
   if (ops->to_trace_init == NULL)
@@ -1961,6 +1976,7 @@ install_dummy_methods (struct target_ops
   ops->to_supports_string_tracing = tdefault_supports_string_tracing;
   ops->to_supports_evaluation_of_breakpoint_conditions = tdefault_supports_evaluation_of_breakpoint_conditions;
   ops->to_can_run_breakpoint_commands = tdefault_can_run_breakpoint_commands;
+  ops->to_can_run_dprintf_agent_call = tdefault_can_run_dprintf_agent_call;
   ops->to_thread_architecture = default_thread_architecture;
   ops->to_trace_init = tdefault_trace_init;
   ops->to_download_tracepoint = tdefault_download_tracepoint;
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -734,6 +734,11 @@ struct target_ops
     int (*to_can_run_breakpoint_commands) (struct target_ops *)
       TARGET_DEFAULT_RETURN (0);
+ /* Does this target support evaluation of dprintf agent call on its
+       end?  */
+    int (*to_can_run_dprintf_agent_call) (struct target_ops *)
+      TARGET_DEFAULT_RETURN (0);
+
     /* Determine current architecture of thread PTID.
The target is supposed to determine the architecture of the code where
@@ -1242,6 +1247,12 @@ int target_supports_disable_randomizatio
 #define target_can_run_breakpoint_commands() \
   (*current_target.to_can_run_breakpoint_commands) (&current_target)
+/* Return true if this target can handle dprintf agent call
+   on its end.  */
+
+#define target_can_run_dprintf_agent_call() \
+  (*current_target.to_can_run_dprintf_agent_call) (&current_target)
+
 extern int target_read_string (CORE_ADDR, char **, int, int *);
extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr,


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