summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/trap.c176
-rw-r--r--sys/amd64/ia32/ia32_syscall.c149
-rw-r--r--sys/i386/i386/trap.c165
-rw-r--r--sys/kern/sys_process.c5
-rw-r--r--sys/sys/proc.h1
5 files changed, 306 insertions, 190 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index df301d1..bd7ee63 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -885,95 +885,131 @@ dblfault_handler(struct trapframe *frame)
panic("double fault");
}
-/*
- * syscall - system call request C handler
- *
- * A system call is essentially treated as a trap.
- */
-void
-syscall(struct trapframe *frame)
-{
- caddr_t params;
+struct syscall_args {
+ u_int code;
struct sysent *callp;
- struct thread *td = curthread;
- struct proc *p = td->td_proc;
- register_t orig_tf_rflags;
- int error;
- int narg;
register_t args[8];
register_t *argp;
- u_int code;
- int reg, regcnt;
- ksiginfo_t ksi;
-
- PCPU_INC(cnt.v_syscall);
+ int narg;
+};
-#ifdef DIAGNOSTIC
- if (ISPL(frame->tf_cs) != SEL_UPL) {
- panic("syscall");
- /* NOT REACHED */
- }
-#endif
+static int
+fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ struct trapframe *frame;
+ caddr_t params;
+ int reg, regcnt, error;
+ p = td->td_proc;
+ frame = td->td_frame;
reg = 0;
regcnt = 6;
- td->td_pticks = 0;
- td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
+
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
- code = frame->tf_rax;
- orig_tf_rflags = frame->tf_rflags;
+ sa->code = frame->tf_rax;
if (p->p_sysent->sv_prepsyscall) {
- (*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, &params);
+ (*p->p_sysent->sv_prepsyscall)(frame, (int *)sa->args,
+ &sa->code, &params);
} else {
- if (code == SYS_syscall || code == SYS___syscall) {
- code = frame->tf_rdi;
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+ sa->code = frame->tf_rdi;
reg++;
regcnt--;
}
}
-
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
+ sa->code &= p->p_sysent->sv_mask;
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
else
- callp = &p->p_sysent->sv_table[code];
+ sa->callp = &p->p_sysent->sv_table[sa->code];
- narg = callp->sy_narg;
- KASSERT(narg <= sizeof(args) / sizeof(args[0]),
+ sa->narg = sa->callp->sy_narg;
+ KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
("Too many syscall arguments!"));
error = 0;
- argp = &frame->tf_rdi;
- argp += reg;
- bcopy(argp, args, sizeof(args[0]) * regcnt);
- if (narg > regcnt) {
+ sa->argp = &frame->tf_rdi;
+ sa->argp += reg;
+ bcopy(sa->argp, sa->args, sizeof(sa->args[0]) * regcnt);
+ if (sa->narg > regcnt) {
KASSERT(params != NULL, ("copyin args with no params!"));
- error = copyin(params, &args[regcnt],
- (narg - regcnt) * sizeof(args[0]));
+ error = copyin(params, &sa->args[regcnt],
+ (sa->narg - regcnt) * sizeof(sa->args[0]));
}
- argp = &args[0];
+ sa->argp = &sa->args[0];
+ /*
+ * This may result in two records if debugger modified
+ * registers or memory during sleep at stop/ptrace point.
+ */
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, argp);
+ ktrsyscall(sa->code, sa->narg, sa->argp);
#endif
+ return (error);
+}
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
+/*
+ * syscall - system call request C handler
+ *
+ * A system call is essentially treated as a trap.
+ */
+void
+syscall(struct trapframe *frame)
+{
+ struct thread *td;
+ struct proc *p;
+ struct syscall_args sa;
+ register_t orig_tf_rflags;
+ int error;
+ ksiginfo_t ksi;
+ PCPU_INC(cnt.v_syscall);
+ td = curthread;
+ p = td->td_proc;
td->td_syscalls++;
+#ifdef DIAGNOSTIC
+ if (ISPL(frame->tf_cs) != SEL_UPL) {
+ panic("syscall");
+ /* NOT REACHED */
+ }
+#endif
+
+ td->td_pticks = 0;
+ td->td_frame = frame;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ orig_tf_rflags = frame->tf_rflags;
+ if (p->p_flag & P_TRACED) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_USERWR;
+ PROC_UNLOCK(p);
+ }
+ error = fetch_syscall_args(td, &sa);
+
+ CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_name, sa.code);
+
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_rdx;
- STOPEVENT(p, S_SCE, narg);
-
+ STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
+ if (td->td_dbgflags & TDB_USERWR) {
+ /*
+ * Reread syscall number and arguments if
+ * debugger modified registers or memory.
+ */
+ error = fetch_syscall_args(td, &sa);
+ if (error != 0)
+ goto retval;
+ td->td_retval[1] = frame->tf_rdx;
+ }
#ifdef KDTRACE_HOOKS
/*
@@ -981,13 +1017,13 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'entry', process the probe.
*/
- if (systrace_probe_func != NULL && callp->sy_entry != 0)
- (*systrace_probe_func)(callp->sy_entry, code, callp,
- args);
+ if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
+ (*systrace_probe_func)(sa.callp->sy_entry, sa.code,
+ sa.callp, sa.args);
#endif
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, argp);
+ AUDIT_SYSCALL_ENTER(sa.code, td);
+ error = (*sa.callp->sy_call)(td, sa.argp);
AUDIT_SYSCALL_EXIT(error, td);
/* Save the latest error return value. */
@@ -999,12 +1035,12 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'return', process the probe.
*/
- if (systrace_probe_func != NULL && callp->sy_return != 0)
- (*systrace_probe_func)(callp->sy_return, code, callp,
- args);
+ if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
+ (*systrace_probe_func)(sa.callp->sy_return, sa.code,
+ sa.callp, sa.args);
#endif
}
-
+ retval:
cpu_set_syscall_retval(td, error);
/*
@@ -1023,14 +1059,16 @@ syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@@ -1038,11 +1076,11 @@ syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
+ td->td_proc->p_pid, td->td_name, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
+ ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@@ -1050,7 +1088,7 @@ syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
- STOPEVENT(p, S_SCX, code);
+ STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
index 5e20876..aa1ae6c 100644
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -88,101 +88,136 @@ extern const char *freebsd32_syscallnames[];
void ia32_syscall(struct trapframe *frame); /* Called from asm code */
-void
-ia32_syscall(struct trapframe *frame)
-{
+struct ia32_syscall_args {
+ u_int code;
caddr_t params;
- int i;
struct sysent *callp;
- struct thread *td = curthread;
- struct proc *p = td->td_proc;
- register_t orig_tf_rflags;
- int error;
+ u_int64_t args64[8];
int narg;
+};
+
+static int
+fetch_ia32_syscall_args(struct thread *td, struct ia32_syscall_args *sa)
+{
+ struct proc *p;
+ struct trapframe *frame;
u_int32_t args[8];
- u_int64_t args64[8];
- u_int code;
- ksiginfo_t ksi;
+ int error, i;
- PCPU_INC(cnt.v_syscall);
- td->td_pticks = 0;
- td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
- params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
- code = frame->tf_rax;
- orig_tf_rflags = frame->tf_rflags;
+ p = td->td_proc;
+ frame = td->td_frame;
+
+ sa->params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
+ sa->code = frame->tf_rax;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
- (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
+ (*p->p_sysent->sv_prepsyscall)(frame, args, &sa->code,
+ &sa->params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
* fuword is MP aware.
*/
- if (code == SYS_syscall) {
+ if (sa->code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
- code = fuword32(params);
- params += sizeof(int);
- } else if (code == SYS___syscall) {
+ sa->code = fuword32(sa->params);
+ sa->params += sizeof(int);
+ } else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
* We use a 32-bit fetch in case params is not
* aligned.
*/
- code = fuword32(params);
- params += sizeof(quad_t);
+ sa->code = fuword32(sa->params);
+ sa->params += sizeof(quad_t);
}
}
-
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
else
- callp = &p->p_sysent->sv_table[code];
-
- narg = callp->sy_narg;
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
- /*
- * copyin and the ktrsyscall()/ktrsysret() code is MP-aware
- */
- if (params != NULL && narg != 0)
- error = copyin(params, (caddr_t)args,
- (u_int)(narg * sizeof(int)));
+ if (sa->params != NULL && sa->narg != 0)
+ error = copyin(sa->params, (caddr_t)args,
+ (u_int)(sa->narg * sizeof(int)));
else
error = 0;
- for (i = 0; i < narg; i++)
- args64[i] = args[i];
+ for (i = 0; i < sa->narg; i++)
+ sa->args64[i] = args[i];
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, args64);
+ ktrsyscall(sa->code, sa->narg, sa->args64);
#endif
+
+ return (error);
+}
+
+void
+ia32_syscall(struct trapframe *frame)
+{
+ struct thread *td;
+ struct proc *p;
+ struct ia32_syscall_args sa;
+ register_t orig_tf_rflags;
+ int error;
+ ksiginfo_t ksi;
+
+ PCPU_INC(cnt.v_syscall);
+ td = curthread;
+ p = td->td_proc;
+ td->td_syscalls++;
+
+ td->td_pticks = 0;
+ td->td_frame = frame;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ orig_tf_rflags = frame->tf_rflags;
+ if (p->p_flag & P_TRACED) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_USERWR;
+ PROC_UNLOCK(p);
+ }
+ error = fetch_ia32_syscall_args(td, &sa);
+
CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_proc->p_comm, code);
+ td->td_proc->p_pid, td->td_name, sa.code);
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_rdx;
- STOPEVENT(p, S_SCE, narg);
-
+ STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
+ if (td->td_dbgflags & TDB_USERWR) {
+ /*
+ * Reread syscall number and arguments if
+ * debugger modified registers or memory.
+ */
+ error = fetch_ia32_syscall_args(td, &sa);
+ if (error != 0)
+ goto retval;
+ td->td_retval[1] = frame->tf_rdx;
+ }
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, args64);
+ AUDIT_SYSCALL_ENTER(sa.code, td);
+ error = (*sa.callp->sy_call)(td, sa.args64);
AUDIT_SYSCALL_EXIT(error, td);
- }
+ /* Save the latest error return value. */
+ td->td_errno = error;
+ }
+ retval:
cpu_set_syscall_retval(td, error);
/*
@@ -201,14 +236,16 @@ ia32_syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ freebsd32_syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ freebsd32_syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???",
- td->td_locks));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ freebsd32_syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@@ -216,10 +253,10 @@ ia32_syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_proc->p_comm, code);
+ td->td_proc->p_pid, td->td_proc->p_comm, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
+ ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@@ -227,7 +264,7 @@ ia32_syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
- STOPEVENT(p, S_SCX, code);
+ STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 1d3dc3b..305cfd2 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -969,97 +969,130 @@ dblfault_handler()
panic("double fault");
}
-/*
- * syscall - system call request C handler
- *
- * A system call is essentially treated as a trap.
- */
-void
-syscall(struct trapframe *frame)
-{
- caddr_t params;
+struct syscall_args {
+ u_int code;
struct sysent *callp;
- struct thread *td = curthread;
- struct proc *p = td->td_proc;
- register_t orig_tf_eflags;
- int error;
- int narg;
int args[8];
- u_int code;
- ksiginfo_t ksi;
+ register_t *argp;
+ int narg;
+};
- PCPU_INC(cnt.v_syscall);
+static int
+fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ struct trapframe *frame;
+ caddr_t params;
+ int error;
-#ifdef DIAGNOSTIC
- if (ISPL(frame->tf_cs) != SEL_UPL) {
- panic("syscall");
- /* NOT REACHED */
- }
-#endif
+ p = td->td_proc;
+ frame = td->td_frame;
- td->td_pticks = 0;
- td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
params = (caddr_t)frame->tf_esp + sizeof(int);
- code = frame->tf_eax;
- orig_tf_eflags = frame->tf_eflags;
+ sa->code = frame->tf_eax;
if (p->p_sysent->sv_prepsyscall) {
- (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
+ (*p->p_sysent->sv_prepsyscall)(frame, sa->args, &sa->code,
+ &params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
*/
- if (code == SYS_syscall) {
+ if (sa->code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
- code = fuword(params);
+ sa->code = fuword(params);
params += sizeof(int);
- } else if (code == SYS___syscall) {
+ } else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
*/
- code = fuword(params);
+ sa->code = fuword(params);
params += sizeof(quad_t);
}
}
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
else
- callp = &p->p_sysent->sv_table[code];
-
- narg = callp->sy_narg;
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
- if (params != NULL && narg != 0)
- error = copyin(params, (caddr_t)args,
- (u_int)(narg * sizeof(int)));
+ if (params != NULL && sa->narg != 0)
+ error = copyin(params, (caddr_t)sa->args,
+ (u_int)(sa->narg * sizeof(int)));
else
error = 0;
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, args);
+ ktrsyscall(sa->code, sa->narg, sa->args);
#endif
+ return (error);
+}
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
+/*
+ * syscall - system call request C handler
+ *
+ * A system call is essentially treated as a trap.
+ */
+void
+syscall(struct trapframe *frame)
+{
+ struct thread *td;
+ struct proc *p;
+ struct syscall_args sa;
+ register_t orig_tf_eflags;
+ int error;
+ ksiginfo_t ksi;
+ PCPU_INC(cnt.v_syscall);
+ td = curthread;
+ p = td->td_proc;
td->td_syscalls++;
+#ifdef DIAGNOSTIC
+ if (ISPL(frame->tf_cs) != SEL_UPL) {
+ panic("syscall");
+ /* NOT REACHED */
+ }
+#endif
+
+ td->td_pticks = 0;
+ td->td_frame = frame;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ orig_tf_eflags = frame->tf_eflags;
+ if (p->p_flag & P_TRACED) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_USERWR;
+ PROC_UNLOCK(p);
+ }
+ error = fetch_syscall_args(td, &sa);
+
+ CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
+ td->td_proc->p_pid, td->td_name, sa.code);
+
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->tf_edx;
- STOPEVENT(p, S_SCE, narg);
-
+ STOPEVENT(p, S_SCE, sa.narg);
PTRACESTOP_SC(p, td, S_PT_SCE);
+ if (td->td_dbgflags & TDB_USERWR) {
+ /*
+ * Reread syscall number and arguments if
+ * debugger modified registers or memory.
+ */
+ error = fetch_syscall_args(td, &sa);
+ if (error != 0)
+ goto retval;
+ td->td_retval[1] = frame->tf_edx;
+ }
#ifdef KDTRACE_HOOKS
/*
@@ -1067,13 +1100,13 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'entry', process the probe.
*/
- if (systrace_probe_func != NULL && callp->sy_entry != 0)
- (*systrace_probe_func)(callp->sy_entry, code, callp,
- args);
+ if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
+ (*systrace_probe_func)(sa.callp->sy_entry, sa.code,
+ sa.callp, sa.args);
#endif
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, args);
+ AUDIT_SYSCALL_ENTER(sa.code, td);
+ error = (*sa.callp->sy_call)(td, sa.args);
AUDIT_SYSCALL_EXIT(error, td);
/* Save the latest error return value. */
@@ -1085,12 +1118,12 @@ syscall(struct trapframe *frame)
* callback and if there is a probe active for the
* syscall 'return', process the probe.
*/
- if (systrace_probe_func != NULL && callp->sy_return != 0)
- (*systrace_probe_func)(callp->sy_return, code, callp,
- args);
+ if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
+ (*systrace_probe_func)(sa.callp->sy_return, sa.code,
+ sa.callp, sa.args);
#endif
}
-
+ retval:
cpu_set_syscall_retval(td, error);
/*
@@ -1109,14 +1142,16 @@ syscall(struct trapframe *frame)
* Check for misbehavior.
*/
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???");
KASSERT(td->td_critnest == 0,
("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???"));
KASSERT(td->td_locks == 0,
("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
+ (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
+ syscallnames[sa.code] : "???", td->td_locks));
/*
* Handle reschedule and other end-of-syscall issues
@@ -1124,11 +1159,11 @@ syscall(struct trapframe *frame)
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
+ td->td_proc->p_pid, td->td_name, sa.code);
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
+ ktrsysret(sa.code, error, td->td_retval[0]);
#endif
/*
@@ -1136,7 +1171,7 @@ syscall(struct trapframe *frame)
* register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited.
*/
- STOPEVENT(p, S_SCX, code);
+ STOPEVENT(p, S_SCX, sa.code);
PTRACESTOP_SC(p, td, S_PT_SCX);
}
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index dfc36ba..3c6394c 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -816,6 +816,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_WRITE_I:
case PT_WRITE_D:
+ td2->td_dbgflags |= TDB_USERWR;
write = 1;
/* FALLTHROUGH */
case PT_READ_I:
@@ -884,6 +885,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PIOD_WRITE_D:
case PIOD_WRITE_I:
+ td2->td_dbgflags |= TDB_USERWR;
uio.uio_rw = UIO_WRITE;
break;
default:
@@ -906,6 +908,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
goto sendsig; /* in PT_CONTINUE above */
case PT_SETREGS:
+ td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(regs, td2, addr);
break;
@@ -914,6 +917,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PT_SETFPREGS:
+ td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(fpregs, td2, addr);
break;
@@ -922,6 +926,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PT_SETDBREGS:
+ td2->td_dbgflags |= TDB_USERWR;
error = PROC_WRITE(dbregs, td2, addr);
break;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 0ae36af..dd9efae 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -341,6 +341,7 @@ do { \
/* Userland debug flags */
#define TDB_SUSPEND 0x00000001 /* Thread is suspended by debugger */
#define TDB_XSIG 0x00000002 /* Thread is exchanging signal under trace */
+#define TDB_USERWR 0x00000004 /* Debugger modified memory or registers */
/*
* "Private" flags kept in td_pflags:
OpenPOWER on IntegriCloud