[Crash-utility] gcore: Add MIPS support

Hatayama, Daisuke d.hatayama at jp.fujitsu.com
Mon Feb 27 05:55:15 UTC 2017


Rabin,

Sorry for my very delayed response.

Thanks for your patch set.
I'll include the patch set in the next version and release it soon.

By the way, please note that I can develop x86 codes only.
I cannot test the MIPS codes at all and this is the same policy as for other architectures.

If you want to keep quality of the MIPS codes good,
please test and fix the MIPS codes at each release and send the corresponding patch set to me.

> -----Original Message-----
> From: crash-utility-bounces at redhat.com
> [mailto:crash-utility-bounces at redhat.com] On Behalf Of Dave Anderson
> Sent: Tuesday, December 27, 2016 10:35 PM
> To: Discussion list for crash utility usage, maintenance and development
> <crash-utility at redhat.com>
> Cc: Rabin Vincent <rabinv at axis.com>
> Subject: Re: [Crash-utility] [PATCH] gcore: Add MIPS support
> 
> 
> Hi Rabin,
> 
> I forwarded your post directly to Daisuke Hatayama for review.
> 
> Thanks,
>   Dave
> 
> ----- Original Message -----
> > From: Rabin Vincent <rabinv at axis.com>
> >
> > This adds basic support for MIPS to the gcore extension.
> > ---
> >  gcore.mk                  |  10 +++
> >  libgcore/gcore_coredump.c |   2 +-
> >  libgcore/gcore_defs.h     |  39 ++++++++++--
> >  libgcore/gcore_mips.c     | 159
> >  ++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 205 insertions(+), 5 deletions(-)
> >  create mode 100644 libgcore/gcore_mips.c
> >
> > diff --git a/gcore.mk b/gcore.mk
> > index c9683d4..ffc9ce7 100644
> > --- a/gcore.mk
> > +++ b/gcore.mk
> > @@ -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/libgcore/gcore_coredump.c b/libgcore/gcore_coredump.c
> > index 892ddf9..e91f29a 100644
> > --- a/libgcore/gcore_coredump.c
> > +++ b/libgcore/gcore_coredump.c
> > @@ -683,7 +683,7 @@ fill_prstatus_note(struct elf_note_info *info, struct
> > task_context *tc,
> >  		   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
> > diff --git a/libgcore/gcore_defs.h b/libgcore/gcore_defs.h
> > index ba1fde2..6fdb943 100644
> > --- a/libgcore/gcore_defs.h
> > +++ b/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(void);
> >  #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_t;
> >  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
> > diff --git a/libgcore/gcore_mips.c b/libgcore/gcore_mips.c
> > new file mode 100644
> > index 0000000..be67d51
> > --- /dev/null
> > +++ b/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 <gcore_defs.h>
> > +#include <stdint.h>
> > +#include <elf.h>
> > +#include <asm/ldt.h>
> > +
> > +#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) */
> > --
> > 2.1.4
> >
> > --
> > Crash-utility mailing list
> > Crash-utility at redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
> >
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility




More information about the Crash-utility mailing list