public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 2/3] GDBServer: introduce --server-output command line option
  2015-03-25 20:48 [PATCH v2 0/3] GDBServer: introduce a dedicated output stream Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command Cleber Rosa
@ 2015-03-25 20:48 ` Cleber Rosa
  2015-03-25 20:55   ` Eli Zaretskii
  2015-03-25 20:48 ` [PATCH v2 1/3] GDBServer: introduce a stream dedicated to the server Cleber Rosa
  2 siblings, 1 reply; 6+ messages in thread
From: Cleber Rosa @ 2015-03-25 20:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: crosa, areis

This command line option will redirect all of the gdbserver's own
output (always sent to stderr) to a separate file.  This feature makes
it possible to distinguish between the inferior process stderr and
gdbserver's own stderr.  Example use case:

 $ gdbserver --server-output=log :2222 bin >bin.out 2>bin.err

Server output will be sent to file named "log", and the inferior
output and error messages will be on files "bin.out" and "bin.err",
respectively.

gdb/Changelog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* NEWS: New feature in the GDBserver: --server-output.

gdb/doc/ChangeLog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* gdb.texinfo (info): Added section on command line and monitor
	commands.
	(gdbserver man): Added section on new command line option.

gdb/gdbserver/ChangeLog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* server.c (set_server_output): New utility function.
	(gdbserver_usage): Add help on '--server-output' option.
	(captured_main): Add command line option parsing for
	'--server-output'.
---
 gdb/NEWS               |  5 +++++
 gdb/doc/gdb.texinfo    | 17 +++++++++++++++++
 gdb/gdbserver/server.c | 28 +++++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 3fa33c9..22044c2 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -96,6 +96,11 @@ vFile:fstat:
 HP/PA running HP-UX           hppa*-*-hpux*
 Itanium running HP-UX         ia64-*-hpux*
 
+* New features in the GDBserver
+
+  ** New option --server-output=file allows users to send the
+     server output to a separate file.
+
 *** Changes in GDB 7.9
 
 * GDB now supports hardware watchpoints on x86 GNU Hurd.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c03ecb0..454f51f 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19204,6 +19204,20 @@ The @option{--remote-debug} option tells @code{gdbserver} to display
 remote protocol debug output.  These options are intended for
 @code{gdbserver} development and for bug reports to the developers.
 
+@cindex @option{--server-output}, @code{gdbserver} option
+The @option{--server-output=@var{file}} option tells @code{gdbserver} to send
+all its output to a file given by @var{file}.  This can be useful, for instance,
+if you need to collect the server output and/or the inferior output, but want
+to keep them separate:
+
+@smallexample
+$ gdbserver --server-output=log :2222 bin >bin.out 2>bin.err
+@end smallexample
+
+Server output will be sent to file named @var{log}, and the inferior
+output and error messages will be on files @var{bin.out} and
+@var{bin.err}, respectively.
+
 @cindex @option{--debug-format}, @code{gdbserver} option
 The @option{--debug-format=option1[,option2,...]} option tells
 @code{gdbserver} to include additional information in each output.
@@ -40892,6 +40906,9 @@ Instruct @code{gdbserver} to include extra information in each line
 of debugging output.
 @xref{Other Command-Line Arguments for gdbserver}.
 
+@item --server-output=file
+Instruct @code{gdbserver} to redirect its own output to @var{file}.
+
 @item --wrapper
 Specify a wrapper to launch programs
 for debugging.  The option should be followed by the name of the
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 73f9f6c..b4a715f 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -723,6 +723,25 @@ get_features_xml (const char *annex)
   return NULL;
 }
 
+/* Opens a file and redirects the server's own output to it  */
+
+static int
+set_server_output (char *output_filename)
+{
+  FILE *tmp;
+
+  tmp = fopen (output_filename, "w");
+  if (tmp == NULL)
+    {
+      fprintf (stderr,
+	       "Could not open server output file '%s': %s\n",
+	       output_filename, strerror(errno));
+      return -1;
+    }
+  server_output = tmp;
+  return 0;
+}
+
 void
 monitor_show_help (void)
 {
@@ -3009,6 +3028,7 @@ gdbserver_usage (FILE *stream)
 	   "                            none\n"
 	   "                            timestamp\n"
 	   "  --remote-debug        Enable remote protocol debugging output.\n"
+	   "  --server-output=FILE  Redirect server's output to FILE.\n"
 	   "  --version             Display version information and exit.\n"
 	   "  --wrapper WRAPPER --  Run WRAPPER to start new programs.\n"
 	   "  --once                Exit after the first connection has "
@@ -3178,7 +3198,13 @@ captured_main (int argc, char *argv[])
 
   while (*next_arg != NULL && **next_arg == '-')
     {
-      if (strcmp (*next_arg, "--version") == 0)
+      if (strncmp (*next_arg, "--server-output=",
+		   sizeof ("--server-output=") - 1) == 0)
+	{
+	  char *out_filename = *next_arg + (sizeof ("--server-output=") - 1);
+	  set_server_output (out_filename);
+	}
+      else if (strcmp (*next_arg, "--version") == 0)
 	{
 	  gdbserver_version ();
 	  exit (0);
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/3] GDBServer: introduce a stream dedicated to the server
  2015-03-25 20:48 [PATCH v2 0/3] GDBServer: introduce a dedicated output stream Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 2/3] GDBServer: introduce --server-output command line option Cleber Rosa
@ 2015-03-25 20:48 ` Cleber Rosa
  2 siblings, 0 replies; 6+ messages in thread
From: Cleber Rosa @ 2015-03-25 20:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: crosa, areis

This dedicated stream, named server_output, is intended to be the
only stream written by the server itself to announce errors. At this
point it is just a pointer to the regular stderr.

gdb/gdbserver/Changelog:
2015-03-24  Cleber Rosa  <crosa@redhat.com>

	* ax.c: Define server_output as an alias of stderr
	when compiling the IPA.
	(ax_vdebug): Replace stderr with server_output.
	* debug.c (debug_vprintf): Replace stderr with server_output.
	(debug_flush): Likewise.
	* event-loop.c (handle_file_event): Likewise.
	* linux-aarch64-low.c (aarch64_show_debug_reg_state):
        Likewise.
	(debug_reg_change_callback): Likewise.
	(aarch64_handle_unaligned_watchpoint): Likewise.
	(aarch64_insert_point): Likewise.
	(aarch64_remove_point): Likewise.
	(aarch64_linux_prepare_to_resume): Likewise.
	* linux-low.c (linux_create_inferior): Likewise.
	(linux_attach): Likewise.
	(check_zombie_leaders): Likewise.
	(linux_resume_one_lwp_throw): Likewise.
	* lynx-low.c (lynx_debug): Likewise.
	(lynx_ptrace): Likewise.
	(lynx_create_inferior): Likewise.
	* mem-break.c (add_breakpoint_condition): Likewise.
	(add_breakpoint_commands): Likewise.
	* notif.c (handle_notif_ack): Likewise.
	(notif_event_enque): Likewise.
	* nto-low.c (nto_trace): Likewise.
	* remote-utils.c (handle_accept_event): Likewise.
	(remote_open): Likewise.
	(putpkt_binary_1): Likewise.
	(input_interrupt): Likewise.
	(readchar): Likewise.
	(getpkt): Likewise.
	* server.c: New server_output stream.
	(start_inferior): Replace stderr with server_output.
	(attach_inferior): Likewise.
	(handle_general_set): Likewise.
	(handle_v_requests): Likewise.
	(print_started_pid): Likewise.
	(print_attached_pid): Likewise.
	(detach_or_kill_for_exit): Likewise.
	(detach_or_kill_for_exit_cleanup): Likewise.
	(captured_main): Point server_output to standard stderr and
	replace stderr with server_output.
	(main): Replace stderr with server_output.
	(process_point_options): Likewise.
	(process_serial_event): Likewise.
	* server.h: New server_output stream definition.
	* spu-low.c (spu_create_inferior): Replace stderr with
        server_output.
	(spu_attach): Likewise.
	(spu_resume): Likewise.
	(spu_wait): Likewise.
	* target.c (mywait): Likewise.
	* thread-db.c (thread_db_create_event): Likewise.
	(try_thread_db_load): Likewise.
	* tracepoint.c: Define server_output as an alias of stderr
	when compiling the IPA.
	(trace_vdebug): Replace stderr with server_output.
	* utils.c: Define server_output as an alias of stderr when
	compiling the IPA.
	(malloc_failure): Replace stderr with gdbserver's own stderr.
	(verror): Likewise.
	(vwarning): Likewise.
	(internal_verror): Likewise.
	(internal_vwarning): Likewise.
	* win32-low.c (OUTMSG): Changed definition of macro to also
	use server_output instead of stderr.
	(OUTMSG2): Likewise.
	* wincecompat.c (perror): Likewise.
