Blame SOURCES/upstream_1.5.0_equiv.patch

6cd514
--- crash-gcore-command-1.3.1/libgcore/gcore_x86.c.orig
6cd514
+++ crash-gcore-command-1.3.1/libgcore/gcore_x86.c
6cd514
@@ -20,10 +20,14 @@
6cd514
 #include <elf.h>
6cd514
 #include <asm/ldt.h>
6cd514
 
6cd514
+#undef MIN
6cd514
+#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
6cd514
+
6cd514
 struct gcore_x86_table
6cd514
 {
6cd514
 #ifdef X86_64
6cd514
 	ulong (*get_old_rsp)(int cpu);
6cd514
+	ulong (*user_stack_pointer)(struct task_context *tc);
6cd514
 #endif
6cd514
 	ulong (*get_thread_struct_fpu)(struct task_context *tc);
6cd514
 	ulong (*get_thread_struct_fpu_size)(void);
6cd514
@@ -42,9 +46,14 @@ static ulong gcore_x86_64_get_old_rsp(in
6cd514
 static ulong gcore_x86_64_get_per_cpu__old_rsp(int cpu);
6cd514
 static ulong gcore_x86_64_get_cpu_pda_oldrsp(int cpu);
6cd514
 static ulong gcore_x86_64_get_cpu__pda_oldrsp(int cpu);
6cd514
+
6cd514
+static ulong gcore_x86_64_user_stack_pointer_userrsp(struct task_context *tc);
6cd514
+static ulong gcore_x86_64_user_stack_pointer_pt_regs(struct task_context *tc);
6cd514
 #endif
6cd514
 
6cd514
 static ulong
6cd514
+gcore_x86_get_thread_struct_fpu_fpregs_state(struct task_context *tc);
6cd514
+static ulong
6cd514
 gcore_x86_get_thread_struct_fpu_thread_xstate(struct task_context *tc);
6cd514
 static ulong gcore_x86_get_thread_struct_fpu_thread_xstate_size(void);
6cd514
 static ulong
6cd514
@@ -78,6 +87,7 @@ static int is_special_ia32_syscall_v26(i
6cd514
 
6cd514
 static int tsk_used_math_v0(ulong task);
6cd514
 static int tsk_used_math_v11(ulong task);
6cd514
+static int tsk_used_math_v4_14(ulong task);
6cd514
 
6cd514
 #ifdef X86_64
6cd514
 static void gcore_x86_64_regset_xstate_init(void);
6cd514
@@ -352,18 +362,15 @@ static int xfpregs_get(struct task_conte
6cd514
 		       unsigned int size,
6cd514
 		       void *buf)
6cd514
 {
6cd514
-	struct i387_fxsave_struct *fxsave = (struct i387_fxsave_struct *)buf;
6cd514
 	union thread_xstate xstate;
6cd514
 
6cd514
 	readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate,
6cd514
-		gxt->get_thread_struct_fpu_size(),
6cd514
+		sizeof(xstate),
6cd514
 		"xfpregs_get: xstate", gcore_verbose_error_handle());
6cd514
-	memcpy(buf, &xstate.fsave, sizeof(xstate.fsave));
6cd514
+	memcpy(buf, &xstate.fsave, MIN(size, sizeof(xstate.fsave)));
6cd514
 
6cd514
 	init_fpu(target->task);
6cd514
 
6cd514
-	*fxsave = xstate.fxsave;
6cd514
-
6cd514
 	return 0;
6cd514
 }
6cd514
 
6cd514
@@ -485,7 +492,7 @@ convert_from_fxsr(struct user_i387_ia32_
6cd514
 	int i;
6cd514
 
6cd514
 	readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate,
6cd514
-		gxt->get_thread_struct_fpu_size(), "convert_from_fxsr: xstate",
6cd514
+		sizeof(xstate), "convert_from_fxsr: xstate",
6cd514
 		gcore_verbose_error_handle());
6cd514
 
6cd514
 	to = (struct _fpreg *) &env->st_space[0];
6cd514
@@ -549,9 +556,9 @@ static int fpregs_get(struct task_contex
6cd514
 
6cd514
 	if (!cpu_has_fxsr()) {
6cd514
 		readmem(gxt->get_thread_struct_fpu(target), KVADDR, &xstate,
6cd514
-			gxt->get_thread_struct_fpu_size(),
6cd514
+			sizeof(xstate),
6cd514
 			"fpregs_get: xstate", gcore_verbose_error_handle());
6cd514
-		memcpy(buf, &xstate.fsave, sizeof(xstate.fsave));
6cd514
+		memcpy(buf, &xstate.fsave, MIN(size, sizeof(xstate.fsave)));
6cd514
 		return 0;
6cd514
 	}
6cd514
 
6cd514
@@ -562,6 +569,14 @@ static int fpregs_get(struct task_contex
6cd514
         return 0;
6cd514
 }
6cd514
 
6cd514
+static ulong gcore_x86_get_thread_struct_fpu_fpregs_state(struct task_context *tc)
6cd514
+{
6cd514
+	return tc->task +
6cd514
+		OFFSET(task_struct_thread) +
6cd514
+		GCORE_OFFSET(thread_struct_fpu) +
6cd514
+		GCORE_OFFSET(fpu_state);
6cd514
+}
6cd514
+
6cd514
 static ulong gcore_x86_get_thread_struct_fpu_thread_xstate(struct task_context *tc)
6cd514
 {
6cd514
 	ulong state;
6cd514
@@ -1010,6 +1025,26 @@ static int tsk_used_math_v11(ulong task)
6cd514
 	return !!(flags & PF_USED_MATH);
6cd514
 }
6cd514
 
6cd514
+static int tsk_used_math_v4_14(ulong task)
6cd514
+{
6cd514
+	unsigned char initialized;
6cd514
+
6cd514
+	if (!cpu_has_fxsr())
6cd514
+		return 0;
6cd514
+
6cd514
+	readmem(task +
6cd514
+		OFFSET(task_struct_thread) +
6cd514
+		GCORE_OFFSET(thread_struct_fpu) +
6cd514
+		MEMBER_OFFSET("fpu", "initialized"),
6cd514
+		KVADDR,
6cd514
+		&initialized,
6cd514
+		sizeof(initialized),
6cd514
+		"tsk_used_math_v4_14: initialized",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	return !!initialized;
6cd514
+}
6cd514
+
6cd514
 static inline int
6cd514
 user_mode(const struct user_regs_struct *regs)
6cd514
 {
6cd514
@@ -1331,6 +1366,23 @@ static inline void restore_rest(ulong ta
6cd514
 }
6cd514
 
6cd514
 /**
6cd514
+ * gcore_x86_64_get_old_rsp_zero() - get rsp at per-cpu area
6cd514
+ *
6cd514
+ * @cpu target CPU's CPU id
6cd514
+ *
6cd514
+ * Given a CPU id, returns a RSP value saved at per-cpu area for the
6cd514
+ * CPU whose id is the given CPU id.
6cd514
+ *
6cd514
+ * This is a method of get_old_rsp() returning always 0 for when no
6cd514
+ * appropriate method is found.
6cd514
+ */
6cd514
+static ulong gcore_x86_64_get_old_rsp_zero(int cpu)
6cd514
+{
6cd514
+	error(WARNING, "failed to detect location of sp register, forcing 0.\n");
6cd514
+	return 0UL;
6cd514
+}
6cd514
+
6cd514
+/**
6cd514
  * gcore_x86_64_get_old_rsp() - get rsp at per-cpu area
6cd514
  *
6cd514
  * @cpu target CPU's CPU id
6cd514
@@ -1421,6 +1473,50 @@ static ulong gcore_x86_64_get_cpu__pda_o
6cd514
 	return oldrsp;
6cd514
 }
6cd514
 
6cd514
+static ulong gcore_x86_64_user_stack_pointer_userrsp(struct task_context *tc)
6cd514
+{
6cd514
+	ulong usersp;
6cd514
+
6cd514
+	/*
6cd514
+	 * rsp is saved in per-CPU old_rsp, which is saved in
6cd514
+	 * thread->usersp at each context switch.
6cd514
+	 */
6cd514
+	if (is_task_active(tc->task))
6cd514
+		return gxt->get_old_rsp(tc->processor);
6cd514
+
6cd514
+	readmem(tc->task + OFFSET(task_struct_thread) +
6cd514
+		GCORE_OFFSET(thread_struct_usersp), KVADDR, &usersp,
6cd514
+		sizeof(usersp),
6cd514
+		"gcore_x86_64_user_stack_pointer_userrsp: usersp",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	return usersp;
6cd514
+}
6cd514
+
6cd514
+static ulong gcore_x86_64_user_stack_pointer_pt_regs(struct task_context *tc)
6cd514
+{
6cd514
+	char *pt_regs_buf;
6cd514
+	ulong sp0, sp;
6cd514
+	struct machine_specific *ms = machdep->machspec;
6cd514
+
6cd514
+	pt_regs_buf = GETBUF(SIZE(pt_regs));
6cd514
+
6cd514
+	readmem(tc->task + OFFSET(task_struct_thread) +
6cd514
+		GCORE_OFFSET(thread_struct_sp0), KVADDR, &sp0,
6cd514
+		sizeof(sp0),
6cd514
+		"gcore_x86_64_user_stack_pointer_pt_regs: sp0",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	readmem(sp0 - SIZE(pt_regs), KVADDR, pt_regs_buf, SIZE(pt_regs),
6cd514
+		"gcore_x86_64_user_stack_pointer_pt_regs: pt_regs",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	sp = ULONG(pt_regs_buf + ms->pto.rsp);
6cd514
+
6cd514
+	FREEBUF(pt_regs_buf);
6cd514
+	return sp;
6cd514
+}
6cd514
+
6cd514
 static int
6cd514
 gcore_find_regs_from_bt_output(FILE *output, char *buf, size_t bufsize)
6cd514
 {
6cd514
@@ -1648,18 +1744,8 @@ restore_regs_syscall_context(struct task
6cd514
 {
6cd514
 	const int nr_syscall = (int)regs->orig_ax;
6cd514
 
6cd514
-	/*
6cd514
-	 * rsp is saved in per-CPU old_rsp, which is saved in
6cd514
-	 * thread->usersp at each context switch.
6cd514
-	 */
6cd514
-	if (is_task_active(target->task)) {
6cd514
-		regs->sp = gxt->get_old_rsp(target->processor);
6cd514
-	} else {
6cd514
-		readmem(target->task + OFFSET(task_struct_thread) +
6cd514
-			GCORE_OFFSET(thread_struct_usersp), KVADDR, &regs->sp,
6cd514
-			sizeof(regs->sp),
6cd514
-			"genregs_get: usersp", gcore_verbose_error_handle());
6cd514
-	}
6cd514
+	if (gxt->user_stack_pointer)
6cd514
+		regs->sp = gxt->user_stack_pointer(target);
6cd514
 
6cd514
 	/*
6cd514
 	 * entire registers are saved for special system calls.
6cd514
@@ -1788,6 +1874,15 @@ static int genregs_get(struct task_conte
6cd514
 		      "system call instruction used could not be found\n");
6cd514
 	case GCORE_KERNEL_ENTRY_IRQ:
6cd514
 	case GCORE_KERNEL_ENTRY_INT80:
6cd514
+		/*
6cd514
+		 * The commit ff467594f2a4be01a0fa5e9ffc223fa930d232dd
6cd514
+		 * in the linux kernel begins saving all registers
6cd514
+		 * including callee-saved registers on the bottom of
6cd514
+		 * the kernel stack even on the IRQ entry. I'm very
6cd514
+		 * happy.
6cd514
+		 */
6cd514
+		if (THIS_KERNEL_VERSION < LINUX(4,2,0))
6cd514
+			restore_rest(target->task, regs, &active_regs);
6cd514
 		restore_rest(target->task, regs, &active_regs);
6cd514
 		restore_segment_registers(target->task, regs);
6cd514
 		break;
6cd514
@@ -1834,14 +1929,31 @@ static void gcore_x86_table_register_get
6cd514
 
6cd514
 	else if (symbol_exists("_cpu_pda"))
6cd514
 		gxt->get_old_rsp = gcore_x86_64_get_cpu__pda_oldrsp;
6cd514
+
6cd514
+	else
6cd514
+		gxt->get_old_rsp = gcore_x86_64_get_old_rsp_zero;
6cd514
+}
6cd514
+
6cd514
+static void gcore_x86_table_register_user_stack_pointer(void)
6cd514
+{
6cd514
+	if (MEMBER_EXISTS("thread_struct", "usersp") ||
6cd514
+	    MEMBER_EXISTS("thread_struct", "userrsp"))
6cd514
+		gxt->user_stack_pointer = gcore_x86_64_user_stack_pointer_userrsp;
6cd514
+
6cd514
+	else if (MEMBER_EXISTS("thread_struct", "sp0"))
6cd514
+		gxt->user_stack_pointer = gcore_x86_64_user_stack_pointer_pt_regs;
6cd514
 }
6cd514
 #endif
6cd514
 
6cd514
 static void gcore_x86_table_register_get_thread_struct_fpu(void)
6cd514
 {
6cd514
 	if (MEMBER_EXISTS("thread_struct", "fpu")) {
6cd514
-		gxt->get_thread_struct_fpu =
6cd514
-			gcore_x86_get_thread_struct_fpu_thread_xstate;
6cd514
+		if (MEMBER_OFFSET("fpu", "state") == 8)
6cd514
+			gxt->get_thread_struct_fpu =
6cd514
+				gcore_x86_get_thread_struct_fpu_thread_xstate;
6cd514
+		else
6cd514
+			gxt->get_thread_struct_fpu =
6cd514
+				gcore_x86_get_thread_struct_fpu_fpregs_state;
6cd514
 		gxt->get_thread_struct_fpu_size =
6cd514
 			gcore_x86_get_thread_struct_fpu_thread_xstate_size;
6cd514
 	} else if (MEMBER_EXISTS("thread_struct", "xstate")) {
6cd514
@@ -1900,7 +2012,9 @@ static void gcore_x86_table_register_is_
6cd514
  */
6cd514
 static void gcore_x86_table_register_tsk_used_math(void)
6cd514
 {
6cd514
-	if (GCORE_VALID_MEMBER(task_struct_used_math))
6cd514
+	if (MEMBER_EXISTS("fpu", "initialized"))
6cd514
+		gxt->tsk_used_math = tsk_used_math_v4_14;
6cd514
+	else if (GCORE_VALID_MEMBER(task_struct_used_math))
6cd514
 		gxt->tsk_used_math = tsk_used_math_v0;
6cd514
 	else
6cd514
 		gxt->tsk_used_math = tsk_used_math_v11;
6cd514
@@ -1911,6 +2025,7 @@ static void gcore_x86_table_register_tsk
6cd514
 void gcore_x86_table_init(void)
6cd514
 {
6cd514
 	gcore_x86_table_register_get_old_rsp();
6cd514
+	gcore_x86_table_register_user_stack_pointer();
6cd514
 	gcore_x86_table_register_get_thread_struct_fpu();
6cd514
 	gcore_x86_table_register_is_special_syscall();
6cd514
 	gcore_x86_table_register_is_special_ia32_syscall();
6cd514
@@ -2248,6 +2363,20 @@ ulong gcore_arch_get_gate_vma(void)
6cd514
 	if (gcore_is_arch_32bit_emulation(CURRENT_CONTEXT()))
6cd514
 		return 0UL;
6cd514
 
6cd514
+	if (symbol_exists("vsyscall_mode")) {
6cd514
+		enum { ENUMERATE, NONE } vsyscall_mode;
6cd514
+
6cd514
+		readmem(symbol_value("vsyscall_mode"),
6cd514
+			KVADDR,
6cd514
+			&vsyscall_mode,
6cd514
+			sizeof(vsyscall_mode),
6cd514
+			"gcore_arch_get_gate_vma: vsyscall_mode",
6cd514
+			gcore_verbose_error_handle());
6cd514
+
6cd514
+		if (vsyscall_mode == NONE)
6cd514
+			return 0UL;
6cd514
+	}
6cd514
+
6cd514
 	return symbol_value("gate_vma");
6cd514
 #else
6cd514
 	return 0UL;
6cd514
--- crash-gcore-command-1.3.1/libgcore/gcore_coredump.c.orig
6cd514
+++ crash-gcore-command-1.3.1/libgcore/gcore_coredump.c
6cd514
@@ -683,7 +683,7 @@ fill_prstatus_note(struct elf_note_info
6cd514
 		   struct memelfnote *memnote)
6cd514
 {
6cd514
 	struct elf_prstatus *prstatus;
6cd514
-#if defined(X86) || defined(X86_64) || defined(ARM) || defined(PPC64)
6cd514
+#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS) || defined(PPC64)
6cd514
 	struct user_regs_struct *regs = (struct user_regs_struct *)memnote->data;
6cd514
 #endif
6cd514
 #ifdef ARM64
6cd514
--- crash-gcore-command-1.3.1/libgcore/gcore_dumpfilter.c.orig
6cd514
+++ crash-gcore-command-1.3.1/libgcore/gcore_dumpfilter.c
6cd514
@@ -18,10 +18,61 @@
6cd514
 
6cd514
 static ulong dumpfilter = GCORE_DUMPFILTER_DEFAULT;
6cd514
 
6cd514
+static int special_mapping_name(ulong vma)
6cd514
+{
6cd514
+	ulong vm_private_data, name_p;
6cd514
+
6cd514
+	readmem(vma + GCORE_OFFSET(vm_area_struct_vm_private_data),
6cd514
+		KVADDR,
6cd514
+		&vm_private_data,
6cd514
+		sizeof(vm_private_data),
6cd514
+		"always_dump_vma: vma->vm_private_data",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	readmem(vm_private_data +
6cd514
+		GCORE_OFFSET(vm_special_mapping_name),
6cd514
+		KVADDR,
6cd514
+		&name_p,
6cd514
+		sizeof(name_p),
6cd514
+		"always_dump_vma: ((struct vm_special_mapping *)vma->vm_private_data)->name",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	return name_p ? TRUE : FALSE;
6cd514
+}
6cd514
+
6cd514
 static int always_dump_vma(ulong vma)
6cd514
 {
6cd514
 	if (vma == gcore_arch_get_gate_vma())
6cd514
 		return TRUE;
6cd514
+
6cd514
+	if (GCORE_VALID_MEMBER(vm_special_mapping_name)) {
6cd514
+		ulong vm_ops, name;
6cd514
+
6cd514
+		readmem(vma + GCORE_OFFSET(vm_area_struct_vm_ops),
6cd514
+			KVADDR,
6cd514
+			&vm_ops,
6cd514
+			sizeof(vm_ops),
6cd514
+			"always_dump_vma: vma->vm_ops",
6cd514
+			gcore_verbose_error_handle());
6cd514
+
6cd514
+		if (!vm_ops)
6cd514
+			goto out;
6cd514
+
6cd514
+		readmem(vm_ops + GCORE_OFFSET(vm_operations_struct_name),
6cd514
+			KVADDR,
6cd514
+			&name,
6cd514
+			sizeof(name),
6cd514
+			"always_dump_vma: vma->vm_ops->name",
6cd514
+			gcore_verbose_error_handle());
6cd514
+
6cd514
+		if (!name)
6cd514
+			goto out;
6cd514
+
6cd514
+		if (name == symbol_value("special_mapping_name"))
6cd514
+			return special_mapping_name(vma);
6cd514
+	}
6cd514
+out:
6cd514
+
6cd514
 	if (gcore_arch_vma_name(vma))
6cd514
 		return TRUE;
6cd514
 	return FALSE;
6cd514
--- crash-gcore-command-1.3.1/libgcore/gcore_defs.h.orig
6cd514
+++ crash-gcore-command-1.3.1/libgcore/gcore_defs.h
6cd514
@@ -94,6 +94,26 @@
6cd514
 #define Elf_Nhdr Elf32_Nhdr
6cd514
 #endif
6cd514
 
6cd514
+#ifdef MIPS
6cd514
+#define ELF_EXEC_PAGESIZE 4096
6cd514
+
6cd514
+#define ELF_MACHINE EM_MIPS
6cd514
+#define ELF_OSABI ELFOSABI_NONE
6cd514
+
6cd514
+#define ELF_CLASS ELFCLASS32
6cd514
+#define ELF_DATA ELFDATA2LSB
6cd514
+#define ELF_ARCH EM_MIPS
6cd514
+
6cd514
+#define Elf_Half Elf32_Half
6cd514
+#define Elf_Word Elf32_Word
6cd514
+#define Elf_Off Elf32_Off
6cd514
+
6cd514
+#define Elf_Ehdr Elf32_Ehdr
6cd514
+#define Elf_Phdr Elf32_Phdr
6cd514
+#define Elf_Shdr Elf32_Shdr
6cd514
+#define Elf_Nhdr Elf32_Nhdr
6cd514
+#endif
6cd514
+
6cd514
 #ifdef ARM64
6cd514
 #define ELF_EXEC_PAGESIZE PAGESIZE()
6cd514
 
6cd514
@@ -290,6 +310,11 @@ extern void gcore_default_regsets_init(v
6cd514
 #define REGSET_VIEW_MACHINE EM_AARCH64
6cd514
 #endif
6cd514
 
6cd514
+#ifdef MIPS
6cd514
+#define REGSET_VIEW_NAME "mips"
6cd514
+#define REGSET_VIEW_MACHINE EM_MIPS
6cd514
+#endif
6cd514
+
6cd514
 #ifdef PPC64
6cd514
 #define REGSET_VIEW_NAME "ppc64"
6cd514
 #define REGSET_VIEW_MACHINE EM_PPC64
6cd514
@@ -594,6 +619,12 @@ struct user_regs_struct32{
6cd514
 #endif /* GCORE_ARCH_COMPAT */
6cd514
 #endif
6cd514
 
6cd514
+#ifdef MIPS
6cd514
+struct user_regs_struct {
6cd514
+	unsigned long gregs[45];
6cd514
+};
6cd514
+#endif
6cd514
+
6cd514
 #ifdef PPC64
6cd514
 /* taken from asm/ptrace.h */
6cd514
 struct user_regs_struct {
6cd514
@@ -620,13 +651,13 @@ struct user_regs_struct {
6cd514
 };
6cd514
 #endif
6cd514
 
6cd514
-#if defined(X86) || defined(X86_64) || defined(ARM)
6cd514
+#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS)
6cd514
 typedef ulong elf_greg_t;
6cd514
 #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
6cd514
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
6cd514
 #endif
6cd514
 
6cd514
-#if defined(X86) || defined(ARM)
6cd514
+#if defined(X86) || defined(ARM) || defined(MIPS)
6cd514
 #define PAGE_SIZE 4096
6cd514
 #endif
6cd514
 #if defined(ARM64) || defined(PPC64)
6cd514
@@ -783,7 +814,7 @@ struct elf_prstatus
6cd514
 	int pr_fpvalid;		/* True if math co-processor being used.  */
6cd514
 };
6cd514
 
6cd514
-#if defined(X86) || defined(X86_64) || defined(ARM)
6cd514
+#if defined(X86) || defined(X86_64) || defined(ARM) || defined(MIPS)
6cd514
 typedef unsigned short __kernel_old_uid_t;
6cd514
 typedef unsigned short __kernel_old_gid_t;
6cd514
 #endif
6cd514
@@ -803,7 +834,7 @@ typedef __kernel_gid_t  __kernel_old_gid
6cd514
 typedef __kernel_old_uid_t      old_uid_t;
6cd514
 typedef __kernel_old_gid_t      old_gid_t;
6cd514
 
6cd514
-#if defined(X86) || defined(ARM)
6cd514
+#if defined(X86) || defined(ARM) || defined(MIPS)
6cd514
 typedef unsigned short __kernel_uid_t;
6cd514
 typedef unsigned short __kernel_gid_t;
6cd514
 #endif
6cd514
@@ -1070,6 +1101,7 @@ struct gcore_offset_table
6cd514
 	long thread_struct_gs;
6cd514
 	long thread_struct_gsindex;
6cd514
 	long thread_struct_i387;
6cd514
+	long thread_struct_sp0;
6cd514
 	long thread_struct_tls_array;
6cd514
 	long thread_struct_usersp;
6cd514
 	long thread_struct_xstate;
6cd514
@@ -1082,6 +1114,10 @@ struct gcore_offset_table
6cd514
 	long vfp_hard_struct_fpregs;
6cd514
 	long vfp_hard_struct_fpscr;
6cd514
 	long vm_area_struct_anon_vma;
6cd514
+	long vm_area_struct_vm_ops;
6cd514
+	long vm_area_struct_vm_private_data;
6cd514
+	long vm_operations_struct_name;
6cd514
+	long vm_special_mapping_name;
6cd514
 	long x8664_pda_oldrsp;
6cd514
 };
6cd514
 
6cd514
--- crash-gcore-command-1.3.1/libgcore/gcore_mips.c.orig
6cd514
+++ crash-gcore-command-1.3.1/libgcore/gcore_mips.c
6cd514
@@ -0,0 +1,159 @@
6cd514
+/* gcore_mips.c -- core analysis suite
6cd514
+ *
6cd514
+ * Copyright (C) 2016 Axis Communications
6cd514
+ *
6cd514
+ * This program is free software; you can redistribute it and/or modify
6cd514
+ * it under the terms of the GNU General Public License as published by
6cd514
+ * the Free Software Foundation; either version 2 of the License, or
6cd514
+ * (at your option) any later version.
6cd514
+ *
6cd514
+ * This program is distributed in the hope that it will be useful,
6cd514
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6cd514
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6cd514
+ * GNU General Public License for more details.
6cd514
+ */
6cd514
+#if defined(MIPS)
6cd514
+
6cd514
+#include "defs.h"
6cd514
+#include <gcore_defs.h>
6cd514
+#include <stdint.h>
6cd514
+#include <elf.h>
6cd514
+#include <asm/ldt.h>
6cd514
+
6cd514
+#define MIPS32_EF_R0		6
6cd514
+#define MIPS32_EF_R1		7
6cd514
+#define MIPS32_EF_R26		32
6cd514
+#define MIPS32_EF_R27		33
6cd514
+#define MIPS32_EF_R31		37
6cd514
+#define MIPS32_EF_LO		38
6cd514
+#define MIPS32_EF_HI		39
6cd514
+#define MIPS32_EF_CP0_EPC	40
6cd514
+#define MIPS32_EF_CP0_BADVADDR	41
6cd514
+#define MIPS32_EF_CP0_STATUS	42
6cd514
+#define MIPS32_EF_CP0_CAUSE	43
6cd514
+
6cd514
+static int gpr_get(struct task_context *target,
6cd514
+		       const struct user_regset *regset,
6cd514
+		       unsigned int size, void *buf)
6cd514
+{
6cd514
+	static int once;
6cd514
+	struct user_regs_struct *regs = buf;
6cd514
+	struct mips_pt_regs_main *mains;
6cd514
+	struct mips_pt_regs_cp0 *cp0;
6cd514
+	char pt_regs[SIZE(pt_regs)];
6cd514
+	int i;
6cd514
+
6cd514
+	/*
6cd514
+	 * All registers are saved in thread_info.regs only on certain types of
6cd514
+	 * entries to the kernel (such as abort handling).  For other types of
6cd514
+	 * entries (such as system calls), only a subset of the registers are
6cd514
+	 * saved on entry and the rest are saved on the stack according to the
6cd514
+	 * ABI's calling conventions.  To always get the full register set we
6cd514
+	 * would have to unwind the stack and find where the registers are by
6cd514
+	 * using DWARF information.  We don't have an implementation for this
6cd514
+	 * right now so warn to avoid misleading the user.  Only warn since
6cd514
+	 * this function is called multiple times even for a single invocation
6cd514
+	 * of the gcore command.
6cd514
+	 */
6cd514
+	if (!once) {
6cd514
+		once = 1;
6cd514
+		error(WARNING, "WARNING: Current register values may be inaccurate\n");
6cd514
+	}
6cd514
+
6cd514
+	readmem(machdep->get_stacktop(target->task) - 32 - SIZE(pt_regs),
6cd514
+		KVADDR, pt_regs, SIZE(pt_regs), "genregs_get: pt_regs",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	mains = (struct mips_pt_regs_main *) (pt_regs + OFFSET(pt_regs_regs));
6cd514
+	cp0 = (struct mips_pt_regs_cp0 *) \
6cd514
+	      (pt_regs + OFFSET(pt_regs_cp0_badvaddr));
6cd514
+
6cd514
+	BZERO(regs, sizeof(*regs));
6cd514
+
6cd514
+	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
6cd514
+		/* k0/k1 are copied as zero. */
6cd514
+		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
6cd514
+			continue;
6cd514
+
6cd514
+		regs->gregs[i] = mains->regs[i - MIPS32_EF_R0];
6cd514
+	}
6cd514
+
6cd514
+	regs->gregs[MIPS32_EF_LO] = mains->lo;
6cd514
+	regs->gregs[MIPS32_EF_HI] = mains->hi;
6cd514
+	regs->gregs[MIPS32_EF_CP0_EPC] = cp0->cp0_epc;
6cd514
+	regs->gregs[MIPS32_EF_CP0_BADVADDR] = cp0->cp0_badvaddr;
6cd514
+	regs->gregs[MIPS32_EF_CP0_STATUS] = mains->cp0_status;
6cd514
+	regs->gregs[MIPS32_EF_CP0_CAUSE] = cp0->cp0_cause;
6cd514
+
6cd514
+	return 0;
6cd514
+}
6cd514
+
6cd514
+enum gcore_regset {
6cd514
+	REGSET_GPR,
6cd514
+};
6cd514
+
6cd514
+static struct user_regset mips_regsets[] = {
6cd514
+	[REGSET_GPR] = {
6cd514
+		.core_note_type = NT_PRSTATUS,
6cd514
+		.name = "CORE",
6cd514
+		.size = ELF_NGREG * sizeof(unsigned int),
6cd514
+		.get = gpr_get,
6cd514
+	},
6cd514
+};
6cd514
+
6cd514
+#ifndef ARRAY_SIZE
6cd514
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
6cd514
+#endif
6cd514
+
6cd514
+static const struct user_regset_view mips_regset_view = {
6cd514
+	.name = "mips",
6cd514
+	.regsets = mips_regsets,
6cd514
+	.n = ARRAY_SIZE(mips_regsets),
6cd514
+	.e_machine = EM_MIPS,
6cd514
+};
6cd514
+
6cd514
+const struct user_regset_view *
6cd514
+task_user_regset_view(void)
6cd514
+{
6cd514
+	return &mips_regset_view;
6cd514
+}
6cd514
+
6cd514
+int gcore_is_arch_32bit_emulation(struct task_context *tc)
6cd514
+{
6cd514
+	return FALSE;
6cd514
+}
6cd514
+
6cd514
+ulong gcore_arch_get_gate_vma(void)
6cd514
+{
6cd514
+	return 0UL;
6cd514
+}
6cd514
+
6cd514
+char *gcore_arch_vma_name(ulong vma)
6cd514
+{
6cd514
+	ulong mm, vm_start, vdso;
6cd514
+
6cd514
+	readmem(vma + OFFSET(vm_area_struct_vm_mm), KVADDR, &mm, sizeof(mm),
6cd514
+		"gcore_arch_vma_name: vma->vm_mm",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	readmem(vma + OFFSET(vm_area_struct_vm_start), KVADDR, &vm_start,
6cd514
+		sizeof(vm_start), "gcore_arch_vma_name: vma->vm_start",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	readmem(mm + GCORE_OFFSET(mm_struct_context) +
6cd514
+		GCORE_OFFSET(mm_context_t_vdso), KVADDR, &vdso,
6cd514
+		sizeof(vdso), "gcore_arch_vma_name: mm->context.vdso",
6cd514
+		gcore_verbose_error_handle());
6cd514
+
6cd514
+	if (mm && vm_start == vdso)
6cd514
+		return "[vdso]";
6cd514
+
6cd514
+	return NULL;
6cd514
+}
6cd514
+
6cd514
+int gcore_arch_vsyscall_has_vm_alwaysdump_flag(void)
6cd514
+{
6cd514
+	return FALSE;
6cd514
+}
6cd514
+
6cd514
+#endif /* defined(MIPS) */
6cd514
--- crash-gcore-command-1.3.1/gcore.c.orig
6cd514
+++ crash-gcore-command-1.3.1/gcore.c
6cd514
@@ -463,10 +463,16 @@ static void gcore_offset_table_init(void
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_info_vfpstate, "thread_info", "vfpstate");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_ds, "thread_struct", "ds");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_es, "thread_struct", "es");
6cd514
-	GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fs");
6cd514
+	if (MEMBER_EXISTS("thread_struct", "fs"))
6cd514
+		GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fs");
6cd514
+	else
6cd514
+		GCORE_MEMBER_OFFSET_INIT(thread_struct_fs, "thread_struct", "fsbase");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_fsindex, "thread_struct", "fsindex");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_fpu, "thread_struct", "fpu");
6cd514
-	GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gs");
6cd514
+	if (MEMBER_EXISTS("thread_struct", "gs"))
6cd514
+		GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gs");
6cd514
+	else
6cd514
+		GCORE_MEMBER_OFFSET_INIT(thread_struct_gs, "thread_struct", "gsbase");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_gsindex, "thread_struct", "gsindex");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_i387, "thread_struct", "i387");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_tls_array, "thread_struct", "tls_array");
6cd514
@@ -474,6 +480,7 @@ static void gcore_offset_table_init(void
6cd514
 		GCORE_MEMBER_OFFSET_INIT(thread_struct_usersp, "thread_struct", "usersp");
6cd514
 	else if (MEMBER_EXISTS("thread_struct", "userrsp"))
6cd514
 		GCORE_MEMBER_OFFSET_INIT(thread_struct_usersp, "thread_struct", "userrsp");
6cd514
+	GCORE_MEMBER_OFFSET_INIT(thread_struct_sp0, "thread_struct", "sp0");
6cd514
 	if (MEMBER_EXISTS("thread_struct", "xstate"))
6cd514
 		GCORE_MEMBER_OFFSET_INIT(thread_struct_xstate, "thread_struct", "xstate");
6cd514
 	else if (MEMBER_EXISTS("thread_struct", "i387"))
6cd514
@@ -482,6 +489,10 @@ static void gcore_offset_table_init(void
6cd514
 	GCORE_MEMBER_OFFSET_INIT(thread_struct_io_bitmap_ptr, "thread_struct", "io_bitmap_ptr");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(user_regset_n, "user_regset", "n");
6cd514
 	GCORE_MEMBER_OFFSET_INIT(vm_area_struct_anon_vma, "vm_area_struct", "anon_vma");
6cd514
+	GCORE_MEMBER_OFFSET_INIT(vm_area_struct_vm_ops, "vm_area_struct", "vm_ops");
6cd514
+	GCORE_MEMBER_OFFSET_INIT(vm_area_struct_vm_private_data, "vm_area_struct", "vm_private_data");
6cd514
+	GCORE_MEMBER_OFFSET_INIT(vm_operations_struct_name, "vm_operations_struct", "name");
6cd514
+	GCORE_MEMBER_OFFSET_INIT(vm_special_mapping_name, "vm_special_mapping", "name");
6cd514
 
6cd514
 	if (symbol_exists("_cpu_pda"))
6cd514
 		GCORE_MEMBER_OFFSET_INIT(x8664_pda_oldrsp, "x8664_pda", "oldrsp");
6cd514
@@ -499,9 +510,15 @@ static void gcore_size_table_init(void)
6cd514
 	GCORE_MEMBER_SIZE_INIT(mm_struct_saved_auxv, "mm_struct", "saved_auxv");
6cd514
 	GCORE_MEMBER_SIZE_INIT(thread_struct_ds, "thread_struct", "ds");
6cd514
 	GCORE_MEMBER_SIZE_INIT(thread_struct_es, "thread_struct", "es");
6cd514
-	GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fs");
6cd514
+	if (MEMBER_EXISTS("thread_struct", "fs"))
6cd514
+		GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fs");
6cd514
+	else
6cd514
+		GCORE_MEMBER_SIZE_INIT(thread_struct_fs, "thread_struct", "fsbase");
6cd514
 	GCORE_MEMBER_SIZE_INIT(thread_struct_fsindex, "thread_struct", "fsindex");
6cd514
-	GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gs");
6cd514
+	if (MEMBER_EXISTS("thread_struct", "gs"))
6cd514
+		GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gs");
6cd514
+	else
6cd514
+		GCORE_MEMBER_SIZE_INIT(thread_struct_gs, "thread_struct", "gsbase");
6cd514
 	GCORE_MEMBER_SIZE_INIT(thread_struct_gsindex, "thread_struct", "gsindex");
6cd514
 	GCORE_MEMBER_SIZE_INIT(thread_struct_tls_array, "thread_struct", "tls_array");
6cd514
 	GCORE_STRUCT_SIZE_INIT(thread_xstate, "thread_xstate");
6cd514
--- crash-gcore-command-1.3.1/gcore.mk.orig
6cd514
+++ crash-gcore-command-1.3.1/gcore.mk
6cd514
@@ -12,9 +12,9 @@
6cd514
 # GNU General Public License for more details.
6cd514
 #
6cd514
 
6cd514
-VERSION=1.3.1
6cd514
-DATE=6 Nov 2014
6cd514
-PERIOD=2010, 2011, 2012, 2013, 2014
6cd514
+VERSION=1.5.0
6cd514
+DATE=30 Nov 2018
6cd514
+PERIOD=2010, 2011, 2012, 2013, 2014, 2016, 2017, 2018
6cd514
 
6cd514
 ARCH=UNSUPPORTED
6cd514
 
6cd514
@@ -42,6 +42,12 @@ ifeq ($(shell arch), aarch64)
6cd514
   ARCH=SUPPORTED
6cd514
 endif
6cd514
 
6cd514
+ifeq ($(shell arch), mips)
6cd514
+  TARGET=MIPS
6cd514
+  TARGET_CFLAGS=
6cd514
+  ARCH=SUPPORTED
6cd514
+endif
6cd514
+
6cd514
 ifeq ($(shell arch), ppc64)
6cd514
   TARGET=PPC64
6cd514
   TARGET_CFLAGS=
6cd514
@@ -85,6 +91,10 @@ ifneq (,$(findstring $(TARGET), ARM64))
6cd514
 GCORE_CFILES += libgcore/gcore_arm64.c
6cd514
 endif
6cd514
 
6cd514
+ifneq (,$(findstring $(TARGET), MIPS))
6cd514
+GCORE_CFILES += libgcore/gcore_mips.c
6cd514
+endif
6cd514
+
6cd514
 ifneq (,$(findstring $(TARGET), PPC64))
6cd514
 GCORE_CFILES += libgcore/gcore_ppc64.c
6cd514
 endif