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] |
At present, there is no way to pass the output of a gdb command directly to the shell for further processing. For example, something similar is not permitted: (gdb) thread apply all bt | less This kind of feature is quite helpful in a scenario where a program under debugger has hundreds of threads running and one wants to examine the stack-trace of all the threads at once. The current behaviour of gdb makes it somewhat difficult since the entire output of gdb command (sometimes more than a number of pages) is dumped onto the screen. One can always redirect the output of gdb using logging mechanism, but that requires offline analysis of the log-file which may not be acceptable in certain situations. Another option is to get a shell using gdb's shell command, but that forces one every time to source the shell profile. Furthermore, the log-file contains entire debug information, parsing that huge file is resource and time consuming. I have implemented a feature which will allow one to pass the output of any gdb command to the shell for further processing. The syntax will be as follows: (gdb) gdb command | `{shell command}` top.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- ui-file.c | 15 ++++++++++++ ui-file.h | 3 ++ 3 files changed, 94 insertions(+), 1 deletion(-)
diff -rup src//gdb/top.c dst//gdb/top.c --- src//gdb/top.c 2011-06-28 00:51:50.000000000 +0530 +++ dst//gdb/top.c 2011-07-19 11:15:38.984381163 +0530 @@ -48,6 +48,7 @@ #include "event-loop.h" #include "gdbthread.h" #include "python/python.h" +#include "ui-file.h" /* readline include files. */ #include "readline/readline.h" @@ -358,6 +359,71 @@ prepare_execute_command (void) return cleanup; } +char * +parse_for_shell_command (char *p) +{ + char *sh_cmd, *cpos, *spos, *epos; + int quote_cnt = 0; + + if ((sh_cmd = strchr (p, '|')) != NULL) + { + spos = p; + epos = p + strlen (p) - 1; + + for (;;) + { + for (cpos = spos; (cpos = memchr (cpos, '"', (sh_cmd-cpos))) != NULL; cpos++) + quote_cnt++; + spos = (sh_cmd + 1); + if ((quote_cnt % 2) == 0 || (sh_cmd = strchr (spos, '|')) == NULL) + break; + } + + if (sh_cmd == NULL) + return NULL; + + cpos = spos; + while (isspace(*cpos)) + cpos++; + + if (*cpos != '`' || *(cpos+1) != '{') + return parse_for_shell_command (cpos); + + spos = cpos; + + cpos = epos; + while (isspace(*cpos)) + cpos--; + + if (*cpos != '`' || *(cpos-1) != '}') + return parse_for_shell_command (cpos); + + epos = cpos; + } + + if (sh_cmd) + { + *spos = *(spos+1) = *epos = *(epos-1) = ' '; + *sh_cmd++ = '\0'; + } + + return sh_cmd; +} + +/* Run execute_command for P and FROM_TTY. Write output in pipe, + do not display it to the screen. */ + +void +execute_command_to_pipe (char *p, int from_tty, FILE *pipe) +{ + FILE *file; + + file = gdb_modify_io (gdb_stdout, pipe); + execute_command (p, from_tty); + pipe = gdb_modify_io (gdb_stdout, file); + pclose (pipe); +} + /* Execute the line P as a command, in the current user context. Pass FROM_TTY as second argument to the defining function. */ @@ -368,7 +434,16 @@ execute_command (char *p, int from_tty) struct cmd_list_element *c; enum language flang; static int warned = 0; - char *line; + char *line, *sh_cmd; + + if ((sh_cmd = parse_for_shell_command (p)) != NULL) + { + FILE *pipe; + + pipe = popen (sh_cmd, "w"); + execute_command_to_pipe (p, from_tty, pipe); + return; + } cleanup = prepare_execute_command (); diff -rup src//gdb/ui-file.c dst//gdb/ui-file.c --- src//gdb/ui-file.c 2011-05-14 11:14:36.000000000 +0530 +++ dst//gdb/ui-file.c 2011-07-15 13:49:34.999910332 +0530 @@ -617,6 +617,21 @@ struct ui_file * stdio_fileopen (FILE *file) { return stdio_file_new (file, 0); + +} + +FILE * +gdb_modify_io (struct ui_file *file, FILE *iostream_new) +{ + FILE *iostream_old; + struct stdio_file *stdio = ui_file_data (file); + + if (stdio->magic != &stdio_file_magic) + internal_error (__FILE__, __LINE__, + _("gdb_modify_io: bad magic number")); + iostream_old = stdio->file; + stdio->file = iostream_new; + return iostream_old; } struct ui_file * diff -rup src//gdb/ui-file.h dst//gdb/ui-file.h --- src//gdb/ui-file.h 2011-05-13 22:58:20.000000000 +0530 +++ dst//gdb/ui-file.h 2011-07-15 13:48:54.603912199 +0530 @@ -126,6 +126,9 @@ extern struct ui_file *stdio_fileopen (F /* Open NAME returning an STDIO based UI_FILE. */ extern struct ui_file *gdb_fopen (char *name, char *mode); +/* Modify the file pointer of an STDIO based UI_FILE. */ +FILE *gdb_modify_io (struct ui_file *file, FILE *iostream_new); + /* Create a file which writes to both ONE and TWO. CLOSE_ONE and CLOSE_TWO indicate whether the original files should be closed when the new file is closed. */
Attachment:
ChangeLog
Description: Binary data
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |