From ef88fac874d16e6d91908a3f446c601c723326ee Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Thu, 11 Nov 2021 14:53:30 +0100 Subject: [PATCH] zdump: Extract common ELF routines from dfo_elf and move to df_elf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The primary goal of this change is to split DFO ELF module into multiple smaller ones for better unit testability. The change doesn't introduce any functionality changes, just shuffling code around. Signed-off-by: Alexander Egorenkov Reviewed-by: Marc Hartmayer Signed-off-by: Jan Höppner --- zdump/Makefile | 2 +- zdump/df_elf.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ zdump/df_elf.h | 17 +++++ zdump/dfo_elf.c | 181 +--------------------------------------------- 4 files changed, 205 insertions(+), 180 deletions(-) create mode 100644 zdump/df_elf.c diff --git a/zdump/Makefile b/zdump/Makefile index ee7d7c12..9120048b 100644 --- a/zdump/Makefile +++ b/zdump/Makefile @@ -49,7 +49,7 @@ OBJECTS = zgetdump.o opts.o zg.o \ dfi_s390tape.o dfi_kdump.o \ dfi_devmem.o dfo.o dfo_mem_chunk.o \ dfo_elf.o dfo_s390.o \ - df_s390.o \ + df_elf.o df_s390.o \ dt.o dt_s390sv.o dt_s390sv_ext.o \ dt_s390mv.o dt_s390mv_ext.o \ dt_scsi.o stdout.o \ diff --git a/zdump/df_elf.c b/zdump/df_elf.c new file mode 100644 index 00000000..ac8d7157 --- /dev/null +++ b/zdump/df_elf.c @@ -0,0 +1,185 @@ +/* + * Copyright IBM Corp. 2001, 2018, 2021 + * + * 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 + +#include "df_elf.h" + +/* + * Initialize ELF header + */ +void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum) +{ + memcpy(ehdr->e_ident, ELFMAG, SELFMAG); + ehdr->e_ident[EI_CLASS] = ELFCLASS64; + ehdr->e_ident[EI_DATA] = ELFDATA2MSB; + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; + ehdr->e_ident[EI_ABIVERSION] = 0; + memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); + ehdr->e_type = ET_CORE; + ehdr->e_machine = EM_S390; + ehdr->e_version = EV_CURRENT; + ehdr->e_entry = 0; + ehdr->e_phoff = sizeof(Elf64_Ehdr); + ehdr->e_shoff = 0; + ehdr->e_flags = 0; + ehdr->e_ehsize = sizeof(Elf64_Ehdr); + ehdr->e_phentsize = sizeof(Elf64_Phdr); + ehdr->e_phnum = phnum; + ehdr->e_shentsize = 0; + ehdr->e_shnum = 0; + ehdr->e_shstrndx = 0; + return ehdr + 1; +} + +/* + * Initialize ELF note + */ +void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len, + const char *name) +{ + Elf64_Nhdr *note; + u64 len; + + note = (Elf64_Nhdr *)buf; + note->n_namesz = strlen(name) + 1; + note->n_descsz = d_len; + note->n_type = type; + len = sizeof(Elf64_Nhdr); + + memcpy(buf + len, name, note->n_namesz); + len = ROUNDUP(len + note->n_namesz, 4); + + memcpy(buf + len, desc, note->n_descsz); + len = ROUNDUP(len + note->n_descsz, 4); + + return PTR_ADD(buf, len); +} + +/* + * Initialize prstatus note + */ +void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu) +{ + struct nt_prstatus_64 nt_prstatus; + static int cpu_nr = 1; + + memset(&nt_prstatus, 0, sizeof(nt_prstatus)); + memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs)); + memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw)); + memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs)); + nt_prstatus.pr_pid = cpu_nr; + cpu_nr++; + + return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus), + "CORE"); +} + +/* + * Initialize fpregset (floating point) note + */ +void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu) +{ + struct nt_fpregset_64 nt_fpregset; + + memset(&nt_fpregset, 0, sizeof(nt_fpregset)); + memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc)); + memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs)); + + return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset), + "CORE"); +} + +/* + * Initialize timer note + */ +void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer), + "LINUX"); +} + +/* + * Initialize TOD clock comparator note + */ +void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp, + sizeof(cpu->todcmp), "LINUX"); +} + +/* + * Initialize TOD programmable register note + */ +void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg, + sizeof(cpu->todpreg), "LINUX"); +} + +/* + * Initialize control register note + */ +void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs), + "LINUX"); +} + +/* + * Initialize prefix register note + */ +void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix, + sizeof(cpu->prefix), "LINUX"); +} + +/* + * Initialize vxrs_low register note + */ +void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low, + sizeof(cpu->vxrs_low), "LINUX"); +} + +/* + * Initialize vxrs_high register note + */ +void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu) +{ + return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high, + sizeof(cpu->vxrs_high), "LINUX"); +} + +/* + * Initialize prpsinfo note + */ +void *nt_prpsinfo(void *ptr) +{ + struct nt_prpsinfo_64 prpsinfo; + + memset(&prpsinfo, 0, sizeof(prpsinfo)); + prpsinfo.pr_state = 0; + prpsinfo.pr_sname = 'R'; + prpsinfo.pr_zomb = 0; + strcpy(prpsinfo.pr_fname, "vmlinux"); + + return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo), "CORE"); +} + +/* + * Initialize vmcoreinfo note + */ +void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo) +{ + if (!vmcoreinfo) + return ptr; + return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo), "VMCOREINFO"); +} diff --git a/zdump/df_elf.h b/zdump/df_elf.h index 37316519..f65f8ecf 100644 --- a/zdump/df_elf.h +++ b/zdump/df_elf.h @@ -18,6 +18,7 @@ #include "lib/zt_common.h" #include "zg.h" +#include "dfi.h" /* * S390 CPU timer note (u64) @@ -115,4 +116,20 @@ static inline void df_elf_ensure_s390x(void) #endif } +void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum); + +void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len, + const char *name); +void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu); +void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu); +void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu); +void *nt_prpsinfo(void *ptr); +void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo); + #endif /* DF_ELF_H */ diff --git a/zdump/dfo_elf.c b/zdump/dfo_elf.c index 6191b8ad..27a93988 100644 --- a/zdump/dfo_elf.c +++ b/zdump/dfo_elf.c @@ -27,34 +27,6 @@ #define HDR_PER_MEMC_SIZE 0x100 #define HDR_BASE_SIZE 0x2000 -/* - * Initialize ELF header - */ -static void *ehdr_init(Elf64_Ehdr *ehdr) -{ - memcpy(ehdr->e_ident, ELFMAG, SELFMAG); - ehdr->e_ident[EI_CLASS] = ELFCLASS64; - ehdr->e_ident[EI_DATA] = ELFDATA2MSB; - ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; - ehdr->e_ident[EI_ABIVERSION] = 0; - memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); - ehdr->e_type = ET_CORE; - ehdr->e_machine = EM_S390; - ehdr->e_version = EV_CURRENT; - ehdr->e_entry = 0; - ehdr->e_phoff = sizeof(Elf64_Ehdr); - ehdr->e_shoff = 0; - ehdr->e_flags = 0; - ehdr->e_ehsize = sizeof(Elf64_Ehdr); - ehdr->e_phentsize = sizeof(Elf64_Phdr); - ehdr->e_phnum = dfi_mem_chunk_cnt() + 1; - ehdr->e_shentsize = 0; - ehdr->e_shnum = 0; - ehdr->e_shstrndx = 0; - return ehdr + 1; -} - /* * Initialize ELF loads program headers */ @@ -83,155 +55,6 @@ static u64 load_phdrs_init(Elf64_Phdr *phdr, u64 elf_offset) return mem_size; } -/* - * Initialize ELF note - */ -static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, - const char *name) -{ - Elf64_Nhdr *note; - u64 len; - - note = (Elf64_Nhdr *)buf; - note->n_namesz = strlen(name) + 1; - note->n_descsz = d_len; - note->n_type = type; - len = sizeof(Elf64_Nhdr); - - memcpy(buf + len, name, note->n_namesz); - len = ROUNDUP(len + note->n_namesz, 4); - - memcpy(buf + len, desc, note->n_descsz); - len = ROUNDUP(len + note->n_descsz, 4); - - return PTR_ADD(buf, len); -} - -/* - * Initialize prstatus note - */ -static void *nt_prstatus(void *ptr, struct dfi_cpu *cpu) -{ - struct nt_prstatus_64 nt_prstatus; - static int cpu_nr = 1; - - memset(&nt_prstatus, 0, sizeof(nt_prstatus)); - memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs)); - memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw)); - memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs)); - nt_prstatus.pr_pid = cpu_nr; - cpu_nr++; - - return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus), - "CORE"); -} - -/* - * Initialize fpregset (floating point) note - */ -static void *nt_fpregset(void *ptr, struct dfi_cpu *cpu) -{ - struct nt_fpregset_64 nt_fpregset; - - memset(&nt_fpregset, 0, sizeof(nt_fpregset)); - memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc)); - memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs)); - - return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset), - "CORE"); -} - -/* - * Initialize timer note - */ -static void *nt_s390_timer(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer), - "LINUX"); -} - -/* - * Initialize TOD clock comparator note - */ -static void *nt_s390_tod_cmp(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp, - sizeof(cpu->todcmp), "LINUX"); -} - -/* - * Initialize TOD programmable register note - */ -static void *nt_s390_tod_preg(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg, - sizeof(cpu->todpreg), "LINUX"); -} - -/* - * Initialize control register note - */ -static void *nt_s390_ctrs(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs), - "LINUX"); -} - -/* - * Initialize prefix register note - */ -static void *nt_s390_prefix(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix, - sizeof(cpu->prefix), "LINUX"); -} - -/* - * Initialize vxrs_low register note - */ -static void *nt_s390_vxrs_low(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low, - sizeof(cpu->vxrs_low), "LINUX"); -} - -/* - * Initialize vxrs_high register note - */ -static void *nt_s390_vxrs_high(void *ptr, struct dfi_cpu *cpu) -{ - return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high, - sizeof(cpu->vxrs_high), "LINUX"); -} - -/* - * Initialize prpsinfo note - */ -static void *nt_prpsinfo(void *ptr) -{ - struct nt_prpsinfo_64 prpsinfo; - - memset(&prpsinfo, 0, sizeof(prpsinfo)); - prpsinfo.pr_state = 0; - prpsinfo.pr_sname = 'R'; - prpsinfo.pr_zomb = 0; - strcpy(prpsinfo.pr_fname, "vmlinux"); - - return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo), "CORE"); -} - -/* - * Initialize vmcoreinfo note - */ -static void *nt_vmcoreinfo(void *ptr) -{ - char *vmcoreinfo = dfi_vmcoreinfo_get(); - - if (!vmcoreinfo) - return ptr; - return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo), "VMCOREINFO"); -} - /* * Initialize the program header entries for the notes and the related segment * data. @@ -260,7 +83,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *segment_start, u64 elf_offset) } } out: - ptr = nt_vmcoreinfo(ptr); + ptr = nt_vmcoreinfo(ptr, dfi_vmcoreinfo_get()); memset(phdr, 0, sizeof(*phdr)); phdr->p_type = PT_NOTE; phdr->p_offset = elf_offset; @@ -315,7 +138,7 @@ static void dfo_elf_init(void) dfi_mem_chunk_cnt() * HDR_PER_MEMC_SIZE; buf = zg_alloc(alloc_size); /* Init elf header */ - ptr = ehdr_init(buf); + ptr = ehdr_init(buf, dfi_mem_chunk_cnt() + 1); /* Init program headers */ phdr_notes = ptr; ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));