tech-toolchain archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Base GDB tracing 32bit applications on amd64 kernel (with 64bit debugger) part 1)
Hi,
with the attached patch against -current, backtraces work again.
List of commits touched:
4b66e9c074e39cd67a49386318770ebc2a6edf82
030b2742098c17c9bd99e797fff5f1c820d6edfe
4cab1e757c7197a01b6dc268c0104fa43ab7f0aa
5542798943417f4d1bdb61d0a49a9f8c1c37445c
ef20f297e5f1527c1b54d4b2de8280a6cca21c71
80d084c7ddc1104b2bf191ccaa8a5347e71253ef
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index bc2c087b7b..b0977b30b1 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -2095,40 +2095,49 @@ cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
int
cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
{
- struct proc *p __diagused = l->l_proc;
+ struct proc *p = l->l_proc;
struct trapframe *tf = l->l_md.md_regs;
const __greg_t *gr;
uint16_t sel;
+ const bool pk32 = (p->p_flag & PK_32) != 0;
- KASSERT((p->p_flag & PK_32) == 0);
gr = mcp->__gregs;
if (((gr[_REG_RFLAGS] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
return EINVAL;
+
+#define VUD(sel) (pk32 ? VALID_USER_DSEL32(sel) : VALID_USER_DSEL(sel))
+#define VUF(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_FSEL32(sel)) \
+ : VALID_USER_DSEL(sel))
+#define VUG(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_GSEL32(sel)) \
+ : VALID_USER_DSEL(sel))
+#define VUC(sel) (pk32 ? VALID_USER_CSEL32(sel) : VALID_USER_CSEL(sel))
+
+
sel = gr[_REG_ES] & 0xffff;
- if (sel != 0 && !VALID_USER_DSEL(sel))
+ if (sel != 0 && !VUD(sel))
return EINVAL;
sel = gr[_REG_FS] & 0xffff;
- if (sel != 0 && !VALID_USER_DSEL(sel))
+ if (sel != 0 && !VUF(sel))
return EINVAL;
sel = gr[_REG_GS] & 0xffff;
- if (sel != 0 && !VALID_USER_DSEL(sel))
+ if (sel != 0 && !VUG(sel))
return EINVAL;
sel = gr[_REG_DS] & 0xffff;
- if (!VALID_USER_DSEL(sel))
+ if (!VUD(sel))
return EINVAL;
#ifndef XENPV
sel = gr[_REG_SS] & 0xffff;
- if (!VALID_USER_DSEL(sel))
+ if (!VUD(sel))
return EINVAL;
sel = gr[_REG_CS] & 0xffff;
- if (!VALID_USER_CSEL(sel))
+ if (!VUC(sel))
return EINVAL;
#endif
diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c
index c204556c91..500a96331e 100644
--- a/sys/arch/amd64/amd64/process_machdep.c
+++ b/sys/arch/amd64/amd64/process_machdep.c
@@ -100,42 +100,48 @@ process_frame(struct lwp *l)
}
int
-process_read_regs(struct lwp *l, struct reg *regs)
+process_read_regs(struct lwp *l, struct reg *regp)
{
struct trapframe *tf = process_frame(l);
- struct proc *p = l->l_proc;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
-
- regs->regs[_REG_RDI] = tf->tf_rdi;
- regs->regs[_REG_RSI] = tf->tf_rsi;
- regs->regs[_REG_RDX] = tf->tf_rdx;
- regs->regs[_REG_R10] = tf->tf_r10;
- regs->regs[_REG_R8] = tf->tf_r8;
- regs->regs[_REG_R9] = tf->tf_r9;
+ long *regs = regp->regs;
+ const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
+
+ regs[_REG_RDI] = tf->tf_rdi;
+ regs[_REG_RSI] = tf->tf_rsi;
+ regs[_REG_RDX] = tf->tf_rdx;
+ regs[_REG_R10] = tf->tf_r10;
+ regs[_REG_R8] = tf->tf_r8;
+ regs[_REG_R9] = tf->tf_r9;
/* argX not touched */
- regs->regs[_REG_RCX] = tf->tf_rcx;
- regs->regs[_REG_R11] = tf->tf_r11;
- regs->regs[_REG_R12] = tf->tf_r12;
- regs->regs[_REG_R13] = tf->tf_r13;
- regs->regs[_REG_R14] = tf->tf_r14;
- regs->regs[_REG_R15] = tf->tf_r15;
- regs->regs[_REG_RBP] = tf->tf_rbp;
- regs->regs[_REG_RBX] = tf->tf_rbx;
- regs->regs[_REG_RAX] = tf->tf_rax;
- regs->regs[_REG_GS] = 0;
- regs->regs[_REG_FS] = 0;
- regs->regs[_REG_ES] = GSEL(GUDATA_SEL, SEL_UPL);
- regs->regs[_REG_DS] = GSEL(GUDATA_SEL, SEL_UPL);
- regs->regs[_REG_TRAPNO] = tf->tf_trapno;
- regs->regs[_REG_ERR] = tf->tf_err;
- regs->regs[_REG_RIP] = tf->tf_rip;
- regs->regs[_REG_CS] = LSEL(LUCODE_SEL, SEL_UPL);
- regs->regs[_REG_RFLAGS] = tf->tf_rflags;
- regs->regs[_REG_RSP] = tf->tf_rsp;
- regs->regs[_REG_SS] = LSEL(LUDATA_SEL, SEL_UPL);
+ regs[_REG_RCX] = tf->tf_rcx;
+ regs[_REG_R11] = tf->tf_r11;
+ regs[_REG_R12] = tf->tf_r12;
+ regs[_REG_R13] = tf->tf_r13;
+ regs[_REG_R14] = tf->tf_r14;
+ regs[_REG_R15] = tf->tf_r15;
+ regs[_REG_RBP] = tf->tf_rbp;
+ regs[_REG_RBX] = tf->tf_rbx;
+ regs[_REG_RAX] = tf->tf_rax;
+ if (pk32) {
+ regs[_REG_GS] = tf->tf_gs & 0xffff;
+ regs[_REG_FS] = tf->tf_fs & 0xffff;
+ regs[_REG_ES] = tf->tf_es & 0xffff;
+ regs[_REG_DS] = tf->tf_ds & 0xffff;
+ regs[_REG_CS] = tf->tf_cs & 0xffff;
+ regs[_REG_SS] = tf->tf_ss & 0xffff;
+ } else {
+ regs[_REG_GS] = 0;
+ regs[_REG_FS] = 0;
+ regs[_REG_ES] = GSEL(GUDATA_SEL, SEL_UPL);
+ regs[_REG_DS] = GSEL(GUDATA_SEL, SEL_UPL);
+ regs[_REG_CS] = LSEL(LUCODE_SEL, SEL_UPL);
+ regs[_REG_SS] = LSEL(LUDATA_SEL, SEL_UPL);
+ }
+ regs[_REG_TRAPNO] = tf->tf_trapno;
+ regs[_REG_ERR] = tf->tf_err;
+ regs[_REG_RIP] = tf->tf_rip;
+ regs[_REG_RFLAGS] = tf->tf_rflags;
+ regs[_REG_RSP] = tf->tf_rsp;
return 0;
}
@@ -143,11 +149,6 @@ process_read_regs(struct lwp *l, struct reg *regs)
int
process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz)
{
- struct proc *p = l->l_proc;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
process_read_fpregs_xmm(l, ®s->fxstate);
@@ -157,11 +158,6 @@ process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz)
int
process_read_dbregs(struct lwp *l, struct dbreg *regs, size_t *sz)
{
- struct proc *p = l->l_proc;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
x86_dbregs_read(l, regs);
@@ -172,13 +168,9 @@ int
process_write_regs(struct lwp *l, const struct reg *regp)
{
struct trapframe *tf = process_frame(l);
- struct proc *p = l->l_proc;
int error;
const long *regs = regp->regs;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
+ const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
/*
* Check for security violations. Note that struct regs is compatible
@@ -204,16 +196,25 @@ process_write_regs(struct lwp *l, const struct reg *regp)
tf->tf_rbp = regs[_REG_RBP];
tf->tf_rbx = regs[_REG_RBX];
tf->tf_rax = regs[_REG_RAX];
- tf->tf_gs = 0;
- tf->tf_fs = 0;
- tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
- tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
+ if (pk32) {
+ tf->tf_gs = regs[_REG_GS] & 0xffff;
+ tf->tf_fs = regs[_REG_FS] & 0xffff;
+ tf->tf_es = regs[_REG_ES] & 0xffff;
+ tf->tf_ds = regs[_REG_DS] & 0xffff;
+ tf->tf_cs = regs[_REG_CS] & 0xffff;
+ tf->tf_ss = regs[_REG_SS] & 0xffff;
+ } else {
+ tf->tf_gs = 0;
+ tf->tf_fs = 0;
+ tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
+ tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
+ tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
+ tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
+ }
/* trapno, err not touched */
tf->tf_rip = regs[_REG_RIP];
- tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
tf->tf_rflags = regs[_REG_RFLAGS];
tf->tf_rsp = regs[_REG_RSP];
- tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
#ifdef XENPV
/* see comment in cpu_setmcontext */
@@ -227,11 +228,6 @@ process_write_regs(struct lwp *l, const struct reg *regp)
int
process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz)
{
- struct proc *p = l->l_proc;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
process_write_fpregs_xmm(l, ®s->fxstate);
return 0;
@@ -240,13 +236,8 @@ process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz)
int
process_write_dbregs(struct lwp *l, const struct dbreg *regs, size_t sz)
{
- struct proc *p = l->l_proc;
int error;
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
-
/*
* Check for security violations.
*/
@@ -276,11 +267,6 @@ int
process_set_pc(struct lwp *l, void *addr)
{
struct trapframe *tf = process_frame(l);
- struct proc *p = l->l_proc;
-
- if (p->p_flag & PK_32) {
- return EINVAL;
- }
if ((uint64_t)addr >= VM_MAXUSER_ADDRESS)
return EINVAL;
diff --git a/sys/kern/sys_ptrace_common.c b/sys/kern/sys_ptrace_common.c
index d77a3453d8..b7f3e25ff3 100644
--- a/sys/kern/sys_ptrace_common.c
+++ b/sys/kern/sys_ptrace_common.c
@@ -124,7 +124,6 @@ __KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.55 2019/06/11 23:18:55 kamil
#include "opt_ptrace.h"
#include "opt_ktrace.h"
#include "opt_pax.h"
-#include "opt_compat_netbsd32.h"
#endif
#if defined(__HAVE_COMPAT_NETBSD32) && !defined(COMPAT_NETBSD32) \
@@ -820,7 +819,7 @@ ptrace_regs(struct lwp *l, struct lwp **lt, int rq, struct ptrace_methods *ptm,
void *addr, size_t data)
{
int error;
- struct proc *t = (*lt)->l_proc;
+ struct proc *t = l->l_proc;
struct vmspace *vm;
if ((error = ptrace_update_lwp(t, lt, data)) != 0)
@@ -864,7 +863,7 @@ ptrace_regs(struct lwp *l, struct lwp **lt, int rq, struct ptrace_methods *ptm,
return EINVAL;
}
- error = proc_vmspace_getref(l->l_proc, &vm);
+ error = proc_vmspace_getref(t, &vm);
if (error)
return error;
@@ -1432,71 +1431,40 @@ out:
return error;
}
-typedef int (*regrfunc_t)(struct lwp *, void *, size_t *);
-typedef int (*regwfunc_t)(struct lwp *, void *, size_t);
-
-#ifdef PT_REGISTERS
-static int
-proc_regio(struct lwp *l, struct uio *uio, size_t ks, regrfunc_t r,
- regwfunc_t w)
+int
+process_doregs(struct lwp *curl /*tracer*/,
+ struct lwp *l /*traced*/,
+ struct uio *uio)
{
- char buf[1024];
+#if defined(PT_GETREGS) || defined(PT_SETREGS)
int error;
+ struct reg r;
char *kv;
- size_t kl;
-
- if (ks > sizeof(buf))
- return E2BIG;
+ int kl;
- if (uio->uio_offset < 0 || uio->uio_offset > (off_t)ks)
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
return EINVAL;
- kv = buf + uio->uio_offset;
- kl = ks - uio->uio_offset;
+ kl = sizeof(r);
+ kv = (char *)&r;
- if (kl > uio->uio_resid)
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if ((size_t)kl > uio->uio_resid)
kl = uio->uio_resid;
- error = (*r)(l, buf, &ks);
+ error = process_read_regs(l, &r);
if (error == 0)
error = uiomove(kv, kl, uio);
if (error == 0 && uio->uio_rw == UIO_WRITE) {
if (l->l_stat != LSSTOP)
error = EBUSY;
else
- error = (*w)(l, buf, ks);
+ error = process_write_regs(l, &r);
}
uio->uio_offset = 0;
return error;
-}
-#endif
-
-int
-process_doregs(struct lwp *curl /*tracer*/,
- struct lwp *l /*traced*/,
- struct uio *uio)
-{
-#if defined(PT_GETREGS) || defined(PT_SETREGS)
- size_t s;
- regrfunc_t r;
- regwfunc_t w;
-
-#ifdef COMPAT_NETBSD32
- const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
-
- if (__predict_false(pk32)) {
- s = sizeof(process_reg32);
- r = (regrfunc_t)process_read_regs32;
- w = (regwfunc_t)process_write_regs32;
- } else
-#endif
- {
- s = sizeof(struct reg);
- r = (regrfunc_t)process_read_regs;
- w = (regwfunc_t)process_write_regs;
- }
- return proc_regio(l, uio, s, r, w);
#else
return EINVAL;
#endif
@@ -1519,25 +1487,33 @@ process_dofpregs(struct lwp *curl /*tracer*/,
struct uio *uio)
{
#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
- size_t s;
- regrfunc_t r;
- regwfunc_t w;
-
-#ifdef COMPAT_NETBSD32
- const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
-
- if (__predict_false(pk32)) {
- s = sizeof(process_fpreg32);
- r = (regrfunc_t)process_read_fpregs32;
- w = (regwfunc_t)process_write_fpregs32;
- } else
-#endif
- {
- s = sizeof(struct fpreg);
- r = (regrfunc_t)process_read_fpregs;
- w = (regwfunc_t)process_write_fpregs;
+ int error;
+ struct fpreg r;
+ char *kv;
+ size_t kl;
+
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
+ return EINVAL;
+
+ kl = sizeof(r);
+ kv = (char *)&r;
+
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if (kl > uio->uio_resid)
+ kl = uio->uio_resid;
+
+ error = process_read_fpregs(l, &r, &kl);
+ if (error == 0)
+ error = uiomove(kv, kl, uio);
+ if (error == 0 && uio->uio_rw == UIO_WRITE) {
+ if (l->l_stat != LSSTOP)
+ error = EBUSY;
+ else
+ error = process_write_fpregs(l, &r, kl);
}
- return proc_regio(l, uio, s, r, w);
+ uio->uio_offset = 0;
+ return error;
#else
return EINVAL;
#endif
@@ -1560,25 +1536,33 @@ process_dodbregs(struct lwp *curl /*tracer*/,
struct uio *uio)
{
#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS)
- size_t s;
- regrfunc_t r;
- regwfunc_t w;
-
-#ifdef COMPAT_NETBSD32
- const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
-
- if (__predict_false(pk32)) {
- s = sizeof(process_dbreg32);
- r = (regrfunc_t)process_read_dbregs32;
- w = (regwfunc_t)process_write_dbregs32;
- } else
-#endif
- {
- s = sizeof(struct dbreg);
- r = (regrfunc_t)process_read_dbregs;
- w = (regwfunc_t)process_write_dbregs;
+ int error;
+ struct dbreg r;
+ char *kv;
+ size_t kl;
+
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
+ return EINVAL;
+
+ kl = sizeof(r);
+ kv = (char *)&r;
+
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if (kl > uio->uio_resid)
+ kl = uio->uio_resid;
+
+ error = process_read_dbregs(l, &r, &kl);
+ if (error == 0)
+ error = uiomove(kv, kl, uio);
+ if (error == 0 && uio->uio_rw == UIO_WRITE) {
+ if (l->l_stat != LSSTOP)
+ error = EBUSY;
+ else
+ error = process_write_dbregs(l, &r, kl);
}
- return proc_regio(l, uio, s, r, w);
+ uio->uio_offset = 0;
+ return error;
#else
return EINVAL;
#endif
Home |
Main Index |
Thread Index |
Old Index