Since the incomplete dump file generated by ENOSPC error can't be analysed
by crash utility, but sometimes this file may contain important information
and the panic problem won't be reproduced, then we came up with an idea to
modify the exist data of the incomplete dump file to make it analysable by
crash utility.
However, we found it will be more suitable to check the incomplete data than
modifying it in make dump file.
So, we change the p_filesz of PT_LOAD header, zero_fill and phys_end of PT_LOAD
segments, to make crash can analyse incomplete ELF dump file, when incomplete
flag exists.
the issue was discussed at
http://lists.infradead.org/pipermail/kexec/2014-October/012669.html
--- a/netdump.c
+++ b/netdump.c
@@ -52,6 +52,7 @@ static char *vmcoreinfo_read_string(const char *);
#define MIN_PAGE_SIZE (4096)
+#define DUMP_ELF_INCOMPLETE 0x1
/*
* Architectures that have configurable page sizes,
* can differ from the host machine's page size.
@@ -488,6 +489,10 @@ check_dumpfile_size(char *file)
if (stat64(file, &stat) < 0)
return;
+ Elf64_Phdr *load64 = nd->load64;
+ Elf32_Phdr *load32 = nd->load32;
+ unsigned int e_flag = (NULL == nd->elf64) ? (nd->elf32)->e_flags :
(nd->elf64)->e_flags;
+ int status = e_flag & DUMP_ELF_INCOMPLETE;
for (i = 0; i < nd->num_pt_load_segments; i++) {
pls = &nd->pt_load_segments[i];
@@ -495,7 +500,19 @@ check_dumpfile_size(char *file)
(pls->phys_end - pls->phys_start);
if (segment_end > stat.st_size) {
- error(WARNING, "%s: may be truncated or incomplete\n"
+ if (!status){
+ error(WARNING, "%s: may be truncated\n"
+ " PT_LOAD p_offset: %lld\n"
+ " p_filesz: %lld\n"
+ " bytes required: %lld\n"
+ " dumpfile size: %lld\n\n",
+ file, pls->file_offset,
+ pls->phys_end - pls->phys_start,
+ segment_end, stat.st_size);
+ return;
+ }
+ else{
+ error(WARNING, "%s: may be incomplete\n"
" PT_LOAD p_offset: %lld\n"
" p_filesz: %lld\n"
" bytes required: %lld\n"
@@ -503,8 +520,25 @@ check_dumpfile_size(char *file)
file, pls->file_offset,
pls->phys_end - pls->phys_start,
segment_end, stat.st_size);
- return;
+ }
+ if (pls->file_offset > stat.st_size){
+ pls->file_offset = 0;
+ pls->phys_start = 0;
+ pls->phys_end = 0;
+ }
+ else {
+ if (NULL == load32)
+ load64->p_filesz = stat.st_size -
pls->file_offset;
+ else
+ load32->p_filesz = stat.st_size -
pls->file_offset;
+ pls->zero_fill = pls->phys_end;
+ pls->phys_end = stat.st_size - pls->file_offset +
pls->phys_start;
+ }
}
+ if (NULL == load32)
+ load64++;
+ else
+ load32++;
}
}