Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
To: Fredrik Hederstierna <fredrik@hederstierna.com>,
	gdb-patches@sourceware.org, simark@simark.ca,
	Alan.Hayward@arm.com, paulmathieu@google.com
Subject: Re: [PATCH v2] Support for corefiles for arm-none-eabi target.
Date: Wed, 21 Oct 2020 11:38:17 -0300	[thread overview]
Message-ID: <45149673-46bb-d32f-b413-5c72739ef074@linaro.org> (raw)
In-Reply-To: <20201020215817.25264-1-fredrik@hederstierna.com>

Hi,

Apologies for the delay in replying.

I think this still needs some more work to cut it down to the bare 
essentials for a core file. I see quite a few things that are 
linux-specific and that shouldn't be included in a potential all-arch 
bare-metal core file format.

As Simon said, siginfo and auxv are *nix concepts.  HWCAP_* constants 
are also *nix/Linux concepts. So those should be dropped unless there is 
good reason to include them.

If we require some of their data, then we should think of a way to make 
that available. For example, AUXV's entry point information.

We should really discuss what the generic core file format for 
bare-metal targets will look like before having a possible patch to 
implement it. At least that's my take on it.

Otherwise we risk having an implementation without a formal definition. 
And core files are already somewhat vaguely-defined anyway.