---
 gdb/gdbserver/ax.c                |  3 +-
 gdb/gdbserver/debug.c             |  6 +--
 gdb/gdbserver/event-loop.c        |  2 +-
 gdb/gdbserver/linux-aarch64-low.c | 28 ++++++-------
 gdb/gdbserver/linux-low.c         | 10 ++---
 gdb/gdbserver/lynx-low.c          | 14 +++----
 gdb/gdbserver/mem-break.c         |  4 +-
 gdb/gdbserver/notif.c             |  4 +-
 gdb/gdbserver/nto-low.c           |  4 +-
 gdb/gdbserver/remote-utils.c      | 54 ++++++++++++-------------
 gdb/gdbserver/server.c            | 83 ++++++++++++++++++++-------------------
 gdb/gdbserver/server.h            |  4 ++
 gdb/gdbserver/spu-low.c           | 14 +++----
 gdb/gdbserver/target.c            |  4 +-
 gdb/gdbserver/thread-db.c         |  4 +-
 gdb/gdbserver/tracepoint.c        |  4 +-
 gdb/gdbserver/utils.c             | 25 ++++++------
 gdb/gdbserver/win32-low.c         |  6 +--
 gdb/gdbserver/wincecompat.c       |  4 +-
 19 files changed, 144 insertions(+), 133 deletions(-)

diff --git a/gdb/gdbserver/ax.c b/gdb/gdbserver/ax.c
index c5b65fa..db94eb7 100644
--- a/gdb/gdbserver/ax.c
+++ b/gdb/gdbserver/ax.c
@@ -26,6 +26,7 @@ static void ax_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
 
 #ifdef IN_PROCESS_AGENT
 int debug_agent = 0;
+#define server_output stderr
 #endif
 
 static void
@@ -36,7 +37,7 @@ ax_vdebug (const char *fmt, ...)
 
   va_start (ap, fmt);
   vsprintf (buf, fmt, ap);
-  fprintf (stderr, PROG "/ax: %s\n", buf);
+  fprintf (server_output, PROG "/ax: %s\n", buf);
   va_end (ap);
 }
 
diff --git a/gdb/gdbserver/debug.c b/gdb/gdbserver/debug.c
index 1a1e333..df59f8b 100644
--- a/gdb/gdbserver/debug.c
+++ b/gdb/gdbserver/debug.c
@@ -48,11 +48,11 @@ debug_vprintf (const char *format, va_list ap)
       /* If gettimeofday doesn't exist, and as a portability solution it has
 	 been replaced with, e.g., time, then it doesn't make sense to print
 	 the microseconds field.  Is there a way to check for that?  */
-      fprintf (stderr, "%ld:%06ld ", (long) tm.tv_sec, (long) tm.tv_usec);
+      fprintf (server_output, "%ld:%06ld ", (long) tm.tv_sec, (long) tm.tv_usec);
     }
 #endif
 
-  vfprintf (stderr, format, ap);
+  vfprintf (server_output, format, ap);
 
 #if !defined (IN_PROCESS_AGENT)
   if (*format)
@@ -67,7 +67,7 @@ debug_vprintf (const char *format, va_list ap)
 void
 debug_flush (void)
 {
-  fflush (stderr);
+  fflush (server_output);
 }
 
 /* Notify the user that the code is entering FUNCTION_NAME.
diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c
index 08a503f..d744602 100644
--- a/gdb/gdbserver/event-loop.c
+++ b/gdb/gdbserver/event-loop.c
@@ -412,7 +412,7 @@ handle_file_event (gdb_fildes_t event_file_desc)
 
 	  if (file_ptr->ready_mask & GDB_EXCEPTION)
 	    {
-	      fprintf (stderr, "Exception condition detected on fd %s\n",
+	      fprintf (server_output, "Exception condition detected on fd %s\n",
 		       pfildes (file_ptr->fd));
 	      file_ptr->error = 1;
 	    }
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index d44175e..f344ba1 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -323,26 +323,26 @@ aarch64_show_debug_reg_state (struct aarch64_debug_reg_state *state,
 {
   int i;
 
-  fprintf (stderr, "%s", func);
+  fprintf (server_output, "%s", func);
   if (addr || len)
-    fprintf (stderr, " (addr=0x%08lx, len=%d, type=%s)",
+    fprintf (server_output, " (addr=0x%08lx, len=%d, type=%s)",
 	     (unsigned long) addr, len,
 	     type == hw_write ? "hw-write-watchpoint"
 	     : (type == hw_read ? "hw-read-watchpoint"
 		: (type == hw_access ? "hw-access-watchpoint"
 		   : (type == hw_execute ? "hw-breakpoint"
 		      : "??unknown??"))));
-  fprintf (stderr, ":\n");
+  fprintf (server_output, ":\n");
 
-  fprintf (stderr, "\tBREAKPOINTs:\n");
+  fprintf (server_output, "\tBREAKPOINTs:\n");
   for (i = 0; i < aarch64_num_bp_regs; i++)
-    fprintf (stderr, "\tBP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
+    fprintf (server_output, "\tBP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
 	     i, paddress (state->dr_addr_bp[i]),
 	     state->dr_ctrl_bp[i], state->dr_ref_count_bp[i]);
 
-  fprintf (stderr, "\tWATCHPOINTs:\n");
+  fprintf (server_output, "\tWATCHPOINTs:\n");
   for (i = 0; i < aarch64_num_wp_regs; i++)
-    fprintf (stderr, "\tWP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
+    fprintf (server_output, "\tWP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
 	     i, paddress (state->dr_addr_wp[i]),
 	     state->dr_ctrl_wp[i], state->dr_ref_count_wp[i]);
 }
@@ -631,8 +631,8 @@ debug_reg_change_callback (struct inferior_list_entry *entry, void *ptr)
 
   if (show_debug_regs)
     {
-      fprintf (stderr, "debug_reg_change_callback: \n\tOn entry:\n");
-      fprintf (stderr, "\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
+      fprintf (server_output, "debug_reg_change_callback: \n\tOn entry:\n");
+      fprintf (server_output, "\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
 	       "dr_changed_wp=0x%llx\n",
 	       pid, lwpid_of (thread), info->dr_changed_bp,
 	       info->dr_changed_wp);
@@ -682,7 +682,7 @@ debug_reg_change_callback (struct inferior_list_entry *entry, void *ptr)
 
   if (show_debug_regs)
     {
-      fprintf (stderr, "\tOn exit:\n\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
+      fprintf (server_output, "\tOn exit:\n\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
 	       "dr_changed_wp=0x%llx\n",
 	       pid, lwpid_of (thread), info->dr_changed_bp,
 	       info->dr_changed_wp);
@@ -921,7 +921,7 @@ aarch64_handle_unaligned_watchpoint (enum target_hw_bp_type type,
 						 aligned_len);
 
       if (show_debug_regs)
-	fprintf (stderr,
+	fprintf (server_output,
  "handle_unaligned_watchpoint: is_insert: %d\n"
  "                             aligned_addr: 0x%s, aligned_len: %d\n"
  "                                next_addr: 0x%s,    next_len: %d\n",
@@ -977,7 +977,7 @@ aarch64_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
   enum target_hw_bp_type targ_type;
 
   if (show_debug_regs)
-    fprintf (stderr, "insert_point on entry (addr=0x%08lx, len=%d)\n",
+    fprintf (server_output, "insert_point on entry (addr=0x%08lx, len=%d)\n",
 	     (unsigned long) addr, len);
 
   /* Determine the type from the raw breakpoint type.  */
@@ -1013,7 +1013,7 @@ aarch64_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
   enum target_hw_bp_type targ_type;
 
   if (show_debug_regs)
-    fprintf (stderr, "remove_point on entry (addr=0x%08lx, len=%d)\n",
+    fprintf (server_output, "remove_point on entry (addr=0x%08lx, len=%d)\n",
 	     (unsigned long) addr, len);
 
   /* Determine the type from the raw breakpoint type.  */
@@ -1154,7 +1154,7 @@ aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
 	= &proc->priv->arch_private->debug_reg_state;
 
       if (show_debug_regs)
-	fprintf (stderr, "prepare_to_resume thread %ld\n", lwpid_of (thread));
+	fprintf (server_output, "prepare_to_resume thread %ld\n", lwpid_of (thread));
 
       /* Watchpoints.  */
       if (DR_HAS_CHANGED (info->dr_changed_wp))
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e4c5420..c1bf202 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -724,9 +724,9 @@ linux_create_inferior (char *program, char **allargs)
       if (errno == ENOENT)
 	execvp (program, allargs);
 
-      fprintf (stderr, "Cannot exec %s: %s.\n", program,
+      fprintf (server_output, "Cannot exec %s: %s.\n", program,
 	       strerror (errno));
-      fflush (stderr);
+      fflush (server_output);
       _exit (0177);
     }
 
@@ -1560,7 +1560,7 @@ check_zombie_leaders (void)
 	     thread execs).  */
 
 	  if (debug_threads)
-	    fprintf (stderr,
+	    fprintf (server_output,
 		     "CZL: Thread group leader %d zombie "
 		     "(it exited, or another thread execd).\n",
 		     leader_pid);
@@ -3584,9 +3584,9 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
 	  if (fast_tp_collecting == 0)
 	    {
 	      if (step == 0)
-		fprintf (stderr, "BAD - reinserting but not stepping.\n");
+		fprintf (server_output, "BAD - reinserting but not stepping.\n");
 	      if (lwp->suspended)
-		fprintf (stderr, "BAD - reinserting and suspended(%d).\n",
+		fprintf (server_output, "BAD - reinserting and suspended(%d).\n",
 			 lwp->suspended);
 	    }
 
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 2f85829..0257f3d 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -53,9 +53,9 @@ lynx_debug (char *string, ...)
     return;
 
   va_start (args, string);
-  fprintf (stderr, "DEBUG(lynx): ");
-  vfprintf (stderr, string, args);
-  fprintf (stderr, "\n");
+  fprintf (server_output, "DEBUG(lynx): ");
+  vfprintf (server_output, string, args);
+  fprintf (server_output, "\n");
   va_end (args);
 }
 
@@ -195,14 +195,14 @@ lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2)
   int saved_errno;
 
   if (debug_threads)
-    fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
+    fprintf (server_output, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, "
              "data=0x%x, addr2=0x%x)",
              ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid),
              addr, data, addr2);
   result = ptrace (request, pid, addr, data, addr2);
   saved_errno = errno;
   if (debug_threads)
-    fprintf (stderr, " -> %d (=0x%x)\n", result, result);
+    fprintf (server_output, " -> %d (=0x%x)\n", result, result);
 
   errno = saved_errno;
   return result;
@@ -250,8 +250,8 @@ lynx_create_inferior (char *program, char **allargs)
       ioctl (0, TIOCSPGRP, &pgrp);
       lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
       execv (program, allargs);
