]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
coredumpctl: Add debug as a gdb alias, and add lldb support (closes #8722) (#8744)
authorRyan Gonzalez <kirbyfan64@users.noreply.github.com>
Wed, 18 Apr 2018 19:32:17 +0000 (14:32 -0500)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Apr 2018 19:32:17 +0000 (21:32 +0200)
man/coredumpctl.xml
src/coredump/coredumpctl.c

index 16bacb84c92805bfa10357daa1ad7d1315572591..c6b0f142bcf8546f8038b1cd42a9e53feb16c062 100644 (file)
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--debugger=</option><replaceable>DEBUGGER</replaceable></term>
+
+        <listitem><para>Use the given debugger for the <command>debug</command>
+        command. If not given and <varname>$SYSTEMD_DEBUGGER</varname> is unset, then
+        <citerefentry><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        will be used. </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>-D</option> <replaceable>DIR</replaceable></term>
         <term><option>--directory=</option><replaceable>DIR</replaceable></term>
       </varlistentry>
 
       <varlistentry>
-        <term><command>gdb</command></term>
-
-        <listitem><para>Invoke the GNU debugger on the last core dump
-        matching specified characteristics. </para></listitem>
+        <term><command>debug</command></term>
+
+        <listitem><para>Invoke a debugger on the last core dump
+        matching specified characteristics. By default,
+        <citerefentry><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        will be used. This may be changed using the <option>--debugger=</option>
+        option or the <varname>$SYSTEMD_DEBUGGER</varname> environment
+        variable.</para></listitem>
       </varlistentry>
 
     </variablelist>
     <example>
       <title>Invoke gdb on the last core dump</title>
 
-      <programlisting># coredumpctl gdb</programlisting>
+      <programlisting># coredumpctl debug</programlisting>
     </example>
 
     <example>
index 95c81f582638f37f8d5ef43f4c46d2ec1f9a1172..e255206228aafee9d3b9f0007d0bdd24127acd3f 100644 (file)
@@ -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 },
                 {}
         };