From: Ryan Gonzalez Date: Wed, 18 Apr 2018 19:32:17 +0000 (-0500) Subject: coredumpctl: Add debug as a gdb alias, and add lldb support (closes #8722) (#8744) X-Git-Tag: v239~389 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c5896b6a8cfcfd1b94f25450a96a1411384f1108;p=thirdparty%2Fsystemd.git coredumpctl: Add debug as a gdb alias, and add lldb support (closes #8722) (#8744) --- diff --git a/man/coredumpctl.xml b/man/coredumpctl.xml index 16bacb84c92..c6b0f142bcf 100644 --- a/man/coredumpctl.xml +++ b/man/coredumpctl.xml @@ -119,6 +119,15 @@ + + DEBUGGER + + Use the given debugger for the debug + command. If not given and $SYSTEMD_DEBUGGER is unset, then + gdb1 + will be used. + + DIR DIR @@ -228,10 +237,14 @@ - gdb - - Invoke the GNU debugger on the last core dump - matching specified characteristics. + debug + + Invoke a debugger on the last core dump + matching specified characteristics. By default, + gdb1 + will be used. This may be changed using the + option or the $SYSTEMD_DEBUGGER environment + variable. @@ -298,7 +311,7 @@ Invoke gdb on the last core dump - # coredumpctl gdb + # coredumpctl debug diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 95c81f58263..e255206228a 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -44,6 +44,7 @@ static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY; static const char* arg_field = NULL; +static const char *arg_debugger = NULL; static const char *arg_directory = NULL; static bool arg_no_pager = false; static int arg_no_legend = false; @@ -142,23 +143,24 @@ static int help(void) { printf("%s [OPTIONS...]\n\n" "List or retrieve coredumps from the journal.\n\n" "Flags:\n" - " -h --help Show this help\n" - " --version Print version string\n" - " --no-pager Do not pipe output into a pager\n" - " --no-legend Do not print the column headers.\n" - " -1 Show information about most recent entry only\n" - " -S --since=DATE Only print coredumps since the date\n" - " -U --until=DATE Only print coredumps until the date\n" - " -r --reverse Show the newest entries first\n" - " -F --field=FIELD List all values a certain field takes\n" - " -o --output=FILE Write output to FILE\n" - " -D --directory=DIR Use journal files from directory\n\n" - " -q --quiet Do not show info messages and privilege warning\n" + " -h --help Show this help\n" + " --version Print version string\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not print the column headers\n" + " --debugger=DEBUGGER Use the given debugger\n" + " -1 Show information about most recent entry only\n" + " -S --since=DATE Only print coredumps since the date\n" + " -U --until=DATE Only print coredumps until the date\n" + " -r --reverse Show the newest entries first\n" + " -F --field=FIELD List all values a certain field takes\n" + " -o --output=FILE Write output to FILE\n" + " -D --directory=DIR Use journal files from directory\n\n" + " -q --quiet Do not show info messages and privilege warning\n" "Commands:\n" " list [MATCHES...] List available coredumps (default)\n" " info [MATCHES...] Show detailed information about one or more coredumps\n" " dump [MATCHES...] Print first matching coredump to stdout\n" - " gdb [MATCHES...] Start gdb for the first matching coredump\n" + " debug [MATCHES...] Start a debugger for the first matching coredump\n" , program_invocation_short_name); return 0; @@ -169,6 +171,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, + ARG_DEBUGGER, }; int c, r; @@ -178,6 +181,7 @@ static int parse_argv(int argc, char *argv[]) { { "version" , no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "debugger", required_argument, NULL, ARG_DEBUGGER }, { "output", required_argument, NULL, 'o' }, { "field", required_argument, NULL, 'F' }, { "directory", required_argument, NULL, 'D' }, @@ -207,6 +211,10 @@ static int parse_argv(int argc, char *argv[]) { arg_no_legend = true; break; + case ARG_DEBUGGER: + arg_debugger = optarg; + break; + case 'o': if (arg_output) { log_error("cannot set output more than once"); @@ -883,15 +891,25 @@ static int dump_core(int argc, char **argv, void *userdata) { return 0; } -static int run_gdb(int argc, char **argv, void *userdata) { +static int run_debug(int argc, char **argv, void *userdata) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; _cleanup_free_ char *exe = NULL, *path = NULL; bool unlink_path = false; - const char *data; + const char *data, *fork_name; size_t len; pid_t pid; int r; + if (!arg_debugger) { + char *env_debugger; + + env_debugger = getenv("SYSTEMD_DEBUGGER"); + if (env_debugger) + arg_debugger = env_debugger; + else + arg_debugger = "gdb"; + } + if (arg_field) { log_error("Option --field/-F only makes sense with list"); return -EINVAL; @@ -937,17 +955,19 @@ static int run_gdb(int argc, char **argv, void *userdata) { /* Don't interfere with gdb and its handling of SIGINT. */ (void) ignore_signals(SIGINT, -1); - r = safe_fork("(gdb)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid); + fork_name = strjoina("(", arg_debugger, ")"); + + r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid); if (r < 0) goto finish; if (r == 0) { - execlp("gdb", "gdb", exe, path, NULL); + execlp(arg_debugger, arg_debugger, exe, "-c", path, NULL); log_open(); - log_error_errno(errno, "Failed to invoke gdb: %m"); + log_error_errno(errno, "Failed to invoke %s: %m", arg_debugger); _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_check("gdb", pid, WAIT_LOG_ABNORMAL); + r = wait_for_terminate_and_check(arg_debugger, pid, WAIT_LOG_ABNORMAL); finish: (void) default_signals(SIGINT, -1); @@ -1023,10 +1043,11 @@ static int check_units_active(void) { static int coredumpctl_main(int argc, char *argv[]) { static const Verb verbs[] = { - { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list }, - { "info", VERB_ANY, VERB_ANY, 0, dump_list }, - { "dump", VERB_ANY, VERB_ANY, 0, dump_core }, - { "gdb", VERB_ANY, VERB_ANY, 0, run_gdb }, + { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list }, + { "info", VERB_ANY, VERB_ANY, 0, dump_list }, + { "dump", VERB_ANY, VERB_ANY, 0, dump_core }, + { "debug", VERB_ANY, VERB_ANY, 0, run_debug }, + { "gdb", VERB_ANY, VERB_ANY, 0, run_debug }, {} };