diff --git a/zdump/df_elf.c b/zdump/df_elf.c index 69965979..c95cf6d6 100644 --- a/zdump/df_elf.c +++ b/zdump/df_elf.c @@ -7,6 +7,8 @@ #include +#include "lib/util_libc.h" + #include "df_elf.h" void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum) @@ -50,6 +52,32 @@ bool ehdr_is_s390x(const Elf64_Ehdr *ehdr) ehdr->e_ident[EI_CLASS] == ELFCLASS64; } +int read_elf_hdr(const struct zg_fh *fh, Elf64_Ehdr *ehdr) +{ + const size_t ehdr_size = sizeof(*ehdr); + + if (zg_size(fh) < ehdr_size) + return -1; + + zg_read(fh, ehdr, ehdr_size, ZG_CHECK); + return 0; +} + +Elf64_Phdr *read_elf_phdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, unsigned int *phdr_count) +{ + const Elf64_Half phnum = ehdr->e_phnum; + size_t phdrs_size; + Elf64_Phdr *phdrs; + + /* Cannot wraparound since `Elf64_Half`` is `uint16_t` */ + phdrs_size = sizeof(*phdrs) * phnum; + phdrs = util_malloc(phdrs_size); + zg_seek(fh, ehdr->e_phoff, ZG_CHECK); + zg_read(fh, phdrs, phdrs_size, ZG_CHECK); + *phdr_count = phnum; + return phdrs; +} + void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len, const char *name) { diff --git a/zdump/df_elf.h b/zdump/df_elf.h index 6862fc32..f5ed7eaa 100644 --- a/zdump/df_elf.h +++ b/zdump/df_elf.h @@ -143,6 +143,19 @@ bool ehdr_is_vmcore(const Elf64_Ehdr *ehdr); */ bool ehdr_is_s390x(const Elf64_Ehdr *ehdr); +/* + * Read ELF header at current offset + */ +int read_elf_hdr(const struct zg_fh *fh, Elf64_Ehdr *ehdr); + +/* + * Read ELF program headers + * + * To read the program headers the offset of @fh is changed. + */ +Elf64_Phdr *read_elf_phdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, + unsigned int *phdr_count); + /* * Initialize ELF note */ diff --git a/zdump/dfi_elf.c b/zdump/dfi_elf.c index a2c31807..d3d77340 100644 --- a/zdump/dfi_elf.c +++ b/zdump/dfi_elf.c @@ -280,15 +280,8 @@ static int pt_notes_add(Elf64_Phdr *phdr) return 0; } -/* - * Read ELF header - */ -static int read_elf_hdr(Elf64_Ehdr *ehdr) +static int check_elf_hdr(const Elf64_Ehdr *ehdr) { - if (zg_size(g.fh) < sizeof(*ehdr)) - return -ENODEV; - zg_read(g.fh, ehdr, sizeof(*ehdr), ZG_CHECK); - if (!ehdr_is_elf_object(ehdr) || !ehdr_is_vmcore(ehdr)) return -ENODEV; if (!ehdr_is_s390x(ehdr)) @@ -301,24 +294,25 @@ static int read_elf_hdr(Elf64_Ehdr *ehdr) */ static int dfi_elf_init(void) { - Elf64_Ehdr ehdr; + unsigned int phnum, i; Elf64_Phdr *phdr; - int i; + Elf64_Ehdr ehdr; util_log_print(UTIL_LOG_DEBUG, "DFI ELF initialization\n"); - if (read_elf_hdr(&ehdr) != 0) + if (read_elf_hdr(g.fh, &ehdr) != 0) + return -ENODEV; + + if (check_elf_hdr(&ehdr) < 0) return -ENODEV; df_elf_ensure_s390x(); dfi_arch_set(DFI_ARCH_64); dfi_cpu_info_init(DFI_CPU_CONTENT_ALL); - phdr = util_malloc(sizeof(*phdr) * ehdr.e_phnum); - zg_seek(g.fh, ehdr.e_phoff, ZG_CHECK); - zg_read(g.fh, phdr, sizeof(*phdr) * ehdr.e_phnum, ZG_CHECK); - util_log_print(UTIL_LOG_DEBUG, "DFI ELF e_phnum %u\n", ehdr.e_phnum); - for (i = 0; i < ehdr.e_phnum; i++) { + phdr = read_elf_phdrs(g.fh, &ehdr, &phnum); + util_log_print(UTIL_LOG_DEBUG, "DFI ELF e_phnum %u\n", phnum); + for (i = 0; i < phnum; i++) { util_log_print(UTIL_LOG_DEBUG, "DFI ELF p_type[%d] 0x%lx\n", i, phdr[i].p_type); switch (phdr[i].p_type) {