Page MenuHomeFreeBSD

D1193.diff
No OneTemporary

D1193.diff

Index: head/contrib/binutils/binutils/readelf.c
===================================================================
--- head/contrib/binutils/binutils/readelf.c
+++ head/contrib/binutils/binutils/readelf.c
@@ -9159,6 +9159,8 @@
return _("NT_PROCSTAT_PSSTRINGS (ps_strings data)");
case NT_PROCSTAT_AUXV:
return _("NT_PROCSTAT_AUXV (auxv data)");
+ case NT_X86_XSTATE:
+ return _("NT_X86_XSTATE (x86 XSAVE extended state)");
default:
return get_note_type(e_type);
}
Index: head/contrib/binutils/include/elf/common.h
===================================================================
--- head/contrib/binutils/include/elf/common.h
+++ head/contrib/binutils/include/elf/common.h
@@ -414,6 +414,7 @@
#define NT_PROCSTAT_OSREL 14
#define NT_PROCSTAT_PSSTRINGS 15
#define NT_PROCSTAT_AUXV 16
+#define NT_X86_XSTATE 0x202
/* Note segments for core files on NetBSD systems. Note name
Index: head/sys/amd64/amd64/elf_machdep.c
===================================================================
--- head/sys/amd64/amd64/elf_machdep.c
+++ head/sys/amd64/amd64/elf_machdep.c
@@ -44,6 +44,7 @@
#include <vm/vm_param.h>
#include <machine/elf.h>
+#include <machine/fpu.h>
#include <machine/md_var.h>
struct sysentvec elf64_freebsd_sysvec = {
@@ -133,11 +134,26 @@
&kfreebsd_brand_info);
void
-elf64_dump_thread(struct thread *td __unused, void *dst __unused,
- size_t *off __unused)
+elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
-}
+ void *buf;
+ size_t len;
+ len = 0;
+ if (use_xsave) {
+ if (dst != NULL) {
+ fpugetregs(td);
+ len += elf64_populate_note(NT_X86_XSTATE,
+ get_pcb_user_save_td(td), dst,
+ cpu_max_ext_state_size, &buf);
+ *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) =
+ xsave_mask;
+ } else
+ len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL,
+ cpu_max_ext_state_size, NULL);
+ }
+ *off = len;
+}
/* Process one elf relocation with addend. */
static int
Index: head/sys/amd64/amd64/fpu.c
===================================================================
--- head/sys/amd64/amd64/fpu.c
+++ head/sys/amd64/amd64/fpu.c
@@ -127,6 +127,13 @@
*/
CTASSERT(sizeof(struct pcb) % XSAVE_AREA_ALIGN == 0);
+/*
+ * Ensure the copy of XCR0 saved in a core is contained in the padding
+ * area.
+ */
+CTASSERT(X86_XSTATE_XCR0_OFFSET >= offsetof(struct savefpu, sv_pad) &&
+ X86_XSTATE_XCR0_OFFSET + sizeof(uint64_t) <= sizeof(struct savefpu));
+
static void fpu_clean_state(void);
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
Index: head/sys/amd64/amd64/ptrace_machdep.c
===================================================================
--- head/sys/amd64/amd64/ptrace_machdep.c
+++ head/sys/amd64/amd64/ptrace_machdep.c
@@ -42,6 +42,7 @@
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
{
+ struct ptrace_xstate_info info;
char *savefpu;
int error;
@@ -49,14 +50,14 @@
return (EOPNOTSUPP);
switch (req) {
- case PT_GETXSTATE:
+ case PT_GETXSTATE_OLD:
fpugetregs(td);
savefpu = (char *)(get_pcb_user_save_td(td) + 1);
error = copyout(savefpu, addr,
cpu_max_ext_state_size - sizeof(struct savefpu));
break;
- case PT_SETXSTATE:
+ case PT_SETXSTATE_OLD:
if (data > cpu_max_ext_state_size - sizeof(struct savefpu)) {
error = EINVAL;
break;
@@ -70,6 +71,36 @@
free(savefpu, M_TEMP);
break;
+ case PT_GETXSTATE_INFO:
+ if (data != sizeof(info)) {
+ error = EINVAL;
+ break;
+ }
+ info.xsave_len = cpu_max_ext_state_size;
+ info.xsave_mask = xsave_mask;
+ error = copyout(&info, addr, data);
+ break;
+
+ case PT_GETXSTATE:
+ fpugetregs(td);
+ savefpu = (char *)(get_pcb_user_save_td(td));
+ error = copyout(savefpu, addr, cpu_max_ext_state_size);
+ break;
+
+ case PT_SETXSTATE:
+ if (data > cpu_max_ext_state_size) {
+ error = EINVAL;
+ break;
+ }
+ savefpu = malloc(data, M_TEMP, M_WAITOK);
+ error = copyin(addr, savefpu, data);
+ if (error == 0)
+ error = fpusetregs(td, (struct savefpu *)savefpu,
+ savefpu + sizeof(struct savefpu), data -
+ sizeof(struct savefpu));
+ free(savefpu, M_TEMP);
+ break;
+
default:
error = EINVAL;
break;
@@ -81,8 +112,6 @@
#ifdef COMPAT_FREEBSD32
#define PT_I386_GETXMMREGS (PT_FIRSTMACH + 0)
#define PT_I386_SETXMMREGS (PT_FIRSTMACH + 1)
-#define PT_I386_GETXSTATE (PT_FIRSTMACH + 2)
-#define PT_I386_SETXSTATE (PT_FIRSTMACH + 3)
static int
cpu32_ptrace(struct thread *td, int req, void *addr, int data)
@@ -104,12 +133,12 @@
fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
break;
- case PT_I386_GETXSTATE:
- error = cpu_ptrace_xstate(td, PT_GETXSTATE, addr, data);
- break;
-
- case PT_I386_SETXSTATE:
- error = cpu_ptrace_xstate(td, PT_SETXSTATE, addr, data);
+ case PT_GETXSTATE_OLD:
+ case PT_SETXSTATE_OLD:
+ case PT_GETXSTATE_INFO:
+ case PT_GETXSTATE:
+ case PT_SETXSTATE:
+ error = cpu_ptrace_xstate(td, req, addr, data);
break;
default:
@@ -131,13 +160,16 @@
return (cpu32_ptrace(td, req, addr, data));
#endif
- /* Support old values of PT_GETXSTATE and PT_SETXSTATE. */
+ /* Support old values of PT_GETXSTATE_OLD and PT_SETXSTATE_OLD. */
if (req == PT_FIRSTMACH + 0)
- req = PT_GETXSTATE;
+ req = PT_GETXSTATE_OLD;
if (req == PT_FIRSTMACH + 1)
- req = PT_SETXSTATE;
+ req = PT_SETXSTATE_OLD;
switch (req) {
+ case PT_GETXSTATE_OLD:
+ case PT_SETXSTATE_OLD:
+ case PT_GETXSTATE_INFO:
case PT_GETXSTATE:
case PT_SETXSTATE:
error = cpu_ptrace_xstate(td, req, addr, data);
Index: head/sys/compat/ia32/ia32_sysvec.c
===================================================================
--- head/sys/compat/ia32/ia32_sysvec.c
+++ head/sys/compat/ia32/ia32_sysvec.c
@@ -187,9 +187,25 @@
&kia32_brand_info);
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)
{
+ void *buf;
+ size_t len;
+
+ len = 0;
+ if (use_xsave) {
+ if (dst != NULL) {
+ fpugetregs(td);
+ len += elf32_populate_note(NT_X86_XSTATE,
+ get_pcb_user_save_td(td), dst,
+ cpu_max_ext_state_size, &buf);
+ *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) =
+ xsave_mask;
+ } else
+ len += elf32_populate_note(NT_X86_XSTATE, NULL, NULL,
+ cpu_max_ext_state_size, NULL);
+ }
+ *off = len;
}
void
Index: head/sys/i386/i386/elf_machdep.c
===================================================================
--- head/sys/i386/i386/elf_machdep.c
+++ head/sys/i386/i386/elf_machdep.c
@@ -45,6 +45,7 @@
#include <machine/elf.h>
#include <machine/md_var.h>
+#include <machine/npx.h>
struct sysentvec elf32_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
@@ -134,11 +135,26 @@
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)
{
-}
+ void *buf;
+ size_t len;
+ len = 0;
+ if (use_xsave) {
+ if (dst != NULL) {
+ npxgetregs(td);
+ len += elf32_populate_note(NT_X86_XSTATE,
+ get_pcb_user_save_td(td), dst,
+ cpu_max_ext_state_size, &buf);
+ *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) =
+ xsave_mask;
+ } else
+ len += elf32_populate_note(NT_X86_XSTATE, NULL, NULL,
+ cpu_max_ext_state_size, NULL);
+ }
+ *off = len;
+}
/* Process one elf relocation with addend. */
static int
Index: head/sys/i386/i386/ptrace_machdep.c
===================================================================
--- head/sys/i386/i386/ptrace_machdep.c
+++ head/sys/i386/i386/ptrace_machdep.c
@@ -46,6 +46,7 @@
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
{
+ struct ptrace_xstate_info info;
char *savefpu;
int error;
@@ -53,14 +54,14 @@
return (EOPNOTSUPP);
switch (req) {
- case PT_GETXSTATE:
+ case PT_GETXSTATE_OLD:
npxgetregs(td);
savefpu = (char *)(get_pcb_user_save_td(td) + 1);
error = copyout(savefpu, addr,
cpu_max_ext_state_size - sizeof(union savefpu));
break;
- case PT_SETXSTATE:
+ case PT_SETXSTATE_OLD:
if (data > cpu_max_ext_state_size - sizeof(union savefpu)) {
error = EINVAL;
break;
@@ -74,6 +75,36 @@
free(savefpu, M_TEMP);
break;
+ case PT_GETXSTATE_INFO:
+ if (data != sizeof(info)) {
+ error = EINVAL;
+ break;
+ }
+ info.xsave_len = cpu_max_ext_state_size;
+ info.xsave_mask = xsave_mask;
+ error = copyout(&info, addr, data);
+ break;
+
+ case PT_GETXSTATE:
+ npxgetregs(td);
+ savefpu = (char *)(get_pcb_user_save_td(td));
+ error = copyout(savefpu, addr, cpu_max_ext_state_size);
+ break;
+
+ case PT_SETXSTATE:
+ if (data > cpu_max_ext_state_size) {
+ error = EINVAL;
+ break;
+ }
+ savefpu = malloc(data, M_TEMP, M_WAITOK);
+ error = copyin(addr, savefpu, data);
+ if (error == 0)
+ error = npxsetregs(td, (union savefpu *)savefpu,
+ savefpu + sizeof(union savefpu), data -
+ sizeof(union savefpu));
+ free(savefpu, M_TEMP);
+ break;
+
default:
error = EINVAL;
break;
@@ -106,6 +137,9 @@
fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
break;
+ case PT_GETXSTATE_OLD:
+ case PT_SETXSTATE_OLD:
+ case PT_GETXSTATE_INFO:
case PT_GETXSTATE:
case PT_SETXSTATE:
error = cpu_ptrace_xstate(td, req, addr, data);
Index: head/sys/i386/isa/npx.c
===================================================================
--- head/sys/i386/isa/npx.c
+++ head/sys/i386/isa/npx.c
@@ -201,6 +201,13 @@
*/
CTASSERT(sizeof(struct pcb) % XSAVE_AREA_ALIGN == 0);
+/*
+ * Ensure the copy of XCR0 saved in a core is contained in the padding
+ * area.
+ */
+CTASSERT(X86_XSTATE_XCR0_OFFSET >= offsetof(struct savexmm, sv_pad) &&
+ X86_XSTATE_XCR0_OFFSET + sizeof(uint64_t) <= sizeof(struct savexmm));
+
static void fpu_clean_state(void);
#endif
Index: head/sys/kern/imgact_elf.c
===================================================================
--- head/sys/kern/imgact_elf.c
+++ head/sys/kern/imgact_elf.c
@@ -1587,7 +1587,50 @@
return (size);
notesize = sizeof(Elf_Note) + /* note header */
- roundup2(8, ELF_NOTE_ROUNDSIZE) + /* note name ("FreeBSD") */
+ roundup2(sizeof(FREEBSD_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) +
+ /* note name */
+ roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */
+
+ return (notesize);
+}
+
+static size_t
+append_note_data(const void *src, void *dst, size_t len)
+{
+ size_t padded_len;
+
+ padded_len = roundup2(len, ELF_NOTE_ROUNDSIZE);
+ if (dst != NULL) {
+ bcopy(src, dst, len);
+ bzero((char *)dst + len, padded_len - len);
+ }
+ return (padded_len);
+}
+
+size_t
+__elfN(populate_note)(int type, void *src, void *dst, size_t size, void **descp)
+{
+ Elf_Note *note;
+ char *buf;
+ size_t notesize;
+
+ buf = dst;
+ if (buf != NULL) {
+ note = (Elf_Note *)buf;
+ note->n_namesz = sizeof(FREEBSD_ABI_VENDOR);
+ note->n_descsz = size;
+ note->n_type = type;
+ buf += sizeof(*note);
+ buf += append_note_data(FREEBSD_ABI_VENDOR, buf,
+ sizeof(FREEBSD_ABI_VENDOR));
+ append_note_data(src, buf, size);
+ if (descp != NULL)
+ *descp = buf;
+ }
+
+ notesize = sizeof(Elf_Note) + /* note header */
+ roundup2(sizeof(FREEBSD_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) +
+ /* note name */
roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */
return (notesize);
@@ -1604,13 +1647,13 @@
return;
}
- note.n_namesz = 8; /* strlen("FreeBSD") + 1 */
+ note.n_namesz = sizeof(FREEBSD_ABI_VENDOR);
note.n_descsz = ninfo->outsize;
note.n_type = ninfo->type;
sbuf_bcat(sb, &note, sizeof(note));
sbuf_start_section(sb, &old_len);
- sbuf_bcat(sb, "FreeBSD", note.n_namesz);
+ sbuf_bcat(sb, FREEBSD_ABI_VENDOR, sizeof(FREEBSD_ABI_VENDOR));
sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0);
if (note.n_descsz == 0)
return;
Index: head/sys/sys/elf_common.h
===================================================================
--- head/sys/sys/elf_common.h
+++ head/sys/sys/elf_common.h
@@ -508,6 +508,7 @@
#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */
#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
+#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
/* Symbol Binding - ELFNN_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */
Index: head/sys/sys/imgact_elf.h
===================================================================
--- head/sys/sys/imgact_elf.h
+++ head/sys/sys/imgact_elf.h
@@ -90,6 +90,7 @@
int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
int __elfN(freebsd_fixup)(register_t **, struct image_params *);
int __elfN(coredump)(struct thread *, struct vnode *, off_t, int);
+size_t __elfN(populate_note)(int, void *, void *, size_t, void **);
/* Machine specific function to dump per-thread information. */
void __elfN(dump_thread)(struct thread *, void *, size_t *);
Index: head/sys/x86/include/fpu.h
===================================================================
--- head/sys/x86/include/fpu.h
+++ head/sys/x86/include/fpu.h
@@ -63,15 +63,7 @@
struct env87 sv_env; /* floating point control/status */
struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
uint8_t sv_pad0[4]; /* saved status word (now unused) */
- /*
- * Bogus padding for emulators. Emulators should use their own
- * struct and arrange to store into this struct (ending here)
- * before it is inspected for ptracing or for core dumps. Some
- * emulators overwrite the whole struct. We have no good way of
- * knowing how much padding to leave. Leave just enough for the
- * GPL emulator's i387_union (176 bytes total).
- */
- uint8_t sv_pad[64]; /* padding; used by emulators */
+ uint8_t sv_pad[64];
};
/* Contents of each SSE extended accumulator. */
@@ -215,4 +207,11 @@
#define __INITIAL_MXCSR__ 0x1F80
#define __INITIAL_MXCSR_MASK__ 0xFFBF
+/*
+ * The current value of %xcr0 is saved in the sv_pad[] field of the FPU
+ * state in the NT_X86_XSTATE note in core dumps. This offset is chosen
+ * to match the offset used by NT_X86_XSTATE in other systems.
+ */
+#define X86_XSTATE_XCR0_OFFSET 464
+
#endif /* !_X86_FPU_H_ */
Index: head/sys/x86/include/ptrace.h
===================================================================
--- head/sys/x86/include/ptrace.h
+++ head/sys/x86/include/ptrace.h
@@ -37,14 +37,25 @@
/*
* On amd64 (PT_FIRSTMACH + 0) and (PT_FIRSTMACH + 1) are old values for
- * PT_GETXSTATE and PT_SETXSTATE. They should not be (re)used.
+ * PT_GETXSTATE_OLD and PT_SETXSTATE_OLD. They should not be (re)used.
*/
#ifdef __i386__
#define PT_GETXMMREGS (PT_FIRSTMACH + 0)
#define PT_SETXMMREGS (PT_FIRSTMACH + 1)
#endif
-#define PT_GETXSTATE (PT_FIRSTMACH + 2)
-#define PT_SETXSTATE (PT_FIRSTMACH + 3)
+#ifdef _KERNEL
+#define PT_GETXSTATE_OLD (PT_FIRSTMACH + 2)
+#define PT_SETXSTATE_OLD (PT_FIRSTMACH + 3)
+#endif
+#define PT_GETXSTATE_INFO (PT_FIRSTMACH + 4)
+#define PT_GETXSTATE (PT_FIRSTMACH + 5)
+#define PT_SETXSTATE (PT_FIRSTMACH + 6)
+
+/* Argument structure for PT_GETXSTATE_INFO. */
+struct ptrace_xstate_info {
+ uint64_t xsave_mask;
+ uint32_t xsave_len;
+};
#endif
Index: head/usr.bin/gcore/elfcore.c
===================================================================
--- head/usr.bin/gcore/elfcore.c
+++ head/usr.bin/gcore/elfcore.c
@@ -47,6 +47,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -101,6 +102,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 *);
+#if defined(__i386__) || defined(__amd64__)
+static void *elf_note_x86_xstate(void *, size_t *);
+#endif
static void *elf_note_procstat_auxv(void *, size_t *);
static void *elf_note_procstat_files(void *, size_t *);
static void *elf_note_procstat_groups(void *, size_t *);
@@ -341,6 +345,9 @@
elf_putnote(NT_PRSTATUS, elf_note_prstatus, tids + i, sb);
elf_putnote(NT_FPREGSET, elf_note_fpregset, tids + i, sb);
elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb);
+#if defined(__i386__) || defined(__amd64__)
+ elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);
+#endif
}
#ifndef ELFCORE_COMPAT_32
@@ -615,6 +622,34 @@
return (thrmisc);
}
+#if defined(__i386__) || defined(__amd64__)
+static void *
+elf_note_x86_xstate(void *arg, size_t *sizep)
+{
+ lwpid_t tid;
+ char *xstate;
+ static bool xsave_checked = false;
+ static struct ptrace_xstate_info info;
+
+ tid = *(lwpid_t *)arg;
+ if (!xsave_checked) {
+ if (ptrace(PT_GETXSTATE_INFO, tid, (void *)&info,
+ sizeof(info)) != 0)
+ info.xsave_len = 0;
+ xsave_checked = true;
+ }
+ if (info.xsave_len == 0) {
+ *sizep = 0;
+ return (NULL);
+ }
+ xstate = calloc(1, info.xsave_len);
+ ptrace(PT_GETXSTATE, tid, xstate, 0);
+ *(uint64_t *)(xstate + X86_XSTATE_XCR0_OFFSET) = info.xsave_mask;
+ *sizep = info.xsave_len;
+ return (xstate);
+}
+#endif
+
static void *
procstat_sysctl(void *arg, int what, size_t structsz, size_t *sizep)
{

File Metadata

Mime Type
text/plain
Expires
Sun, Jan 19, 7:08 AM (20 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15931936
Default Alt Text
D1193.diff (16 KB)

Event Timeline