This patch enables crash utility to handle elf notes content in DUMPFILE if
kdump hedaer version >= 4. The processing of data content will be architecture
dependent.
makedumpfile tool is enhanced to store elf notes content from vmcore to
DUMPFILE starting from kdump header version 4.
---------------------------------------------------------------
commit 1fb344e934f87b9c124e487a21e111c7bdc977ba
Author: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
Date: Fri Oct 8 09:18:59 2010 +0900
[PATCH] Add ELF note section to the kdump-compressed format.
---------------------------------------------------------------
A new arch dependent interface has been added to machdep_table structure which
needs to be populated during machdep_init(SETUP_ENV) call.
struct machdep_table {
...
...
void (*process_elf_notes)(void *, unsigned long);
}
ChangeLog:
- Modified __diskdump_memory_dump() function to display contents of
all 4 additional fields in the kdump_sub_header.
- Modified __diskdump_memory_dump() to dump the vmcoreinfo ASCII strings.
Signed-off-by: Mahesh Salgaonkar <mahesh(a)linux.vnet.ibm.com>
---
defs.h | 1
diskdump.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diskdump.h | 4 +++
3 files changed, 86 insertions(+)
Index: crash-5.0.9/diskdump.c
===================================================================
--- crash-5.0.9.orig/diskdump.c
+++ crash-5.0.9/diskdump.c
@@ -189,6 +189,7 @@ static int read_dump_header(char *file)
struct disk_dump_header *header = NULL;
struct disk_dump_sub_header *sub_header = NULL;
struct kdump_sub_header *sub_header_kdump = NULL;
+ unsigned char *notes_buf = NULL;
int bitmap_len;
int block_size = (int)sysconf(_SC_PAGESIZE);
off_t offset;
@@ -355,6 +356,31 @@ restart:
goto err;
}
+ /* process elf notes data */
+ if (KDUMP_CMPRS_VALID() && (dd->header->header_version >= 4)
&&
+ (sub_header_kdump->offset_note) &&
+ (sub_header_kdump->size_note) && (machdep->process_elf_notes)) {
+ unsigned long size_note = sub_header_kdump->size_note;
+ offset = sub_header_kdump->offset_note;
+
+ if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
+ error(INFO, "compressed kdump: cannot lseek dump elf"
+ " notes\n");
+ goto err;
+ }
+
+ if ((notes_buf = malloc(size_note)) == NULL)
+ error(FATAL, "compressed kdump: cannot malloc notes"
+ " buffer\n");
+
+ if (read(dd->dfd, notes_buf, size_note) < size_note) {
+ error(INFO, "compressed kdump: cannot read notes data"
+ "\n");
+ goto err;
+ }
+ machdep->process_elf_notes(notes_buf, size_note);
+ }
+
/* For split dumpfile */
if (KDUMP_CMPRS_VALID()) {
is_split = ((dd->header->header_version >= 2) &&
@@ -399,6 +425,8 @@ err:
free(sub_header);
if (sub_header_kdump)
free(sub_header_kdump);
+ if (notes_buf)
+ free(notes_buf);
if (dd->bitmap)
free(dd->bitmap);
if (dd->dumpable_bitmap)
@@ -786,6 +814,43 @@ int diskdump_memory_used(void)
return 0;
}
+void dump_vmcoreinfo(FILE *fp)
+{
+ char *buf = NULL;
+ unsigned long i = 0;
+ unsigned long size_vmcoreinfo = dd->sub_header_kdump->size_vmcoreinfo;
+ off_t offset = dd->sub_header_kdump->offset_vmcoreinfo;
+ const off_t failed = (off_t)-1;
+
+ if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
+ error(INFO, "compressed kdump: cannot lseek dump vmcoreinfo\n");
+ return;
+ }
+
+ if ((buf = malloc(size_vmcoreinfo)) == NULL) {
+ error(FATAL, "compressed kdump: cannot malloc vmcoreinfo"
+ " buffer\n");
+ }
+
+ if (read(dd->dfd, buf, size_vmcoreinfo) < size_vmcoreinfo) {
+ error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
+ goto err;
+ }
+
+ fprintf(fp, " ");
+ for (i = 0; i < size_vmcoreinfo; i++) {
+ fprintf(fp, "%c", buf[i]);
+ if (buf[i] == '\n')
+ fprintf(fp, " ");
+ }
+ if (buf[i - 1] != '\n')
+ fprintf(fp, "\n");
+err:
+ if (buf)
+ free(buf);
+ return;
+}
+
/*
* This function is dump-type independent, and could be used
* to dump the diskdump_data structure contents and perhaps
@@ -954,6 +1019,22 @@ __diskdump_memory_dump(FILE *fp)
fprintf(fp, " start_pfn: %lu\n",
dd->sub_header_kdump->start_pfn);
fprintf(fp, " end_pfn: %lu\n",
dd->sub_header_kdump->end_pfn);
}
+ if (dh->header_version >= 3) {
+ fprintf(fp, " offset_vmcoreinfo: %lx\n",
+ dd->sub_header_kdump->offset_vmcoreinfo);
+ fprintf(fp, " size_vmcoreinfo: %lu\n",
+ dd->sub_header_kdump->size_vmcoreinfo);
+ if (dd->sub_header_kdump->offset_vmcoreinfo &&
+ dd->sub_header_kdump->size_vmcoreinfo) {
+ dump_vmcoreinfo(fp);
+ }
+ }
+ if (dh->header_version >= 4) {
+ fprintf(fp, " offset_note: %lx\n",
+ dd->sub_header_kdump->offset_note);
+ fprintf(fp, " size_note: %lu\n",
+ dd->sub_header_kdump->size_note);
+ }
fprintf(fp, "\n");
} else
fprintf(fp, "(n/a)\n\n");
Index: crash-5.0.9/diskdump.h
===================================================================
--- crash-5.0.9.orig/diskdump.h
+++ crash-5.0.9/diskdump.h
@@ -63,6 +63,10 @@ struct kdump_sub_header {
int split; /* header_version 2 and later */
unsigned long start_pfn; /* header_version 2 and later */
unsigned long end_pfn; /* header_version 2 and later */
+ off_t offset_vmcoreinfo;/* header_version 3 and later */
+ unsigned long size_vmcoreinfo; /* header_version 3 and later */
+ off_t offset_note; /* header_version 4 and later */
+ unsigned long size_note; /* header_version 4 and later */
};
/* page flags */
Index: crash-5.0.9/defs.h
===================================================================
--- crash-5.0.9.orig/defs.h
+++ crash-5.0.9/defs.h
@@ -807,6 +807,7 @@ struct machdep_table {
int (*xen_kdump_p2m_create)(struct xen_kdump_data *);
int (*in_alternate_stack)(int, ulong);
void (*dumpfile_init)(int, void *);
+ void (*process_elf_notes)(void *, unsigned long);
};
/*