[PATCH] makedumpfile: search for a debug vmlinux

Cliff Wickman cpw at sgi.com
Wed Aug 28 18:08:07 EDT 2013


From: Cliff Wickman <cpw at sgi.com>


makedumpfile needs the debug info from either /proc/vmcore or in vmlinux
to know how to find free pages using the buddy method.

The distro procedures do not pass the vmlinux (with the -x option), so
add a search for a debug vmlinux in the usual locations.
It's not needed if the page info is in vmcore.  But warn if it is found
in neither place.

Diffed against makedumpfile-1.5.4
Signed-off-by: Cliff Wickman <cpw at sgi.com>
---
 makedumpfile.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

Index: makedumpfile-1.5.4/makedumpfile.c
===================================================================
--- makedumpfile-1.5.4.orig/makedumpfile.c
+++ makedumpfile-1.5.4/makedumpfile.c
@@ -23,6 +23,7 @@
 #include <stddef.h>
 #include <ctype.h>
 #include <sys/time.h>
+#include <sys/stat.h>
 
 struct symbol_table	symbol_table;
 struct size_table	size_table;
@@ -33,6 +34,7 @@ struct srcfile_table	srcfile_table;
 
 struct vm_table		vt = { 0 };
 struct DumpInfo		*info = NULL;
+struct utsname		utsname;
 
 char filename_stdout[] = FILENAME_STDOUT;
 
@@ -62,6 +64,7 @@ unsigned long long num_dumped;
 int retcd = FAILED;	/* return code */
 int aflag = 0;
 int total_cycles = 0;
+static int no_vmlinux;
 
 #define INITIALIZE_LONG_TABLE(table, value) \
 do { \
@@ -2987,6 +2990,9 @@ initial(void)
 		if (!read_vmcoreinfo_from_vmcore(offset, size, FALSE))
 			return FALSE;
 		debug_info = TRUE;
+		if ((OFFSET(page.private) == NOT_FOUND_STRUCTURE) &&
+		    no_vmlinux)
+			PROGRESS_MSG("No vmlinux and no page info in vmcore\n");
 	}
 
 out:
@@ -7799,6 +7805,7 @@ create_dumpfile(void)
 		return FALSE;
 
 	if (!info->flag_refiltering && !info->flag_sadump) {
+		/* cpw: we get debug info from /proc/vmcore here */
 		if (!get_elf_info(info->fd_memory, info->name_memory))
 			return FALSE;
 	}
@@ -8740,6 +8747,91 @@ static struct option longopts[] = {
 	{0, 0, 0, 0}
 };
 
+/*
+ * Look for a debug vmlinux in the usual places.
+ */
+void
+find_vmlinux()
+{
+	int ret;
+	char pathname[200];
+	struct stat stat_buf;
+
+	ret = uname(&utsname);
+	if (ret < 0) {
+		fprintf(stderr, "uname failed; errno %d", errno);
+	}
+
+	/* these may work if the crash kernel is in multi-user mode */
+	sprintf(pathname, "/usr/lib/debug/lib/modules/%s/vmlinux",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/usr/lib/debug/boot/vmlinux-%s.debug",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/boot/vmlinux-%s", utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+
+	/*
+	 * the crash kernel normally runs with the root device mounted
+	 * as /root or /mnt
+	 */
+	sprintf(pathname, "/root/usr/lib/debug/lib/modules/%s/vmlinux",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/root/usr/lib/debug/boot/vmlinux-%s.debug",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/root/boot/vmlinux-%s", utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/mnt/usr/lib/debug/lib/modules/%s/vmlinux",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/mnt/usr/lib/debug/boot/vmlinux-%s.debug",
+		utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+	sprintf(pathname, "/mnt/boot/vmlinux-%s", utsname.release);
+	if (stat(pathname, &stat_buf) == 0) {
+		info->name_vmlinux = pathname;
+		PROGRESS_MSG("Using %s.\n", pathname);
+		return;
+	}
+
+	no_vmlinux = 1;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -8888,6 +8980,11 @@ main(int argc, char *argv[])
 	if (flag_debug)
 		message_level |= ML_PRINT_DEBUG_MSG;
 
+	if (!info->flag_read_vmcoreinfo && !info->name_vmlinux) {
+		/* -x not specified, so look in standard places */
+		find_vmlinux();
+	}
+
 	if (info->flag_show_usage) {
 		print_usage();
 		return COMPLETED;



More information about the kexec mailing list