On 10/20/20 6:58 PM, Fredrik Hederstierna wrote:
> From: fredrikhederstierna <fredrik@hederstierna.com>
> 
> ---
>   gdb/arm-none-tdep.c | 368 ++++++++++++++++++++++++++++++++++++++++++++
>   gdb/arm-none-tdep.h |  60 ++++++++
>   gdb/arm-tdep.c      |   8 +
>   gdb/configure.tgt   |   6 +-
>   gdb/none-tdep.c     | 335 ++++++++++++++++++++++++++++++++++++++++
>   gdb/none-tdep.h     |  39 +++++
>   6 files changed, 815 insertions(+), 1 deletion(-)
>   create mode 100644 gdb/arm-none-tdep.c
>   create mode 100644 gdb/arm-none-tdep.h
>   create mode 100644 gdb/none-tdep.c
>   create mode 100644 gdb/none-tdep.h
> 
> diff --git a/gdb/arm-none-tdep.c b/gdb/arm-none-tdep.c
> new file mode 100644
> index 0000000000..9d83a8b913
> --- /dev/null
> +++ b/gdb/arm-none-tdep.c
> @@ -0,0 +1,368 @@
> +/* none on ARM target support.
> +
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   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 3 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.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "defs.h"
> +#include "target.h"
> +#include "value.h"
> +#include "gdbtypes.h"
> +#include "gdbcore.h"
> +#include "frame.h"
> +#include "regcache.h"
> +#include "solib-svr4.h"
> +#include "osabi.h"
> +#include "regset.h"
> +#include "trad-frame.h"
> +#include "tramp-frame.h"
> +#include "breakpoint.h"
> +#include "auxv.h"
> +
> +#include "aarch32-tdep.h"
> +#include "arch/arm.h"
> +#include "arm-tdep.h"
> +#include "arm-none-tdep.h"
> +#include "glibc-tdep.h"
> +#include "arch-utils.h"
> +#include "inferior.h"
> +#include "gdbthread.h"
> +#include "symfile.h"
> +
> +#include "cli/cli-utils.h"
> +#include "stap-probe.h"
> +#include "parser-defs.h"
> +#include "user-regs.h"
> +#include <ctype.h>
> +
> +#include "elf-bfd.h"
> +#include "coff/internal.h"
> +#include "elf/arm.h"
> +
> +#include "elf/common.h"
> +
> +/* ---- based on arm-linux-tdep.h ---- */
> +
> +#define ARM_NONE_SIZEOF_NWFPE (8 * ARM_FP_REGISTER_SIZE \
> +				+ 2 * ARM_INT_REGISTER_SIZE \
> +				+ 8 + ARM_INT_REGISTER_SIZE)
> +
> +/* The index to access CSPR in user_regs defined in GLIBC.  */
> +#define ARM_CPSR_GREGNUM 16
> +
> +/* Support for register format used by the NWFPE FPA emulator.  Each
> +   register takes three words, where either the first one, two, or
> +   three hold a single, double, or extended precision value (depending
> +   on the corresponding tag).  The register set is eight registers,
> +   followed by the fpsr and fpcr, followed by eight tag bytes, and a
> +   final word flag which indicates whether NWFPE has been
> +   initialized.  */
> +
> +#define NWFPE_FPSR_OFFSET (8 * ARM_FP_REGISTER_SIZE)
> +#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + ARM_INT_REGISTER_SIZE)
> +#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + ARM_INT_REGISTER_SIZE)
> +#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8)
> +
> +/* Reuse ARM GNU/Linux HWCAP values for none.  These are in defined in
> +   <asm/elf.h> in current kernels.  */
> +#define HWCAP_VFP       64
> +#define HWCAP_IWMMXT    512
> +#define HWCAP_NEON      4096
> +#define HWCAP_VFPv3     8192
> +#define HWCAP_VFPv3D16  16384
> +
> +/* Core file and register set support.  */
> +
> +#define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE)
> +
> +/* ---- based on arm-linux-tdep.c ---- */
> +
> +void
> +arm_none_supply_gregset (const struct regset *regset,
> +			  struct regcache *regcache,
> +			  int regnum, const void *gregs_buf, size_t len)
> +{
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  const gdb_byte *gregs = (const gdb_byte *) gregs_buf;
> +  int regno;
> +  CORE_ADDR reg_pc;
> +  gdb_byte pc_buf[ARM_INT_REGISTER_SIZE];
> +
> +  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno);
> +
> +  if (regnum == ARM_PS_REGNUM || regnum == -1)
> +    {
> +      if (arm_apcs_32)
> +	regcache->raw_supply (ARM_PS_REGNUM,
> +			      gregs + ARM_INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
> +      else
> +	regcache->raw_supply (ARM_PS_REGNUM,
> +			     gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
> +    }
> +
> +  if (regnum == ARM_PC_REGNUM || regnum == -1)
> +    {
> +      reg_pc = extract_unsigned_integer (
> +		 gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM,
> +		 ARM_INT_REGISTER_SIZE, byte_order);
> +      reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
> +      store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order,
> +			      reg_pc);
> +      regcache->raw_supply (ARM_PC_REGNUM, pc_buf);
> +    }
> +}
> +
> +void
> +arm_none_collect_gregset (const struct regset *regset,
> +			   const struct regcache *regcache,
> +			   int regnum, void *gregs_buf, size_t len)
> +{
> +  gdb_byte *gregs = (gdb_byte *) gregs_buf;
> +  int regno;
> +
> +  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache->raw_collect (regno,
> +			    gregs + ARM_INT_REGISTER_SIZE * regno);
> +
> +  if (regnum == ARM_PS_REGNUM || regnum == -1)
> +    {
> +      if (arm_apcs_32)
> +	regcache->raw_collect (ARM_PS_REGNUM,
> +			      gregs + ARM_INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
> +      else
> +	regcache->raw_collect (ARM_PS_REGNUM,
> +			      gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
> +    }
> +
> +  if (regnum == ARM_PC_REGNUM || regnum == -1)
> +    regcache->raw_collect (ARM_PC_REGNUM,
> +			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
> +}
> +
> +/* Support for register format used by the NWFPE FPA emulator.  */
> +
> +#define typeNone		0x00
> +#define typeSingle		0x01
> +#define typeDouble		0x02
> +#define typeExtended		0x03
> +
> +void
> +arm_none_supply_nwfpe_register (struct regcache *regcache, int regno,
> +				const gdb_byte *regs)
> +{
> +  const gdb_byte *reg_data;
> +  gdb_byte reg_tag;
> +  gdb_byte buf[ARM_FP_REGISTER_SIZE];
> +
> +  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
> +  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
> +  memset (buf, 0, ARM_FP_REGISTER_SIZE);
> +
> +  switch (reg_tag)
> +    {
> +    case typeSingle:
> +      memcpy (buf, reg_data, 4);
> +      break;
> +    case typeDouble:
> +      memcpy (buf, reg_data + 4, 4);
> +      memcpy (buf + 4, reg_data, 4);
> +      break;
> +    case typeExtended:
> +      /* We want sign and exponent, then least significant bits,
> +	 then most significant.  NWFPE does sign, most, least.  */
> +      memcpy (buf, reg_data, 4);
> +      memcpy (buf + 4, reg_data + 8, 4);
> +      memcpy (buf + 8, reg_data + 4, 4);
> +      break;
> +    default:
> +      break;
> +    }
> +
> +  regcache->raw_supply (regno, buf);
> +}
> +
> +void
> +arm_none_collect_nwfpe_register (const struct regcache *regcache, int regno,
> +				 gdb_byte *regs)
> +{
> +  gdb_byte *reg_data;
> +  gdb_byte reg_tag;
> +  gdb_byte buf[ARM_FP_REGISTER_SIZE];
> +
> +  regcache->raw_collect (regno, buf);
> +
> +  /* NOTE drow/2006-06-07: This code uses the tag already in the
> +     register buffer.  I've preserved that when moving the code
> +     from the native file to the target file.  But this doesn't
> +     always make sense.  */
> +
> +  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
> +  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
> +
> +  switch (reg_tag)
> +    {
> +    case typeSingle:
> +      memcpy (reg_data, buf, 4);
> +      break;
> +    case typeDouble:
> +      memcpy (reg_data, buf + 4, 4);
> +      memcpy (reg_data + 4, buf, 4);
> +      break;
> +    case typeExtended:
> +      memcpy (reg_data, buf, 4);
> +      memcpy (reg_data + 4, buf + 8, 4);
> +      memcpy (reg_data + 8, buf + 4, 4);
> +      break;
> +    default:
> +      break;
> +    }
> +}
> +
> +void
> +arm_none_supply_nwfpe (const struct regset *regset,
> +			struct regcache *regcache,
> +			int regnum, const void *regs_buf, size_t len)
> +{
> +  const gdb_byte *regs = (const gdb_byte *) regs_buf;
> +  int regno;
> +
> +  if (regnum == ARM_FPS_REGNUM || regnum == -1)
> +    regcache->raw_supply (ARM_FPS_REGNUM,
> +			 regs + NWFPE_FPSR_OFFSET);
> +
> +  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      arm_none_supply_nwfpe_register (regcache, regno, regs);
> +}
> +
> +void
> +arm_none_collect_nwfpe (const struct regset *regset,
> +			 const struct regcache *regcache,
> +			 int regnum, void *regs_buf, size_t len)
> +{
> +  gdb_byte *regs = (gdb_byte *) regs_buf;
> +  int regno;
> +
> +  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      arm_none_collect_nwfpe_register (regcache, regno, regs);
> +
> +  if (regnum == ARM_FPS_REGNUM || regnum == -1)
> +    regcache->raw_collect (ARM_FPS_REGNUM,
> +			   regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM);
> +}
> +
> +/* Support VFP register format.  */
> +
> +#define ARM_NONE_SIZEOF_VFP (32 * 8 + 4)
> +
> +static void
> +arm_none_supply_vfp (const struct regset *regset,
> +		      struct regcache *regcache,
> +		      int regnum, const void *regs_buf, size_t len)
> +{
> +  const gdb_byte *regs = (const gdb_byte *) regs_buf;
> +  int regno;
> +
> +  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
> +    regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8);
> +
> +  for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8);
> +}
> +
> +static void
> +arm_none_collect_vfp (const struct regset *regset,
> +			 const struct regcache *regcache,
> +			 int regnum, void *regs_buf, size_t len)
> +{
> +  gdb_byte *regs = (gdb_byte *) regs_buf;
> +  int regno;
> +
> +  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
> +    regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8);
> +
> +  for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8);
> +}
> +
> +static const struct regset arm_none_gregset =
> +  {
> +    NULL, arm_none_supply_gregset, arm_none_collect_gregset
> +  };
> +
> +static const struct regset arm_none_fpregset =
> +  {
> +    NULL, arm_none_supply_nwfpe, arm_none_collect_nwfpe
> +  };
> +
> +static const struct regset arm_none_vfpregset =
> +  {
> +    NULL, arm_none_supply_vfp, arm_none_collect_vfp
> +  };
> +
> +/* Iterate over core file register note sections.  */
> +
> +void
> +arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch,
> +					iterate_over_regset_sections_cb *cb,
> +					void *cb_data,
> +					const struct regcache *regcache)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> +  cb (".reg", ARM_NONE_SIZEOF_GREGSET, ARM_NONE_SIZEOF_GREGSET,
> +	&arm_none_gregset, NULL, cb_data);
> +
> +  if (tdep->vfp_register_count > 0)
> +    cb (".reg-arm-vfp", ARM_NONE_SIZEOF_VFP, ARM_NONE_SIZEOF_VFP,
> +	&arm_none_vfpregset, "VFP floating-point", cb_data);
> +  else if (tdep->have_fpa_registers)
> +    cb (".reg2", ARM_NONE_SIZEOF_NWFPE, ARM_NONE_SIZEOF_NWFPE,
> +	&arm_none_fpregset, "FPA floating-point", cb_data);
> +}
> +
> +/* Determine target description from core file.  */
> +
> +const struct target_desc *
> +arm_none_core_read_description (struct gdbarch *gdbarch,
> +				struct target_ops *target,
> +				bfd *abfd)
> +{
> +  CORE_ADDR arm_hwcap = 0;
> +  if (target_auxv_search (target, AT_HWCAP, &arm_hwcap) != 1)
> +    return nullptr;
> +
> +  if (arm_hwcap & HWCAP_VFP)
> +    {
> +      /* NEON implies VFPv3-D32 or no-VFP unit.  Say that we only support
> +         Neon with VFPv3-D32.  */
> +      if (arm_hwcap & HWCAP_NEON)
> +	return aarch32_read_description ();
> +      else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
> +	return arm_read_description (ARM_FP_TYPE_VFPV3);
> +
> +      return arm_read_description (ARM_FP_TYPE_VFPV2);
> +    }
> +
> +  return nullptr;
> +}
> diff --git a/gdb/arm-none-tdep.h b/gdb/arm-none-tdep.h
> new file mode 100644
> index 0000000000..7927c0aff3
> --- /dev/null
> +++ b/gdb/arm-none-tdep.h
> @@ -0,0 +1,60 @@
> +/* none on ARM target support, prototypes.
> +
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   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 3 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.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef ARM_NONE_TDEP_H
> +#define ARM_NONE_TDEP_H
> +
> +#include "gdbarch.h"
> +#include "target.h"
> +#include "bfd.h"
> +
> +struct regset;
> +struct regcache;
> +
> +void arm_none_supply_gregset (const struct regset *regset,
> +			       struct regcache *regcache,
> +			       int regnum, const void *gregs_buf, size_t len);
> +void arm_none_collect_gregset (const struct regset *regset,
> +				const struct regcache *regcache,
> +				int regnum, void *gregs_buf, size_t len);
> +
> +void arm_none_supply_nwfpe_register (struct regcache *regcache, int regno,
> +				     const gdb_byte *regs);
> +void arm_none_collect_nwfpe_register (const struct regcache *regcache, int regno,
> +				      gdb_byte *regs);
> +
> +void arm_none_supply_nwfpe (const struct regset *regset,
> +			     struct regcache *regcache,
> +			     int regnum, const void *regs_buf, size_t len);
> +void arm_none_collect_nwfpe (const struct regset *regset,
> +			      const struct regcache *regcache,
> +			      int regnum, void *regs_buf, size_t len);
> +
> +void
> +arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch,
> +                                       iterate_over_regset_sections_cb *cb,
> +                                       void *cb_data,
> +                                       const struct regcache *regcache);
> +
> +const struct target_desc *
> +arm_none_core_read_description (struct gdbarch *gdbarch,
> +				struct target_ops *target,
> +				bfd *abfd);
> +
> +#endif /* ARM_NONE_TDEP_H */
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index a214f22d7a..be47cc2228 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -50,6 +50,8 @@
>   #include "arch/arm.h"
>   #include "arch/arm-get-next-pcs.h"
>   #include "arm-tdep.h"
> +#include "none-tdep.h"
> +#include "arm-none-tdep.h"
>   #include "gdb/sim-arm.h"
>   
>   #include "elf-bfd.h"
> @@ -9453,6 +9455,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>     /* Virtual tables.  */
>     set_gdbarch_vbit_in_delta (gdbarch, 1);
>   
> +  /* Default none core file support, can be overridden by osabi. */
> +  none_init_corefile (info, gdbarch);
> +  set_gdbarch_iterate_over_regset_sections (gdbarch,
> +                                            arm_none_iterate_over_regset_sections);
> +  set_gdbarch_core_read_description (gdbarch, arm_none_core_read_description);
> +
>     /* Hook in the ABI-specific overrides, if they have been registered.  */
>     gdbarch_init_osabi (info, gdbarch);
>   
> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
> index d865ecdcb6..f4a1540464 100644
> --- a/gdb/configure.tgt
> +++ b/gdb/configure.tgt
> @@ -64,7 +64,8 @@ arc*-*-*)
>   
>   arm*-*-*)
>   	cpu_obs="aarch32-tdep.o arch/aarch32.o arch/arm.o \
> -		 arch/arm-get-next-pcs.o arm-tdep.o";;
> +		 arch/arm-get-next-pcs.o arm-tdep.o \
> +		 none-tdep.o arm-none-tdep.o";;
>   
>   hppa*-*-*)
>   	# Target: HP PA-RISC
> @@ -798,4 +799,7 @@ for t in x ${gdb_target_obs}; do
>     if test "$t" = linux-tdep.o; then
>       gdb_have_gcore=true
>     fi
> +  if test "$t" = arm-none-tdep.o; then
> +    gdb_have_gcore=true
> +  fi
>   done
> diff --git a/gdb/none-tdep.c b/gdb/none-tdep.c
> new file mode 100644
> index 0000000000..5ac5c6c707
> --- /dev/null
> +++ b/gdb/none-tdep.c
> @@ -0,0 +1,335 @@
> +/* Target-dependent code for none, architecture independent.
> +
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   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 3 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.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "defs.h"
> +#include "gdbtypes.h"
> +#include "none-tdep.h"
> +#include "auxv.h"
> +#include "target.h"
> +#include "gdbthread.h"
> +#include "gdbcore.h"
> +#include "regcache.h"
> +#include "regset.h"
> +#include "elf/common.h"
> +#include "elf-bfd.h"            /* for elfcore_write_* */
> +#include "inferior.h"
> +#include "cli/cli-utils.h"
> +#include "arch-utils.h"
> +#include "gdb_obstack.h"
> +#include "observable.h"
> +#include "objfiles.h"
> +#include "infcall.h"
> +#include "gdbcmd.h"
> +#include "gdb_regex.h"
> +#include "gdbsupport/enum-flags.h"
> +#include "gdbsupport/gdb_optional.h"
> +
> +#include <ctype.h>
> +
> +/* ---- based on linux-tdep.c ---- */
> +
> +/* Structure for passing information from
> +   none_collect_thread_registers via an iterator to
> +   none_collect_regset_section_cb. */
> +
> +struct none_collect_regset_section_cb_data
> +{
> +  struct gdbarch *gdbarch;
> +  const struct regcache *regcache;
> +  bfd *obfd;
> +  char *note_data;
> +  int *note_size;
> +  unsigned long lwp;
> +  enum gdb_signal stop_signal;
> +  int abort_iteration;
> +};
> +
> +/* Callback for iterate_over_regset_sections that records a single
> +   regset in the corefile note section.  */
> +
> +static void
> +none_collect_regset_section_cb (const char *sect_name, int supply_size,
> +                                int collect_size, const struct regset *regset,
> +                                const char *human_name, void *cb_data)
> +{
> +  struct none_collect_regset_section_cb_data *data
> +    = (struct none_collect_regset_section_cb_data *) cb_data;
> +  bool variable_size_section = (regset != NULL
> +				&& regset->flags & REGSET_VARIABLE_SIZE);
> +
> +  if (!variable_size_section)
> +    gdb_assert (supply_size == collect_size);
> +
> +  if (data->abort_iteration)
> +    return;
> +
> +  gdb_assert (regset && regset->collect_regset);
> +
> +  /* This is intentionally zero-initialized by using std::vector, so
> +     that any padding bytes in the core file will show as 0.  */
> +  std::vector<gdb_byte> buf (collect_size);
> +
> +  regset->collect_regset (regset, data->regcache, -1, buf.data (),
> +			  collect_size);
> +
> +  /* PRSTATUS still needs to be treated specially.  */
> +  if (strcmp (sect_name, ".reg") == 0)
> +    data->note_data = (char *) elfcore_write_prstatus
> +      (data->obfd, data->note_data, data->note_size, data->lwp,
> +       gdb_signal_to_host (data->stop_signal), buf.data ());
> +  else
> +    data->note_data = (char *) elfcore_write_register_note
> +      (data->obfd, data->note_data, data->note_size,
> +       sect_name, buf.data (), collect_size);
> +
> +  if (data->note_data == NULL)
> +    data->abort_iteration = 1;
> +}
> +
> +/* Records the thread's register state for the corefile note
> +   section.  */
> +
> +static char *
> +none_collect_thread_registers (const struct regcache *regcache,
> +                               ptid_t ptid, bfd *obfd,
> +                               char *note_data, int *note_size,
> +                               enum gdb_signal stop_signal)
> +{
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  struct none_collect_regset_section_cb_data data;
> +
> +  data.gdbarch = gdbarch;
> +  data.regcache = regcache;
> +  data.obfd = obfd;
> +  data.note_data = note_data;
> +  data.note_size = note_size;
> +  data.stop_signal = stop_signal;
> +  data.abort_iteration = 0;
> +
> +  /* For remote targets the LWP may not be available, so use the TID.  */
> +  data.lwp = ptid.lwp ();
> +  if (!data.lwp)
> +    data.lwp = ptid.tid ();
> +
> +  gdbarch_iterate_over_regset_sections (gdbarch,
> +					none_collect_regset_section_cb,
> +					&data, regcache);
> +  return data.note_data;
> +}
> +
> +/* Fetch the siginfo data for the specified thread, if it exists.  If
> +   there is no data, or we could not read it, return an empty
> +   buffer.  */
> +
> +static gdb::byte_vector
> +none_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch)
> +{
> +  struct type *siginfo_type;
> +  LONGEST bytes_read;
> +
> +  if (!gdbarch_get_siginfo_type_p (gdbarch))
> +    return gdb::byte_vector ();
> +
> +  scoped_restore_current_thread save_current_thread;
> +  switch_to_thread (thread);
> +
> +  siginfo_type = gdbarch_get_siginfo_type (gdbarch);
> +
> +  gdb::byte_vector buf (TYPE_LENGTH (siginfo_type));
> +
> +  bytes_read = target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
> +			    buf.data (), 0, TYPE_LENGTH (siginfo_type));
> +  if (bytes_read != TYPE_LENGTH (siginfo_type))
> +    buf.clear ();
> +
> +  return buf;
> +}
> +
> +struct none_corefile_thread_data
> +{
> +  struct gdbarch *gdbarch;
> +  bfd *obfd;
> +  char *note_data;
> +  int *note_size;
> +  enum gdb_signal stop_signal;
> +};
> +
> +/* Records the thread's register state for the corefile note
> +   section.  */
> +
> +static void
> +none_corefile_thread (struct thread_info *info,
> +                      struct none_corefile_thread_data *args)
> +{
> +  struct regcache *regcache;
> +
> +  regcache = get_thread_arch_regcache (info->inf->process_target (),
> +				       info->ptid, args->gdbarch);
> +
> +  target_fetch_registers (regcache, -1);
> +  gdb::byte_vector siginfo_data = none_get_siginfo_data (info, args->gdbarch);
> +
> +  args->note_data = none_collect_thread_registers
> +    (regcache, info->ptid, args->obfd, args->note_data,
> +     args->note_size, args->stop_signal);
> +
> +  /* Don't return anything if we got no register information above,
> +     such a core file is useless.  */
> +  if (args->note_data != NULL)
> +    if (!siginfo_data.empty ())
> +      args->note_data = elfcore_write_note (args->obfd,
> +					    args->note_data,
> +					    args->note_size,
> +					    "CORE", NT_SIGINFO,
> +					    siginfo_data.data (),
> +					    siginfo_data.size ());
> +}
> +
> +/* Find the signalled thread.  In case there's more than one signalled
> +   thread, prefer the current thread, if it is signalled.  If no
> +   thread was signalled, default to the current thread, unless it has
> +   exited, in which case return NULL.  */
> +
> +static thread_info *
> +find_signalled_thread ()
> +{
> +  thread_info *curr_thr = inferior_thread ();
> +  if (curr_thr->state != THREAD_EXITED
> +      && curr_thr->suspend.stop_signal != GDB_SIGNAL_0)
> +    return curr_thr;
> +
> +  for (thread_info *thr : current_inferior ()->non_exited_threads ())
> +    if (thr->suspend.stop_signal != GDB_SIGNAL_0)
> +      return thr;
> +
> +  /* Default to the current thread, unless it has exited.  */
> +  if (curr_thr->state != THREAD_EXITED)
> +    return curr_thr;
> +
> +  return nullptr;
> +}
> +
> +/* Fills the "to_make_corefile_note" target vector.  Builds the note
> +   section for a corefile, and returns it in a malloc buffer.  */
> +
> +char *
> +none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
> +                          none_collect_thread_registers_ftype collect)
> +{
> +  struct none_corefile_thread_data thread_args;
> +  char *note_data = NULL;
> +
> +  /* Process information.  */
> +  if (get_exec_file (0))
> +    {
> +      const char *fname = lbasename (get_exec_file (0));
> +      char *psargs = xstrdup (fname);
> +
> +      if (get_inferior_args ())
> +        psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
> +			   (char *) NULL);
> +
> +      note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
> +                                          fname, psargs);
> +      xfree (psargs);
> +    }
> +
> +  if (!note_data)
> +    return NULL;
> +
> +  /* Thread register information.  */
> +  try
> +    {
> +      update_thread_list ();
> +    }
> +  catch (const gdb_exception_error &e)
> +    {
> +      exception_print (gdb_stderr, e);
> +    }
> +
> +  /* Like the kernel, prefer dumping the signalled thread first.
> +     "First thread" is what tools use to infer the signalled
> +     thread.  */
> +  thread_info *signalled_thr = find_signalled_thread ();
> +
> +  thread_args.gdbarch = gdbarch;
> +  thread_args.obfd = obfd;
> +  thread_args.note_data = note_data;
> +  thread_args.note_size = note_size;
> +  if (signalled_thr != nullptr)
> +    thread_args.stop_signal = signalled_thr->suspend.stop_signal;
> +  else
> +    thread_args.stop_signal = GDB_SIGNAL_0;
> +
> +  if (signalled_thr != nullptr)
> +    none_corefile_thread (signalled_thr, &thread_args);
> +  for (thread_info *thr : current_inferior ()->non_exited_threads ())
> +    {
> +      if (thr == signalled_thr)
> +	continue;
> +
> +      none_corefile_thread (thr, &thread_args);
> +    }
> +
> +  note_data = thread_args.note_data;
> +  if (!note_data)
> +    return NULL;
> +
> +  /* Auxillary vector.  */
> +  gdb::optional<gdb::byte_vector> auxv =
> +    target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL);
> +  if (auxv && !auxv->empty ())
> +    {
> +      note_data = elfcore_write_note (obfd, note_data, note_size,
> +                                      "CORE", NT_AUXV, auxv->data (),
> +                                      auxv->size ());
> +      if (!note_data)
> +        return NULL;
> +    }
> +
> +  /* make_cleanup (xfree, note_data); */
> +  return note_data;
> +}
> +
> +static char *
> +none_make_corefile_notes_1 (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
> +{
> +  return none_make_corefile_notes (gdbarch, obfd, note_size,
> +                                   none_collect_thread_registers);
> +}
> +
> +/* Setup default core file support for none targets.
> +   Can be overridden later by OSABI.  */
> +
> +void
> +none_init_corefile (struct gdbarch_info info,
> +                    struct gdbarch *gdbarch)
> +{
> +  /* Default core file support.  */
> +  set_gdbarch_make_corefile_notes (gdbarch, none_make_corefile_notes_1);
> +}
> +
> +/* Provide a prototype to silence -Wmissing-prototypes.  */
> +extern initialize_file_ftype _initialize_none_tdep;
> +
> +void
> +_initialize_none_tdep (void)
> +{
> +  /* No special actions.  */
> +}
> diff --git a/gdb/none-tdep.h b/gdb/none-tdep.h
> new file mode 100644
> index 0000000000..4aea7004d8
> --- /dev/null
> +++ b/gdb/none-tdep.h
> @@ -0,0 +1,39 @@
> +/* Target-dependent code for none, architecture independent.
> +
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   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 3 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.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef NONE_TDEP_H
> +#define NONE_TDEP_H
> +
> +#include "bfd.h"
> +
> +struct regcache;
> +
> +typedef char *(*none_collect_thread_registers_ftype) (const struct regcache *,
> +                                                      ptid_t,
> +                                                      bfd *, char *, int *,
> +                                                      enum gdb_signal);
> +char *
> +none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
> +                          none_collect_thread_registers_ftype collect);
> +
> +void
> +none_init_corefile (struct gdbarch_info info,
> +                    struct gdbarch *gdbarch);
> +
> +#endif /* none-tdep.h */
> 

  parent reply	other threads:[~2020-10-21 14:38 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-17  0:02 [PATCH] gdb: add support for handling core dumps on arm-none-eabi Fredrik Hederstierna via Gdb-patches
2020-10-19  2:08 ` Simon Marchi
2020-10-19 13:13   ` Luis Machado via Gdb-patches
2020-10-19 13:15   ` Alan Hayward via Gdb-patches
2020-10-19 15:25   ` Paul Mathieu via Gdb-patches
2020-10-20 11:41     ` Fredrik Hederstierna via Gdb-patches
2020-10-20 12:39       ` Simon Marchi
2020-10-20 14:00         ` Fredrik Hederstierna via Gdb-patches
2020-10-20 15:04           ` Simon Marchi
2020-10-20 22:05             ` Fredrik Hederstierna via Gdb-patches
2020-10-20 23:06               ` Simon Marchi
2020-10-22  0:52                 ` Fredrik Hederstierna via Gdb-patches
2020-10-22  1:24                   ` Simon Marchi
2020-10-22  1:49                   ` Simon Marchi
2020-10-22 22:32                     ` Fredrik Hederstierna via Gdb-patches
2020-10-23  0:37                       ` Simon Marchi
2020-10-25 21:06                         ` Fredrik Hederstierna via Gdb-patches
2020-10-26 11:24                           ` Luis Machado via Gdb-patches
2020-10-26 15:49                             ` Fredrik Hederstierna via Gdb-patches
2020-10-27 16:53                               ` Paul Mathieu via Gdb-patches
2021-01-14 12:36                                 ` Fredrik Hederstierna via Gdb-patches
2021-01-14 12:50                                   ` Luis Machado via Gdb-patches
2021-01-18 11:09                                     ` Andrew Burgess
2021-01-18 14:01                                       ` Luis Machado via Gdb-patches
2021-06-21  6:30                                         ` [PATCH] sim: arm: add support for handling core dumps Fredrik Hederstierna via Gdb-patches
2021-06-22  3:20                                           ` Mike Frysinger via Gdb-patches
2021-06-24 13:01                                             ` Alan Hayward via Gdb-patches
2021-06-29  9:11                                               ` Fredrik Hederstierna via Gdb-patches
2021-01-18 11:01                                   ` [PATCH] gdb: add support for handling core dumps on arm-none-eabi Andrew Burgess
2021-06-22  2:16                           ` Mike Frysinger via Gdb-patches
2020-10-20 19:34       ` [PATCH] gdb: Support corefiles for arm-none-eabi Fredrik Hederstierna
2020-10-20 21:49       ` Fredrik Hederstierna
2020-10-20 21:58       ` [PATCH v2] Support for corefiles for arm-none-eabi target Fredrik Hederstierna
2020-10-21  2:51         ` Simon Marchi
2020-10-21 14:38         ` Luis Machado via Gdb-patches [this message]
2020-10-22  0:44       ` [PATCH v3][PR gdb/14383]: gdb: corefile support " Fredrik Hederstierna
2020-10-22  0:44         ` [PATCH v3][PR gdb/14383]: Support for corefiles " Fredrik Hederstierna
2020-10-25 20:46       ` [PATCH] " Fredrik Hederstierna
2020-10-25 20:50       ` [PATCH v4][PR gdb/14383] " Fredrik Hederstierna

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=45149673-46bb-d32f-b413-5c72739ef074@linaro.org \
    --to=gdb-patches@sourceware.org \
    --cc=Alan.Hayward@arm.com \
    --cc=fredrik@hederstierna.com \
    --cc=luis.machado@linaro.org \
    --cc=paulmathieu@google.com \
    --cc=simark@simark.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox