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