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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility