This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
General ``monitor'' command; remote ``qRcmd,...'' packet
- To: gdb-patches@sourceware.cygnus.com
- Subject: General ``monitor'' command; remote ``qRcmd,...'' packet
- From: Andrew Cagney <ac131313@cygnus.com>
- Date: Thu, 05 Aug 1999 18:40:50 +1000
- DJ-Gateway: from newsgroup cygnus.patches.gdb
- Newsgroups: cygnus.patches.gdb
- Organization: Cygnus Solutions
FYI,
I'm just checking in the attached patch. It takes the ``monitor''
command found in monitor.c and generalizes it.
For remote.c, I've implemented ``monitor'' command using the recently
specified ``qRcmd'' packet.
In addition I've clarified a number of aspects of the ``qRcmd'' packet.
As an example:
(gdb) monitor hello
Sending packet: $qRcmd,68656c6c6f#ca...Ack
Packet received: 68656c6c6f
hello(gdb) quit
enjoy,
Andrew
Thu Aug 5 16:22:10 1999 Andrew Cagney <cagney@b1.cygnus.com>
* remote.c (init_remote_ops): Initialize remote_ops.to_rcmd.
(init_remote_async_ops): Initialize remote_async_ops.to_query.
(remote_rcmd): New function.
* monitor.c (monitor_rcmd): Rename monitor_command.
(init_base_monitor_ops): Initialize monitor_ops.to_rcmd.
(_initialize_remote_monitors): Move "monitor" command from here.
* target.c (initialize_targets): To here.
(monitor_command): New function. Implement "monitor" command.
* target.c (cleanup_target): de_fault to_rcmd.
(update_current_target): INHERIT to_rcmd.
(debug_to_rcmd): New function.
(setup_target_debug): Initialize current_target.to_rcmd.
* target.h (struct target_ops): Add field to_rcmd.
(target_rcmd): Define.
Thu Aug 5 17:57:41 1999 Andrew Cagney <cagney@b1.cygnus.com>
* remote.texi (protocol qRcmd): Allow ``OK'' and ``O...''
response
packets.
? diffs
Index: monitor.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/monitor.c,v
retrieving revision 1.1.1.5
diff -p -r1.1.1.5 monitor.c
*** monitor.c 1999/08/02 23:45:50 1.1.1.5
--- monitor.c 1999/08/05 08:27:09
*************** static void monitor_vsprintf PARAMS ((ch
*** 67,74 ****
static int readchar PARAMS ((int timeout));
- static void monitor_command PARAMS ((char *args, int fromtty));
-
static void monitor_fetch_register PARAMS ((int regno));
static void monitor_store_register PARAMS ((int regno));
--- 67,72 ----
*************** monitor_stop ()
*** 2261,2274 ****
monitor_printf_noecho (current_monitor->stop);
}
! /* Put a command string, in args, out to MONITOR. Output from MONITOR
! is placed on the users terminal until the prompt is seen. FIXME: We
! read the characters ourseleves here cause of a nasty echo. */
static void
! monitor_command (args, from_tty)
! char *args;
! int from_tty;
{
char *p;
int resp_len;
--- 2259,2271 ----
monitor_printf_noecho (current_monitor->stop);
}
! /* Put a COMMAND string out to MONITOR. Output from MONITOR is placed
! in OUTPUT until the prompt is seen. FIXME: We read the characters
! ourseleves here cause of a nasty echo. */
static void
! monitor_rcmd (char *command,
! struct gdb_file *outbuf)
{
char *p;
int resp_len;
*************** monitor_command (args, from_tty)
*** 2282,2292 ****
/* Send the command. Note that if no args were supplied, then we're
just sending the monitor a newline, which is sometimes useful. */
! monitor_printf ("%s\r", (args ? args : ""));
resp_len = monitor_expect_prompt (buf, sizeof buf);
! fputs_unfiltered (buf, gdb_stdout); /* Output the response */
}
/* Convert hex digit A to a number. */
--- 2279,2289 ----
/* Send the command. Note that if no args were supplied, then we're
just sending the monitor a newline, which is sometimes useful. */
! monitor_printf ("%s\r", (command ? command : ""));
resp_len = monitor_expect_prompt (buf, sizeof buf);
! fputs_unfiltered (buf, outbuf); /* Output the response */
}
/* Convert hex digit A to a number. */
*************** init_base_monitor_ops (void)
*** 2369,2374 ****
--- 2366,2372 ----
monitor_ops.to_notice_signals = 0;
monitor_ops.to_thread_alive = 0;
monitor_ops.to_stop = monitor_stop;
+ monitor_ops.to_rcmd = monitor_rcmd;
monitor_ops.to_pid_to_exec_file = NULL;
monitor_ops.to_core_file_to_sym_file = NULL;
monitor_ops.to_stratum = process_stratum;
*************** _initialize_remote_monitors ()
*** 2407,2413 ****
When enabled, a hashmark \'#\' is displayed.",
&setlist),
&showlist);
-
- add_com ("monitor", class_obscure, monitor_command,
- "Send a command to the debug monitor.");
}
--- 2405,2408 ----
Index: remote.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/remote.c,v
retrieving revision 1.1.1.13
diff -p -r1.1.1.13 remote.c
*** remote.c 1999/07/27 00:51:01 1.1.1.13
--- remote.c 1999/08/05 08:27:46
*************** remote_query (query_type, buf, outbuf, b
*** 4287,4292 ****
--- 4287,4345 ----
}
static void
+ remote_rcmd (char *command,
+ struct gdb_file *outbuf)
+ {
+ int i;
+ char *buf = alloca (PBUFSIZ);
+ char *p = buf;
+
+ if (!remote_desc)
+ error ("remote rcmd is only available after target open");
+
+ /* The query prefix */
+ strcpy (buf, "qRcmd,");
+ p = strchr (buf, '\0');
+
+ if ((strlen (buf) + strlen (command) * 2) + 8/*misc*/)
+ error ("\"monitor\" command is too long\n");
+
+ /* Encode the actual command */
+ for (i = 0; command[i]; i++)
+ {
+ *p++ = tohex ((command[i] >> 4) & 0xf);
+ *p++ = tohex (command[i] & 0xf);
+ }
+ *p = '\0';
+
+ if (putpkt (buf) < 0)
+ error ("Communication problem with target\n");
+
+ /* get/display the response */
+ while (1)
+ {
+ /* XXX - see also tracepoint.c:remote_get_noisy_reply() */
+ buf[0] = '\0';
+ getpkt (buf, 0);
+ if (buf[0] == '\0')
+ error ("Target does not support this command\n");
+ if (buf[0] == 'O' && buf[1] != 'K')
+ {
+ remote_console_output (buf + 1); /* 'O' message from stub */
+ continue;
+ }
+ if (strcmp (buf, "OK") == 0)
+ break;
+ for (p = buf; p[0] != '\0' && p[1] != '\0'; p += 2)
+ {
+ char c = (fromhex (p[0]) << 4) + fromhex (p[1]);
+ fputc_unfiltered (c, outbuf);
+ }
+ break;
+ }
+ }
+
+ static void
packet_command (args, from_tty)
char *args;
int from_tty;
*************** Specify the serial device it is connecte
*** 4498,4503 ****
--- 4551,4557 ----
remote_ops.to_find_new_threads = remote_threads_info;
remote_ops.to_stop = remote_stop;
remote_ops.to_query = remote_query;
+ remote_ops.to_rcmd = remote_rcmd;
remote_ops.to_stratum = process_stratum;
remote_ops.to_has_all_memory = 1;
remote_ops.to_has_memory = 1;
*************** Specify the serial device it is connecte
*** 4952,4957 ****
--- 5006,5012 ----
remote_async_ops.to_find_new_threads = remote_threads_info;
remote_async_ops.to_stop = remote_stop;
remote_async_ops.to_query = remote_query;
+ remote_async_ops.to_rcmd = remote_rcmd;
remote_async_ops.to_stratum = process_stratum;
remote_async_ops.to_has_all_memory = 1;
remote_async_ops.to_has_memory = 1;
Index: target.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/target.c,v
retrieving revision 1.1.1.9
diff -p -r1.1.1.9 target.c
*** target.c 1999/07/19 23:28:13 1.1.1.9
--- target.c 1999/08/05 08:28:06
*************** cleanup_target (t)
*** 444,449 ****
--- 444,450 ----
de_fault (to_thread_alive, (int (*)PARAMS ((int))) target_ignore);
de_fault (to_stop, (void (*)PARAMS ((void))) target_ignore);
de_fault (to_query, (int (*)PARAMS ((int /*char */ , char *, char *, int *))) target_ignore);
+ de_fault (to_rcmd, (void (*) (char *, struct gdb_file *)) tcomplain);
de_fault (to_enable_exception_callback, (struct symtab_and_line * (*)PARAMS ((enum exception_event_kind, int))) nosupport_runtime);
de_fault (to_get_current_exception_event, (struct exception_event_record * (*)PARAMS ((void))) nosupport_runtime);
*************** update_current_target ()
*** 527,532 ****
--- 528,534 ----
INHERIT (to_find_new_threads, t);
INHERIT (to_stop, t);
INHERIT (to_query, t);
+ INHERIT (to_rcmd, t);
INHERIT (to_enable_exception_callback, t);
INHERIT (to_get_current_exception_event, t);
INHERIT (to_pid_to_exec_file, t);
*************** debug_to_query (type, req, resp, siz)
*** 2602,2607 ****
--- 2604,2617 ----
return retval;
}
+ static void
+ debug_to_rcmd (char *command,
+ struct gdb_file *outbuf)
+ {
+ debug_target.to_rcmd (command, outbuf);
+ fprintf_unfiltered (gdb_stdlog, "target_rcmd (%s, ...)\n", command);
+ }
+
static struct symtab_and_line *
debug_to_enable_exception_callback (kind, enable)
enum exception_event_kind kind;
*************** setup_target_debug ()
*** 2707,2712 ****
--- 2717,2723 ----
current_target.to_thread_alive = debug_to_thread_alive;
current_target.to_stop = debug_to_stop;
current_target.to_query = debug_to_query;
+ current_target.to_rcmd = debug_to_rcmd;
current_target.to_enable_exception_callback = debug_to_enable_exception_callback;
current_target.to_get_current_exception_event = debug_to_get_current_exception_event;
current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
*************** static char targ_desc[] =
*** 2720,2725 ****
--- 2731,2749 ----
Shows the entire stack of targets currently in use (including the exec-file,\n\
core-file, and process, if any), as well as the symbol file name.";
+ static void
+ do_monitor_command (char *cmd,
+ int from_tty)
+ {
+ if ((current_target.to_rcmd == (void*) tcomplain)
+ || (current_target.to_rcmd == debug_to_rcmd
+ && (debug_target.to_rcmd == (void*) tcomplain)))
+ {
+ error ("\"monitor\" command not supported by this target.\n");
+ }
+ target_rcmd (cmd, gdb_stdtarg);
+ }
+
void
initialize_targets ()
{
*************** initialize_targets ()
*** 2735,2740 ****
--- 2759,2768 ----
"Set target debugging.\n\
When non-zero, target debugging is enabled.", &setlist),
&showlist);
+
+
+ add_com ("monitor", class_obscure, do_monitor_command,
+ "Send a command to the remote monitor (remote targets only).");
if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
abort ();
Index: target.h
===================================================================
RCS file: /cvs/gdb/gdb/gdb/target.h,v
retrieving revision 1.1.1.6
diff -p -r1.1.1.6 target.h
*** target.h 1999/07/07 20:10:39 1.1.1.6
--- target.h 1999/08/05 08:28:19
*************** struct target_ops
*** 376,381 ****
--- 376,382 ----
void (*to_find_new_threads) PARAMS ((void));
void (*to_stop) PARAMS ((void));
int (*to_query) PARAMS ((int /*char */ , char *, char *, int *));
+ void (*to_rcmd) (char *command, struct gdb_file *output);
struct symtab_and_line *(*to_enable_exception_callback) PARAMS ((enum exception_event_kind, int));
struct exception_event_record *(*to_get_current_exception_event) PARAMS ((void));
char *(*to_pid_to_exec_file) PARAMS ((int pid));
*************** print_section_info PARAMS ((struct targe
*** 929,934 ****
--- 930,943 ----
#define target_query(query_type, query, resp_buffer, bufffer_size) \
(*current_target.to_query) (query_type, query, resp_buffer, bufffer_size)
+
+ /* Send the specified COMMAND to the target's monitor
+ (shell,interpreter) for execution. The result of the query is
+ placed in OUTBUF. */
+
+ #define target_rcmd(command, outbuf) \
+ (*current_target.to_rcmd) (command, outbuf)
+
/* Get the symbol information for a breakpointable routine called when
an exception event occurs.
Index: doc/remote.texi
===================================================================
RCS file: /cvs/gdb/gdb/gdb/doc/remote.texi,v
retrieving revision 1.1.1.3
diff -p -r1.1.1.3 remote.texi
*** remote.texi 1999/06/28 16:02:16 1.1.1.3
--- remote.texi 1999/08/05 08:28:49
*************** See @code{remote.c:remote_unpack_thread_
*** 770,778 ****
execution. @emph{Implementors should note that providing access to a
stubs's interpreter may have security implications}.
@item
! @tab reply @var{OUTPUT}
@tab
! The @var{OUTPUT} (hex encoded). Must be non-empty.
@item
@tab reply @samp{}
@tab
--- 770,781 ----
execution. @emph{Implementors should note that providing access to a
stubs's interpreter may have security implications}.
@item
! @tab reply @var{OUTPUT} or @var{OK}
@tab
! The @var{OUTPUT} is the hex encoded output from the command. @var{OK}
! is returned when the @var{OUTPUT} would have been empty. The target may
! also respond with a number of intermediate @code{O}@var{OUTPUT} packets.
!
@item
@tab reply @samp{}
@tab