mirror of
https://github.com/AuxXxilium/eudev.git
synced 2024-11-23 23:10:57 +07:00
coredumpctl: add 'gdb' verb to start gdb right-away on a collected coredump
This commit is contained in:
parent
684341b073
commit
ada45c785f
@ -121,6 +121,16 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term><command>gdb</command></term>
|
||||
|
||||
<listitem><para>Invoke the GNU
|
||||
debugger on the last coredump matching
|
||||
specified characteristics.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
@ -179,7 +189,8 @@
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
@ -36,6 +38,7 @@ static enum {
|
||||
ACTION_NONE,
|
||||
ACTION_LIST,
|
||||
ACTION_DUMP,
|
||||
ACTION_GDB,
|
||||
} arg_action = ACTION_LIST;
|
||||
|
||||
static Set *matches = NULL;
|
||||
@ -191,6 +194,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_action = ACTION_LIST;
|
||||
else if (streq(cmd, "dump"))
|
||||
arg_action = ACTION_DUMP;
|
||||
else if (streq(cmd, "gdb"))
|
||||
arg_action = ACTION_GDB;
|
||||
else {
|
||||
log_error("Unknown action '%s'", cmd);
|
||||
return -EINVAL;
|
||||
@ -304,13 +309,9 @@ static int dump_list(sd_journal *j) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_core(sd_journal* j) {
|
||||
const char *data;
|
||||
size_t len, ret;
|
||||
static int focus(sd_journal *j) {
|
||||
int r;
|
||||
|
||||
assert(j);
|
||||
|
||||
r = sd_journal_seek_tail(j);
|
||||
if (r == 0)
|
||||
r = sd_journal_previous(j);
|
||||
@ -318,17 +319,23 @@ static int dump_core(sd_journal* j) {
|
||||
log_error("Failed to search journal: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
log_error("No match found");
|
||||
return -ESRCH;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
|
||||
if (r != 0) {
|
||||
log_error("retrieve COREDUMP field: %s", strerror(-r));
|
||||
static int dump_core(sd_journal* j) {
|
||||
const void *data;
|
||||
size_t len, ret;
|
||||
int r;
|
||||
|
||||
assert(j);
|
||||
|
||||
r = focus(j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
print_entry(output ? stdout : stderr, j, false);
|
||||
|
||||
@ -337,9 +344,17 @@ static int dump_core(sd_journal* j) {
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
assert(len >= 9);
|
||||
r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
|
||||
if (r < 0) {
|
||||
log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
ret = fwrite(data+9, len-9, 1, output ? output : stdout);
|
||||
assert(len >= 9);
|
||||
data = (const uint8_t*) data + 9;
|
||||
len -= 9;
|
||||
|
||||
ret = fwrite(data, len, 1, output ? output : stdout);
|
||||
if (ret != 1) {
|
||||
log_error("dumping coredump: %m (%zu)", ret);
|
||||
return -errno;
|
||||
@ -352,6 +367,100 @@ static int dump_core(sd_journal* j) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_gdb(sd_journal *j) {
|
||||
char path[] = "/var/tmp/coredump-XXXXXX";
|
||||
const void *data;
|
||||
size_t len;
|
||||
ssize_t sz;
|
||||
pid_t pid;
|
||||
_cleanup_free_ char *exe = NULL;
|
||||
int r;
|
||||
_cleanup_close_ int fd = -1;
|
||||
siginfo_t st;
|
||||
|
||||
assert(j);
|
||||
|
||||
r = focus(j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
print_entry(stdout, j, false);
|
||||
|
||||
r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
|
||||
if (r < 0) {
|
||||
log_error("Failed to retrieve COREDUMP_EXE field: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(len >= 13);
|
||||
data = (const uint8_t*) data + 13;
|
||||
len -= 13;
|
||||
|
||||
exe = strndup(data, len);
|
||||
if (!exe)
|
||||
return log_oom();
|
||||
|
||||
if (endswith(exe, " (deleted)")) {
|
||||
log_error("Binary already deleted.");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
|
||||
if (r < 0) {
|
||||
log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(len >= 9);
|
||||
data = (const uint8_t*) data + 9;
|
||||
len -= 9;
|
||||
|
||||
fd = mkostemp(path, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_error("Failed to create temporary file: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
sz = write(fd, data, len);
|
||||
if (sz < 0) {
|
||||
log_error("Failed to write temporary file: %s", strerror(errno));
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
if (sz != (ssize_t) len) {
|
||||
log_error("Short write to temporary file.");
|
||||
r = -EIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
close_nointr_nofail(fd);
|
||||
fd = -1;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
log_error("Failed to fork(): %m");
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
if (pid == 0) {
|
||||
execlp("gdb", "gdb", exe, path, NULL);
|
||||
log_error("Failed to invoke gdb: %m");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
r = wait_for_terminate(pid, &st);
|
||||
if (r < 0) {
|
||||
log_error("Failed to wait for gdb: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = st.si_code == CLD_EXITED ? st.si_status : 255;
|
||||
|
||||
finish:
|
||||
unlink(path);
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sd_journal *j = NULL;
|
||||
const char* match;
|
||||
@ -387,16 +496,23 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
switch(arg_action) {
|
||||
|
||||
case ACTION_LIST:
|
||||
if (!arg_no_pager)
|
||||
pager_open();
|
||||
|
||||
r = dump_list(j);
|
||||
break;
|
||||
|
||||
case ACTION_DUMP:
|
||||
r = dump_core(j);
|
||||
break;
|
||||
case ACTION_NONE:
|
||||
|
||||
case ACTION_GDB:
|
||||
r = run_gdb(j);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Shouldn't be here");
|
||||
}
|
||||
|
||||
@ -411,5 +527,5 @@ end:
|
||||
if (output)
|
||||
fclose(output);
|
||||
|
||||
return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
return r >= 0 ? r : EXIT_FAILURE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user