-      fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno));
-      fflush (stderr);
+      fprintf (server_output, "Cannot exec %s: %s.\n", program, strerror (errno));
+      fflush (server_output);
       _exit (0177);
     }
 
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 70fab2e..e2fa503 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -1179,7 +1179,7 @@ add_breakpoint_condition (struct breakpoint *bp, char **condition)
 
   if (cond == NULL)
     {
-      fprintf (stderr, "Condition evaluation failed. "
+      fprintf (server_output, "Condition evaluation failed. "
 	       "Assuming unconditional.\n");
       return 0;
     }
@@ -1279,7 +1279,7 @@ add_breakpoint_commands (struct breakpoint *bp, char **command,
 
   if (cmd == NULL)
     {
-      fprintf (stderr, "Command evaluation failed. "
+      fprintf (server_output, "Command evaluation failed. "
 	       "Disabling.\n");
       return 0;
     }
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 436c1b8..af10a14 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -104,7 +104,7 @@ handle_notif_ack (char *own_buf, int packet_len)
 	= QUEUE_deque (notif_event_p, np->queue);
 
       if (remote_debug)
-	fprintf (stderr, "%s: acking %d\n", np->ack_name,
+	fprintf (server_output, "%s: acking %d\n", np->ack_name,
 		 QUEUE_length (notif_event_p, np->queue));
 
       xfree (head);
@@ -124,7 +124,7 @@ notif_event_enque (struct notif_server *notif,
   QUEUE_enque (notif_event_p, notif->queue, event);
 
   if (remote_debug)
-    fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
+    fprintf (server_output, "pending events: %s %d\n", notif->notif_name,
 	     QUEUE_length (notif_event_p, notif->queue));
 
 }
diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
index 801d76a..f3d52dd 100644
--- a/gdb/gdbserver/nto-low.c
+++ b/gdb/gdbserver/nto-low.c
@@ -44,9 +44,9 @@ nto_trace (const char *fmt, ...)
 
   if (debug_threads == 0)
     return;
-  fprintf (stderr, "nto:");
+  fprintf (server_output, "nto:");
   va_start (arg_list, fmt);
-  vfprintf (stderr, fmt, arg_list);
+  vfprintf (server_output, fmt, arg_list);
   va_end (arg_list);
 }
 
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 1de86be..34f3a07 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -194,7 +194,7 @@ handle_accept_event (int err, gdb_client_data client_data)
   delete_file_handler (listen_desc);
 
   /* Convert IP address to string.  */
-  fprintf (stderr, "Remote debugging from host %s\n",
+  fprintf (server_output, "Remote debugging from host %s\n",
 	   inet_ntoa (sockaddr.sin_addr));
 
   enable_async_notification (remote_desc);
@@ -296,7 +296,7 @@ remote_open (char *name)
 
   if (strcmp (name, STDIO_CONNECTION_NAME) == 0)
     {
-      fprintf (stderr, "Remote debugging using stdio\n");
+      fprintf (server_output, "Remote debugging using stdio\n");
 
       /* Use stdin as the handle of the connection.
 	 We only select on reads, for example.  */
@@ -368,7 +368,7 @@ remote_open (char *name)
       }
 #endif
 
-      fprintf (stderr, "Remote debugging using %s\n", name);
+      fprintf (server_output, "Remote debugging using %s\n", name);
 
       enable_async_notification (remote_desc);
 
@@ -389,8 +389,8 @@ remote_open (char *name)
 	perror_with_name ("Can't determine port");
       port = ntohs (sockaddr.sin_port);
 
-      fprintf (stderr, "Listening on port %d\n", port);
-      fflush (stderr);
+      fprintf (server_output, "Listening on port %d\n", port);
+      fflush (server_output);
 
       /* Register the event loop handler.  */
       add_file_handler (listen_desc, handle_accept_event, NULL);
@@ -658,18 +658,18 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
 	  if (remote_debug)
 	    {
 	      if (is_notif)
-		fprintf (stderr, "putpkt (\"%s\"); [notif]\n", buf2);
+		fprintf (server_output, "putpkt (\"%s\"); [notif]\n", buf2);
 	      else
-		fprintf (stderr, "putpkt (\"%s\"); [noack mode]\n", buf2);
-	      fflush (stderr);
+		fprintf (server_output, "putpkt (\"%s\"); [noack mode]\n", buf2);
+	      fflush (server_output);
 	    }
 	  break;
 	}
 
       if (remote_debug)
 	{
-	  fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2);
-	  fflush (stderr);
+	  fprintf (server_output, "putpkt (\"%s\"); [looking for ack]\n", buf2);
+	  fflush (server_output);
 	}
 
       cc = readchar ();
@@ -682,8 +682,8 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
 
       if (remote_debug)
 	{
-	  fprintf (stderr, "[received '%c' (0x%x)]\n", cc, cc);
-	  fflush (stderr);
+	  fprintf (server_output, "[received '%c' (0x%x)]\n", cc, cc);
+	  fflush (server_output);
 	}
 
       /* Check for an input interrupt while we're here.  */
@@ -744,16 +744,16 @@ input_interrupt (int unused)
 
       if (cc == 0)
 	{
-	  fprintf (stderr, "client connection closed\n");
+	  fprintf (server_output, "client connection closed\n");
 	  return;
 	}
       else if (cc != 1 || c != '\003' || current_thread == NULL)
 	{
-	  fprintf (stderr, "input_interrupt, count = %d c = %d ", cc, c);
+	  fprintf (server_output, "input_interrupt, count = %d c = %d ", cc, c);
 	  if (isprint (c))
-	    fprintf (stderr, "('%c')\n", c);
+	    fprintf (server_output, "('%c')\n", c);
 	  else
-	    fprintf (stderr, "('\\x%02x')\n", c & 0xff);
+	    fprintf (server_output, "('\\x%02x')\n", c & 0xff);
 	  return;
 	}
 
@@ -881,7 +881,7 @@ readchar (void)
       if (readchar_bufcnt <= 0)
 	{
 	  if (readchar_bufcnt == 0)
-	    fprintf (stderr, "readchar: Got EOF\n");
+	    fprintf (server_output, "readchar: Got EOF\n");
 	  else
 	    perror ("readchar");
 
@@ -959,8 +959,8 @@ getpkt (char *buf)
 	    break;
 	  if (remote_debug)
 	    {
-	      fprintf (stderr, "[getpkt: discarding char '%c']\n", c);
-	      fflush (stderr);
+	      fprintf (server_output, "[getpkt: discarding char '%c']\n", c);
+	      fflush (server_output);
 	    }
 
 	  if (c < 0)
@@ -988,7 +988,7 @@ getpkt (char *buf)
 
       if (noack_mode)
 	{
-	  fprintf (stderr,
+	  fprintf (server_output,
 		   "Bad checksum, sentsum=0x%x, csum=0x%x, "
 		   "buf=%s [no-ack-mode, Bad medium?]\n",
 		   (c1 << 4) + c2, csum, buf);
@@ -996,7 +996,7 @@ getpkt (char *buf)
 	  break;
 	}
 
-      fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+      fprintf (server_output, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
 	       (c1 << 4) + c2, csum, buf);
       if (write_prim ("-", 1) != 1)
 	return -1;
@@ -1006,8 +1006,8 @@ getpkt (char *buf)
     {
       if (remote_debug)
 	{
-	  fprintf (stderr, "getpkt (\"%s\");  [sending ack] \n", buf);
-	  fflush (stderr);
+	  fprintf (server_output, "getpkt (\"%s\");  [sending ack] \n", buf);
+	  fflush (server_output);
 	}
 
       if (write_prim ("+", 1) != 1)
@@ -1015,16 +1015,16 @@ getpkt (char *buf)
 
       if (remote_debug)
 	{
-	  fprintf (stderr, "[sent ack]\n");
-	  fflush (stderr);
+	  fprintf (server_output, "[sent ack]\n");
+	  fflush (server_output);
 	}
     }
   else
     {
       if (remote_debug)
 	{
-	  fprintf (stderr, "getpkt (\"%s\");  [no ack sent] \n", buf);
-	  fflush (stderr);
+	  fprintf (server_output, "getpkt (\"%s\");  [no ack sent] \n", buf);
+	  fflush (server_output);
 	}
     }
 
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 96b31b8..73f9f6c 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -60,6 +60,7 @@ int multi_process;
 int non_stop;
 int swbreak_feature;
 int hwbreak_feature;
+FILE *server_output;
 
 /* Whether we should attempt to disable the operating system's address
    space randomization feature before starting an inferior.  */
@@ -231,9 +232,9 @@ start_inferior (char **argv)
 
   /* FIXME: we don't actually know at this point that the create
      actually succeeded.  We won't know that until we wait.  */
-  fprintf (stderr, "Process %s created; pid = %ld\n", argv[0],
+  fprintf (server_output, "Process %s created; pid = %ld\n", argv[0],
 	   signal_pid);
-  fflush (stderr);
+  fflush (server_output);
 
 #ifdef SIGTTOU
   signal (SIGTTOU, SIG_IGN);
@@ -297,8 +298,8 @@ attach_inferior (int pid)
   if (myattach (pid) != 0)
     return -1;
 
-  fprintf (stderr, "Attached; pid = %d\n", pid);
-  fflush (stderr);
+  fprintf (server_output, "Attached; pid = %d\n", pid);
+  fflush (server_output);
 
   /* FIXME - It may be that we should get the SIGNAL_PID from the
      attach function, so that it can be the main thread instead of
@@ -578,8 +579,8 @@ handle_general_set (char *own_buf)
     {
       if (remote_debug)
 	{
-	  fprintf (stderr, "[noack mode enabled]\n");
-	  fflush (stderr);
+	  fprintf (server_output, "[noack mode enabled]\n");
+	  fflush (server_output);
 	}
 
       noack_mode = 1;
@@ -601,7 +602,7 @@ handle_general_set (char *own_buf)
 	{
 	  /* We don't know what this mode is, so complain to
 	     GDB.  */
-	  fprintf (stderr, "Unknown non-stop mode requested: %s\n",
+	  fprintf (server_output, "Unknown non-stop mode requested: %s\n",
 		   own_buf);
 	  write_enn (own_buf);
 	  return;
@@ -610,7 +611,7 @@ handle_general_set (char *own_buf)
       req_str = req ? "non-stop" : "all-stop";
       if (start_non_stop (req) != 0)
 	{
-	  fprintf (stderr, "Setting %s mode failed\n", req_str);
+	  fprintf (server_output, "Setting %s mode failed\n", req_str);
 	  write_enn (own_buf);
 	  return;
 	}
@@ -618,7 +619,7 @@ handle_general_set (char *own_buf)
       non_stop = req;
 
       if (remote_debug)
-	fprintf (stderr, "[%s mode enabled]\n", req_str);
+	fprintf (server_output, "[%s mode enabled]\n", req_str);
 
       write_ok (own_buf);
       return;
@@ -635,9 +636,9 @@ handle_general_set (char *own_buf)
       if (remote_debug)
 	{
 	  if (disable_randomization)
-	    fprintf (stderr, "[address space randomization disabled]\n");
+	    fprintf (server_output, "[address space randomization disabled]\n");
 	  else
-	    fprintf (stderr, "[address space randomization enabled]\n");
+	    fprintf (server_output, "[address space randomization enabled]\n");
 	}
 
       write_ok (own_buf);
@@ -667,7 +668,7 @@ handle_general_set (char *own_buf)
       /* Update the flag.  */
       use_agent = req;
       if (remote_debug)
-	fprintf (stderr, "[%s agent]\n", req ? "Enable" : "Disable");
+	fprintf (server_output, "[%s agent]\n", req ? "Enable" : "Disable");
       write_ok (own_buf);
       return;
     }
@@ -2696,7 +2697,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
     {
       if ((!extended_protocol || !multi_process) && target_running ())
 	{
-	  fprintf (stderr, "Already debugging a process\n");
+	  fprintf (server_output, "Already debugging a process\n");
 	  write_enn (own_buf);
 	  return;
 	}
@@ -2708,7 +2709,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
     {
       if ((!extended_protocol || !multi_process) && target_running ())
 	{
-	  fprintf (stderr, "Already debugging a process\n");
+	  fprintf (server_output, "Already debugging a process\n");
 	  write_enn (own_buf);
 	  return;
 	}
@@ -2720,7 +2721,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
     {
       if (!target_running ())
 	{
-	  fprintf (stderr, "No process to kill\n");
+	  fprintf (server_output, "No process to kill\n");
 	  write_enn (own_buf);
 	  return;
 	}
@@ -3088,7 +3089,7 @@ print_started_pid (struct inferior_list_entry *entry)
   if (! process->attached)
     {
       int pid = ptid_get_pid (process->entry.id);
-      fprintf (stderr, " %d", pid);
+      fprintf (server_output, " %d", pid);
     }
 }
 
@@ -3103,7 +3104,7 @@ print_attached_pid (struct inferior_list_entry *entry)
   if (process->attached)
     {
       int pid = ptid_get_pid (process->entry.id);
-      fprintf (stderr, " %d", pid);
+      fprintf (server_output, " %d", pid);
     }
 }
 
@@ -3120,15 +3121,15 @@ detach_or_kill_for_exit (void)
 
   if (have_started_inferiors_p ())
     {
-      fprintf (stderr, "Killing process(es):");
+      fprintf (server_output, "Killing process(es):");
       for_each_inferior (&all_processes, print_started_pid);
-      fprintf (stderr, "\n");
+      fprintf (server_output, "\n");
     }
   if (have_attached_inferiors_p ())
     {
-      fprintf (stderr, "Detaching process(es):");
+      fprintf (server_output, "Detaching process(es):");
       for_each_inferior (&all_processes, print_attached_pid);
-      fprintf (stderr, "\n");
+      fprintf (server_output, "\n");
     }
 
   /* Now we can kill or detach the inferiors.  */
@@ -3153,7 +3154,7 @@ detach_or_kill_for_exit_cleanup (void *ignore)
   CATCH (exception, RETURN_MASK_ALL)
     {
       fflush (stdout);
-      fprintf (stderr, "Detach or kill failed: %s\n", exception.message);
+      fprintf (server_output, "Detach or kill failed: %s\n", exception.message);
       exit_code = 1;
     }
   END_CATCH
@@ -3173,6 +3174,8 @@ captured_main (int argc, char *argv[])
   volatile int attach = 0;
   int was_running;
 
+  server_output = stderr;
+
   while (*next_arg != NULL && **next_arg == '-')
     {
       if (strcmp (*next_arg, "--version") == 0)
@@ -3199,7 +3202,7 @@ captured_main (int argc, char *argv[])
 
 	  if (next_arg == wrapper_argv || *next_arg == NULL)
 	    {
-	      gdbserver_usage (stderr);
+	      gdbserver_usage (server_output);
 	      exit (1);
 	    }
 
@@ -3216,7 +3219,7 @@ captured_main (int argc, char *argv[])
 
 	  if (error_msg != NULL)
 	    {
-	      fprintf (stderr, "%s", error_msg);
+	      fprintf (server_output, "%s", error_msg);
 	      exit (1);
 	    }
 	}
@@ -3253,9 +3256,9 @@ captured_main (int argc, char *argv[])
 		}
 	      else
 		{
-		  fprintf (stderr, "Don't know how to disable \"%s\".\n\n",
+		  fprintf (server_output, "Don't know how to disable \"%s\".\n\n",
 			   tok);
-		  gdbserver_show_disableable (stderr);
+		  gdbserver_show_disableable (server_output);
 		  exit (1);
 		}
 	    }
@@ -3275,7 +3278,7 @@ captured_main (int argc, char *argv[])
 	run_once = 1;
       else
 	{
-	  fprintf (stderr, "Unknown argument: %s\n", *next_arg);
+	  fprintf (server_output, "Unknown argument: %s\n", *next_arg);
 	  exit (1);
 	}
 
@@ -3287,7 +3290,7 @@ captured_main (int argc, char *argv[])
   next_arg++;
   if (port == NULL || (!attach && !multi_mode && *next_arg == NULL))
     {
-      gdbserver_usage (stderr);
+      gdbserver_usage (server_output);
       exit (1);
     }
 
@@ -3322,7 +3325,7 @@ captured_main (int argc, char *argv[])
 
   if (bad_attach)
     {
-      gdbserver_usage (stderr);
+      gdbserver_usage (server_output);
       exit (1);
     }
 
@@ -3410,7 +3413,7 @@ captured_main (int argc, char *argv[])
 	  if (exit_requested || run_once)
 	    throw_quit ("Quit");
 
-	  fprintf (stderr,
+	  fprintf (server_output,
 		   "Remote side has terminated connection.  "
 		   "GDBserver will reopen the connection.\n");
 
@@ -3442,7 +3445,7 @@ captured_main (int argc, char *argv[])
 		}
 	      else
 		{
-		  fprintf (stderr,
+		  fprintf (server_output,
 			   "Disconnected tracing disabled; "
 			   "stopping trace run.\n");
 		  stop_tracing ();
@@ -3476,8 +3479,8 @@ main (int argc, char *argv[])
       if (exception.reason == RETURN_ERROR)
 	{
 	  fflush (stdout);
-	  fprintf (stderr, "%s\n", exception.message);
-	  fprintf (stderr, "Exiting\n");
+	  fprintf (server_output, "%s\n", exception.message);
+	  fprintf (server_output, "Exiting\n");
 	  exit_code = 1;
 	}
 
@@ -3538,7 +3541,7 @@ process_point_options (struct breakpoint *bp, char **packet)
 	}
       else
 	{
-	  fprintf (stderr, "Unknown token %c, ignoring.\n",
+	  fprintf (server_output, "Unknown token %c, ignoring.\n",
 		   *dataptr);
 	  /* Skip tokens until we find one that we recognize.  */
 	  skip_to_semicolon (&dataptr);
@@ -3618,12 +3621,12 @@ process_serial_event (void)
 	    }
 
 	  if (tracing && disconnected_tracing)
-	    fprintf (stderr,
+	    fprintf (server_output,
 		     "Disconnected tracing in effect, "
 		     "leaving gdbserver attached to the process\n");
 
 	  if (any_persistent_commands ())
-	    fprintf (stderr,
+	    fprintf (server_output,
 		     "Persistent commands are present, "
 		     "leaving gdbserver attached to the process\n");
 
@@ -3653,7 +3656,7 @@ process_serial_event (void)
 	  break; /* from switch/case */
 	}
 
-      fprintf (stderr, "Detaching from process %d\n", pid);
+      fprintf (server_output, "Detaching from process %d\n", pid);
       stop_tracing ();
       if (detach_inferior (pid) != 0)
 	write_enn (own_buf);
@@ -3907,7 +3910,7 @@ process_serial_event (void)
 	   reply to it, either.  */
 	return 0;
 
-      fprintf (stderr, "Killing all inferiors\n");
+      fprintf (server_output, "Killing all inferiors\n");
       for_each_inferior (&all_processes, kill_inferior_callback);
 
       /* When using the extended protocol, we wait with no program
@@ -3951,7 +3954,7 @@ process_serial_event (void)
 	  if (target_running ())
 	    for_each_inferior (&all_processes,
 			       kill_inferior_callback);
-	  fprintf (stderr, "GDBserver restarting\n");
+	  fprintf (server_output, "GDBserver restarting\n");
 
 	  /* Wait till we are at 1st instruction in prog.  */
 	  if (program_argv != NULL)
@@ -4000,7 +4003,7 @@ process_serial_event (void)
 	  /* Be transparent when GDB is connected through stdio -- no
 	     need to spam GDB's console.  */
 	  if (!remote_connection_is_stdio ())
-	    fprintf (stderr, "GDBserver exiting\n");
+	    fprintf (server_output, "GDBserver exiting\n");
 	  remote_close ();
 	  exit (0);
 	}
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 91d4080..4c5c916 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -86,6 +86,10 @@ extern int run_once;
 extern int multi_process;
 extern int non_stop;
 
+/* dedicated stream for the server error messages so that the inferior
+   stderr is not mixed with server's own.  */
+extern FILE *server_output;
+
 /* True if the "swbreak+" feature is active.  In that case, GDB wants
    us to report whether a trap is explained by a software breakpoint
    and for the server to handle PC adjustment if necessary on this
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index 73f1786..dda5a79 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -281,9 +281,9 @@ spu_create_inferior (char *program, char **allargs)
       if (errno == ENOENT)
 	execvp (program, allargs);
 
-      fprintf (stderr, "Cannot exec %s: %s.\n", program,
+      fprintf (server_output, "Cannot exec %s: %s.\n", program,
 	       strerror (errno));
-      fflush (stderr);
+      fflush (server_output);
       _exit (0177);
     }
 
@@ -304,9 +304,9 @@ spu_attach (unsigned long  pid)
 
   if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
     {
-      fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+      fprintf (server_output, "Cannot attach to process %ld: %s (%d)\n", pid,
 	       strerror (errno), errno);
-      fflush (stderr);
+      fflush (server_output);
       _exit (0177);
     }
 
@@ -396,7 +396,7 @@ spu_resume (struct thread_resume *resume_info, size_t n)
   /* We don't support hardware single-stepping right now, assume
      GDB knows to use software single-stepping.  */
   if (resume_info[i].kind == resume_step)
-    fprintf (stderr, "Hardware single-step not supported.\n");
+    fprintf (server_output, "Hardware single-step not supported.\n");
 
   regcache_invalidate ();
 
@@ -445,7 +445,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 
   if (WIFEXITED (w))
     {
-      fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+      fprintf (server_output, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
       ourstatus->kind =  TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = WEXITSTATUS (w);
       clear_inferiors ();
@@ -453,7 +453,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
     }
   else if (!WIFSTOPPED (w))
     {
-      fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+      fprintf (server_output, "\nChild terminated with signal = %x \n", WTERMSIG (w));
       ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
       ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (w));
       clear_inferiors ();
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index 14999e6..708a43a 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -120,10 +120,10 @@ mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
   if (!remote_connection_is_stdio ())
     {
       if (ourstatus->kind == TARGET_WAITKIND_EXITED)
-	fprintf (stderr,
+	fprintf (server_output,
 		 "\nChild exited with status %d\n", ourstatus->value.integer);
       else if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
-	fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
+	fprintf (server_output, "\nChild terminated with signal = 0x%x (%s)\n",
 		 gdb_signal_to_host (ourstatus->value.sig),
 		 gdb_signal_to_name (ourstatus->value.sig));
     }
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index 5bf808e..e0e25df 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -205,7 +205,7 @@ thread_db_create_event (CORE_ADDR where)
      (except for its own creation, of course).  */
   err = thread_db->td_ta_event_getmsg_p (thread_db->thread_agent, &msg);
   if (err != TD_OK)
-    fprintf (stderr, "thread getmsg err: %s\n",
+    fprintf (server_output, "thread getmsg err: %s\n",
 	     thread_db_err_str (err));
 
   /* If we do not know about the main thread yet, this would be a good time to
@@ -726,7 +726,7 @@ try_thread_db_load (const char *library)
 	  const char *const libpath = dladdr_to_soname (td_init);
 
 	  if (libpath != NULL)
-	    fprintf (stderr, "Host %s resolved to: %s.\n",
+	    fprintf (server_output, "Host %s resolved to: %s.\n",
 		     library, libpath);
 	}
     }
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 3ce9580..f3639be 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -63,6 +63,8 @@
 
 #ifdef IN_PROCESS_AGENT
 
+#define server_output stderr
+
 static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
 
 static void
@@ -73,7 +75,7 @@ trace_vdebug (const char *fmt, ...)
 
   va_start (ap, fmt);
   vsprintf (buf, fmt, ap);
-  fprintf (stderr, PROG "/tracepoint: %s\n", buf);
+  fprintf (server_output, PROG "/tracepoint: %s\n", buf);
   va_end (ap);
 }
 
diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
index e89a862..d11f101 100644
--- a/gdb/gdbserver/utils.c
+++ b/gdb/gdbserver/utils.c
@@ -21,6 +21,7 @@
 #ifdef IN_PROCESS_AGENT
 #  define PREFIX "ipa: "
 #  define TOOLNAME "GDBserver in-process agent"
+#  define server_output stderr
 #else
 #  define PREFIX "gdbserver: "
 #  define TOOLNAME "GDBserver"
@@ -31,7 +32,7 @@
 void
 malloc_failure (long size)
 {
-  fprintf (stderr,
+  fprintf (server_output,
 	   PREFIX "ran out of memory while trying to allocate %lu bytes\n",
 	   (unsigned long) size);
   exit (1);
@@ -78,8 +79,8 @@ verror (const char *string, va_list args)
 {
 #ifdef IN_PROCESS_AGENT
   fflush (stdout);
-  vfprintf (stderr, string, args);
-  fprintf (stderr, "\n");
+  vfprintf (server_output, string, args);
+  fprintf (server_output, "\n");
   exit (1);
 #else
   throw_verror (GENERIC_ERROR, string, args);
@@ -89,9 +90,9 @@ verror (const char *string, va_list args)
 void
 vwarning (const char *string, va_list args)
 {
-  fprintf (stderr, PREFIX);
-  vfprintf (stderr, string, args);
-  fprintf (stderr, "\n");
+  fprintf (server_output, PREFIX);
+  vfprintf (server_output, string, args);
+  fprintf (server_output, "\n");
 }
 
 /* Report a problem internal to GDBserver, and exit.  */
@@ -99,10 +100,10 @@ vwarning (const char *string, va_list args)
 void
 internal_verror (const char *file, int line, const char *fmt, va_list args)
 {
-  fprintf (stderr,  "\
+  fprintf (server_output,  "\
 %s:%d: A problem internal to " TOOLNAME " has been detected.\n", file, line);
-  vfprintf (stderr, fmt, args);
-  fprintf (stderr, "\n");
+  vfprintf (server_output, fmt, args);
+  fprintf (server_output, "\n");
   exit (1);
 }
 
@@ -111,10 +112,10 @@ internal_verror (const char *file, int line, const char *fmt, va_list args)
 void
 internal_vwarning (const char *file, int line, const char *fmt, va_list args)
 {
-  fprintf (stderr,  "\
+  fprintf (server_output,  "\
 %s:%d: A problem internal to " TOOLNAME " has been detected.\n", file, line);
-  vfprintf (stderr, fmt, args);
-  fprintf (stderr, "\n");
+  vfprintf (server_output, fmt, args);
+  fprintf (server_output, "\n");
 }
 
 /* Convert a CORE_ADDR into a HEX string, like %lx.
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 6c86765..80e3a97 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -39,15 +39,15 @@
 #include <sys/cygwin.h>
 #endif
 
-#define OUTMSG(X) do { printf X; fflush (stderr); } while (0)
+#define OUTMSG(X) do { fprintf (server_output, X); fflush (server_output); } while (0)
 
 #define OUTMSG2(X) \
   do						\
     {						\
       if (debug_threads)			\
 	{					\
-	  printf X;				\
-	  fflush (stderr);			\
+	  fprintf (server_output, X);		\
+	  fflush (server_output);		\
 	}					\
     } while (0)
 
diff --git a/gdb/gdbserver/wincecompat.c b/gdb/gdbserver/wincecompat.c
index 269015b..7dff15f 100644
--- a/gdb/gdbserver/wincecompat.c
+++ b/gdb/gdbserver/wincecompat.c
@@ -24,9 +24,9 @@ void
 perror (const char *s)
 {
   if (s && *s)
-    fprintf (stderr, "%s: %s\n", s, strwinerror (GetLastError ()));
+    fprintf (server_output, "%s: %s\n", s, strwinerror (GetLastError ()));
   else
-    fprintf (stderr, "%s\n", strwinerror (GetLastError ()));
+    fprintf (server_output, "%s\n", strwinerror (GetLastError ()));
 }
 
 void
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command
  2015-03-25 20:48 [PATCH v2 0/3] GDBServer: introduce a dedicated output stream Cleber Rosa
@ 2015-03-25 20:48 ` Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 2/3] GDBServer: introduce --server-output command line option Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 1/3] GDBServer: introduce a stream dedicated to the server Cleber Rosa
  2 siblings, 0 replies; 6+ messages in thread
From: Cleber Rosa @ 2015-03-25 20:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: crosa, areis

This monitor command, just like the command line option --server-output,
will redirect all of the gdbserver's own output (always sent to stderr)
to a separate file.

gdb/Changelog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* NEWS: New feature in the GDBserver: monitor set server-output.

gdb/doc/Changelog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* gdb.texinfo (info): Add documentation about the 'monitor set
	server-output' command.

gdb/gdbserver/Changelog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* server.c (monitor_show_help): Add help message about the
	'monitor set server-output' command.
	(handle_monitor_command): Respond to 'set server-output' command.

gdb/testsuite/ChangeLog:
2015-03-25  Cleber Rosa  <crosa@redhat.com>

	* gdb.server/server-mon.exp: Add tests with the 'monitor set
	server-output' command succeeding and failing.
---
 gdb/NEWS                                |  2 ++
 gdb/doc/gdb.texinfo                     |  3 +++
 gdb/gdbserver/server.c                  | 24 +++++++++++++++++++++---
 gdb/testsuite/gdb.server/server-mon.exp |  8 ++++++++
 4 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 22044c2..d8e74bb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -100,6 +100,8 @@ Itanium running HP-UX         ia64-*-hpux*
 
   ** New option --server-output=file allows users to send the
      server output to a separate file.
+  ** New monitor command "monitor set server-output", the monitor
+     command counterpart of command line option --server-output.
 
 *** Changes in GDB 7.9
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 454f51f..b3442b1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19321,6 +19321,9 @@ Include a timestamp in each line of debugging output.
 Options are processed in order.  Thus, for example, if @option{none}
 appears last then no additional information is added to debugging output.
 
+@item monitor set server-output @var{output_filename}
+Redirect the server output to a file given by @var{output_filename}.
+
 @item monitor set libthread-db-search-path [PATH]
 @cindex gdbserver, search path for @code{libthread_db}
 When this command is issued, @var{path} is a colon-separated list of
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index b4a715f..51251f9 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -754,9 +754,9 @@ monitor_show_help (void)
   monitor_output ("    Enable remote protocol debugging messages\n");
   monitor_output ("  set debug-format option1[,option2,...]\n");
   monitor_output ("    Add additional information to debugging messages\n");
-  monitor_output ("    Options: all, none");
-  monitor_output (", timestamp");
-  monitor_output ("\n");
+  monitor_output ("    Options: all, none, timestamp\n");
+  monitor_output ("  set server-output output_filename\n");
+  monitor_output ("    Redirects the server output to output_filename\n");
   monitor_output ("  exit\n");
   monitor_output ("    Quit GDBserver\n");
 }
@@ -1105,6 +1105,24 @@ handle_monitor_command (char *mon, char *own_buf)
 	  xfree (error_msg);
 	}
     }
+  else if (strncmp (mon, "set server-output ",
+		    sizeof ("set server-output ") -1) == 0)
+    {
+      char *out_filename = mon + (sizeof ("set server-output ") - 1);
+      if (set_server_output (out_filename) == 0) {
+	char *monitor_msg = xstrprintf ("Redirected server output to '%s'\n",
+					out_filename);
+	monitor_output (monitor_msg);
+	xfree (monitor_msg);
+      }
+      else
+	{
+	  char *monitor_msg = xstrprintf ("Failed to set server output to '%s'\n",
+					  out_filename);
+	  monitor_output (monitor_msg);
+	  xfree (monitor_msg);
+	}
+    }
   else if (strcmp (mon, "help") == 0)
     monitor_show_help ();
   else if (strcmp (mon, "exit") == 0)
diff --git a/gdb/testsuite/gdb.server/server-mon.exp b/gdb/testsuite/gdb.server/server-mon.exp
index a4c03ee..a19bc11 100644
--- a/gdb/testsuite/gdb.server/server-mon.exp
+++ b/gdb/testsuite/gdb.server/server-mon.exp
@@ -54,3 +54,11 @@ gdb_test "monitor set debug-format all" \
     "All extra debug format options enabled\\."
 gdb_test "monitor set debug-format none" \
     "All extra debug format options disabled\\."
+
+# Tests the monitor command that sends stderr output to another file
+gdb_test "monitor set server-output /dev/null" \
+    "Redirected server output to '/dev/null'"
+
+# Tests the monitor command that sends stderr output to another file
+gdb_test "monitor set server-output /im/pro/ba/ble/pa/th" \
+    "Failed to set server output to '/im/pro/ba/ble/pa/th'"
-- 
1.9.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 0/3] GDBServer: introduce a dedicated output stream
@ 2015-03-25 20:48 Cleber Rosa
  2015-03-25 20:48 ` [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command Cleber Rosa
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Cleber Rosa @ 2015-03-25 20:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: crosa, areis

This patch series add command line options and monitor commands that
will redirect all of the gdbserver's own output (always sent to
stderr) to a separate file.  This feature makes it possible to
distinguish between the inferior process stderr and gdbserver's own
stderr.

This happens to be needed for the Avocado[1] project GDB
support[2][3].  One of Avocado's GDB features is that it lets users
"transparently" run binaries instrumented by GDB.  A test that
executes binaries can give the user the opportunity to interact with
the process running within gdb(server).  This uses a combination of
gdb (with MI) and gdbserver. So far so good.

But, since Avocado is a test framework, it lets tests PASS or FAIL
depending on executed commands' STDERR and STDOUT matching what the
test writer expects.  Matching against STDOUT is already doable as
gdbserver doesn't write to stdout, but it does write to stderr, the
same stderr that the inferior process writes to.

This is what happened to each of the patches from the first version:

 [PATCH 1/4] GDBServer: introduce a stderr stream dedicated to the server

	* Renamed server_stderr to server_output.
        * lynx-low.c (lynx_debug): New substitution of stderr with
	server_output.
	* nto-low.c (nto_trace): Likewise.
	* tracepoint.c: Define server_output as an alias of stderr
	when compiling the IPA.
	(trace_vdebug): Replace stderr with server_output.
	* win32-low.c (OUTMSG): Changed definition of macro to also
	use server_output instead of stderr.
	(OUTMSG2): Likewise.
	* wincecompat.c (perror): Likewise.

 [PATCH 2/4] GDBServer: give more complete usage information

 	* Dropped. Pedro sent a new and better version to the
 	list. Obviously this version 2 now is 3 patches long.

 [PATCH 3/4] GDBServer: introduce --server-stderr command line option

 	* Renamed --server-stderr to --server-output.
   	* Better document the new features by making it clear that the
          server output can be redirected to another file. In other
          words, stderr is really an implementation detail.
	* Replaced mentions of PATH for FILE in the documentation and
	  in the command line option usage message.
	* Replace variables named path to out(put)_filename.
	* Renamed redirection utility function from set_server_stderr
	  to set_server_output to keep it in sync with command line
	  and

 [PATCH 4/4]: GDBServer: add 'monitor set server-stderr' command

	* Monitor command renamed to "monitor set server-output" from "monitor
	set server-stderr"

So now we have on this series v2:

 [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command
 [PATCH v2 2/3] GDBServer: introduce --server-output command line option
 [PATCH v2 3/3] GDBServer: introduce a stream dedicated to the server

Thanks (again),
Cleber Rosa.

[1] - http://github.com/avocado-framework
[2] - http://avocado-framework.readthedocs.org/en/latest/DebuggingWithGDB.html
[3] - https://github.com/avocado-framework/avocado/blob/master/avocado/gdb.py

---
 gdb/NEWS                                |   7 ++++
 gdb/doc/gdb.texinfo                     |  20 +++++++++++
 gdb/gdbserver/ax.c                      |   3 +-
 gdb/gdbserver/debug.c                   |   6 ++--
 gdb/gdbserver/event-loop.c              |   2 +-
 gdb/gdbserver/linux-aarch64-low.c       |  28 ++++++++--------
 gdb/gdbserver/linux-low.c               |  10 +++---
 gdb/gdbserver/lynx-low.c                |  14 ++++----
 gdb/gdbserver/mem-break.c               |   4 +--
 gdb/gdbserver/notif.c                   |   4 +--
 gdb/gdbserver/nto-low.c                 |   4 +--
 gdb/gdbserver/remote-utils.c            |  54 +++++++++++++++---------------
 gdb/gdbserver/server.c                  | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
 gdb/gdbserver/server.h                  |   4 +++
 gdb/gdbserver/spu-low.c                 |  14 ++++----
 gdb/gdbserver/target.c                  |   4 +--
 gdb/gdbserver/thread-db.c               |   4 +--
 gdb/gdbserver/tracepoint.c              |   4 ++-
 gdb/gdbserver/utils.c                   |  25 +++++++-------
 gdb/gdbserver/win32-low.c               |   6 ++--
 gdb/gdbserver/wincecompat.c             |   4 +--
 gdb/testsuite/gdb.server/server-mon.exp |   8 +++++
 22 files changed, 227 insertions(+), 137 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] GDBServer: introduce --server-output command line option
  2015-03-25 20:48 ` [PATCH v2 2/3] GDBServer: introduce --server-output command line option Cleber Rosa
@ 2015-03-25 20:55   ` Eli Zaretskii
  2015-03-25 21:08     ` Cleber Rosa
  0 siblings, 1 reply; 6+ messages in thread
From: Eli Zaretskii @ 2015-03-25 20:55 UTC (permalink / raw)
  To: Cleber Rosa; +Cc: gdb-patches, crosa, areis

> From: Cleber Rosa <crosa@redhat.com>
> Cc: crosa@redhat.com, areis@redhat.com
> Date: Wed, 25 Mar 2015 17:47:51 -0300
> 
> This command line option will redirect all of the gdbserver's own
> output (always sent to stderr) to a separate file.  This feature makes
> it possible to distinguish between the inferior process stderr and
> gdbserver's own stderr.  Example use case:
> 
>  $ gdbserver --server-output=log :2222 bin >bin.out 2>bin.err
> 
> Server output will be sent to file named "log", and the inferior
> output and error messages will be on files "bin.out" and "bin.err",
> respectively.
> 
> gdb/Changelog:
> 2015-03-25  Cleber Rosa  <crosa@redhat.com>
> 
> 	* NEWS: New feature in the GDBserver: --server-output.
> 
> gdb/doc/ChangeLog:
> 2015-03-25  Cleber Rosa  <crosa@redhat.com>
> 
> 	* gdb.texinfo (info): Added section on command line and monitor
> 	commands.
> 	(gdbserver man): Added section on new command line option.

OK for the documentation parts, with one comment:

> +Server output will be sent to file named @var{log}, and the inferior
> +output and error messages will be on files @var{bin.out} and
> +@var{bin.err}, respectively.

These all should be @file, not @var, since they are literal file
names.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] GDBServer: introduce --server-output command line option
  2015-03-25 20:55   ` Eli Zaretskii
@ 2015-03-25 21:08     ` Cleber Rosa
  0 siblings, 0 replies; 6+ messages in thread
From: Cleber Rosa @ 2015-03-25 21:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, areis

On 03/25/2015 05:55 PM, Eli Zaretskii wrote:
> These all should be @file, not @var, since they are literal file
> names.

Oh, my bad. Thanks again!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-03-25 21:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-25 20:48 [PATCH v2 0/3] GDBServer: introduce a dedicated output stream Cleber Rosa
2015-03-25 20:48 ` [PATCH v2 3/3] GDBServer: add 'monitor set server-output' command Cleber Rosa
2015-03-25 20:48 ` [PATCH v2 2/3] GDBServer: introduce --server-output command line option Cleber Rosa
2015-03-25 20:55   ` Eli Zaretskii
2015-03-25 21:08     ` Cleber Rosa
2015-03-25 20:48 ` [PATCH v2 1/3] GDBServer: introduce a stream dedicated to the server Cleber Rosa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).