diff --git a/zdump/Makefile b/zdump/Makefile index 40c7d465..fbb851b8 100644 --- a/zdump/Makefile +++ b/zdump/Makefile @@ -44,7 +44,7 @@ all: check_dep_fuse check_dep_zlib zgetdump OBJECTS = zgetdump.o opts.o zg.o zg_error.o zg_print.o \ dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \ - dfi_lkcd.o dfi_elf.o \ + dfi_lkcd.o dfi_elf.o dfi_elf_common.o \ dfi_s390.o dfi_s390_ext.o\ dfi_s390mv.o dfi_s390mv_ext.o \ dfi_s390tape.o dfi_kdump.o \ diff --git a/zdump/dfi_elf.c b/zdump/dfi_elf.c index 93e46f90..8925fa39 100644 --- a/zdump/dfi_elf.c +++ b/zdump/dfi_elf.c @@ -24,6 +24,7 @@ #include "df_elf.h" #include "dfi.h" #include "dfi_mem_chunk.h" +#include "dfi_elf_common.h" /* * Read memory for given memory chunk @@ -37,44 +38,6 @@ static void dfi_elf_mem_chunk_read_fn(struct dfi_mem_chunk *mem_chunk, u64 off, zg_read(g.fh, buf, cnt, ZG_CHECK); } -/* - * Add load (memory chunk) to DFI dump - */ -static int pt_load_add(const Elf64_Phdr *phdr) -{ - u64 *off_ptr; - - util_log_print(UTIL_LOG_DEBUG, - "DFI ELF p_paddr 0x%016lx p_vaddr 0x%016lx p_offset 0x%016lx p_filesz 0x%016lx p_memsz 0x%016lx\n", - phdr->p_paddr, phdr->p_vaddr, phdr->p_offset, - phdr->p_filesz, phdr->p_memsz); - - if (phdr->p_paddr != phdr->p_vaddr) { - STDERR("Dump file \"%s\" is a user space core dump\n", - g.opts.device); - return -EINVAL; - } - if (phdr->p_memsz == 0) - return -EINVAL; - if (phdr->p_offset + phdr->p_filesz > zg_size(g.fh)) - return -EINVAL; - if (phdr->p_filesz > phdr->p_memsz) - return -EINVAL; - if (phdr->p_filesz > 0) { - off_ptr = zg_alloc(sizeof(*off_ptr)); - *off_ptr = phdr->p_offset; - dfi_mem_chunk_add(phdr->p_paddr, phdr->p_filesz, off_ptr, - dfi_elf_mem_chunk_read_fn, zg_free); - } - if (phdr->p_memsz - phdr->p_filesz > 0) { - /* Add zero memory chunk */ - dfi_mem_chunk_add(phdr->p_paddr + phdr->p_filesz, - phdr->p_memsz - phdr->p_filesz, NULL, - dfi_mem_chunk_read_zero, NULL); - } - return 0; -} - /* * Ensure that CPU is already defined by prstatus note */ @@ -295,12 +258,17 @@ static int dfi_elf_init(void) util_log_print(UTIL_LOG_DEBUG, "DFI ELF p_type[%d] 0x%lx\n", i, phdr->p_type); switch (phdr->p_type) { - case PT_LOAD: - if (pt_load_add(phdr)) { + case PT_LOAD: { + u64 *off_ptr = zg_alloc(sizeof(*off_ptr)); + *off_ptr = phdr->p_offset; + + if (pt_load_add(g.fh, phdr, (void **)&off_ptr, dfi_elf_mem_chunk_read_fn, + free) < 0) { + free(off_ptr); rc = -EINVAL; goto free_phdrs; } - break; + } break; case PT_NOTE: if (pt_notes_add(phdr)) { rc = -EINVAL; diff --git a/zdump/dfi_elf_common.c b/zdump/dfi_elf_common.c new file mode 100644 index 00000000..3cb58077 --- /dev/null +++ b/zdump/dfi_elf_common.c @@ -0,0 +1,61 @@ +/* + * zgetdump - Tool for copying and converting System z dumps + * + * Common ELF core dump input format definitions + * + * Copyright IBM Corp. 2001, 2022 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "dfi_elf_common.h" + +#include + +#include "lib/util_log.h" + +int pt_load_add(const struct zg_fh *fh, const Elf64_Phdr *phdr, void **data, + dfi_mem_chunk_read_fn read_fn, dfi_mem_chunk_free_fn free_fn) +{ + assert(fh); + assert(phdr); + assert(data); + assert(read_fn); + assert(free_fn); + + util_log_print( + UTIL_LOG_DEBUG, + "%s p_paddr 0x%016lx p_vaddr 0x%016lx p_offset 0x%016lx p_filesz 0x%016lx p_memsz 0x%016lx\n", + __func__, phdr->p_paddr, phdr->p_vaddr, phdr->p_offset, phdr->p_filesz, + phdr->p_memsz); + + if (phdr->p_paddr != phdr->p_vaddr) { + STDERR("Dump file \"%s\" is a user space core dump\n", fh->path); + return -EINVAL; + } + if (phdr->p_memsz == 0) + return -EINVAL; + if (phdr->p_offset + phdr->p_filesz > zg_size(fh)) + return -EINVAL; + if (phdr->p_filesz > phdr->p_memsz) + return -EINVAL; + /* check for wrap-around */ + if (phdr->p_paddr + phdr->p_filesz < phdr->p_paddr) + return -EINVAL; + + if (phdr->p_filesz > 0) { + dfi_mem_chunk_add(phdr->p_paddr, phdr->p_filesz, *data, read_fn, free_fn); + *data = NULL; + } else { + /* Free @data directly as it's not used */ + free_fn(*data); + *data = NULL; + } + if (phdr->p_memsz - phdr->p_filesz > 0) { + /* Add zero memory chunk */ + dfi_mem_chunk_add(phdr->p_paddr + phdr->p_filesz, phdr->p_memsz - phdr->p_filesz, + NULL, dfi_mem_chunk_read_zero, NULL); + } + return 0; +} diff --git a/zdump/dfi_elf_common.h b/zdump/dfi_elf_common.h new file mode 100644 index 00000000..0db3e4de --- /dev/null +++ b/zdump/dfi_elf_common.h @@ -0,0 +1,36 @@ +/* + * zgetdump - Tool for copying and converting System z dumps + * + * Common ELF core dump input format definitions + * + * Copyright IBM Corp. 2001, 2022 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef DFI_ELF_COMMON_H +#define DFI_ELF_COMMON_H + +#include + +#include "dfi_mem_chunk.h" +#include "zg.h" + +/** + * pt_load_add: + * @fh: (not nullable): open input file + * @phdr: (not nullable): program ELF header of the load segment to add + * @data: (not nullable): arbitrary pointer passed to the read callback @read_fn + * @read_fn: (not nullable): callback used for reading the data of a memory chunk + * @free_fn: (not nullable): function called to cleanup @data + * + * Add load (memory chunk) to DFI dump. After a successful call, @data belongs + * to the mem_chunk structure created and the @data pointer is set to %NULL. + * + * Returns: %0 on success, returns < 0 in case of an error + */ +int pt_load_add(const struct zg_fh *fh, const Elf64_Phdr *phdr, void **data, + dfi_mem_chunk_read_fn read_fn, dfi_mem_chunk_free_fn free_fn); + +#endif /* DFI_ELF_COMMON_H */