Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111613777
D34650.id104176.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D34650.id104176.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 7, 12:51 AM (16 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17015458
Default Alt Text
D34650.id104176.diff (8 KB)
Attached To
Mode
D34650: x86: Add a NT_X86_SEGBASES register set.
Attached
Detach File
Event Timeline
Log In to Comment