From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4419 invoked by alias); 5 Apr 2011 18:50:32 -0000 Received: (qmail 4393 invoked by uid 22791); 5 Apr 2011 18:50:27 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL,BAYES_00,MSGID_FROM_MTA_HEADER,SPF_SOFTFAIL,TW_EG,TW_GR,TW_HW,TW_OC,TW_VF,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mtagate7.uk.ibm.com (HELO mtagate7.uk.ibm.com) (194.196.100.167) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 05 Apr 2011 18:50:19 +0000 Received: from d06nrmr1707.portsmouth.uk.ibm.com (d06nrmr1707.portsmouth.uk.ibm.com [9.149.39.225]) by mtagate7.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p35IoGFX001475; Tue, 5 Apr 2011 18:50:16 GMT Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1707.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p35IowYw1896484; Tue, 5 Apr 2011 19:50:58 +0100 Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p35IoGWC022131; Tue, 5 Apr 2011 12:50:16 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id p35IoER0021774; Tue, 5 Apr 2011 12:50:15 -0600 Message-Id: <201104051850.p35IoER0021774@d06av02.portsmouth.uk.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Tue, 05 Apr 2011 20:50:14 +0200 Subject: [rfc/rfa] VFP/NEON register set support for ARM core files To: gdb-patches@sourceware.org, binutils@sourceware.org Date: Tue, 05 Apr 2011 18:50:00 -0000 From: "Ulrich Weigand" Cc: patches@linaro.org, dave.martin@linaro.org, will.deacon@arm.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-04/txt/msg00075.txt.bz2 Hello, the ARM kernel currently does not save VFP/NEON registers into core files. However, the patch set available here: http://lists.infradead.org/pipermail/linux-arm-kernel/2011-April/047222.html will add support by providing a new NT_ARM_VFP core file note type, analogously to how vector registers are handled e.g. on ppc or i386. This patch adds corresponding support to BFD and GDB to read such notes, and write them as well (for GDB's generate-core-file command). Tested on armv7l-unknown-linux-gnuabi on a Linux 2.6.38 kernel with the above patch set applied. Fixes one gcore.exp test case failure. Are the BFD parts OK? I'm planning on committing the GDB parts once kernel support has been accepted and BFD parts are approved. ChangeLog: include/elf/ * common.h (NT_ARM_VFP): Define. bfd/ * elf-bfd.h (elfcore_write_arm_vfp): Add prototype. * elf.c (elfcore_grok_arm_vfp): New function. (elfcore_grok_note): Call it to handle NT_ARM_VFP notes. (elfcore_write_arm_vfp): New function. (elfcore_write_register_note): Call it to handle .reg-arm-vfp. gdb/ * arm-linux-tdep.c: Include "auxv.h". (AT_HWCAP): Define. (ARM_LINUX_SIZEOF_VFP): Define. (arm_linux_supply_vfp): New function. (arm_linux_collect_vfp): Likewise. (arm_linux_regset_from_core_section): Handle .reg-arm-vfp sections. (arm_linux_fpa_regset_sections): New variable. (arm_linux_vfp_regset_sections): Likewise. (arm_linux_core_read_description): New function. (arm_linux_init_abi): Install arm_linux_core_read_description and arm_linux_fpa_regset_sections or arm_linux_vfp_regset_sections as appropriate for the architecture. * arm-tdep.h (struct gdbarch_tdep): Add member "vfpregset". (tdesc_arm_with_m): Declare. (tdesc_arm_with_iwmmxt): Likewise. (tdesc_arm_with_vfpv2): Likewise. (tdesc_arm_with_vfpv3): Likewise. (tdesc_arm_with_neon): Likewise. * arm-linux-nat.c: Move features/*.c includes ... * arm-tdep.c: ... here. * arm-linux-nat.c (arm_linux_read_description): Move initializing target description data structures ... * arm-tdep.c (_initialize_arm_tdep): ... here. * arm-linux-nat.c (HWCAP_VFP, HWCAP_IWMMXT, HWCAP_NEON, HWCAP_VFPv3, HWCAP_VFPv3D16): Move definitions ... * arm-linux-tdep.h: ... here. Index: bfd/elf-bfd.h =================================================================== RCS file: /cvs/src/src/bfd/elf-bfd.h,v retrieving revision 1.315 diff -u -p -r1.315 elf-bfd.h --- bfd/elf-bfd.h 14 Mar 2011 15:54:57 -0000 1.315 +++ bfd/elf-bfd.h 1 Apr 2011 19:19:42 -0000 @@ -2210,6 +2210,8 @@ extern char *elfcore_write_s390_ctrs (bfd *, char *, int *, const void *, int); extern char *elfcore_write_s390_prefix (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_arm_vfp + (bfd *, char *, int *, const void *, int); extern char *elfcore_write_lwpstatus (bfd *, char *, int *, long, int, const void *); extern char *elfcore_write_register_note Index: bfd/elf.c =================================================================== RCS file: /cvs/src/src/bfd/elf.c,v retrieving revision 1.530 diff -u -p -r1.530 elf.c --- bfd/elf.c 14 Mar 2011 15:54:58 -0000 1.530 +++ bfd/elf.c 1 Apr 2011 19:19:43 -0000 @@ -7950,6 +7950,12 @@ elfcore_grok_s390_prefix (bfd *abfd, Elf return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note); } +static bfd_boolean +elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note); +} + #if defined (HAVE_PRPSINFO_T) typedef prpsinfo_t elfcore_psinfo_t; #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ @@ -8363,6 +8369,13 @@ elfcore_grok_note (bfd *abfd, Elf_Intern else return TRUE; + case NT_ARM_VFP: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_arm_vfp (abfd, note); + else + return TRUE; + case NT_PRPSINFO: case NT_PSINFO: if (bed->elf_backend_grok_psinfo) @@ -9088,6 +9101,18 @@ elfcore_write_s390_prefix (bfd *abfd, } char * +elfcore_write_arm_vfp (bfd *abfd, + char *buf, + int *bufsiz, + const void *arm_vfp, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_VFP, arm_vfp, size); +} + +char * elfcore_write_register_note (bfd *abfd, char *buf, int *bufsiz, @@ -9117,6 +9142,8 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-s390-prefix") == 0) return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-arm-vfp") == 0) + return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size); return NULL; } Index: gdb/arm-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/arm-linux-nat.c,v retrieving revision 1.47 diff -u -p -r1.47 arm-linux-nat.c --- gdb/arm-linux-nat.c 21 Feb 2011 15:03:37 -0000 1.47 +++ gdb/arm-linux-nat.c 1 Apr 2011 19:19:43 -0000 @@ -44,11 +44,6 @@ /* Defines ps_err_e, struct ps_prochandle. */ #include "gdb_proc_service.h" -#include "features/arm-with-iwmmxt.c" -#include "features/arm-with-vfpv2.c" -#include "features/arm-with-vfpv3.c" -#include "features/arm-with-neon.c" - #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 22 #endif @@ -68,13 +63,6 @@ #define PTRACE_SETHBPREGS 30 #endif -/* These are in in current kernels. */ -#define HWCAP_VFP 64 -#define HWCAP_IWMMXT 512 -#define HWCAP_NEON 4096 -#define HWCAP_VFPv3 8192 -#define HWCAP_VFPv3D16 16384 - /* A flag for whether the WMMX registers are available. */ static int arm_linux_has_wmmx_registers; @@ -696,8 +684,6 @@ arm_linux_read_description (struct targe if (arm_hwcap & HWCAP_IWMMXT) { arm_linux_has_wmmx_registers = 1; - if (tdesc_arm_with_iwmmxt == NULL) - initialize_tdesc_arm_with_iwmmxt (); return tdesc_arm_with_iwmmxt; } @@ -712,22 +698,16 @@ arm_linux_read_description (struct targe if (arm_hwcap & HWCAP_NEON) { arm_linux_vfp_register_count = 32; - if (tdesc_arm_with_neon == NULL) - initialize_tdesc_arm_with_neon (); result = tdesc_arm_with_neon; } else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3) { arm_linux_vfp_register_count = 32; - if (tdesc_arm_with_vfpv3 == NULL) - initialize_tdesc_arm_with_vfpv3 (); result = tdesc_arm_with_vfpv3; } else { arm_linux_vfp_register_count = 16; - if (tdesc_arm_with_vfpv2 == NULL) - initialize_tdesc_arm_with_vfpv2 (); result = tdesc_arm_with_vfpv2; } Index: gdb/arm-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v retrieving revision 1.85 diff -u -p -r1.85 arm-linux-tdep.c --- gdb/arm-linux-tdep.c 1 Apr 2011 11:57:02 -0000 1.85 +++ gdb/arm-linux-tdep.c 1 Apr 2011 19:19:43 -0000 @@ -33,6 +33,7 @@ #include "trad-frame.h" #include "tramp-frame.h" #include "breakpoint.h" +#include "auxv.h" #include "arm-tdep.h" #include "arm-linux-tdep.h" @@ -45,6 +46,9 @@ #include "gdb_string.h" +/* This is defined in on ARM GNU/Linux systems. */ +#define AT_HWCAP 16 + extern int arm_apcs_32; /* Under ARM GNU/Linux the traditional way of performing a breakpoint @@ -638,6 +642,44 @@ arm_linux_collect_nwfpe (const struct re regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM); } +/* Support VFP register format. */ + +#define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4) + +static void +arm_linux_supply_vfp (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *regs_buf, size_t len) +{ + const gdb_byte *regs = regs_buf; + int regno; + + if (regnum == ARM_FPSCR_REGNUM || regnum == -1) + regcache_raw_supply (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache_raw_supply (regcache, regno, + regs + (regno - ARM_D0_REGNUM) * 8); +} + +static void +arm_linux_collect_vfp (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *regs_buf, size_t len) +{ + gdb_byte *regs = regs_buf; + int regno; + + if (regnum == ARM_FPSCR_REGNUM || regnum == -1) + regcache_raw_collect (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache_raw_collect (regcache, regno, + regs + (regno - ARM_D0_REGNUM) * 8); +} + /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ @@ -665,9 +707,62 @@ arm_linux_regset_from_core_section (stru return tdep->fpregset; } + if (strcmp (sect_name, ".reg-arm-vfp") == 0 + && sect_size == ARM_LINUX_SIZEOF_VFP) + { + if (tdep->vfpregset == NULL) + tdep->vfpregset = regset_alloc (gdbarch, arm_linux_supply_vfp, + arm_linux_collect_vfp); + return tdep->vfpregset; + } + + return NULL; +} + +/* Core file register set sections. */ + +static struct core_regset_section arm_linux_fpa_regset_sections[] = +{ + { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, + { ".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point" }, + { NULL, 0} +}; + +static struct core_regset_section arm_linux_vfp_regset_sections[] = +{ + { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, + { ".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point" }, + { NULL, 0} +}; + +/* Determine target description from core file. */ + +static const struct target_desc * +arm_linux_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 NULL; + + 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 tdesc_arm_with_neon; + else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3) + return tdesc_arm_with_vfpv3; + else + return tdesc_arm_with_vfpv2; + } + return NULL; } + /* Copy the value of next pc of sigreturn and rt_sigrturn into PC, return 1. In addition, set IS_THUMB depending on whether we will return to ARM or Thumb code. Return 0 if it is not a @@ -1041,6 +1136,12 @@ arm_linux_init_abi (struct gdbarch_info /* Core file support. */ set_gdbarch_regset_from_core_section (gdbarch, arm_linux_regset_from_core_section); + set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description); + + if (tdep->have_vfp_registers) + set_gdbarch_core_regset_sections (gdbarch, arm_linux_vfp_regset_sections); + else if (tdep->have_fpa_registers) + set_gdbarch_core_regset_sections (gdbarch, arm_linux_fpa_regset_sections); set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); Index: gdb/arm-linux-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/arm-linux-tdep.h,v retrieving revision 1.9 diff -u -p -r1.9 arm-linux-tdep.h --- gdb/arm-linux-tdep.h 1 Jan 2011 15:32:57 -0000 1.9 +++ gdb/arm-linux-tdep.h 1 Apr 2011 19:19:43 -0000 @@ -59,3 +59,12 @@ void arm_linux_supply_nwfpe (const struc void arm_linux_collect_nwfpe (const struct regset *regset, const struct regcache *regcache, int regnum, void *regs_buf, size_t len); + +/* ARM GNU/Linux HWCAP values. These are in defined in + in current kernels. */ +#define HWCAP_VFP 64 +#define HWCAP_IWMMXT 512 +#define HWCAP_NEON 4096 +#define HWCAP_VFPv3 8192 +#define HWCAP_VFPv3D16 16384 + Index: gdb/arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.340 diff -u -p -r1.340 arm-tdep.c --- gdb/arm-tdep.c 1 Apr 2011 11:57:02 -0000 1.340 +++ gdb/arm-tdep.c 1 Apr 2011 19:19:45 -0000 @@ -56,6 +56,10 @@ #include "vec.h" #include "features/arm-with-m.c" +#include "features/arm-with-iwmmxt.c" +#include "features/arm-with-vfpv2.c" +#include "features/arm-with-vfpv3.c" +#include "features/arm-with-neon.c" static int arm_debug; @@ -8707,6 +8711,10 @@ _initialize_arm_tdep (void) /* Initialize the standard target descriptions. */ initialize_tdesc_arm_with_m (); + initialize_tdesc_arm_with_iwmmxt (); + initialize_tdesc_arm_with_vfpv2 (); + initialize_tdesc_arm_with_vfpv3 (); + initialize_tdesc_arm_with_neon (); /* Get the number of possible sets of register names defined in opcodes. */ num_disassembly_options = get_arm_regname_num_options (); Index: gdb/arm-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.h,v retrieving revision 1.50 diff -u -p -r1.50 arm-tdep.h --- gdb/arm-tdep.h 1 Apr 2011 11:57:03 -0000 1.50 +++ gdb/arm-tdep.h 1 Apr 2011 19:19:45 -0000 @@ -190,7 +190,7 @@ struct gdbarch_tdep enum struct_return struct_return; /* Cached core file helpers. */ - struct regset *gregset, *fpregset; + struct regset *gregset, *fpregset, *vfpregset; /* ISA-specific data types. */ struct type *arm_ext_type; @@ -339,4 +339,11 @@ extern const struct regset * armbsd_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size); +/* Target descriptions. */ +extern struct target_desc *tdesc_arm_with_m; +extern struct target_desc *tdesc_arm_with_iwmmxt; +extern struct target_desc *tdesc_arm_with_vfpv2; +extern struct target_desc *tdesc_arm_with_vfpv3; +extern struct target_desc *tdesc_arm_with_neon; + #endif /* arm-tdep.h */ Index: include/elf/common.h =================================================================== RCS file: /cvs/src/src/include/elf/common.h,v retrieving revision 1.126 diff -u -p -r1.126 common.h --- include/elf/common.h 10 Mar 2011 10:23:37 -0000 1.126 +++ include/elf/common.h 1 Apr 2011 19:19:46 -0000 @@ -538,6 +538,8 @@ /* note name must be "LINUX". */ #define NT_S390_PREFIX 0x305 /* S390 prefix register */ /* note name must be "LINUX". */ +#define NT_ARM_VFP 0x400 /* ARM VFP registers */ + /* note name must be "LINUX". */ /* Note segments for core files on dir-style procfs systems. */ -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com