From 27efb0a2422308cb6ba1170bbaa32546fce5a85b Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 14 Sep 2017 15:07:48 +0000 Subject: [PATCH] Add a NT_ARM_VFP ELF core note to hold VFP registers for each thread. The core note matches the format and layout of NT_ARM_VFP on Linux. Debuggers use the AT_HWCAP flags to determine how many VFP registers are actually used and their format. Reviewed by: mmel (earlier version w/o gcore) MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D12293 --- sys/arm/arm/elf_machdep.c | 17 +++++++++++++++-- sys/sys/elf_common.h | 1 + usr.bin/gcore/elfcore.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 26e3754d3c8c..fba35eb159c6 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef VFP +#include +#endif static boolean_t elf32_arm_abi_supported(struct image_params *); @@ -127,9 +130,19 @@ elf32_arm_abi_supported(struct image_params *imgp) } void -elf32_dump_thread(struct thread *td __unused, void *dst __unused, - size_t *off __unused) +elf32_dump_thread(struct thread *td, void *dst, size_t *off) { +#ifdef VFP + mcontext_vfp_t vfp; + + if (dst != NULL) { + get_vfpcontext(td, &vfp); + *off = elf32_populate_note(NT_ARM_VFP, &vfp, dst, sizeof(vfp), + NULL); + } else + *off = elf32_populate_note(NT_ARM_VFP, NULL, NULL, sizeof(vfp), + NULL); +#endif } /* diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index c66bbae499eb..8634e0a9d5db 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -757,6 +757,7 @@ typedef struct { #define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */ #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ #define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */ +#define NT_ARM_VFP 0x400 /* ARM VFP registers */ /* Symbol Binding - ELFNN_ST_BIND - st_info */ #define STB_LOCAL 0 /* Local symbol */ diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c index ff1010001c3f..ae52d61c9281 100644 --- a/usr.bin/gcore/elfcore.c +++ b/usr.bin/gcore/elfcore.c @@ -109,6 +109,9 @@ static void *elf_note_prpsinfo(void *, size_t *); static void *elf_note_prstatus(void *, size_t *); static void *elf_note_thrmisc(void *, size_t *); static void *elf_note_ptlwpinfo(void *, size_t *); +#if defined(__arm__) +static void *elf_note_arm_vfp(void *, size_t *); +#endif #if defined(__i386__) || defined(__amd64__) static void *elf_note_x86_xstate(void *, size_t *); #endif @@ -368,6 +371,9 @@ elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep) elf_putnote(NT_FPREGSET, elf_note_fpregset, tids + i, sb); elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb); elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb); +#if defined(__arm__) + elf_putnote(NT_ARM_VFP, elf_note_arm_vfp, tids + i, sb); +#endif #if defined(__i386__) || defined(__amd64__) elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb); #endif @@ -718,6 +724,31 @@ elf_note_ptlwpinfo(void *arg, size_t *sizep) return (p); } +#if defined(__arm__) +static void * +elf_note_arm_vfp(void *arg, size_t *sizep) +{ + lwpid_t tid; + struct vfpreg *vfp; + static bool has_vfp = true; + struct vfpreg info; + + tid = *(lwpid_t *)arg; + if (has_vfp) { + if (ptrace(PT_GETVFPREGS, tid, (void *)&info, 0) != 0) + has_vfp = false; + } + if (!has_vfp) { + *sizep = 0; + return (NULL); + } + vfp = calloc(1, sizeof(*vfp)); + memcpy(vfp, &info, sizeof(*vfp)); + *sizep = sizeof(*vfp); + return (vfp); +} +#endif + #if defined(__i386__) || defined(__amd64__) static void * elf_note_x86_xstate(void *arg, size_t *sizep)