From 063d7b451da3dbaac4cf45fa0fe6488f8acb4a4d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 21 Aug 2026 07:47:45 +0900 Subject: [PATCH] coredumpctl: move verb_run_debug() to coredumpctl-debugger.c --- src/coredump/coredumpctl-debugger.c | 149 +++++++++++++++++++++++++++ src/coredump/coredumpctl-debugger.h | 6 ++ src/coredump/coredumpctl.c | 152 +--------------------------- src/coredump/meson.build | 1 + 4 files changed, 161 insertions(+), 147 deletions(-) create mode 100644 src/coredump/coredumpctl-debugger.c create mode 100644 src/coredump/coredumpctl-debugger.h diff --git a/src/coredump/coredumpctl-debugger.c b/src/coredump/coredumpctl-debugger.c new file mode 100644 index 0000000000..482f86024d --- /dev/null +++ b/src/coredump/coredumpctl-debugger.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "sd-journal.h" + +#include "coredumpctl.h" +#include "coredumpctl-core.h" +#include "coredumpctl-debugger.h" +#include "coredumpctl-info.h" +#include "coredumpctl-journal.h" +#include "coredumpctl-util.h" +#include "log.h" +#include "path-util.h" +#include "pidref.h" +#include "process-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" + +int verb_run_debug(int argc, char *argv[], uintptr_t _data, void *userdata) { + static const struct sigaction sa = { + .sa_sigaction = sigterm_process_group_handler, + .sa_flags = SA_SIGINFO, + }; + + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_free_ char *exe = NULL, *path = NULL; + _cleanup_strv_free_ char **debugger_call = NULL; + bool unlink_path = false; + const char *data, *fork_name; + size_t len; + int r; + + if (!arg_debugger) { + char *env_debugger; + + env_debugger = getenv("SYSTEMD_DEBUGGER"); + if (env_debugger) + arg_debugger = env_debugger; + else + arg_debugger = "gdb"; + } + + r = strv_extend(&debugger_call, arg_debugger); + if (r < 0) + return log_oom(); + + r = strv_extend_strv(&debugger_call, arg_debugger_args, false); + if (r < 0) + return log_oom(); + + if (arg_field) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --field/-F only makes sense with list"); + + r = acquire_journal(&j, strv_skip(argv, 1)); + if (r < 0) + return r; + + r = focus(j); + if (r < 0) + return r; + + if (!arg_quiet) { + print_info(stdout, j, false); + fputs("\n", stdout); + } + + r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len); + if (r < 0) + return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m"); + + assert(len > STRLEN("COREDUMP_EXE=")); + data += STRLEN("COREDUMP_EXE="); + len -= STRLEN("COREDUMP_EXE="); + + exe = strndup(data, len); + if (!exe) + return log_oom(); + + if (endswith(exe, " (deleted)")) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Binary already deleted."); + + if (!path_is_absolute(exe)) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Binary is not an absolute path."); + + r = resolve_filename(arg_root, &exe); + if (r < 0) + return r; + + r = save_core(j, NULL, &path, &unlink_path); + if (r < 0) + return r; + + r = strv_extend_many(&debugger_call, exe, "-c", path); + if (r < 0) + return log_oom(); + + if (arg_root) { + if (streq(arg_debugger, "gdb")) { + const char *sysroot_cmd; + sysroot_cmd = strjoina("set sysroot ", arg_root); + + r = strv_extend_many(&debugger_call, "-iex", sysroot_cmd); + if (r < 0) + return log_oom(); + } else if (streq(arg_debugger, "lldb")) { + const char *sysroot_cmd; + sysroot_cmd = strjoina("platform select --sysroot ", arg_root, " host"); + + r = strv_extend_many(&debugger_call, "-O", sysroot_cmd); + if (r < 0) + return log_oom(); + } + } + + /* Don't interfere with gdb and its handling of SIGINT. */ + (void) ignore_signals(SIGINT); + (void) sigaction(SIGTERM, &sa, NULL); + + fork_name = strjoina("(", debugger_call[0], ")"); + + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = pidref_safe_fork( + fork_name, + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, + &pidref); + if (r < 0) + goto finish; + if (r == 0) { + execvp(debugger_call[0], debugger_call); + log_open(); + log_error_errno(errno, "Failed to invoke %s: %m", debugger_call[0]); + _exit(EXIT_FAILURE); + } + + r = pidref_wait_for_terminate_and_check(debugger_call[0], &pidref, WAIT_LOG_ABNORMAL); + +finish: + (void) default_signals(SIGINT, SIGTERM); + + if (unlink_path) { + log_debug("Removed temporary file %s", path); + (void) unlink(path); + } + + return r; +} diff --git a/src/coredump/coredumpctl-debugger.h b/src/coredump/coredumpctl-debugger.h new file mode 100644 index 0000000000..d3fe114906 --- /dev/null +++ b/src/coredump/coredumpctl-debugger.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "forward.h" + +int verb_run_debug(int argc, char *argv[], uintptr_t _data, void *userdata); diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 4e9c8bfd70..b6c63be8ba 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -1,12 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include -#include -#include -#include #include "sd-bus.h" -#include "sd-journal.h" #include "sd-json.h" #include "alloc-util.h" @@ -17,10 +13,8 @@ #include "bus-util.h" #include "coredumpctl.h" #include "coredumpctl-core.h" -#include "coredumpctl-info.h" -#include "coredumpctl-journal.h" +#include "coredumpctl-debugger.h" #include "coredumpctl-list.h" -#include "coredumpctl-util.h" #include "dissect-image.h" #include "dlopen-note.h" #include "extract-word.h" @@ -34,10 +28,6 @@ #include "pager.h" #include "parse-argument.h" #include "parse-util.h" -#include "path-util.h" -#include "pidref.h" -#include "process-util.h" -#include "signal-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -230,142 +220,10 @@ VERB_SCOPE(, verb_dump_list, "info", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, "Show detailed information about one or more coredumps"); VERB_SCOPE(, verb_dump_core, "dump", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, "Print first matching coredump to stdout"); - -VERB(verb_run_debug, "debug", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, - "Start a debugger for the first matching coredump"); -VERB(verb_run_debug, "gdb", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, - /* help= */ NULL); -static int verb_run_debug(int argc, char *argv[], uintptr_t _data, void *userdata) { - static const struct sigaction sa = { - .sa_sigaction = sigterm_process_group_handler, - .sa_flags = SA_SIGINFO, - }; - - _cleanup_(sd_journal_closep) sd_journal *j = NULL; - _cleanup_free_ char *exe = NULL, *path = NULL; - _cleanup_strv_free_ char **debugger_call = NULL; - bool unlink_path = false; - const char *data, *fork_name; - size_t len; - int r; - - if (!arg_debugger) { - char *env_debugger; - - env_debugger = getenv("SYSTEMD_DEBUGGER"); - if (env_debugger) - arg_debugger = env_debugger; - else - arg_debugger = "gdb"; - } - - r = strv_extend(&debugger_call, arg_debugger); - if (r < 0) - return log_oom(); - - r = strv_extend_strv(&debugger_call, arg_debugger_args, false); - if (r < 0) - return log_oom(); - - if (arg_field) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Option --field/-F only makes sense with list"); - - r = acquire_journal(&j, strv_skip(argv, 1)); - if (r < 0) - return r; - - r = focus(j); - if (r < 0) - return r; - - if (!arg_quiet) { - print_info(stdout, j, false); - fputs("\n", stdout); - } - - r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len); - if (r < 0) - return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m"); - - assert(len > STRLEN("COREDUMP_EXE=")); - data += STRLEN("COREDUMP_EXE="); - len -= STRLEN("COREDUMP_EXE="); - - exe = strndup(data, len); - if (!exe) - return log_oom(); - - if (endswith(exe, " (deleted)")) - return log_error_errno(SYNTHETIC_ERRNO(ENOENT), - "Binary already deleted."); - - if (!path_is_absolute(exe)) - return log_error_errno(SYNTHETIC_ERRNO(ENOENT), - "Binary is not an absolute path."); - - r = resolve_filename(arg_root, &exe); - if (r < 0) - return r; - - r = save_core(j, NULL, &path, &unlink_path); - if (r < 0) - return r; - - r = strv_extend_many(&debugger_call, exe, "-c", path); - if (r < 0) - return log_oom(); - - if (arg_root) { - if (streq(arg_debugger, "gdb")) { - const char *sysroot_cmd; - sysroot_cmd = strjoina("set sysroot ", arg_root); - - r = strv_extend_many(&debugger_call, "-iex", sysroot_cmd); - if (r < 0) - return log_oom(); - } else if (streq(arg_debugger, "lldb")) { - const char *sysroot_cmd; - sysroot_cmd = strjoina("platform select --sysroot ", arg_root, " host"); - - r = strv_extend_many(&debugger_call, "-O", sysroot_cmd); - if (r < 0) - return log_oom(); - } - } - - /* Don't interfere with gdb and its handling of SIGINT. */ - (void) ignore_signals(SIGINT); - (void) sigaction(SIGTERM, &sa, NULL); - - fork_name = strjoina("(", debugger_call[0], ")"); - - _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; - r = pidref_safe_fork( - fork_name, - FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, - &pidref); - if (r < 0) - goto finish; - if (r == 0) { - execvp(debugger_call[0], debugger_call); - log_open(); - log_error_errno(errno, "Failed to invoke %s: %m", debugger_call[0]); - _exit(EXIT_FAILURE); - } - - r = pidref_wait_for_terminate_and_check(debugger_call[0], &pidref, WAIT_LOG_ABNORMAL); - -finish: - (void) default_signals(SIGINT, SIGTERM); - - if (unlink_path) { - log_debug("Removed temporary file %s", path); - (void) unlink(path); - } - - return r; -} +VERB_SCOPE(, verb_run_debug, "debug", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, + "Start a debugger for the first matching coredump"); +VERB_SCOPE(, verb_run_debug, "gdb", "[MATCHES…]", VERB_ANY, VERB_ANY, 0, + /* help= */ NULL); static int check_units_active(void) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; diff --git a/src/coredump/meson.build b/src/coredump/meson.build index ab186fd472..084088dde8 100644 --- a/src/coredump/meson.build +++ b/src/coredump/meson.build @@ -20,6 +20,7 @@ systemd_coredump_export_sources = files( coredumpctl_sources = files( 'coredumpctl.c', 'coredumpctl-core.c', + 'coredumpctl-debugger.c', 'coredumpctl-info.c', 'coredumpctl-journal.c', 'coredumpctl-list.c',