[UPDATED PATCH v2 8/8] makedumpfile: Add erase information in ELF formatted dumpfile
Mahesh J Salgaonkar
mahesh at linux.vnet.ibm.com
Fri Jul 15 05:16:02 EDT 2011
Hi,
This is an updated patch that fixes a problem where empty ELF note gets
populated when info->size_eraseinfo is zero. This updated patch now does
not introduce new ELF note if info->size_eraseinfo == 0.
Thanks,
-Mahesh.
makedumpfile: Add erase information in ELF formatted dumpfile
From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
This patch implements support for inclusion of erase information in ELF
formatted dumpfile. This patch introduces a additional ELF Note section
that contains erase information.
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
makedumpfile.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.h | 17 ++++++++
2 files changed, 142 insertions(+), 1 deletions(-)
diff --git a/makedumpfile.c b/makedumpfile.c
index 7ff94ac..f48953e 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3352,6 +3352,9 @@ get_pt_note_info(off_t off_note, unsigned long sz_note)
return FALSE;
}
info->p2m_mfn = p2m_mfn;
+ } else if (n_type == NT_ERASE_INFO) {
+ info->offset_eraseinfo = offset_desc;
+ info->size_eraseinfo = size_desc;
}
offset += offset_next_note(note);
}
@@ -4647,6 +4650,15 @@ write_cache_bufsz(struct cache_data *cd)
}
int
+write_cache_zero(struct cache_data *cd, size_t size)
+{
+ memset(cd->buf + cd->buf_size, 0, size);
+ cd->buf_size += size;
+
+ return write_cache_bufsz(cd);
+}
+
+int
read_buf_from_stdin(void *buf, int buf_size)
{
int read_size = 0, tmp_read_size = 0;
@@ -5799,10 +5811,12 @@ write_elf_header(struct cache_data *cd_header)
{
int i, num_loads_dumpfile, phnum;
off_t offset_note_memory, offset_note_dumpfile;
- size_t size_note;
+ size_t size_note, size_eraseinfo = 0;
Elf64_Ehdr ehdr64;
Elf32_Ehdr ehdr32;
Elf64_Phdr note;
+ char size_str[MAX_SIZE_STR_LEN];
+ struct filter_info *fl_info = filter_info;
char *buf = NULL;
const off_t failed = (off_t)-1;
@@ -5855,6 +5869,36 @@ write_elf_header(struct cache_data *cd_header)
}
/*
+ * Pre-calculate the required size to store eraseinfo in ELF note
+ * section so that we can add enough space in ELF notes section and
+ * adjust the PT_LOAD offset accordingly.
+ */
+ while (fl_info) {
+ struct erase_info *ei;
+
+ if (!fl_info->erase_info_idx)
+ continue;
+ ei = &erase_info[fl_info->erase_info_idx];
+ if (fl_info->nullify)
+ sprintf(size_str, "nullify\n");
+ else
+ sprintf(size_str, "%ld\n", fl_info->size);
+
+ size_eraseinfo += strlen("erase ") +
+ strlen(ei->symbol_expr) + 1 +
+ strlen(size_str);
+ fl_info = fl_info->next;
+ }
+
+ /*
+ * Store the size_eraseinfo for later use in write_elf_eraseinfo()
+ * function. This will overwrite the size fetched during
+ * get elf_info() function but we are ok with that.
+ */
+ info->size_eraseinfo = size_eraseinfo;
+ DEBUG_MSG("erase info size: %lu\n", info->size_eraseinfo);
+
+ /*
* Write a PT_NOTE header.
*/
if (!(phnum = get_phnum_memory()))
@@ -5884,6 +5928,19 @@ write_elf_header(struct cache_data *cd_header)
note.p_offset = offset_note_dumpfile;
size_note = note.p_filesz;
+ /*
+ * Modify the note size in PT_NOTE header to accomodate eraseinfo data.
+ * Eraseinfo will be written later.
+ */
+ if (info->size_eraseinfo) {
+ if (info->flag_elf64_memory)
+ note.p_filesz += sizeof(Elf64_Nhdr);
+ else
+ note.p_filesz += sizeof(Elf32_Nhdr);
+ note.p_filesz += roundup(ERASEINFO_NOTE_NAME_BYTES, 4) +
+ roundup(size_eraseinfo, 4);
+ }
+
if (!write_elf_phdr(cd_header, ¬e))
goto out;
@@ -5910,10 +5967,14 @@ write_elf_header(struct cache_data *cd_header)
size_note, info->name_dumpfile))
goto out;
+ /* Set the size_note with new size. */
+ size_note = note.p_filesz;
+
/*
* Set an offset of PT_LOAD segment.
*/
info->offset_load_dumpfile = offset_note_dumpfile + size_note;
+ info->offset_note_dumpfile = offset_note_dumpfile;
ret = TRUE;
out:
@@ -6728,6 +6789,67 @@ out:
}
int
+write_elf_eraseinfo(struct cache_data *cd_header)
+{
+ char note[MAX_SIZE_NHDR];
+ char buf[ERASEINFO_NOTE_NAME_BYTES + 4];
+ unsigned long note_header_size, size_eraseinfo;
+
+ if (!info->size_eraseinfo)
+ return TRUE;
+
+ DEBUG_MSG("Writing erase info...\n");
+
+ /* calculate the eraseinfo ELF note offset */
+ cd_header->offset = info->offset_note_dumpfile +
+ roundup(info->size_note, 4);
+
+ /* Write eraseinfo ELF note header. */
+ memset(note, 0, sizeof(note));
+ if (info->flag_elf64_memory) {
+ Elf64_Nhdr *nh = (Elf64_Nhdr *)note;
+
+ note_header_size = sizeof(Elf64_Nhdr);
+ nh->n_namesz = ERASEINFO_NOTE_NAME_BYTES;
+ nh->n_descsz = info->size_eraseinfo;
+ nh->n_type = NT_ERASE_INFO;
+ } else {
+ Elf32_Nhdr *nh = (Elf32_Nhdr *)note;
+
+ note_header_size = sizeof(Elf32_Nhdr);
+ nh->n_namesz = ERASEINFO_NOTE_NAME_BYTES;
+ nh->n_descsz = info->size_eraseinfo;
+ nh->n_type = NT_ERASE_INFO;
+ }
+ if (!write_cache(cd_header, note, note_header_size))
+ return FALSE;
+
+ /* Write eraseinfo Note name */
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, ERASEINFO_NOTE_NAME, ERASEINFO_NOTE_NAME_BYTES);
+ if (!write_cache(cd_header, buf,
+ roundup(ERASEINFO_NOTE_NAME_BYTES, 4)))
+ return FALSE;
+
+ info->offset_eraseinfo = cd_header->offset;
+ if (!write_eraseinfo(cd_header, &size_eraseinfo))
+ return FALSE;
+
+ /*
+ * The actual eraseinfo written may be less than pre-calculated size.
+ * Hence fill up the rest of size with zero's.
+ */
+ if (size_eraseinfo < info->size_eraseinfo)
+ write_cache_zero(cd_header,
+ info->size_eraseinfo - size_eraseinfo);
+
+ DEBUG_MSG("offset_eraseinfo: %lx, size_eraseinfo: %ld\n",
+ info->offset_eraseinfo, info->size_eraseinfo);
+
+ return TRUE;
+}
+
+int
write_kdump_eraseinfo(struct cache_data *cd_page)
{
off_t offset_eraseinfo;
@@ -7581,6 +7703,8 @@ writeout_dumpfile(void)
goto out;
if (!write_elf_pages(&cd_header, &cd_page))
goto out;
+ if (!write_elf_eraseinfo(&cd_header))
+ goto out;
} else {
if (!write_kdump_header())
goto out;
diff --git a/makedumpfile.h b/makedumpfile.h
index 2e4b902..662bc97 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -504,6 +504,22 @@ do { \
#define MAX_SIZE_STR_LEN (21)
/*
+ * ELF note section for erase information
+ *
+ * According to elf.h the unused values are 0x15(21) through 0xff. The value
+ * range 0x1XX, 0x2XX and 0x3XX is been used for PPC, i386 and s390
+ * respectively.
+ *
+ * Using 0xff to be on safer side so that any new Elf Note addition in elf.h
+ * after 0x15 value would not clash.
+ */
+#ifndef NT_ERASE_INFO
+#define NT_ERASE_INFO (0xff) /* Contains erased information. */
+#endif
+#define ERASEINFO_NOTE_NAME "ERASEINFO"
+#define ERASEINFO_NOTE_NAME_BYTES (sizeof(ERASEINFO_NOTE_NAME))
+
+/*
* The value of dependence on machine
*/
#define PAGE_OFFSET (info->page_offset)
@@ -977,6 +993,7 @@ struct DumpInfo {
* ELF NOTE section in dump memory image info:
*/
off_t offset_note;
+ off_t offset_note_dumpfile;
unsigned long size_note;
/*
--
Mahesh J Salgaonkar
More information about the kexec
mailing list