Page MenuHomeFreeBSD

D34650.diff
No OneTemporary

D34650.diff

diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c
--- a/contrib/elftoolchain/readelf/readelf.c
+++ b/contrib/elftoolchain/readelf/readelf.c
@@ -1195,6 +1195,7 @@
case 17: return "NT_PTLWPINFO";
case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
+ case 0x200: return "NT_X86_SEGBASES (x86 segment base registers)";
case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
case 0x400: return "NT_ARM_VFP (arm VFP registers)";
case 0x401: return "NT_ARM_TLS (arm TLS register)";
diff --git a/sys/amd64/amd64/ptrace_machdep.c b/sys/amd64/amd64/ptrace_machdep.c
--- a/sys/amd64/amd64/ptrace_machdep.c
+++ b/sys/amd64/amd64/ptrace_machdep.c
@@ -32,11 +32,13 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/elf.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -52,6 +54,106 @@
};
#endif
+static bool
+get_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ struct segbasereg *reg;
+ struct pcb *pcb;
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ if (td == curthread)
+ update_pcb_bases(pcb);
+ reg->r_fsbase = pcb->pcb_fsbase;
+ reg->r_gsbase = pcb->pcb_gsbase;
+ }
+ *sizep = sizeof(*reg);
+ return (true);
+}
+
+static bool
+set_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ struct segbasereg *reg;
+ struct pcb *pcb;
+
+ KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ set_pcb_flags(pcb, PCB_FULL_IRET);
+ pcb->pcb_fsbase = reg->r_fsbase;
+ td->td_frame->tf_fs = _ufssel;
+ pcb->pcb_gsbase = reg->r_gsbase;
+ td->td_frame->tf_gs = _ugssel;
+
+ return (true);
+}
+
+static struct regset regset_segbases = {
+ .note = NT_X86_SEGBASES,
+ .size = sizeof(struct segbasereg),
+ .get = get_segbases,
+ .set = set_segbases,
+};
+ELF_REGSET(regset_segbases);
+
+#ifdef COMPAT_FREEBSD32
+static bool
+get_segbases32(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ struct segbasereg32 *reg;
+ struct pcb *pcb;
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ if (td == curthread)
+ update_pcb_bases(pcb);
+ reg->r_fsbase = (uint32_t)pcb->pcb_fsbase;
+ reg->r_gsbase = (uint32_t)pcb->pcb_gsbase;
+ }
+ *sizep = sizeof(*reg);
+ return (true);
+}
+
+static bool
+set_segbases32(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ struct segbasereg32 *reg;
+ struct pcb *pcb;
+
+ KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ set_pcb_flags(pcb, PCB_FULL_IRET);
+ pcb->pcb_fsbase = reg->r_fsbase;
+ td->td_frame->tf_fs = _ufssel;
+ pcb->pcb_gsbase = reg->r_gsbase;
+ td->td_frame->tf_gs = _ugssel;
+
+ return (true);
+}
+
+static struct regset regset_segbases32 = {
+ .note = NT_X86_SEGBASES,
+ .size = sizeof(struct segbasereg32),
+ .get = get_segbases32,
+ .set = set_segbases32,
+};
+ELF32_REGSET(regset_segbases32);
+#endif
+
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
{
diff --git a/sys/amd64/ia32/ia32_reg.c b/sys/amd64/ia32/ia32_reg.c
--- a/sys/amd64/ia32/ia32_reg.c
+++ b/sys/amd64/ia32/ia32_reg.c
@@ -32,6 +32,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/elf.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
@@ -266,3 +267,52 @@
dr.dr[i] = 0;
return (set_dbregs(td, &dr));
}
+
+static bool
+get_i386_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ struct segbasereg32 *reg;
+ struct pcb *pcb;
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ if (td == curthread)
+ update_pcb_bases(pcb);
+ reg->r_fsbase = pcb->pcb_fsbase;
+ reg->r_gsbase = pcb->pcb_gsbase;
+ }
+ *sizep = sizeof(*reg);
+ return (true);
+}
+
+static bool
+set_i386_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ struct segbasereg32 *reg;
+ struct pcb *pcb;
+
+ KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ pcb = td->td_pcb;
+ set_pcb_flags(pcb, PCB_FULL_IRET);
+ pcb->pcb_fsbase = reg->r_fsbase;
+ td->td_frame->tf_fs = _ufssel;
+ pcb->pcb_gsbase = reg->r_gsbase;
+ td->td_frame->tf_gs = _ugssel;
+
+ return (true);
+}
+
+static struct regset regset_i386_segbases = {
+ .note = NT_X86_SEGBASES,
+ .size = sizeof(struct segbasereg),
+ .get = get_i386_segbases,
+ .set = set_i386_segbases,
+};
+ELF32_REGSET(regset_i386_segbases);
diff --git a/sys/i386/i386/ptrace_machdep.c b/sys/i386/i386/ptrace_machdep.c
--- a/sys/i386/i386/ptrace_machdep.c
+++ b/sys/i386/i386/ptrace_machdep.c
@@ -34,15 +34,64 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/elf.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
+#include <sys/reg.h>
#include <machine/frame.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+static uint32_t
+get_segbase(struct segment_descriptor *sdp)
+{
+ return (sdp->sd_hibase << 24 | sdp->sd_lobase);
+}
+
+static bool
+get_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ struct segbasereg *reg;
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+ reg->r_fsbase = get_segbase(&td->td_pcb->pcb_fsd);
+ reg->r_gsbase = get_segbase(&td->td_pcb->pcb_gsd);
+ }
+ *sizep = sizeof(*reg);
+ return (true);
+}
+
+static bool
+set_segbases(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ struct segbasereg *reg;
+
+ KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__));
+ reg = buf;
+
+ fill_based_sd(&td->td_pcb->pcb_fsd, reg->r_fsbase);
+ td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL);
+ fill_based_sd(&td->td_pcb->pcb_gsd, reg->r_gsbase);
+ td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL);
+
+ return (true);
+}
+
+static struct regset regset_segbases = {
+ .note = NT_X86_SEGBASES,
+ .size = sizeof(struct segbasereg),
+ .get = get_segbases,
+ .set = set_segbases,
+};
+ELF_REGSET(regset_segbases);
+
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
{
@@ -173,7 +222,7 @@
case PT_GETGSBASE:
sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd :
&td->td_pcb->pcb_gsd;
- r = sdp->sd_hibase << 24 | sdp->sd_lobase;
+ r = get_segbase(sdp);
error = copyout(&r, addr, sizeof(r));
break;
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -823,6 +823,7 @@
#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */
#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
#define NT_ARM_VFP 0x400 /* ARM VFP registers */
#define NT_ARM_TLS 0x401 /* ARM TLS register */
diff --git a/sys/x86/include/reg.h b/sys/x86/include/reg.h
--- a/sys/x86/include/reg.h
+++ b/sys/x86/include/reg.h
@@ -86,6 +86,7 @@
#define __reg32 reg
#define __fpreg32 fpreg
#define __dbreg32 dbreg
+#define __segbasereg32 segbasereg
#else
#define __reg32 reg32
#define __reg64 reg
@@ -93,6 +94,8 @@
#define __fpreg64 fpreg
#define __dbreg32 dbreg32
#define __dbreg64 dbreg
+#define __segbasereg32 segbasereg32
+#define __segbasereg64 segbasereg
#define __HAVE_REG32
#endif
@@ -236,12 +239,27 @@
#define DBREG_DRX(d,x) ((d)->dr[(x)]) /* reference dr0 - dr7 by
register number */
+/*
+ * Register set accessible via NT_X86_SEGBASES.
+ */
+struct __segbasereg32 {
+ __uint32_t r_fsbase;
+ __uint32_t r_gsbase;
+};
+
+struct __segbasereg64 {
+ __uint64_t r_fsbase;
+ __uint64_t r_gsbase;
+};
+
#undef __reg32
#undef __reg64
#undef __fpreg32
#undef __fpreg64
#undef __dbreg32
#undef __dbreg64
+#undef __segbasereg32
+#undef __segbasereg64
#ifdef _KERNEL
/*
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -379,6 +379,7 @@
elf_putregnote(NT_ARM_VFP, tids[i], sb);
#endif
#if defined(__i386__) || defined(__amd64__)
+ elf_putregnote(NT_X86_SEGBASES, tids[i], sb);
elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);
#endif
#if defined(__powerpc__)

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 3, 4:24 PM (22 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13375990
Default Alt Text
D34650.diff (8 KB)

Event Timeline