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));