commit 43ff3bc08158f47011e69bf8761e6ce745c55f8f Author: CentOS Sources Date: Thu Aug 1 20:21:39 2019 -0400 import crash-gcore-command-1.3.1-3.el8 diff --git a/.crash-gcore-command.metadata b/.crash-gcore-command.metadata new file mode 100644 index 0000000..ebba7a9 --- /dev/null +++ b/.crash-gcore-command.metadata @@ -0,0 +1 @@ +9f1a889ad7b3f01c88866dac44cabddd7d35f99c SOURCES/crash-gcore-command-1.3.1.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f92527 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/crash-gcore-command-1.3.1.tar.gz diff --git a/SOURCES/arm64_thread_struct_fpsimd_state.patch b/SOURCES/arm64_thread_struct_fpsimd_state.patch new file mode 100644 index 0000000..ad819a9 --- /dev/null +++ b/SOURCES/arm64_thread_struct_fpsimd_state.patch @@ -0,0 +1,15 @@ + +--- crash-gcore-command-1.3.1/gcore.c.orig ++++ crash-gcore-command-1.3.1/gcore.c +@@ -501,6 +501,10 @@ static void gcore_offset_table_init(void + GCORE_MEMBER_OFFSET_INIT(vfp_hard_struct_fpscr, "vfp_hard_struct", "fpscr"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_fpsimd_state, "thread_struct", "fpsimd_state"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_tp_value, "thread_struct", "tp_value"); ++ if (GCORE_INVALID_MEMBER(thread_struct_fpsimd_state)) { ++ GCORE_ANON_MEMBER_OFFSET_INIT(thread_struct_fpsimd_state, "thread_struct", "uw.fpsimd_state"); ++ GCORE_ANON_MEMBER_OFFSET_INIT(thread_struct_tp_value, "thread_struct", "uw.tp_value"); ++ } + } + + static void gcore_size_table_init(void) + diff --git a/SOURCES/rhel8_build.patch b/SOURCES/rhel8_build.patch new file mode 100644 index 0000000..053a733 --- /dev/null +++ b/SOURCES/rhel8_build.patch @@ -0,0 +1,11 @@ +--- crash-gcore-command-1.3.1/gcore.mk.orig ++++ crash-gcore-command-1.3.1/gcore.mk +@@ -102,7 +102,7 @@ gcore.so: gcore.c $(INCDIR)/defs.h + echo "gcore: architecture not supported"; \ + else \ + make -f gcore.mk $(GCORE_OFILES) && \ +- gcc $(RPM_OPT_FLAGS) $(CFLAGS) $(TARGET_CFLAGS) $(COMMON_CFLAGS) $(ARCH_CFLAGS) -nostartfiles -shared -rdynamic $(GCORE_OFILES) -o $@ $< ; \ ++ gcc $(RPM_OPT_FLAGS) $(CFLAGS) $(TARGET_CFLAGS) $(COMMON_CFLAGS) $(ARCH_CFLAGS) -nostartfiles -shared -rdynamic $(GCORE_OFILES) -Wl,-z,now -o $@ $< ; \ + fi; + + %.o: %.c $(INCDIR)/defs.h diff --git a/SOURCES/upstream_1.5.0_equiv.patch b/SOURCES/upstream_1.5.0_equiv.patch new file mode 100644 index 0000000..118d23b --- /dev/null +++ b/SOURCES/upstream_1.5.0_equiv.patch @@ -0,0 +1,751 @@ +--- crash-gcore-command-1.3.1/libgcore/gcore_x86.c.orig ++++ crash-gcore-command-1.3.1/libgcore/gcore_x86.c +@@ -20,10 +20,14 @@ + #include + #include + ++#undef MIN ++#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y)) ++ + struct gcore_x86_table + { + #ifdef X86_64 + ulong (*get_old_rsp)(int cpu); ++ ulong (*user_stack_pointer)(struct task_context *tc); + #endif + ulong (*get_thread_struct_fpu)(struct task_context *tc); + ulong (*get_thread_struct_fpu_size)(void); +@@ -42,9 +46,14 @@ static ulong gcore_x86_64_get_old_rsp(in + static ulong gcore_x86_64_get_per_cpu__old_rsp(int cpu); + static ulong gcore_x86_64_get_cpu_pda_oldrsp(int cpu); + static ulong gcore_x86_64_get_cpu__pda_oldrsp(int cpu); ++ ++static ulong gcore_x86_64_user_stack_pointer_userrsp(struct task_context *tc); ++static ulong gcore_x86_64_user_stack_pointer_pt_regs(struct task_context *tc); + #endif + + static ulong ++gcore_x86_get_thread_struct_fpu_fpregs_state(struct task_context *tc); ++static ulong + gcore_x86_get_thread_struct_fpu_thread_xstate(struct task_context *tc); + static ulong gcore_x86_get_thread_struct_fpu_thread_xstate_size(void); + static ulong +@@ -78,6 +87,7 @@ static int is_special_ia32_syscall_v26(i + + static int tsk_used_math_v0(ulong task); + static int tsk_used_math_v11(ulong task); ++static int tsk_used_math_v4_14(ulong task); + + #ifdef X86_64 + static void gcore_x86_64_regset_xstate_init(void); +@@ -352,18 +362,15 @@ static int xfpregs_get(struct task_conte + unsigned int size, + void *buf) + { +- struct i387_fxsave_struct *fxsave = (struct i387_fxsave_struct *)buf; + union thread_xstate xstate; + + readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate, +- gxt->get_thread_struct_fpu_size(), ++ sizeof(xstate), + "xfpregs_get: xstate", gcore_verbose_error_handle()); +- memcpy(buf, &xstate.fsave, sizeof(xstate.fsave)); ++ memcpy(buf, &xstate.fsave, MIN(size, sizeof(xstate.fsave))); + + init_fpu(target->task); + +- *fxsave = xstate.fxsave; +- + return 0; + } + +@@ -485,7 +492,7 @@ convert_from_fxsr(struct user_i387_ia32_ + int i; + + readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate, +- gxt->get_thread_struct_fpu_size(), "convert_from_fxsr: xstate", ++ sizeof(xstate), "convert_from_fxsr: xstate", + gcore_verbose_error_handle()); + + to = (struct _fpreg *) &env->st_space[0]; +@@ -549,9 +556,9 @@ static int fpregs_get(struct task_contex + + if (!cpu_has_fxsr()) { + readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate, +- gxt->get_thread_struct_fpu_size(), ++ sizeof(xstate), + "fpregs_get: xstate", gcore_verbose_error_handle()); +- memcpy(buf, &xstate.fsave, sizeof(xstate.fsave)); ++ memcpy(buf, &xstate.fsave, MIN(size, sizeof(xstate.fsave))); + return 0; + } + +@@ -562,6 +569,14 @@ static int fpregs_get(struct task_contex + return 0; + } + ++static ulong gcore_x86_get_thread_struct_fpu_fpregs_state(struct task_context *tc) ++{ ++ return tc->task + ++ OFFSET(task_struct_thread) + ++ GCORE_OFFSET(thread_struct_fpu) + ++ GCORE_OFFSET(fpu_state); ++} ++ + static ulong gcore_x86_get_thread_struct_fpu_thread_xstate(struct task_context *tc) + { + ulong state; +@@ -1010,6 +1025,26 @@ static int tsk_used_math_v11(ulong task) + return !!(flags & PF_USED_MATH); + } + ++static int tsk_used_math_v4_14(ulong task) ++{ ++ unsigned char initialized; ++ ++ if (!cpu_has_fxsr()) ++ return 0; ++ ++ readmem(task + ++ OFFSET(task_struct_thread) + ++ GCORE_OFFSET(thread_struct_fpu) + ++ MEMBER_OFFSET("fpu", "initialized"), ++ KVADDR, ++ &initialized, ++ sizeof(initialized), ++ "tsk_used_math_v4_14: initialized", ++ gcore_verbose_error_handle()); ++ ++ return !!initialized; ++} ++ + static inline int + user_mode(const struct user_regs_struct *regs) + { +@@ -1331,6 +1366,23 @@ static inline void restore_rest(ulong ta + } + + /** ++ * gcore_x86_64_get_old_rsp_zero() - get rsp at per-cpu area ++ * ++ * @cpu target CPU's CPU id ++ * ++ * Given a CPU id, returns a RSP value saved at per-cpu area for the ++ * CPU whose id is the given CPU id. ++ * ++ * This is a method of get_old_rsp() returning always 0 for when no ++ * appropriate method is found. ++ */ ++static ulong gcore_x86_64_get_old_rsp_zero(int cpu) ++{ ++ error(WARNING, "failed to detect location of sp register, forcing 0.\n"); ++ return 0UL; ++} ++ ++/** + * gcore_x86_64_get_old_rsp() - get rsp at per-cpu area + * + * @cpu target CPU's CPU id +@@ -1421,6 +1473,50 @@ static ulong gcore_x86_64_get_cpu__pda_o + return oldrsp; + } + ++static ulong gcore_x86_64_user_stack_pointer_userrsp(struct task_context *tc) ++{ ++ ulong usersp; ++ ++ /* ++ * rsp is saved in per-CPU old_rsp, which is saved in ++ * thread->usersp at each context switch. ++ */ ++ if (is_task_active(tc->task)) ++ return gxt->get_old_rsp(tc->processor); ++ ++ readmem(tc->task + OFFSET(task_struct_thread) + ++ GCORE_OFFSET(thread_struct_usersp), KVADDR, &usersp, ++ sizeof(usersp), ++ "gcore_x86_64_user_stack_pointer_userrsp: usersp", ++ gcore_verbose_error_handle()); ++ ++ return usersp; ++} ++ ++static ulong gcore_x86_64_user_stack_pointer_pt_regs(struct task_context *tc) ++{ ++ char *pt_regs_buf; ++ ulong sp0, sp; ++ struct machine_specific *ms = machdep->machspec; ++ ++ pt_regs_buf = GETBUF(SIZE(pt_regs)); ++ ++ readmem(tc->task + OFFSET(task_struct_thread) + ++ GCORE_OFFSET(thread_struct_sp0), KVADDR, &sp0, ++ sizeof(sp0), ++ "gcore_x86_64_user_stack_pointer_pt_regs: sp0", ++ gcore_verbose_error_handle()); ++ ++ readmem(sp0 - SIZE(pt_regs), KVADDR, pt_regs_buf, SIZE(pt_regs), ++ "gcore_x86_64_user_stack_pointer_pt_regs: pt_regs", ++ gcore_verbose_error_handle()); ++ ++ sp = ULONG(pt_regs_buf + ms->pto.rsp); ++ ++ FREEBUF(pt_regs_buf); ++ return sp; ++} ++ + static int + gcore_find_regs_from_bt_output(FILE *output, char *buf, size_t bufsize) + { +@@ -1648,18 +1744,8 @@ restore_regs_syscall_context(struct task + { + const int nr_syscall = (int)regs->orig_ax; + +- /* +- * rsp is saved in per-CPU old_rsp, which is saved in +- * thread->usersp at each context switch. +- */ +- if (is_task_active(target->task)) { +- regs->sp = gxt->get_old_rsp(target->processor); +- } else { +- readmem(target->task + OFFSET(task_struct_thread) + +- GCORE_OFFSET(thread_struct_usersp), KVADDR, ®s->sp, +- sizeof(regs->sp), +- "genregs_get: usersp", gcore_verbose_error_handle()); +- } ++ if (gxt->user_stack_pointer) ++ regs->sp = gxt->user_stack_pointer(target); + + /* + * entire registers are saved for special system calls. +@@ -1788,6 +1874,15 @@ static int genregs_get(struct task_conte + "system call instruction used could not be found\n"); + case GCORE_KERNEL_ENTRY_IRQ: + case GCORE_KERNEL_ENTRY_INT80: ++ /* ++ * The commit ff467594f2a4be01a0fa5e9ffc223fa930d232dd ++ * in the linux kernel begins saving all registers ++ * including callee-saved registers on the bottom of ++ * the kernel stack even on the IRQ entry. I'm very ++ * happy. ++ */ ++ if (THIS_KERNEL_VERSION < LINUX(4,2,0)) ++ restore_rest(target->task, regs, &active_regs); + restore_rest(target->task, regs, &active_regs); + restore_segment_registers(target->task, regs); + break; +@@ -1834,14 +1929,31 @@ static void gcore_x86_table_register_get + + else if (symbol_exists("_cpu_pda")) + gxt->get_old_rsp = gcore_x86_64_get_cpu__pda_oldrsp; ++ ++ else ++ gxt->get_old_rsp = gcore_x86_64_get_old_rsp_zero; ++} ++ ++static void gcore_x86_table_register_user_stack_pointer(void) ++{ ++ if (MEMBER_EXISTS("thread_struct", "usersp") || ++ MEMBER_EXISTS("thread_struct", "userrsp")) ++ gxt->user_stack_pointer = gcore_x86_64_user_stack_pointer_userrsp; ++ ++ else if (MEMBER_EXISTS("thread_struct", "sp0")) ++ gxt->user_stack_pointer = gcore_x86_64_user_stack_pointer_pt_regs; + } + #endif + + static void gcore_x86_table_register_get_thread_struct_fpu(void) + { + if (MEMBER_EXISTS("thread_struct", "fpu")) { +- gxt->get_thread_struct_fpu = +- gcore_x86_get_thread_struct_fpu_thread_xstate; ++ if (MEMBER_OFFSET("fpu", "state") == 8) ++ gxt->get_thread_struct_fpu = ++ gcore_x86_get_thread_struct_fpu_thread_xstate; ++ else ++ gxt->get_thread_struct_fpu = ++ gcore_x86_get_thread_struct_fpu_fpregs_state; + gxt->get_thread_struct_fpu_size = + gcore_x86_get_thread_struct_fpu_thread_xstate_size; + } else if (MEMBER_EXISTS("thread_struct", "xstate")) { +@@ -1900,7 +2012,9 @@ static void gcore_x86_table_register_is_ + */ + static void gcore_x86_table_register_tsk_used_math(void) + { +- if (GCORE_VALID_MEMBER(task_struct_used_math)) ++ if (MEMBER_EXISTS("fpu", "initialized")) ++ gxt->tsk_used_math = tsk_used_math_v4_14; ++ else if (GCORE_VALID_MEMBER(task_struct_used_math)) + gxt->tsk_used_math = tsk_used_math_v0; + else + gxt->tsk_used_math = tsk_used_math_v11; +@@ -1911,6 +2025,7 @@ static void gcore_x86_table_register_tsk + void gcore_x86_table_init(void) + { + gcore_x86_table_register_get_old_rsp(); ++ gcore_x86_table_register_user_stack_pointer(); + gcore_x86_table_register_get_thread_struct_fpu(); + gcore_x86_table_register_is_special_syscall(); + gcore_x86_table_register_is_special_ia32_syscall(); +@@ -2248,6 +2363,20 @@ ulong gcore_arch_get_gate_vma(void) + if (gcore_is_arch_32bit_emulation(CURRENT_CONTEXT())) + return 0UL; + ++ if (symbol_exists("vsyscall_mode")) { ++ enum { ENUMERATE, NONE } vsyscall_mode; ++ ++ readmem(symbol_value("vsyscall_mode"), ++ KVADDR, ++ &vsyscall_mode, ++ sizeof(vsyscall_mode), ++ "gcore_arch_get_gate_vma: vsyscall_mode", ++ gcore_verbose_error_handle()); ++ ++ if (vsyscall_mode == NONE) ++ return 0UL; ++ } ++ + return symbol_value("gate_vma"); + #else + return 0UL; +--- crash-gcore-command-1.3.1/libgcore/gcore_coredump.c.orig ++++ crash-gcore-command-1.3.1/libgcore/gcore_coredump.c +@@ -683,7 +683,7 @@ fill_prstatus_note(struct elf_note_info + struct memelfnote *memnote) + { + struct elf_prstatus *prstatus; +-#if defined(X86) || defined(X86_64) || defined(ARM) || defined(PPC64) ++#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS) || defined(PPC64) + struct user_regs_struct *regs = (struct user_regs_struct *)memnote->data; + #endif + #ifdef ARM64 +--- crash-gcore-command-1.3.1/libgcore/gcore_dumpfilter.c.orig ++++ crash-gcore-command-1.3.1/libgcore/gcore_dumpfilter.c +@@ -18,10 +18,61 @@ + + static ulong dumpfilter = GCORE_DUMPFILTER_DEFAULT; + ++static int special_mapping_name(ulong vma) ++{ ++ ulong vm_private_data, name_p; ++ ++ readmem(vma + GCORE_OFFSET(vm_area_struct_vm_private_data), ++ KVADDR, ++ &vm_private_data, ++ sizeof(vm_private_data), ++ "always_dump_vma: vma->vm_private_data", ++ gcore_verbose_error_handle()); ++ ++ readmem(vm_private_data + ++ GCORE_OFFSET(vm_special_mapping_name), ++ KVADDR, ++ &name_p, ++ sizeof(name_p), ++ "always_dump_vma: ((struct vm_special_mapping *)vma->vm_private_data)->name", ++ gcore_verbose_error_handle()); ++ ++ return name_p ? TRUE : FALSE; ++} ++ + static int always_dump_vma(ulong vma) + { + if (vma == gcore_arch_get_gate_vma()) + return TRUE; ++ ++ if (GCORE_VALID_MEMBER(vm_special_mapping_name)) { ++ ulong vm_ops, name; ++ ++ readmem(vma + GCORE_OFFSET(vm_area_struct_vm_ops), ++ KVADDR, ++ &vm_ops, ++ sizeof(vm_ops), ++ "always_dump_vma: vma->vm_ops", ++ gcore_verbose_error_handle()); ++ ++ if (!vm_ops) ++ goto out; ++ ++ readmem(vm_ops + GCORE_OFFSET(vm_operations_struct_name), ++ KVADDR, ++ &name, ++ sizeof(name), ++ "always_dump_vma: vma->vm_ops->name", ++ gcore_verbose_error_handle()); ++ ++ if (!name) ++ goto out; ++ ++ if (name == symbol_value("special_mapping_name")) ++ return special_mapping_name(vma); ++ } ++out: ++ + if (gcore_arch_vma_name(vma)) + return TRUE; + return FALSE; +--- crash-gcore-command-1.3.1/libgcore/gcore_defs.h.orig ++++ crash-gcore-command-1.3.1/libgcore/gcore_defs.h +@@ -94,6 +94,26 @@ + #define Elf_Nhdr Elf32_Nhdr + #endif + ++#ifdef MIPS ++#define ELF_EXEC_PAGESIZE 4096 ++ ++#define ELF_MACHINE EM_MIPS ++#define ELF_OSABI ELFOSABI_NONE ++ ++#define ELF_CLASS ELFCLASS32 ++#define ELF_DATA ELFDATA2LSB ++#define ELF_ARCH EM_MIPS ++ ++#define Elf_Half Elf32_Half ++#define Elf_Word Elf32_Word ++#define Elf_Off Elf32_Off ++ ++#define Elf_Ehdr Elf32_Ehdr ++#define Elf_Phdr Elf32_Phdr ++#define Elf_Shdr Elf32_Shdr ++#define Elf_Nhdr Elf32_Nhdr ++#endif ++ + #ifdef ARM64 + #define ELF_EXEC_PAGESIZE PAGESIZE() + +@@ -290,6 +310,11 @@ extern void gcore_default_regsets_init(v + #define REGSET_VIEW_MACHINE EM_AARCH64 + #endif + ++#ifdef MIPS ++#define REGSET_VIEW_NAME "mips" ++#define REGSET_VIEW_MACHINE EM_MIPS ++#endif ++ + #ifdef PPC64 + #define REGSET_VIEW_NAME "ppc64" + #define REGSET_VIEW_MACHINE EM_PPC64 +@@ -594,6 +619,12 @@ struct user_regs_struct32{ + #endif /* GCORE_ARCH_COMPAT */ + #endif + ++#ifdef MIPS ++struct user_regs_struct { ++ unsigned long gregs[45]; ++}; ++#endif ++ + #ifdef PPC64 + /* taken from asm/ptrace.h */ + struct user_regs_struct { +@@ -620,13 +651,13 @@ struct user_regs_struct { + }; + #endif + +-#if defined(X86) || defined(X86_64) || defined(ARM) ++#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS) + typedef ulong elf_greg_t; + #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) + typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + #endif + +-#if defined(X86) || defined(ARM) ++#if defined(X86) || defined(ARM) || defined(MIPS) + #define PAGE_SIZE 4096 + #endif + #if defined(ARM64) || defined(PPC64) +@@ -783,7 +814,7 @@ struct elf_prstatus + int pr_fpvalid; /* True if math co-processor being used. */ + }; + +-#if defined(X86) || defined(X86_64) || defined(ARM) ++#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS) + typedef unsigned short __kernel_old_uid_t; + typedef unsigned short __kernel_old_gid_t; + #endif +@@ -803,7 +834,7 @@ typedef __kernel_gid_t __kernel_old_gid + typedef __kernel_old_uid_t old_uid_t; + typedef __kernel_old_gid_t old_gid_t; + +-#if defined(X86) || defined(ARM) ++#if defined(X86) || defined(ARM) || defined(MIPS) + typedef unsigned short __kernel_uid_t; + typedef unsigned short __kernel_gid_t; + #endif +@@ -1070,6 +1101,7 @@ struct gcore_offset_table + long thread_struct_gs; + long thread_struct_gsindex; + long thread_struct_i387; ++ long thread_struct_sp0; + long thread_struct_tls_array; + long thread_struct_usersp; + long thread_struct_xstate; +@@ -1082,6 +1114,10 @@ struct gcore_offset_table + long vfp_hard_struct_fpregs; + long vfp_hard_struct_fpscr; + long vm_area_struct_anon_vma; ++ long vm_area_struct_vm_ops; ++ long vm_area_struct_vm_private_data; ++ long vm_operations_struct_name; ++ long vm_special_mapping_name; + long x8664_pda_oldrsp; + }; + +--- crash-gcore-command-1.3.1/libgcore/gcore_mips.c.orig ++++ crash-gcore-command-1.3.1/libgcore/gcore_mips.c +@@ -0,0 +1,159 @@ ++/* gcore_mips.c -- core analysis suite ++ * ++ * Copyright (C) 2016 Axis Communications ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#if defined(MIPS) ++ ++#include "defs.h" ++#include ++#include ++#include ++#include ++ ++#define MIPS32_EF_R0 6 ++#define MIPS32_EF_R1 7 ++#define MIPS32_EF_R26 32 ++#define MIPS32_EF_R27 33 ++#define MIPS32_EF_R31 37 ++#define MIPS32_EF_LO 38 ++#define MIPS32_EF_HI 39 ++#define MIPS32_EF_CP0_EPC 40 ++#define MIPS32_EF_CP0_BADVADDR 41 ++#define MIPS32_EF_CP0_STATUS 42 ++#define MIPS32_EF_CP0_CAUSE 43 ++ ++static int gpr_get(struct task_context *target, ++ const struct user_regset *regset, ++ unsigned int size, void *buf) ++{ ++ static int once; ++ struct user_regs_struct *regs = buf; ++ struct mips_pt_regs_main *mains; ++ struct mips_pt_regs_cp0 *cp0; ++ char pt_regs[SIZE(pt_regs)]; ++ int i; ++ ++ /* ++ * All registers are saved in thread_info.regs only on certain types of ++ * entries to the kernel (such as abort handling). For other types of ++ * entries (such as system calls), only a subset of the registers are ++ * saved on entry and the rest are saved on the stack according to the ++ * ABI's calling conventions. To always get the full register set we ++ * would have to unwind the stack and find where the registers are by ++ * using DWARF information. We don't have an implementation for this ++ * right now so warn to avoid misleading the user. Only warn since ++ * this function is called multiple times even for a single invocation ++ * of the gcore command. ++ */ ++ if (!once) { ++ once = 1; ++ error(WARNING, "WARNING: Current register values may be inaccurate\n"); ++ } ++ ++ readmem(machdep->get_stacktop(target->task) - 32 - SIZE(pt_regs), ++ KVADDR, pt_regs, SIZE(pt_regs), "genregs_get: pt_regs", ++ gcore_verbose_error_handle()); ++ ++ mains = (struct mips_pt_regs_main *) (pt_regs + OFFSET(pt_regs_regs)); ++ cp0 = (struct mips_pt_regs_cp0 *) \ ++ (pt_regs + OFFSET(pt_regs_cp0_badvaddr)); ++ ++ BZERO(regs, sizeof(*regs)); ++ ++ for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) { ++ /* k0/k1 are copied as zero. */ ++ if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27) ++ continue; ++ ++ regs->gregs[i] = mains->regs[i - MIPS32_EF_R0]; ++ } ++ ++ regs->gregs[MIPS32_EF_LO] = mains->lo; ++ regs->gregs[MIPS32_EF_HI] = mains->hi; ++ regs->gregs[MIPS32_EF_CP0_EPC] = cp0->cp0_epc; ++ regs->gregs[MIPS32_EF_CP0_BADVADDR] = cp0->cp0_badvaddr; ++ regs->gregs[MIPS32_EF_CP0_STATUS] = mains->cp0_status; ++ regs->gregs[MIPS32_EF_CP0_CAUSE] = cp0->cp0_cause; ++ ++ return 0; ++} ++ ++enum gcore_regset { ++ REGSET_GPR, ++}; ++ ++static struct user_regset mips_regsets[] = { ++ [REGSET_GPR] = { ++ .core_note_type = NT_PRSTATUS, ++ .name = "CORE", ++ .size = ELF_NGREG * sizeof(unsigned int), ++ .get = gpr_get, ++ }, ++}; ++ ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++#endif ++ ++static const struct user_regset_view mips_regset_view = { ++ .name = "mips", ++ .regsets = mips_regsets, ++ .n = ARRAY_SIZE(mips_regsets), ++ .e_machine = EM_MIPS, ++}; ++ ++const struct user_regset_view * ++task_user_regset_view(void) ++{ ++ return &mips_regset_view; ++} ++ ++int gcore_is_arch_32bit_emulation(struct task_context *tc) ++{ ++ return FALSE; ++} ++ ++ulong gcore_arch_get_gate_vma(void) ++{ ++ return 0UL; ++} ++ ++char *gcore_arch_vma_name(ulong vma) ++{ ++ ulong mm, vm_start, vdso; ++ ++ readmem(vma + OFFSET(vm_area_struct_vm_mm), KVADDR, &mm, sizeof(mm), ++ "gcore_arch_vma_name: vma->vm_mm", ++ gcore_verbose_error_handle()); ++ ++ readmem(vma + OFFSET(vm_area_struct_vm_start), KVADDR, &vm_start, ++ sizeof(vm_start), "gcore_arch_vma_name: vma->vm_start", ++ gcore_verbose_error_handle()); ++ ++ readmem(mm + GCORE_OFFSET(mm_struct_context) + ++ GCORE_OFFSET(mm_context_t_vdso), KVADDR, &vdso, ++ sizeof(vdso), "gcore_arch_vma_name: mm->context.vdso", ++ gcore_verbose_error_handle()); ++ ++ if (mm && vm_start == vdso) ++ return "[vdso]"; ++ ++ return NULL; ++} ++ ++int gcore_arch_vsyscall_has_vm_alwaysdump_flag(void) ++{ ++ return FALSE; ++} ++ ++#endif /* defined(MIPS) */ +--- crash-gcore-command-1.3.1/gcore.c.orig ++++ crash-gcore-command-1.3.1/gcore.c +@@ -463,10 +463,16 @@ static void gcore_offset_table_init(void + GCORE_MEMBER_OFFSET_INIT(thread_info_vfpstate, "thread_info", "vfpstate"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_ds, "thread_struct", "ds"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_es, "thread_struct", "es"); +- GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fs"); ++ if (MEMBER_EXISTS("thread_struct", "fs")) ++ GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fs"); ++ else ++ GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fsbase"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_fsindex, "thread_struct", "fsindex"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_fpu, "thread_struct", "fpu"); +- GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gs"); ++ if (MEMBER_EXISTS("thread_struct", "gs")) ++ GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gs"); ++ else ++ GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gsbase"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_gsindex, "thread_struct", "gsindex"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_i387, "thread_struct", "i387"); + GCORE_MEMBER_OFFSET_INIT(thread_struct_tls_array, "thread_struct", "tls_array"); +@@ -474,6 +480,7 @@ static void gcore_offset_table_init(void + GCORE_MEMBER_OFFSET_INIT(thread_struct_usersp, "thread_struct", "usersp"); + else if (MEMBER_EXISTS("thread_struct", "userrsp")) + GCORE_MEMBER_OFFSET_INIT(thread_struct_usersp, "thread_struct", "userrsp"); ++ GCORE_MEMBER_OFFSET_INIT(thread_struct_sp0, "thread_struct", "sp0"); + if (MEMBER_EXISTS("thread_struct", "xstate")) + GCORE_MEMBER_OFFSET_INIT(thread_struct_xstate, "thread_struct", "xstate"); + else if (MEMBER_EXISTS("thread_struct", "i387")) +@@ -482,6 +489,10 @@ static void gcore_offset_table_init(void + GCORE_MEMBER_OFFSET_INIT(thread_struct_io_bitmap_ptr, "thread_struct", "io_bitmap_ptr"); + GCORE_MEMBER_OFFSET_INIT(user_regset_n, "user_regset", "n"); + GCORE_MEMBER_OFFSET_INIT(vm_area_struct_anon_vma, "vm_area_struct", "anon_vma"); ++ GCORE_MEMBER_OFFSET_INIT(vm_area_struct_vm_ops, "vm_area_struct", "vm_ops"); ++ GCORE_MEMBER_OFFSET_INIT(vm_area_struct_vm_private_data, "vm_area_struct", "vm_private_data"); ++ GCORE_MEMBER_OFFSET_INIT(vm_operations_struct_name, "vm_operations_struct", "name"); ++ GCORE_MEMBER_OFFSET_INIT(vm_special_mapping_name, "vm_special_mapping", "name"); + + if (symbol_exists("_cpu_pda")) + GCORE_MEMBER_OFFSET_INIT(x8664_pda_oldrsp, "x8664_pda", "oldrsp"); +@@ -499,9 +510,15 @@ static void gcore_size_table_init(void) + GCORE_MEMBER_SIZE_INIT(mm_struct_saved_auxv, "mm_struct", "saved_auxv"); + GCORE_MEMBER_SIZE_INIT(thread_struct_ds, "thread_struct", "ds"); + GCORE_MEMBER_SIZE_INIT(thread_struct_es, "thread_struct", "es"); +- GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fs"); ++ if (MEMBER_EXISTS("thread_struct", "fs")) ++ GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fs"); ++ else ++ GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fsbase"); + GCORE_MEMBER_SIZE_INIT(thread_struct_fsindex, "thread_struct", "fsindex"); +- GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gs"); ++ if (MEMBER_EXISTS("thread_struct", "gs")) ++ GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gs"); ++ else ++ GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gsbase"); + GCORE_MEMBER_SIZE_INIT(thread_struct_gsindex, "thread_struct", "gsindex"); + GCORE_MEMBER_SIZE_INIT(thread_struct_tls_array, "thread_struct", "tls_array"); + GCORE_STRUCT_SIZE_INIT(thread_xstate, "thread_xstate"); +--- crash-gcore-command-1.3.1/gcore.mk.orig ++++ crash-gcore-command-1.3.1/gcore.mk +@@ -12,9 +12,9 @@ + # GNU General Public License for more details. + # + +-VERSION=1.3.1 +-DATE=6 Nov 2014 +-PERIOD=2010, 2011, 2012, 2013, 2014 ++VERSION=1.5.0 ++DATE=30 Nov 2018 ++PERIOD=2010, 2011, 2012, 2013, 2014, 2016, 2017, 2018 + + ARCH=UNSUPPORTED + +@@ -42,6 +42,12 @@ ifeq ($(shell arch), aarch64) + ARCH=SUPPORTED + endif + ++ifeq ($(shell arch), mips) ++ TARGET=MIPS ++ TARGET_CFLAGS= ++ ARCH=SUPPORTED ++endif ++ + ifeq ($(shell arch), ppc64) + TARGET=PPC64 + TARGET_CFLAGS= +@@ -85,6 +91,10 @@ ifneq (,$(findstring $(TARGET), ARM64)) + GCORE_CFILES += libgcore/gcore_arm64.c + endif + ++ifneq (,$(findstring $(TARGET), MIPS)) ++GCORE_CFILES += libgcore/gcore_mips.c ++endif ++ + ifneq (,$(findstring $(TARGET), PPC64)) + GCORE_CFILES += libgcore/gcore_ppc64.c + endif diff --git a/SPECS/crash-gcore-command.spec b/SPECS/crash-gcore-command.spec new file mode 100644 index 0000000..cb4d4cc --- /dev/null +++ b/SPECS/crash-gcore-command.spec @@ -0,0 +1,105 @@ +# +# crash core analysis suite +# +Summary: Gcore extension module for the crash utility +Name: crash-gcore-command +Version: 1.3.1 +Release: 3%{?dist} +License: GPLv2 +Group: Development/Debuggers +Source: %{name}-%{version}.tar.gz +URL: http://people.redhat.com/anderson/extensions/%{name}-%{version}.tar.gz +# Vendor: FUJITSU LIMITED +# Packager: HATAYAMA Daisuke +ExclusiveOS: Linux +ExclusiveArch: x86_64 %{ix86} arm aarch64 ppc64 ppc64le +Buildroot: %{_tmppath}/%{name}-root +BuildRequires: crash-devel >= 5.1.5, zlib-devel lzo-devel snappy-devel +Requires: crash >= 5.1.5 +Patch0: rhel8_build.patch +Patch1: upstream_1.5.0_equiv.patch +Patch2: arm64_thread_struct_fpsimd_state.patch + +%description +Command for creating a core dump file of a user-space task that was +running in a kernel dumpfile. + +%prep +%setup -q -n %{name}-%{version} +%patch0 -p1 -b rhel8_build.patch +%patch1 -p1 -b upstream_1.5.0_equiv.patch +%patch2 -p1 -b arm64_thread_struct_fpsimd_state.patch + +%build +make -f gcore.mk + +%install +rm -Rf $RPM_BUILD_ROOT +mkdir -p %{buildroot}%{_libdir}/crash/extensions/ +cp %{_builddir}/%{name}-%{version}/gcore.so %{buildroot}%{_libdir}/crash/extensions/ + +%clean +rm -rf %{buildroot} +rm -Rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%{_libdir}/crash/extensions/gcore.so +%doc COPYING + +%changelog +* Tue Dec 4 2018 Dave Anderson - 1.3.1-3 +- Fix x86_64 "invalid structure member offset: thread_struct_fs" + Resolves: rhbz#1589019 +- Fix arm64 "invalid structure member offset: thread_struct_fpsimd_state" + Resolves: rhbz#1625810 + +* Wed Sep 10 2018 Dave Anderson - 1.3.1-2 +- Address annocheck link issue + Resolves: rhbz#1630556 + +* Mon Aug 13 2018 Dave Anderson - 1.3.1-1 +- Bump release for mass rebuild + Resolves: rhbz#1615509 + +* Thu Nov 6 2014 Dave Anderson - 1.3.1-0 +- Rebase to 1.3.1 to address 32-bit x86 build error. +- Resolves: rhbz#1077311 + +* Tue Nov 4 2014 Dave Anderson - 1.3.0-0 +- Add aarch64 support +- Resolves: rhbz#1077311 +- Add ppc64/ppc64le support +- Resolves: rhbz#1125485 + +* Fri Dec 27 2013 Daniel Mach - 1.2.1-2 +- Mass rebuild 2013-12-27 + + +* Tue Aug 20 2013 Dave Anderson - 1.2.1-1 + crash utility has added LZO and snappy compression in addition to zlib. + +* Thu May 23 2013 HATAYAMA Daisuke - 1.2.1-0 + Fixes for missing VDSO and vsyscall pages in core dump. + +* Wed Nov 21 2012 HATAYAMA Daisuke - 1.2-0 + Support recent kernels around 3.6. + +* Tue Jan 31 2012 Dave Anderson - 1.0-3 + Address Pkgwrangler/rpmlint issues. + Resolves: rbhz#692799 + +* Wed Jan 25 2012 Dave Anderson - 1.0-2 + Compile with RPM_OPT_FLAGS and fix warnings generated from using it. + Resolves: rbhz#692799 + +* Thu Apr 13 2011 HATAYAMA Daisuke - 1.0-1 +- Remove inclusion of kvmdump.h and unwind_x86_64.h due to non-supporting issue + on crash-devel package. Instead, use a new interface for them. +- Remove ppc64, ia64, s390 and s390x from ExclusiveArch, leave x86_64 + and %%{ix86} there. +- Add descriptions in BuildRequires and Requires about crash and crash-devel. + +* Wed Apr 6 2011 HATAYAMA Daisuke - 1.0-0 +- Initial crash-gcore-command package +