summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThadeu Lima de Souza Cascardo <cascardo@debian.org>2020-03-02 04:48:06 -0300
committerThadeu Lima de Souza Cascardo <cascardo@debian.org>2020-03-02 04:48:06 -0300
commit5975a25c8789536fe91ff57d360f5f8cc6f47fd8 (patch)
tree3fb59e62845f281b9887fb798cf8d9d15c913a34
parent4e5c6d36a8f673c97b7c63bea39278c3fa7b40be (diff)
parente7301654029330bbf49693002fa72223f9b3fb36 (diff)
Update to upstream 1.6.7
[git-debrebase anchor: new upstream 1.6.7, merge]
-rw-r--r--Makefile11
-rw-r--r--README11
-rw-r--r--arch/arm64.c41
-rw-r--r--arch/x86_64.c32
-rw-r--r--elf_info.c40
-rw-r--r--elf_info.h1
-rw-r--r--makedumpfile.82
-rw-r--r--makedumpfile.c308
-rw-r--r--makedumpfile.conf.52
-rw-r--r--makedumpfile.h11
-rw-r--r--makedumpfile.spec2
11 files changed, 302 insertions, 159 deletions
diff --git a/Makefile b/Makefile
index 1fdb628..388faf7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# makedumpfile
-VERSION=1.6.6
-DATE=27 Jun 2019
+VERSION=1.6.7
+DATE=16 Jan 2020
# Honour the environment variable CC
ifeq ($(strip $CC),)
@@ -50,7 +50,7 @@ OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c
OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
-LIBS = -ldw -lbz2 -lebl -ldl -lelf -lz
+LIBS = -ldw -lbz2 -ldl -lelf -lz
ifneq ($(LINKTYPE), dynamic)
LIBS := -static $(LIBS)
endif
@@ -79,6 +79,11 @@ LINK_TEST_PROG="int clock_gettime(); int main(){ return clock_gettime(); }"
LIBS := $(LIBS) $(call try-run,\
echo $(LINK_TEST_PROG) | $(CC) $(CFLAGS) -o "$$TMP" -x c -,,-lrt)
+# elfutils-0.178 or later does not install libebl.a.
+LINK_TEST_PROG="int main() { return 0; }"
+LIBS := $(LIBS) $(call try-run,\
+ echo $(LINK_TEST_PROG) | $(CC) -o "$$TMP" -x c - -lebl,-lebl,)
+
all: makedumpfile
$(OBJ_PART): $(SRC_PART)
diff --git a/README b/README
index 947da42..d260eac 100644
--- a/README
+++ b/README
@@ -6,13 +6,13 @@
* REQUIREMENTS
Please download the following library file and install it exactly as below;
do NOT use "make install".
- - elfutils-0.142.tar.gz
+ - elfutils-0.144.tar.gz
The "make install" of elfutils installs some commands (ld, readelf, etc.),
and compiling problems sometimes happen due to using the installed
commands. To install only the library & header files, use the following
method:
- # tar -zxvf elfutils-0.142.tar.gz
- # cd elfutils-0.142
+ # tar -zxvf elfutils-0.144.tar.gz
+ # cd elfutils-0.144
# ./configure
# make
#
@@ -130,6 +130,9 @@
4.20 | OK | ** | | | | ** | | -- | OK | OK | | |
5.0 | OK | ** | | | | ** | | -- | OK | OK | | |
5.1 | OK | ** | | | | ** | | -- | OK | OK | | |
+ 5.2 | | ** | | | | ** | | -- | | OK | | |
+ 5.3 | | ** | | | | ** | | -- | | OK | | |
+ 5.4 | OK | ** | | | | ** | | -- | OK | OK | | |
OK : Support.
-- : Not support.
@@ -202,6 +205,6 @@
* BUG REPORT
If finding some bugs, please send the information to the following:
- Kazuhito Hagio <k-hagio@ab.jp.nec.com>
+ Kazuhito Hagio <k-hagio-ab@nec.com>
kexec-ml <kexec@lists.infradead.org>
diff --git a/arch/arm64.c b/arch/arm64.c
index 0535193..43164cc 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -205,47 +205,6 @@ get_phys_base_arm64(void)
return FALSE;
}
-unsigned long
-get_kaslr_offset_arm64(unsigned long vaddr)
-{
- unsigned int i;
- char buf[BUFSIZE_FGETS], *endp;
-
- if (!info->kaslr_offset && info->file_vmcoreinfo) {
- if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) {
- ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n",
- info->name_vmcoreinfo, strerror(errno));
- return FALSE;
- }
-
- while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) {
- i = strlen(buf);
- if (!i)
- break;
- if (buf[i - 1] == '\n')
- buf[i - 1] = '\0';
- if (strncmp(buf, STR_KERNELOFFSET,
- strlen(STR_KERNELOFFSET)) == 0) {
- info->kaslr_offset =
- strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16);
- DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset);
- }
- }
- }
-
- if (vaddr >= __START_KERNEL_map &&
- vaddr < __START_KERNEL_map + info->kaslr_offset) {
- DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset);
- return info->kaslr_offset;
- } else {
- /*
- * TODO: we need to check if it is vmalloc/vmmemmap/module
- * address, we will have different offset
- */
- return 0;
- }
-}
-
ulong
get_stext_symbol(void)
{
diff --git a/arch/x86_64.c b/arch/x86_64.c
index 3c0fdc5..b5e2954 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -69,7 +69,7 @@ get_kaslr_offset_x86_64(unsigned long vaddr)
strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16);
}
}
- if (!info->kaslr_offset)
+ if (!info->kaslr_offset || !vaddr)
return 0;
if (NUMBER(KERNEL_IMAGE_SIZE) != NOT_FOUND_NUMBER)
@@ -77,14 +77,14 @@ get_kaslr_offset_x86_64(unsigned long vaddr)
else
kernel_image_size = KERNEL_IMAGE_SIZE_KASLR_ORIG;
+ /*
+ * Returns the kaslr offset only if the vaddr needs it to be added,
+ * i.e. only kernel text address for now. Otherwise returns 0.
+ */
if (vaddr >= __START_KERNEL_map &&
vaddr < __START_KERNEL_map + kernel_image_size)
return info->kaslr_offset;
else
- /*
- * TODO: we need to check if it is vmalloc/vmmemmap/module
- * address, we will have different offset
- */
return 0;
}
@@ -673,12 +673,22 @@ find_vmemmap_x86_64()
if (init_level4_pgt == NOT_FOUND_SYMBOL) {
ERRMSG("init_level4_pgt/init_top_pgt not found\n");
- return FAILED;
+ return FALSE;
}
if (NUMBER(sme_mask) != NOT_FOUND_NUMBER)
pmask &= ~(NUMBER(sme_mask));
+ /*
+ * vmemmap region can be randomized by KASLR.
+ * (currently we don't utilize info->vmemmap_end on x86_64.)
+ */
+ if (info->mem_map_data &&
+ info->mem_map_data[0].mem_map != NOT_MEMMAP_ADDR)
+ info->vmemmap_start = info->mem_map_data[0].mem_map;
+
+ DEBUG_MSG("vmemmap_start: %16lx\n", info->vmemmap_start);
+
pagestructsize = size_table.page;
hugepagesize = PTRS_PER_PMD * info->page_size;
vaddr_base = info->vmemmap_start;
@@ -705,7 +715,7 @@ find_vmemmap_x86_64()
if (!readmem(PADDR, (unsigned long long)pgdp, (void *)&pud_addr,
sizeof(unsigned long))) {
ERRMSG("Can't get pgd entry for slot %d.\n", pgd_index);
- return FAILED;
+ return FALSE;
}
/* mask the pgd entry for the address of the pud page */
@@ -716,7 +726,7 @@ find_vmemmap_x86_64()
if (!readmem(PADDR, (unsigned long long)pud_addr, (void *)pud_page,
PTRS_PER_PUD * sizeof(unsigned long))) {
ERRMSG("Can't get pud entry for pgd slot %ld.\n", pgdindex);
- return FAILED;
+ return FALSE;
}
/* step thru each pmd address in the pud page */
/* pudp points to an entry in the pud page */
@@ -729,7 +739,7 @@ find_vmemmap_x86_64()
if (!readmem(PADDR, pmd_addr, (void *)pmd_page,
PTRS_PER_PMD * sizeof(unsigned long))) {
ERRMSG("Can't get pud entry for slot %ld.\n", pudindex);
- return FAILED;
+ return FALSE;
}
/* pmdp points to an entry in the pmd */
for (pmdp = (unsigned long *)pmd_page, pmdindex = 0;
@@ -805,7 +815,7 @@ find_vmemmap_x86_64()
num_pmds_valid++;
if (!(pmd & _PAGE_PSE)) {
printf("vmemmap pmd not huge, abort\n");
- return FAILED;
+ return FALSE;
}
} else {
if (last_valid) {
@@ -937,7 +947,7 @@ find_vmemmap_x86_64()
i++;
} while (cur != vmaphead);
nr_gvmem_pfns = i;
- return COMPLETED;
+ return TRUE;
}
#endif /* x86_64 */
diff --git a/elf_info.c b/elf_info.c
index 204bfbf..7d72742 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -123,8 +123,11 @@ check_elf_format(int fd, char *filename, int *phnum, unsigned int *num_load)
(*num_load) = 0;
if ((ehdr64.e_ident[EI_CLASS] == ELFCLASS64)
&& (ehdr32.e_ident[EI_CLASS] != ELFCLASS32)) {
- (*phnum) = ehdr64.e_phnum;
- for (i = 0; i < ehdr64.e_phnum; i++) {
+ if (!get_elf64_phnum(fd, filename, &ehdr64, phnum)) {
+ ERRMSG("Can't get phnum.\n");
+ return FALSE;
+ }
+ for (i = 0; i < (*phnum); i++) {
if (!get_elf64_phdr(fd, filename, i, &load64)) {
ERRMSG("Can't find Phdr %d.\n", i);
return FALSE;
@@ -1036,6 +1039,34 @@ is_xen_memory(void)
}
int
+get_elf64_phnum(int fd, char *filename, Elf64_Ehdr *ehdr, int *phnum)
+{
+ Elf64_Shdr shdr;
+
+ /*
+ * Extended Numbering support
+ * See include/uapi/linux/elf.h and elf(5) for more information.
+ */
+ if (ehdr->e_phnum == PN_XNUM) {
+ if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) {
+ ERRMSG("Can't seek %s at 0x%llx. %s\n", filename,
+ (ulonglong)ehdr->e_shoff, strerror(errno));
+ return FALSE;
+ }
+ if (read(fd, &shdr, ehdr->e_shentsize) != ehdr->e_shentsize) {
+ ERRMSG("Can't read %s at 0x%llx. %s\n", filename,
+ (ulonglong)ehdr->e_shoff, strerror(errno));
+ return FALSE;
+ }
+
+ *phnum = shdr.sh_info;
+ } else
+ *phnum = ehdr->e_phnum;
+
+ return TRUE;
+}
+
+int
get_phnum_memory(void)
{
int phnum;
@@ -1047,7 +1078,10 @@ get_phnum_memory(void)
ERRMSG("Can't get ehdr64.\n");
return FALSE;
}
- phnum = ehdr64.e_phnum;
+ if (!get_elf64_phnum(fd_memory, name_memory, &ehdr64, &phnum)) {
+ ERRMSG("Can't get phnum.\n");
+ return FALSE;
+ }
} else { /* ELF32 */
if (!get_elf32_ehdr(fd_memory, name_memory, &ehdr32)) {
ERRMSG("Can't get ehdr32.\n");
diff --git a/elf_info.h b/elf_info.h
index cd4ffa6..934b608 100644
--- a/elf_info.h
+++ b/elf_info.h
@@ -54,6 +54,7 @@ int get_kcore_dump_loads(void);
int is_elf64_memory(void);
int is_xen_memory(void);
+int get_elf64_phnum(int fd, char *filename, Elf64_Ehdr *ehdr, int *phnum);
int get_phnum_memory(void);
int get_phdr_memory(int index, Elf64_Phdr *phdr);
off_t get_offset_pt_load_memory(void);
diff --git a/makedumpfile.8 b/makedumpfile.8
index d6b7a57..f3d13db 100644
--- a/makedumpfile.8
+++ b/makedumpfile.8
@@ -1,4 +1,4 @@
-.TH MAKEDUMPFILE 8 "27 Jun 2019" "makedumpfile v1.6.6" "Linux System Administrator's Manual"
+.TH MAKEDUMPFILE 8 "16 Jan 2020" "makedumpfile v1.6.7" "Linux System Administrator's Manual"
.SH NAME
makedumpfile \- make a small dumpfile of kdump
.SH SYNOPSIS
diff --git a/makedumpfile.c b/makedumpfile.c
index d76a435..e290fbd 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -56,6 +56,14 @@ static void first_cycle(mdf_pfn_t start, mdf_pfn_t max, struct cycle *cycle)
if (cycle->end_pfn > max)
cycle->end_pfn = max;
+ /*
+ * Mitigate statistics problem in ELF dump mode.
+ * A cycle must start with a pfn that is divisible by BITPERBYTE.
+ * See create_bitmap_from_memhole().
+ */
+ if (info->flag_elf_dumpfile && cycle->start_pfn < start)
+ cycle->start_pfn = round(start, BITPERBYTE);
+
cycle->exclude_pfn_start = 0;
cycle->exclude_pfn_end = 0;
}
@@ -89,6 +97,7 @@ mdf_pfn_t pfn_user;
mdf_pfn_t pfn_free;
mdf_pfn_t pfn_hwpoison;
mdf_pfn_t pfn_offline;
+mdf_pfn_t pfn_elf_excluded;
mdf_pfn_t num_dumped;
@@ -3936,6 +3945,66 @@ free_for_parallel()
}
}
+unsigned long
+get_kaslr_offset_general(unsigned long vaddr)
+{
+ unsigned int i;
+ char buf[BUFSIZE_FGETS], *endp;
+ static unsigned long _text = NOT_FOUND_SYMBOL;
+ static unsigned long _end = NOT_FOUND_SYMBOL;
+
+ if (!info->kaslr_offset && info->file_vmcoreinfo) {
+ if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) {
+ ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+
+ while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) {
+ i = strlen(buf);
+ if (!i)
+ break;
+ if (buf[i - 1] == '\n')
+ buf[i - 1] = '\0';
+ if (strncmp(buf, STR_KERNELOFFSET,
+ strlen(STR_KERNELOFFSET)) == 0) {
+ info->kaslr_offset = strtoul(buf +
+ strlen(STR_KERNELOFFSET), &endp, 16);
+ DEBUG_MSG("info->kaslr_offset: %lx\n",
+ info->kaslr_offset);
+ }
+ }
+ }
+ if (!info->kaslr_offset || !vaddr)
+ return 0;
+
+ if (_text == NOT_FOUND_SYMBOL) {
+ /*
+ * Currently, the return value of this function is used in
+ * resolve_config_entry() only, and in that case, we must
+ * have a vmlinux.
+ */
+ if (info->name_vmlinux) {
+ _text = get_symbol_addr("_text");
+ _end = get_symbol_addr("_end");
+ }
+ DEBUG_MSG("_text: %lx, _end: %lx\n", _text, _end);
+ if (_text == NOT_FOUND_SYMBOL || _end == NOT_FOUND_SYMBOL) {
+ ERRMSG("Cannot determine _text and _end address\n");
+ return FALSE;
+ }
+ }
+
+ /*
+ * Returns the kaslr offset only if the vaddr needs it to be added,
+ * i.e. only kernel text address for now. Otherwise returns 0.
+ */
+ if (_text <= vaddr && vaddr <= _end)
+ return info->kaslr_offset;
+ else
+ return 0;
+}
+
int
find_kaslr_offsets()
{
@@ -3963,8 +4032,10 @@ find_kaslr_offsets()
* function might need to read from vmcoreinfo, therefore we have
* called this function between open_vmcoreinfo() and
* close_vmcoreinfo()
+ * And the argument is not needed, because we don't use the return
+ * value here. So pass it 0 explicitly.
*/
- get_kaslr_offset(SYMBOL(_stext));
+ get_kaslr_offset(0);
close_vmcoreinfo();
@@ -4740,7 +4811,7 @@ exclude_nodata_pages(struct cycle *cycle)
if (pfn < cycle->start_pfn)
pfn = cycle->start_pfn;
if (pfn_end >= cycle->end_pfn)
- pfn_end = cycle->end_pfn - 1;
+ pfn_end = cycle->end_pfn;
while (pfn < pfn_end) {
clear_bit_on_2nd_bitmap(pfn, cycle);
++pfn;
@@ -6213,20 +6284,20 @@ init_save_control()
flags = O_RDWR|O_CREAT|O_TRUNC;
if ((sc.sc_fd = open(sc.sc_filename, flags, S_IRUSR|S_IWUSR)) < 0) {
ERRMSG("Can't open the pfn file %s.\n", sc.sc_filename);
- return FAILED;
+ return FALSE;
}
unlink(sc.sc_filename);
sc.sc_buf = malloc(info->page_size);
if (!sc.sc_buf) {
ERRMSG("Can't allocate a page for pfn buf.\n");
- return FAILED;
+ return FALSE;
}
sc.sc_buflen = info->page_size;
sc.sc_bufposition = 0;
sc.sc_fileposition = 0;
sc.sc_filelen = 0;
- return COMPLETED;
+ return TRUE;
}
/*
@@ -6243,7 +6314,7 @@ save_deletes(unsigned long startpfn, unsigned long numpfns)
if (i != sc.sc_buflen) {
ERRMSG("save: Can't write a page to %s\n",
sc.sc_filename);
- return FAILED;
+ return FALSE;
}
sc.sc_filelen += sc.sc_buflen;
sc.sc_bufposition = 0;
@@ -6252,12 +6323,12 @@ save_deletes(unsigned long startpfn, unsigned long numpfns)
scp->startpfn = startpfn;
scp->numpfns = numpfns;
sc.sc_bufposition += sizeof(struct sc_entry);
- return COMPLETED;
+ return TRUE;
}
/*
* Get a starting pfn and number of pfns for delete from bitmap.
- * Return 0 for success, 1 for 'no more'
+ * Return TRUE(1) for success, FALSE(0) for 'no more'
*/
int
get_deletes(unsigned long *startpfn, unsigned long *numpfns)
@@ -6266,14 +6337,14 @@ get_deletes(unsigned long *startpfn, unsigned long *numpfns)
struct sc_entry *scp;
if (sc.sc_fileposition >= sc.sc_filelen) {
- return FAILED;
+ return FALSE;
}
if (sc.sc_bufposition == sc.sc_buflen) {
i = read(sc.sc_fd, sc.sc_buf, sc.sc_buflen);
if (i <= 0) {
ERRMSG("Can't read a page from %s.\n", sc.sc_filename);
- return FAILED;
+ return FALSE;
}
sc.sc_bufposition = 0;
}
@@ -6282,7 +6353,7 @@ get_deletes(unsigned long *startpfn, unsigned long *numpfns)
*numpfns = scp->numpfns;
sc.sc_bufposition += sizeof(struct sc_entry);
sc.sc_fileposition += sizeof(struct sc_entry);
- return COMPLETED;
+ return TRUE;
}
/*
@@ -6290,7 +6361,7 @@ get_deletes(unsigned long *startpfn, unsigned long *numpfns)
* that represent them.
* (pfn ranges are literally start and end, not start and end+1)
* see the array of vmemmap pfns and the pfns they represent: gvmem_pfns
- * Return COMPLETED for delete, FAILED for not to delete.
+ * Return TRUE(1) for delete, FALSE(0) for not to delete.
*/
int
find_vmemmap_pages(unsigned long startpfn, unsigned long endpfn, unsigned long *vmappfn,
@@ -6315,7 +6386,7 @@ find_vmemmap_pages(unsigned long startpfn, unsigned long endpfn, unsigned long *
start_vmemmap_pfn = vmapp->vmap_pfn_start + vmemmap_pfns;
*vmappfn = start_vmemmap_pfn;
- npfns_offset = endpfn - vmapp->rep_pfn_start;
+ npfns_offset = (endpfn+1) - vmapp->rep_pfn_start;
vmemmap_offset = npfns_offset * size_table.page;
// round down to page boundary
vmemmap_offset -= (vmemmap_offset % pagesize);
@@ -6323,12 +6394,12 @@ find_vmemmap_pages(unsigned long startpfn, unsigned long endpfn, unsigned long *
end_vmemmap_pfn = vmapp->vmap_pfn_start + vmemmap_pfns;
npages = end_vmemmap_pfn - start_vmemmap_pfn;
if (npages == 0)
- return FAILED;
+ return FALSE;
*nmapnpfns = npages;
- return COMPLETED;
+ return TRUE;
}
}
- return FAILED;
+ return FALSE;
}
/*
@@ -6359,12 +6430,12 @@ find_unused_vmemmap_pages(void)
if (lseek(bitmap1->fd, new_offset1, SEEK_SET) < 0 ) {
ERRMSG("Can't seek the bitmap(%s). %s\n",
bitmap1->file_name, strerror(errno));
- return FAILED;
+ return FALSE;
}
if (read(bitmap1->fd, bitmap1->buf, BUFSIZE_BITMAP) != BUFSIZE_BITMAP) {
ERRMSG("Can't read the bitmap(%s). %s\n",
bitmap1->file_name, strerror(errno));
- return FAILED;
+ return FALSE;
}
bitmap1->no_block = pfn / PFN_BUFBITMAP;
@@ -6372,12 +6443,12 @@ find_unused_vmemmap_pages(void)
if (lseek(bitmap2->fd, new_offset2, SEEK_SET) < 0 ) {
ERRMSG("Can't seek the bitmap(%s). %s\n",
bitmap2->file_name, strerror(errno));
- return FAILED;
+ return FALSE;
}
if (read(bitmap2->fd, bitmap2->buf, BUFSIZE_BITMAP) != BUFSIZE_BITMAP) {
ERRMSG("Can't read the bitmap(%s). %s\n",
bitmap2->file_name, strerror(errno));
- return FAILED;
+ return FALSE;
}
bitmap2->no_block = pfn / PFN_BUFBITMAP;
@@ -6422,12 +6493,11 @@ find_unused_vmemmap_pages(void)
endpfn = startpfn +
(numwords * BITS_PER_WORD) - 1;
if (find_vmemmap_pages(startpfn, endpfn,
- &vmapstartpfn, &vmapnumpfns) ==
- COMPLETED) {
- if (save_deletes(vmapstartpfn,
- vmapnumpfns) == FAILED) {
+ &vmapstartpfn, &vmapnumpfns)) {
+ if (!save_deletes(vmapstartpfn,
+ vmapnumpfns)) {
ERRMSG("save_deletes failed\n");
- return FAILED;
+ return FALSE;
}
deleted_pages += vmapnumpfns;
}
@@ -6444,11 +6514,10 @@ find_unused_vmemmap_pages(void)
not start and end + 1 */
endpfn = startpfn + (numwords * BITS_PER_WORD) - 1;
if (find_vmemmap_pages(startpfn, endpfn,
- &vmapstartpfn, &vmapnumpfns) == COMPLETED) {
- if (save_deletes(vmapstartpfn, vmapnumpfns)
- == FAILED) {
+ &vmapstartpfn, &vmapnumpfns)) {
+ if (!save_deletes(vmapstartpfn, vmapnumpfns)) {
ERRMSG("save_deletes failed\n");
- return FAILED;
+ return FALSE;
}
deleted_pages += vmapnumpfns;
}
@@ -6457,7 +6526,7 @@ find_unused_vmemmap_pages(void)
}
PROGRESS_MSG("\nExcluded %ld unused vmemmap pages\n", deleted_pages);
- return COMPLETED;
+ return TRUE;
}
/*
@@ -6468,7 +6537,7 @@ delete_unused_vmemmap_pages(void)
{
unsigned long startpfn, numpfns, pfn, i;
- while (get_deletes(&startpfn, &numpfns) == COMPLETED) {
+ while (get_deletes(&startpfn, &numpfns)) {
for (i = 0, pfn = startpfn; i < numpfns; i++, pfn++) {
clear_bit_on_2nd_bitmap_for_kernel(pfn, (struct cycle *)0);
// note that this is never to be used in cyclic mode!
@@ -6496,23 +6565,23 @@ reset_save_control()
{
int i;
if (sc.sc_bufposition == 0)
- return COMPLETED;
+ return TRUE;
i = write(sc.sc_fd, sc.sc_buf, sc.sc_buflen);
if (i != sc.sc_buflen) {
ERRMSG("reset: Can't write a page to %s\n",
sc.sc_filename);
- return FAILED;
+ return FALSE;
}
sc.sc_filelen += sc.sc_bufposition;
if (lseek(sc.sc_fd, 0, SEEK_SET) < 0) {
ERRMSG("Can't seek the pfn file %s).", sc.sc_filename);
- return FAILED;
+ return FALSE;
}
sc.sc_fileposition = 0;
sc.sc_bufposition = sc.sc_buflen; /* trigger 1st read */
- return COMPLETED;
+ return TRUE;
}
int
@@ -6602,11 +6671,11 @@ create_2nd_bitmap(struct cycle *cycle)
/* --exclude-unused-vm means exclude vmemmap page structures for unused pages */
if (info->flag_excludevm) {
- if (init_save_control() == FAILED)
+ if (!init_save_control())
return FALSE;
- if (find_unused_vmemmap_pages() == FAILED)
+ if (!find_unused_vmemmap_pages())
return FALSE;
- if (reset_save_control() == FAILED)
+ if (!reset_save_control())
return FALSE;
delete_unused_vmemmap_pages();
finalize_save_control();
@@ -6864,10 +6933,17 @@ write_elf_header(struct cache_data *cd_header)
ERRMSG("Can't get ehdr64.\n");
goto out;
}
+
+ /* For PT_NOTE */
+ num_loads_dumpfile++;
+
/*
- * PT_NOTE(1) + PT_LOAD(1+)
+ * Extended Numbering support
+ * See include/uapi/linux/elf.h and elf(5) for more information.
*/
- ehdr64.e_phnum = 1 + num_loads_dumpfile;
+ ehdr64.e_phnum = (num_loads_dumpfile >= PN_XNUM) ?
+ PN_XNUM : num_loads_dumpfile;
+
} else { /* ELF32 */
if (!get_elf32_ehdr(info->fd_memory,
info->name_memory, &ehdr32)) {
@@ -6881,20 +6957,6 @@ write_elf_header(struct cache_data *cd_header)
}
/*
- * Write an ELF header.
- */
- if (is_elf64_memory()) { /* ELF64 */
- if (!write_buffer(info->fd_dumpfile, 0, &ehdr64, sizeof(ehdr64),
- info->name_dumpfile))
- goto out;
-
- } else { /* ELF32 */
- if (!write_buffer(info->fd_dumpfile, 0, &ehdr32, sizeof(ehdr32),
- info->name_dumpfile))
- goto out;
- }
-
- /*
* 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.
@@ -6927,15 +6989,12 @@ write_elf_header(struct cache_data *cd_header)
if (is_elf64_memory()) { /* ELF64 */
cd_header->offset = sizeof(ehdr64);
offset_note_dumpfile = sizeof(ehdr64)
- + sizeof(Elf64_Phdr) * ehdr64.e_phnum;
+ + sizeof(Elf64_Phdr) * num_loads_dumpfile;
} else {
cd_header->offset = sizeof(ehdr32);
offset_note_dumpfile = sizeof(ehdr32)
+ sizeof(Elf32_Phdr) * ehdr32.e_phnum;
}
- offset_note_memory = note.p_offset;
- note.p_offset = offset_note_dumpfile;
- size_note = note.p_filesz;
/*
* Reserve a space to store the whole program headers.
@@ -6945,6 +7004,35 @@ write_elf_header(struct cache_data *cd_header)
goto out;
/*
+ * Write the initial section header just after the program headers
+ * if necessary. This order is not typical, but looks enough for now.
+ */
+ if (is_elf64_memory() && ehdr64.e_phnum == PN_XNUM) {
+ Elf64_Shdr shdr64;
+
+ ehdr64.e_shoff = offset_note_dumpfile;
+ ehdr64.e_shentsize = sizeof(shdr64);
+ ehdr64.e_shnum = 1;
+ ehdr64.e_shstrndx = SHN_UNDEF;
+
+ memset(&shdr64, 0, sizeof(shdr64));
+ shdr64.sh_type = SHT_NULL;
+ shdr64.sh_size = ehdr64.e_shnum;
+ shdr64.sh_link = ehdr64.e_shstrndx;
+ shdr64.sh_info = num_loads_dumpfile;
+
+ if (!write_buffer(info->fd_dumpfile, offset_note_dumpfile,
+ &shdr64, sizeof(shdr64), info->name_dumpfile))
+ goto out;
+
+ offset_note_dumpfile += sizeof(shdr64);
+ }
+
+ offset_note_memory = note.p_offset;
+ 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.
*/
@@ -6961,6 +7049,20 @@ write_elf_header(struct cache_data *cd_header)
goto out;
/*
+ * Write the ELF header.
+ */
+ if (is_elf64_memory()) { /* ELF64 */
+ if (!write_buffer(info->fd_dumpfile, 0, &ehdr64, sizeof(ehdr64),
+ info->name_dumpfile))
+ goto out;
+
+ } else { /* ELF32 */
+ if (!write_buffer(info->fd_dumpfile, 0, &ehdr32, sizeof(ehdr32),
+ info->name_dumpfile))
+ goto out;
+ }
+
+ /*
* Write a PT_NOTE segment.
* PT_LOAD header will be written later.
*/
@@ -7344,7 +7446,8 @@ create_dump_bitmap(void)
if (!prepare_bitmap2_buffer())
goto out;
- info->num_dumpable = get_num_dumpable_cyclic();
+ if (!(info->num_dumpable = get_num_dumpable_cyclic()))
+ goto out;
if (!info->flag_elf_dumpfile)
free_bitmap2_buffer();
@@ -7362,7 +7465,8 @@ create_dump_bitmap(void)
if (!create_2nd_bitmap(&cycle))
goto out;
- info->num_dumpable = get_num_dumpable_cyclic();
+ if (!(info->num_dumpable = get_num_dumpable_cyclic()))
+ goto out;
}
ret = TRUE;
@@ -7595,6 +7699,9 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
}
for (pfn = MAX(pfn_start, cycle.start_pfn); pfn < cycle.end_pfn; pfn++) {
+ if (info->flag_cyclic)
+ pfn_memhole--;
+
if (!is_dumpable(info->bitmap2, pfn, &cycle)) {
num_excluded++;
if ((pfn == pfn_end - 1) && frac_tail)
@@ -7639,6 +7746,9 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
continue;
}
+ /* The number of pages excluded actually in ELF format */
+ pfn_elf_excluded += num_excluded;
+
/*
* If the number of the contiguous pages to be excluded
* is 256 or more, those pages are excluded really.
@@ -7691,6 +7801,9 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
}
}
+ /* The number of pages excluded actually in ELF format */
+ pfn_elf_excluded += num_excluded;
+
/*
* Write the last PT_LOAD.
*/
@@ -7891,10 +8004,6 @@ kdump_thread_function_cyclic(void *arg) {
#ifdef USELZO
lzo_bytep wrkmem = WRKMEM_PARALLEL(kdump_thread_args->thread_num);
#endif
-#ifdef USESNAPPY
- unsigned long len_buf_out_snappy =
- snappy_max_compressed_length(info->page_size);
-#endif
buf = BUF_PARALLEL(kdump_thread_args->thread_num);
buf_out = BUF_OUT_PARALLEL(kdump_thread_args->thread_num);
@@ -8016,7 +8125,7 @@ kdump_thread_function_cyclic(void *arg) {
#ifdef USESNAPPY
} else if ((info->flag_compress
& DUMP_DH_COMPRESSED_SNAPPY)
- && ((size_out = len_buf_out_snappy),
+ && ((size_out = kdump_thread_args->len_buf_out),
snappy_compress((char *)buf,
info->page_size,
(char *)buf_out,
@@ -8298,35 +8407,32 @@ write_kdump_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_pag
unsigned long len_buf_out;
struct timespec ts_start;
const off_t failed = (off_t)-1;
- unsigned long len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
-
int ret = FALSE;
+ z_stream z_stream, *stream = NULL;
+#ifdef USELZO
+ lzo_bytep wrkmem = NULL;
+#endif
if (info->flag_elf_dumpfile)
return FALSE;
- len_buf_out_zlib = len_buf_out_lzo = len_buf_out_snappy = 0;
+ if (info->flag_compress & DUMP_DH_COMPRESSED_ZLIB) {
+ if (!initialize_zlib(&z_stream, Z_BEST_SPEED)) {
+ ERRMSG("Can't initialize the zlib stream.\n");
+ goto out;
+ }
+ stream = &z_stream;
+ }
#ifdef USELZO
- lzo_bytep wrkmem;
-
if ((wrkmem = malloc(LZO1X_1_MEM_COMPRESS)) == NULL) {
ERRMSG("Can't allocate memory for the working memory. %s\n",
strerror(errno));
goto out;
}
-
- len_buf_out_lzo = info->page_size + info->page_size / 16 + 64 + 3;
-#endif
-#ifdef USESNAPPY
- len_buf_out_snappy = snappy_max_compressed_length(info->page_size);
#endif
- len_buf_out_zlib = compressBound(info->page_size);
-
- len_buf_out = MAX(len_buf_out_zlib,
- MAX(len_buf_out_lzo,
- len_buf_out_snappy));
+ len_buf_out = calculate_len_buf_out(info->page_size);
if ((buf_out = malloc(len_buf_out)) == NULL) {
ERRMSG("Can't allocate memory for the compression buffer. %s\n",
@@ -8392,8 +8498,8 @@ write_kdump_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_pag
size_out = len_buf_out;
if ((info->flag_compress & DUMP_DH_COMPRESSED_ZLIB)
&& ((size_out = len_buf_out),
- compress2(buf_out, &size_out, buf, info->page_size,
- Z_BEST_SPEED) == Z_OK)
+ compress_mdf(stream, buf_out, &size_out,
+ buf, info->page_size, Z_BEST_SPEED) == Z_OK)
&& (size_out < info->page_size)) {
pd.flags = DUMP_DH_COMPRESSED_ZLIB;
pd.size = size_out;
@@ -8409,7 +8515,7 @@ write_kdump_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_pag
#endif
#ifdef USESNAPPY
} else if ((info->flag_compress & DUMP_DH_COMPRESSED_SNAPPY)
- && ((size_out = len_buf_out_snappy),
+ && ((size_out = len_buf_out),
snappy_compress((char *)buf, info->page_size,
(char *)buf_out,
(size_t *)&size_out)
@@ -8441,6 +8547,8 @@ out:
if (wrkmem != NULL)
free(wrkmem);
#endif
+ if (stream != NULL)
+ finalize_zlib(stream);
print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
print_execution_time(PROGRESS_COPY, &ts_start);
@@ -9778,12 +9886,13 @@ print_report(void)
pfn_excluded = pfn_zero + pfn_cache + pfn_cache_private
+ pfn_user + pfn_free + pfn_hwpoison + pfn_offline;
- shrinking = (pfn_original - pfn_excluded) * 100;
- shrinking = shrinking / pfn_original;
REPORT_MSG("\n");
REPORT_MSG("Original pages : 0x%016llx\n", pfn_original);
REPORT_MSG(" Excluded pages : 0x%016llx\n", pfn_excluded);
+ if (info->flag_elf_dumpfile)
+ REPORT_MSG(" in ELF format : 0x%016llx\n",
+ pfn_elf_excluded);
REPORT_MSG(" Pages filled with zero : 0x%016llx\n", pfn_zero);
REPORT_MSG(" Non-private cache pages : 0x%016llx\n", pfn_cache);
REPORT_MSG(" Private cache pages : 0x%016llx\n",
@@ -9794,8 +9903,20 @@ print_report(void)
REPORT_MSG(" Offline pages : 0x%016llx\n", pfn_offline);
REPORT_MSG(" Remaining pages : 0x%016llx\n",
pfn_original - pfn_excluded);
- REPORT_MSG(" (The number of pages is reduced to %lld%%.)\n",
- shrinking);
+
+ if (info->flag_elf_dumpfile) {
+ REPORT_MSG(" in ELF format : 0x%016llx\n",
+ pfn_original - pfn_elf_excluded);
+
+ pfn_excluded = pfn_elf_excluded;
+ }
+
+ if (pfn_original != 0) {
+ shrinking = (pfn_original - pfn_excluded) * 100;
+ shrinking = shrinking / pfn_original;
+ REPORT_MSG(" (The number of pages is reduced to %lld%%.)\n",
+ shrinking);
+ }
REPORT_MSG("Memory Hole : 0x%016llx\n", pfn_memhole);
REPORT_MSG("--------------------------------------------------\n");
REPORT_MSG("Total pages : 0x%016llx\n", info->max_mapnr);
@@ -10032,6 +10153,10 @@ writeout_multiple_dumpfiles(void)
info->split_start_pfn = SPLITTING_START_PFN(i);
info->split_end_pfn = SPLITTING_END_PFN(i);
+ if (!info->flag_cyclic) {
+ info->bitmap1->fd = info->fd_bitmap;
+ info->bitmap2->fd = info->fd_bitmap;
+ }
if (!reopen_dump_memory())
exit(1);
if ((status = writeout_dumpfile()) == FALSE)
@@ -10093,7 +10218,7 @@ create_dumpfile(void)
/* create an array of translations from pfn to vmemmap pages */
if (info->flag_excludevm) {
- if (find_vmemmap() == FAILED) {
+ if (!find_vmemmap()) {
ERRMSG("Can't find vmemmap pages\n");
info->flag_excludevm = 0;
}
@@ -11487,6 +11612,13 @@ main(int argc, char *argv[])
return COMPLETED;
}
+ DEBUG_MSG("makedumpfile: version " VERSION " (released on " RELEASE_DATE ")\n");
+ DEBUG_MSG("command line: ");
+ for (i = 0; i < argc; i++) {
+ DEBUG_MSG("%s ", argv[i]);
+ }
+ DEBUG_MSG("\n\n");
+
if (elf_version(EV_CURRENT) == EV_NONE ) {
/*
* library out of date
diff --git a/makedumpfile.conf.5 b/makedumpfile.conf.5
index 873a7e6..fe377c2 100644
--- a/makedumpfile.conf.5
+++ b/makedumpfile.conf.5
@@ -1,4 +1,4 @@
-.TH MAKEDUMPFILE.CONF 5 "27 Jun 2019" "makedumpfile v1.6.6" "Linux System Administrator's Manual"
+.TH MAKEDUMPFILE.CONF 5 "16 Jan 2020" "makedumpfile v1.6.7" "Linux System Administrator's Manual"
.SH NAME
makedumpfile.conf \- The filter configuration file for makedumpfile(8).
.SH DESCRIPTION
diff --git a/makedumpfile.h b/makedumpfile.h
index 24b2f69..68d9691 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -195,7 +195,7 @@ isAnon(unsigned long mapping)
* 2. it has been verified that (1UL<<2) was never set, so it is
* safe to mask that bit off even in old kernels.
*/
-#define SECTION_MAP_LAST_BIT (1UL<<3)
+#define SECTION_MAP_LAST_BIT (1UL<<4)
#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
#define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT())
#define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT())
@@ -495,7 +495,7 @@ do { \
#define KVER_MIN_SHIFT 16
#define KERNEL_VERSION(x,y,z) (((x) << KVER_MAJ_SHIFT) | ((y) << KVER_MIN_SHIFT) | (z))
#define OLDEST_VERSION KERNEL_VERSION(2, 6, 15) /* linux-2.6.15 */
-#define LATEST_VERSION KERNEL_VERSION(5, 1, 9) /* linux-5.1.9 */
+#define LATEST_VERSION KERNEL_VERSION(5, 4, 8) /* linux-5.4.8 */
/*
* vmcoreinfo in /proc/vmcore
@@ -542,7 +542,6 @@ do { \
#ifdef __aarch64__
unsigned long get_kvbase_arm64(void);
#define KVBASE get_kvbase_arm64()
-#define __START_KERNEL_map (0xffffffff80000000UL)
#endif /* aarch64 */
@@ -965,6 +964,7 @@ typedef unsigned long pgd_t;
static inline int stub_true() { return TRUE; }
static inline int stub_true_ul(unsigned long x) { return TRUE; }
static inline int stub_false() { return FALSE; }
+unsigned long get_kaslr_offset_general(unsigned long vaddr);
#define paddr_to_vaddr_general(X) ((X) + PAGE_OFFSET)
#ifdef __aarch64__
@@ -974,7 +974,6 @@ unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr);
int get_versiondep_info_arm64(void);
int get_xen_basic_info_arm64(void);
int get_xen_info_arm64(void);
-unsigned long get_kaslr_offset_arm64(unsigned long vaddr);
#define paddr_to_vaddr_arm64(X) (((X) - info->phys_base) | PAGE_OFFSET)
#define find_vmemmap() stub_false()
@@ -983,7 +982,7 @@ unsigned long get_kaslr_offset_arm64(unsigned long vaddr);
#define get_phys_base() get_phys_base_arm64()
#define get_machdep_info() get_machdep_info_arm64()
#define get_versiondep_info() get_versiondep_info_arm64()
-#define get_kaslr_offset(X) get_kaslr_offset_arm64(X)
+#define get_kaslr_offset(X) get_kaslr_offset_general(X)
#define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X)
#define get_xen_info_arch(X) get_xen_info_arm64(X)
#define is_phys_addr(X) stub_true_ul(X)
@@ -1076,7 +1075,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr);
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_s390x()
#define get_versiondep_info() stub_true()
-#define get_kaslr_offset(X) stub_false()
+#define get_kaslr_offset(X) get_kaslr_offset_general(X)
#define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X)
#define paddr_to_vaddr(X) paddr_to_vaddr_general(X)
#define is_phys_addr(X) is_iomem_phys_addr_s390x(X)
diff --git a/makedumpfile.spec b/makedumpfile.spec
index 8e86376..6d8670a 100644
--- a/makedumpfile.spec
+++ b/makedumpfile.spec
@@ -1,6 +1,6 @@
Name: makedumpfile
Summary: makedumpfile package
-Version: 1.6.6
+Version: 1.6.7
Release: 1
Group: Applications/Text
License: GPL