With this change /usr/bin/crash will try to work with ramdump files without
creating the temporary KDUMP elf header if MEMORY-IMAGE starts with the "raw:"
prefix. This looks useful to me, especially because ramdump_to_elf() doesn't
support x86-64.
For example, I am running qemu with
-object memory-backend-file,id=MEM,size=128m,mem-path=/tmp/MEM,share=on
-numa node,memdev=MEM
options and after I crash the kernel (/bin/bash running as "init" exits)
$ ./crash ../VMLINUX raw:/tmp/MEM@0
reports:
KERNEL: ../VMLINUX
DUMPFILES: ramdump [raw]
/tmp/MEM
CPUS: 2 [OFFLINE: 1]
DATE: Mon Apr 25 11:47:26 2016
UPTIME: 00:00:07
LOAD AVERAGE: 0.00, 0.00, 0.00
TASKS: 45
NODENAME: (none)
RELEASE: 3.10.0+
VERSION: #42 SMP Sun Apr 3 17:09:09 CEST 2016
MACHINE: x86_64 (2593 Mhz)
MEMORY: 127.5 MB
PANIC: "Kernel panic - not syncing: Attempted to kill init!
exitcode=0x00000000"
PID: 1
COMMAND: "bash"
TASK: ffff880007150000 [THREAD_INFO: ffff880007158000]
CPU: 0
STATE: TASK_RUNNING (PANIC)
crash> bt
PID: 1 TASK: ffff880007150000 CPU: 0 COMMAND: "bash"
#0 [ffff88000715bc28] __schedule at ffffffff816801c0
#1 [ffff88000715bc40] __module_text_address at ffffffff810ef782
#2 [ffff88000715bc58] is_module_text_address at ffffffff810f625e
#3 [ffff88000715bc68] __kernel_text_address at ffffffff810a85ad
#4 [ffff88000715bc80] print_context_stack at ffffffff810174e3
#5 [ffff88000715bce0] dump_trace at ffffffff81016391
#6 [ffff88000715bd60] show_trace_log_lvl at ffffffff810176ad
#7 [ffff88000715bda8] up at ffffffff810b1cf2
#8 [ffff88000715bdc8] console_unlock at ffffffff8108137e
#9 [ffff88000715be08] i8042_panic_blink at ffffffff814c362d
#10 [ffff88000715be28] panic at ffffffff81679de0
#11 [ffff88000715beb0] do_exit at ffffffff810870ff
#12 [ffff88000715bf40] do_group_exit at ffffffff81087183
#13 [ffff88000715bf70] sys_exit_group at ffffffff81087204
#14 [ffff88000715bf80] system_call_fastpath at ffffffff8168ba89
RIP: 00007f2493bdaaf8 RSP: 00007fff2ae49ee8 RFLAGS: 00010206
RAX: 00000000000000e7 RBX: ffffffff8168ba89 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 000000000000003c RDI: 0000000000000000
RBP: 00007f2493ec98b8 R8: 00000000000000e7 R9: ffffffffffffff98
R10: 00007f24934dcd98 R11: 0000000000000246 R12: ffffffff81087204
R13: ffff88000715bf78 R14: 0000000000000000 R15: 00007f2493ecec60
ORIG_RAX: 00000000000000e7 CS: 0033 SS: 002b
and everything else seems to work too.
Note:
- The usage of CRASHBUILTIN doesn't look nice, we need to cleanup
this logic. I hope we can do this later, and it seems to me that
the usage of MEMORY_SOURCES/DUMPFILE_TYPES needs some cleanups in
any case.
- I can't verify this because x86-64 is not supported, but afaics
the current usage of RAMDUMP/is_ramdump_image/read_ramdump is not
right. RAMDUMP should be always set if is_ramdump() returns true,
and read_ramdump() should not be used if we set KDUMP.
But I can't test this, so the patch adds another is_ramdump_image()
block before ramdump_to_elf(). Which obviously asks for cleanup too.
Signed-off-by: Oleg Nesterov <oleg(a)redhat.com>
---
filesys.c | 2 +-
main.c | 11 +++++++++++
ramdump.c | 21 ++++++++++++++++++++-
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/filesys.c b/filesys.c
index de04486..a1d1d1e 100644
--- a/filesys.c
+++ b/filesys.c
@@ -207,7 +207,7 @@ memory_source_init(void)
return;
}
- if (pc->dumpfile) {
+ if (pc->dumpfile && !(pc->flags & CRASHBUILTIN)) {
if (!file_exists(pc->dumpfile, NULL))
error(FATAL, "%s: %s\n", pc->dumpfile,
strerror(ENOENT));
diff --git a/main.c b/main.c
index 821bb4e..9b72c7e 100644
--- a/main.c
+++ b/main.c
@@ -428,6 +428,17 @@ main(int argc, char **argv)
"too many dumpfile arguments\n");
program_usage(SHORT_FORM);
}
+
+ if (is_ramdump_image()) {
+ /*
+ * FIXME: we set CRASHBUILTIN to tell memory_source_init()
+ * it should ignore pc->dumpfile and for memory_page_size().
+ */
+ pc->flags |= CRASHBUILTIN;
+ optind++;
+ continue;
+ }
+
pc->dumpfile = ramdump_to_elf();
if (is_kdump(pc->dumpfile, KDUMP_LOCAL)) {
pc->flags |= KDUMP;
diff --git a/ramdump.c b/ramdump.c
index c6a8a85..e9716ae 100644
--- a/ramdump.c
+++ b/ramdump.c
@@ -232,14 +232,22 @@ end:
return e_file;
}
+#define PREFIX(ptr, pat) \
+ (strncmp((ptr), (pat), sizeof(pat)-1) ? 0 : \
+ ((ptr) += sizeof(pat)-1, 1))
+
int is_ramdump(char *p)
{
char *x = NULL, *y = NULL, *pat;
size_t len;
char *pattern;
struct stat64 st;
+ int is_raw = 0;
int err = 0;
+ if (PREFIX(p, "raw:"))
+ is_raw = 1;
+
if (nodes || !strchr(p, '@'))
return 0;
@@ -276,6 +284,13 @@ int is_ramdump(char *p)
pat = NULL;
}
+ if (nodes && is_raw) {
+ pc->flags2 |= RAMDUMP;
+ /* also disables get_live_memory_source() logic in fd_init() */
+ pc->dumpfile = "ramdump";
+ pc->readmem = read_ramdump;
+ pc->writemem = NULL;
+ }
return nodes;
}
@@ -345,7 +360,11 @@ show_ramdump_files(void)
{
int i;
- fprintf(fp, "%s [temporary ELF header]\n", elf_default);
+ if (pc->flags & KDUMP)
+ fprintf(fp, "%s [temporary ELF header]\n", elf_default);
+ else
+ fprintf(fp, "%s [raw]\n", pc->dumpfile);
+
for (i = 0; i < nodes; i++) {
fprintf(fp, "%s %s",
i ? "\n" : "", ramdump[i].path);
--
2.5.0