diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | arch/arm64.c | 41 | ||||
-rw-r--r-- | arch/x86_64.c | 32 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | debian/patches/0001-Remove-libebl-linkage.patch | 22 | ||||
-rw-r--r-- | debian/patches/0002-adapt-makefile-to-debian.patch | 45 | ||||
-rw-r--r-- | debian/patches/series | 2 | ||||
-rw-r--r-- | elf_info.c | 40 | ||||
-rw-r--r-- | elf_info.h | 1 | ||||
-rw-r--r-- | makedumpfile.8 | 2 | ||||
-rw-r--r-- | makedumpfile.c | 308 | ||||
-rw-r--r-- | makedumpfile.conf.5 | 2 | ||||
-rw-r--r-- | makedumpfile.h | 11 | ||||
-rw-r--r-- | makedumpfile.spec | 2 |
15 files changed, 307 insertions, 227 deletions
@@ -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),) @@ -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) @@ -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/debian/changelog b/debian/changelog index 83686fd..4aed634 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +makedumpfile (1:1.6.7-1) UNRELEASED; urgency=medium + + * Update to new upstream version 1.6.7. + + -- Thadeu Lima de Souza Cascardo <cascardo@debian.org> Mon, 02 Mar 2020 04:48:06 -0300 + makedumpfile (1:1.6.6-4) unstable; urgency=medium * Let the kernel decide the crashkernel offset for ppc64el (LP: #1741860) diff --git a/debian/patches/0001-Remove-libebl-linkage.patch b/debian/patches/0001-Remove-libebl-linkage.patch deleted file mode 100644 index 7a4f7a1..0000000 --- a/debian/patches/0001-Remove-libebl-linkage.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Louis Bouchard <louis.bouchard@ubuntu.com> -Date: Mon, 17 Dec 2018 15:21:09 -0200 -Subject: Remove libebl from link options - -Description: Remove libebl from link options ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 1fdb628..df21b93 100644 ---- a/Makefile -+++ b/Makefile -@@ -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 diff --git a/debian/patches/0002-adapt-makefile-to-debian.patch b/debian/patches/0002-adapt-makefile-to-debian.patch deleted file mode 100644 index 2e55af5..0000000 --- a/debian/patches/0002-adapt-makefile-to-debian.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Louis Bouchard <louis.bouchard@ubuntu.com> -Date: Mon, 17 Dec 2018 15:21:09 -0200 -Subject: adapt-makefile-to-debian - -=================================================================== ---- - Makefile | 18 +++++------------- - 1 file changed, 5 insertions(+), 13 deletions(-) - -diff --git a/Makefile b/Makefile -index df21b93..ed4fd1a 100644 ---- a/Makefile -+++ b/Makefile -@@ -90,26 +90,18 @@ $(OBJ_ARCH): $(SRC_ARCH) - - makedumpfile: $(SRC_BASE) $(OBJ_PART) $(OBJ_ARCH) - $(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -rdynamic -o $@ $< $(LIBS) -- echo .TH MAKEDUMPFILE 8 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.8 -- grep -v "^.TH MAKEDUMPFILE 8" $(VPATH)makedumpfile.8 >> temp.8 -- mv temp.8 makedumpfile.8 -- gzip -c ./makedumpfile.8 > ./makedumpfile.8.gz -- echo .TH MAKEDUMPFILE.CONF 5 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.5 -- grep -v "^.TH MAKEDUMPFILE.CONF 5" $(VPATH)makedumpfile.conf.5 >> temp.5 -- mv temp.5 makedumpfile.conf.5 -- gzip -c ./makedumpfile.conf.5 > ./makedumpfile.conf.5.gz - - eppic_makedumpfile.so: extension_eppic.c - $(CC) $(CFLAGS) $(LDFLAGS) -shared -rdynamic -o $@ extension_eppic.c -fPIC -leppic -ltinfo - - clean: -- rm -f $(OBJ) $(OBJ_PART) $(OBJ_ARCH) makedumpfile makedumpfile.8.gz makedumpfile.conf.5.gz -+ rm -f $(OBJ) $(OBJ_PART) $(OBJ_ARCH) makedumpfile - - install: -- install -m 755 -d ${DESTDIR}/usr/sbin ${DESTDIR}/usr/share/man/man5 ${DESTDIR}/usr/share/man/man8 ${DESTDIR}/etc -- install -m 755 -t ${DESTDIR}/usr/sbin makedumpfile $(VPATH)makedumpfile-R.pl -- install -m 644 -t ${DESTDIR}/usr/share/man/man8 makedumpfile.8.gz -- install -m 644 -t ${DESTDIR}/usr/share/man/man5 makedumpfile.conf.5.gz -+ install -m 755 -d ${DESTDIR}/usr/bin ${DESTDIR}/usr/share/man/man5 ${DESTDIR}/usr/share/man/man8 ${DESTDIR}/etc -+ install -m 755 -t ${DESTDIR}/usr/bin makedumpfile makedumpfile-R.pl -+ install -m 644 -t ${DESTDIR}/usr/share/man/man8 makedumpfile.8 -+ install -m 644 -t ${DESTDIR}/usr/share/man/man5 makedumpfile.conf.5 - install -m 644 -D $(VPATH)makedumpfile.conf ${DESTDIR}/etc/makedumpfile.conf.sample - mkdir -p ${DESTDIR}/usr/share/makedumpfile-${VERSION}/eppic_scripts - install -m 644 -t ${DESTDIR}/usr/share/makedumpfile-${VERSION}/eppic_scripts/ $(VPATH)eppic_scripts/* diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 8d0f986..0000000 --- a/debian/patches/series +++ /dev/null @@ -1,2 +0,0 @@ -0001-Remove-libebl-linkage.patch -0002-adapt-makefile-to-debian.patch @@ -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"); @@ -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 |