On 03/14/12 06:37, Dave Anderson wrote: Well, ok, I kept stumble fingering the gdb commands, so here's a working patch. Under the covers, the "cmd_gdb" peeks into the command when it sees it is a "set" command. It already does this. But if it is a "set gdb" command, then it just redirects to the internal "cmd_set" function. I also jiggered the arguments to accommodate the fact that the first argument is no longer "gdb". And I fixed the prompt to be "gdb> " to distinguish from both "crash> " and "(gdb) ". I also really hate procedures that go beyond 100 lines or so, so I did not add to the cmd_set length.
diff --git a/cmdline.c b/cmdline.c index f5fd133..ae7edb5 100755 --- a/cmdline.c +++ b/cmdline.c @@ -131,7 +131,6 @@ process_command_line(void) check_special_handling(pc->command_line); } else { - fflush(fp); if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL) clean_exit(1); strcpy(pc->orig_line, pc->command_line); diff --git a/defs.h b/defs.h index bddf2bc..2aa0348 100755 --- a/defs.h +++ b/defs.h @@ -437,12 +437,13 @@ struct program_context { off_t ifile_offset; /* current offset into input file */ char *runtime_ifile_cmd; /* runtime command using input file */ char *kvmdump_mapfile; /* storage of physical to file offsets */ - ulonglong flags2; /* flags overrun */ -#define FLAT (0x1ULL) -#define ELF_NOTES (0x2ULL) -#define GET_OSRELEASE (0x4ULL) -#define REMOTE_DAEMON (0x8ULL) + ulonglong flags2; /* flags overrun */ +#define FLAT (0x01ULL) +#define ELF_NOTES (0x02ULL) +#define GET_OSRELEASE (0x04ULL) +#define REMOTE_DAEMON (0x08ULL) #define ERASEINFO_DATA (0x10ULL) +#define GDB_CMD_MODE (0x20ULL) #define FLAT_FORMAT() (pc->flags2 & FLAT) #define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES) char *cleanup; diff --git a/gdb_interface.c b/gdb_interface.c index fa642bb..ea5d9c1 100755 --- a/gdb_interface.c +++ b/gdb_interface.c @@ -750,23 +750,35 @@ void cmd_gdb(void) { char buf[BUFSIZE]; + char ** av = args; - if (!args[optind]) + if ((pc->flags2 & GDB_CMD_MODE) == 0) + av++; + + if (*av == NULL) cmd_usage(pc->curcmd, SYNOPSIS); - /* - * Intercept set commands in case something has to be done here. - */ - if (STREQ(args[1], "set")) { - if (args[2] && args[3] && STREQ(args[2], "output-radix")) { - pc->output_radix = stol(args[3], FAULT_ON_ERROR, NULL); - } - } + if (STREQ(*av, "set")) { + if (STREQ(av[1], "gdb")) { + /* + * someone typed "set gdb". We do it, not GDB. + */ + cmd_set(); + return; + } + + /* + * Intercept set commands in case something has to be done here. + */ + if (STREQ(av[1], "output-radix") && av[2]) { + pc->output_radix = stol(av[2], FAULT_ON_ERROR, NULL); + } + } /* * If the command is not restricted, pass it on. */ - if (!is_restricted_command(args[1], FAULT_ON_ERROR)) { + if (!is_restricted_command(*av, FAULT_ON_ERROR)) { if (STREQ(pc->command_line, "gdb")) { strcpy(buf, &pc->orig_line[3]); strip_beginning_whitespace(buf); @@ -934,6 +946,12 @@ get_frame_offset(ulong pc) return (error(FATAL, "get_frame_offset: invalid request for non-alpha systems!\n")); } -#endif /* !ALPHA */ - - +#endif /* !ALPHA */ +/* + * Local Variables: + * mode: C + * c-file-style: "k&r" + * indent-tabs-mode: nil + * c-basic-offset: 8 + * End: + */ diff --git a/main.c b/main.c index 043f9f0..6de1808 100755 --- a/main.c +++ b/main.c @@ -798,6 +798,9 @@ get_command_table_entry(char *name) { struct command_table_entry *cp; struct extension_table *ext; + + if (pc->flags2 & GDB_CMD_MODE) + name = "gdb"; if ((pc->flags & MINIMAL_MODE) && !minimal_functions(name)) return NULL; @@ -1721,3 +1724,11 @@ get_osrelease(char *dumpfile) clean_exit(retval); } +/* + * Local Variables: + * mode: C + * c-file-style: "k&r" + * indent-tabs-mode: nil + * c-basic-offset: 8 + * End: + */ diff --git a/tools.c b/tools.c index 78fc493..a82a481 100755 --- a/tools.c +++ b/tools.c @@ -17,6 +17,7 @@ #include "defs.h" #include <ctype.h> +#include <stdbool.h> static void print_number(struct number_option *, int, int); static long alloc_hq_entry(void); @@ -1690,6 +1691,159 @@ backspace(int cnt) fprintf(fp, "\b"); } +static bool +cmd_set_opts(int runtime) +{ + for (;;) { + int c = getopt(argcnt, args, "pvc:a:"); + int cpu; + ulong value; + struct task_context *tc; + + switch(c) + { + case EOF: return false; + + case 'c': + if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) + option_not_supported(c); + + if (!runtime) + return true; + + if (ACTIVE()) { + error(INFO, "not allowed on a live system\n"); + argerrs++; + break; + } + cpu = dtoi(optarg, FAULT_ON_ERROR, NULL); + set_cpu(cpu); + return true; + + case 'p': + if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) + option_not_supported(c); + + if (!runtime) + return true; + + if (ACTIVE()) { + set_context(NO_TASK, pc->program_pid); + show_context(CURRENT_CONTEXT()); + return true; + } + + if (!tt->panic_task) { + error(INFO, "no panic task found!\n"); + return true; + } + set_context(tt->panic_task, NO_PID); + show_context(CURRENT_CONTEXT()); + return true; + + case 'v': + if (!runtime) + return true; + + show_options(); + return true; + + case 'a': + if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) + option_not_supported(c); + + if (!runtime) + return true; + + if (ACTIVE()) + error(FATAL, + "-a option not allowed on live systems\n"); + + switch (str_to_context(optarg, &value, &tc)) + { + int i; + + case STR_PID: + if ((i = TASKS_PER_PID(value)) > 1) + error(FATAL, + "pid %d has %d tasks: " + "use a task address\n", + value, i); + break; + + case STR_TASK: + break; + + case STR_INVALID: + error(FATAL, "invalid task or pid value: %s\n", + optarg); + } + + cpu = tc->processor; + tt->active_set[cpu] = tc->task; + if (tt->panic_threads[cpu]) + tt->panic_threads[cpu] = tc->task; + fprintf(fp, "\"%s\" task %lx has been marked as the " + "active task on cpu %d\n", + tc->comm, tc->task, cpu); + return true; + + default: + argerrs++; + break; + } + } +} + +static bool +set_on_or_off(char * arg, ulong * res) +{ + if (STREQ(arg, "on")) { + *res = 1; + return true; + } + if (STREQ(arg, "off")) { + *res = 0; + return true; + } + if (IS_A_NUMBER(arg)) + return stol(arg, FAULT_ON_ERROR, NULL); + return false; +} + +static bool +do_set_gdb(void) +{ + static char * sv_p = NULL; + + char * arg = args[optind]; + ulong v; + + if (arg == NULL) + return; + + if (sv_p == NULL) + sv_p = pc->prompt; + + optind++; + + if (! set_on_or_off(args[optind], &v)) + return false; + + if (v) { + pc->flags2 |= GDB_CMD_MODE; + pc->prompt = "gdb> "; + + } else { + pc->flags2 &= ~GDB_CMD_MODE; + + if (sv_p != NULL) + pc->prompt = sv_p; + } + + return true; +} + /* * Set/display process context or internal variables. Processes are set * by their task or PID number, or to the panic context with the -p flag. @@ -1725,10 +1879,9 @@ cmd_set(void) { int i, c; ulong value; - int cpu, runtime, from_rc_file; + int runtime, from_rc_file; char buf[BUFSIZE]; char *extra_message; - struct task_context *tc; #define defer() do { } while (0) #define already_done() do { } while (0) @@ -1736,97 +1889,8 @@ cmd_set(void) extra_message = NULL; runtime = pc->flags & RUNTIME ? TRUE : FALSE; from_rc_file = pc->curcmd_flags & FROM_RCFILE ? TRUE : FALSE; - - while ((c = getopt(argcnt, args, "pvc:a:")) != EOF) { - switch(c) - { - case 'c': - if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) - option_not_supported(c); - - if (!runtime) - return; - - if (ACTIVE()) { - error(INFO, "not allowed on a live system\n"); - argerrs++; - break; - } - cpu = dtoi(optarg, FAULT_ON_ERROR, NULL); - set_cpu(cpu); - return; - - case 'p': - if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) - option_not_supported(c); - - if (!runtime) - return; - - if (ACTIVE()) { - set_context(NO_TASK, pc->program_pid); - show_context(CURRENT_CONTEXT()); - return; - } - - if (!tt->panic_task) { - error(INFO, "no panic task found!\n"); - return; - } - set_context(tt->panic_task, NO_PID); - show_context(CURRENT_CONTEXT()); - return; - - case 'v': - if (!runtime) - return; - - show_options(); - return; - - case 'a': - if (XEN_HYPER_MODE() || (pc->flags & MINIMAL_MODE)) - option_not_supported(c); - - if (!runtime) - return; - - if (ACTIVE()) - error(FATAL, - "-a option not allowed on live systems\n"); - - switch (str_to_context(optarg, &value, &tc)) - { - case STR_PID: - if ((i = TASKS_PER_PID(value)) > 1) - error(FATAL, - "pid %d has %d tasks: " - "use a task address\n", - value, i); - break; - - case STR_TASK: - break; - - case STR_INVALID: - error(FATAL, "invalid task or pid value: %s\n", - optarg); - } - - cpu = tc->processor; - tt->active_set[cpu] = tc->task; - if (tt->panic_threads[cpu]) - tt->panic_threads[cpu] = tc->task; - fprintf(fp, - "\"%s\" task %lx has been marked as the active task on cpu %d\n", - tc->comm, tc->task, cpu); - return; - - default: - argerrs++; - break; - } - } + if (cmd_set_opts(runtime)) + return; if (argerrs) { if (runtime) @@ -1851,14 +1915,8 @@ cmd_set(void) optind++; if (!runtime) defer(); - else if (STREQ(args[optind], "on")) - pc->debug = 1; - else if (STREQ(args[optind], "off")) - pc->debug = 0; - else if (IS_A_NUMBER(args[optind])) - pc->debug = stol(args[optind], - FAULT_ON_ERROR, NULL); - else + else if (! set_on_or_off(args[optind], + &pc->debug)) goto invalid_set_command; } if (runtime) @@ -1870,22 +1928,16 @@ cmd_set(void) } else if (STREQ(args[optind], "hash")) { if (args[optind+1]) { + ulong v; optind++; if (!runtime) defer(); - else if (STREQ(args[optind], "on")) + else if (! set_on_or_off(args[++optind], &v)) + goto invalid_set_command; + else if (v) pc->flags |= HASH; - else if (STREQ(args[optind], "off")) + else pc->flags &= ~HASH; - else if (IS_A_NUMBER(args[optind])) { - value = stol(args[optind], - FAULT_ON_ERROR, NULL); - if (value) - pc->flags |= HASH; - else - pc->flags &= ~HASH; - } else - goto invalid_set_command; } if (runtime) @@ -2286,12 +2338,18 @@ cmd_set(void) "on" : "off"); return; + } else if (STREQ(args[optind], "gdb")) { + if (! do_set_gdb()) + goto invalid_set_command; + return; + } else if (XEN_HYPER_MODE()) { error(FATAL, "invalid argument for the Xen hypervisor\n"); } else if (pc->flags & MINIMAL_MODE) { error(FATAL, "invalid argument in minimal mode\n"); } else if (runtime) { ulong pid, task; + struct task_context *tc; switch (str_to_context(args[optind], &value, &tc)) { @@ -2324,7 +2382,7 @@ cmd_set(void) invalid_set_command: - sprintf(buf, "invalid command"); + strcpy(buf, "invalid command"); if (!runtime) sprintf(&buf[strlen(buf)], " in .%src file", pc->program_name); strcat(buf, ": "); @@ -4914,3 +4972,11 @@ make_cpumask_error: return UNUSED; } +/* + * Local Variables: + * mode: C + * c-file-style: "k&r" + * indent-tabs-mode: nil + * c-basic-offset: 8 + * End: + */
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility