Use a regset for NT_ARM_VFP.

This includes adding support for NT_ARM_VFP for 32-bit binaries
running under aarch64 kernels both for ptrace(), and coredumps via the
kernel and gcore.

Reviewed by:	andrew, markj
Sponsored by:	University of Cambridge, Google, Inc.
Differential Revision:	https://reviews.freebsd.org/D34448
This commit is contained in:
John Baldwin 2022-03-23 13:33:06 -07:00
parent a47fd6929f
commit add00c381e
7 changed files with 78 additions and 24 deletions

View File

@ -145,19 +145,9 @@ elf32_arm_abi_supported(struct image_params *imgp, int32_t *osrel __unused,
} }
void void
elf32_dump_thread(struct thread *td, void *dst, size_t *off) elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{ {
#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
} }
bool bool

View File

@ -28,12 +28,45 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <sys/elf.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/reg.h>
#ifdef VFP #ifdef VFP
#include <machine/vfp.h> #include <machine/vfp.h>
#endif #endif
#ifdef VFP
static bool
get_arm_vfp(struct regset *rs, struct thread *td, void *buf, size_t *sizep)
{
if (buf != NULL) {
KASSERT(*sizep == sizeof(mcontext_vfp_t),
("%s: invalid size", __func__));
get_vfpcontext(td, buf);
}
*sizep = sizeof(mcontext_vfp_t);
return (true);
}
static bool
set_arm_vfp(struct regset *rs, struct thread *td, void *buf,
size_t size)
{
KASSERT(size == sizeof(mcontext_vfp_t), ("%s: invalid size", __func__));
set_vfpcontext(td, buf);
return (true);
}
static struct regset regset_arm_vfp = {
.note = NT_ARM_VFP,
.size = sizeof(mcontext_vfp_t),
.get = get_arm_vfp,
.set = set_arm_vfp,
};
ELF_REGSET(regset_arm_vfp);
#endif
int int
cpu_ptrace(struct thread *td, int req, void *addr, int data) cpu_ptrace(struct thread *td, int req, void *addr, int data)
{ {

View File

@ -288,5 +288,4 @@ freebsd32_setregs(struct thread *td, struct image_params *imgp,
void void
elf32_dump_thread(struct thread *td, void *dst, size_t *off) elf32_dump_thread(struct thread *td, void *dst, size_t *off)
{ {
/* XXX: VFP */
} }

View File

@ -61,10 +61,6 @@ extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
*/ */
#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link)
#ifdef VFP
static void get_fpcontext32(struct thread *td, mcontext32_vfp_t *);
#endif
/* /*
* Stubs for machine dependent 32-bits system calls. * Stubs for machine dependent 32-bits system calls.
*/ */
@ -127,7 +123,7 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
} }
#ifdef VFP #ifdef VFP
static void void
get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp) get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{ {
struct pcb *pcb; struct pcb *pcb;
@ -159,7 +155,7 @@ get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
} }
} }
static void void
set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp) set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{ {
struct pcb *pcb; struct pcb *pcb;
@ -176,6 +172,7 @@ set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
critical_exit(); critical_exit();
} }
#endif #endif
static void static void
get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
{ {

View File

@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/elf.h>
#include <sys/exec.h> #include <sys/exec.h>
#include <sys/imgact.h> #include <sys/imgact.h>
#include <sys/kernel.h> #include <sys/kernel.h>
@ -48,6 +49,38 @@ __FBSDID("$FreeBSD$");
#include <machine/armreg.h> #include <machine/armreg.h>
#if defined(VFP) && defined(COMPAT_FREEBSD32)
static bool
get_arm_vfp(struct regset *rs, struct thread *td, void *buf, size_t *sizep)
{
if (buf != NULL) {
KASSERT(*sizep == sizeof(mcontext32_vfp_t),
("%s: invalid size", __func__));
get_fpcontext32(td, buf);
}
*sizep = sizeof(mcontext32_vfp_t);
return (true);
}
static bool
set_arm_vfp(struct regset *rs, struct thread *td, void *buf,
size_t size)
{
KASSERT(size == sizeof(mcontext32_vfp_t), ("%s: invalid size",
__func__));
set_fpcontext32(td, buf);
return (true);
}
static struct regset regset_arm_vfp = {
.note = NT_ARM_VFP,
.size = sizeof(mcontext32_vfp_t),
.get = get_arm_vfp,
.set = set_arm_vfp,
};
ELF32_REGSET(regset_arm_vfp);
#endif
int int
ptrace_set_pc(struct thread *td, u_long addr) ptrace_set_pc(struct thread *td, u_long addr)
{ {

View File

@ -94,6 +94,11 @@ int is_fpu_kern_thread(u_int);
#define VFP_FPSR_FROM_FPSCR(vpscr) ((vpscr) &~ 0x7c00000) #define VFP_FPSR_FROM_FPSCR(vpscr) ((vpscr) &~ 0x7c00000)
#define VFP_FPCR_FROM_FPSCR(vpsrc) ((vpsrc) & 0x7c00000) #define VFP_FPCR_FROM_FPSCR(vpsrc) ((vpsrc) & 0x7c00000)
#ifdef COMPAT_FREEBSD32
void get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp);
void set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp);
#endif
#endif #endif
#endif #endif

View File

@ -110,9 +110,6 @@ static void elf_detach(void); /* atexit() handler. */
static void *elf_note_prpsinfo(void *, size_t *); static void *elf_note_prpsinfo(void *, size_t *);
static void *elf_note_thrmisc(void *, size_t *); static void *elf_note_thrmisc(void *, size_t *);
static void *elf_note_ptlwpinfo(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__) #if defined(__i386__) || defined(__amd64__)
static void *elf_note_x86_xstate(void *, size_t *); static void *elf_note_x86_xstate(void *, size_t *);
#endif #endif
@ -375,8 +372,8 @@ elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep)
elf_putregnote(NT_FPREGSET, tids[i], sb); elf_putregnote(NT_FPREGSET, tids[i], sb);
elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb); elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb);
elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb); elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb);
#if defined(__arm__) #if (defined(ELFCORE_COMPAT_32) && defined(__aarch64__)) || defined(__arm__)
elf_putnote(NT_ARM_VFP, elf_note_arm_vfp, tids + i, sb); elf_putregnote(NT_ARM_VFP, tids[i], sb);
#endif #endif
#if defined(__i386__) || defined(__amd64__) #if defined(__i386__) || defined(__amd64__)
elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb); elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);