Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 May 2010 15:06:22 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Ali Polatel <alip@exherbo.org>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Ability to tell the difference between normal and syscall traps
Message-ID:  <20100511120622.GU83316@deviant.kiev.zoral.com.ua>
In-Reply-To: <20100511103500.GH8186@harikalardiyari>
References:  <20100508111509.GB8186@harikalardiyari> <20100508123626.GC83316@deviant.kiev.zoral.com.ua> <20100509053303.GD8186@harikalardiyari> <20100509135807.GH83316@deviant.kiev.zoral.com.ua> <20100509182851.GE8186@harikalardiyari> <20100509214359.GJ83316@deviant.kiev.zoral.com.ua> <20100510164847.GF8186@harikalardiyari> <20100510170947.GP83316@deviant.kiev.zoral.com.ua> <20100511103500.GH8186@harikalardiyari>

next in thread | previous in thread | raw e-mail | index | archive | help

--V4yrq4dHtCqH+JvC
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, May 11, 2010 at 01:35:00PM +0300, Ali Polatel wrote:
> Kostik Belousov yazm??:
> > On Mon, May 10, 2010 at 07:48:47PM +0300, Ali Polatel wrote:
> > > Kostik Belousov yazm??:
> > > > On Sun, May 09, 2010 at 09:28:51PM +0300, Ali Polatel wrote:
> > > > > Kostik Belousov yazm??:
> > > > > > On Sun, May 09, 2010 at 08:33:03AM +0300, Ali Polatel wrote:
> > > > > > > Kostik Belousov yazm??:
> > > > > > > > On Sat, May 08, 2010 at 02:15:09PM +0300, Ali Polatel wrote:
> > > > > > > > > Does FreeBSD's ptrace have a way to tell the difference b=
etween normal
> > > > > > > > > traps and those caused by a system call?
> > > > > > > > >=20
> > > > > > > > > On Linux? this is possible by passing PTRACE_O_TRACESYSGO=
OD option to the
> > > > > > > > > ptrace request PTRACE_SETOPTIONS which makes the kernel s=
et bit 7 in the
> > > > > > > > > syscall number when delivering system call traps,
> > > > > > > > > (i.e., deliver (SIGTRAP | 0x80)).
> > > > > > > > >=20
> > > > > > > > > I'm not sure if this is possible on FreeBSD. PT_LWPINFO r=
equest looks
> > > > > > > > > related but can't be sure.
> > > > > > > > >=20
> > > > > > > > > ?: http://linux.die.net/man/2/ptrace
> > > > > > > >=20
> > > > > > > > There is already procfs(5)-based interface to get a reason =
for stop.
> > > > > > > > Look at the ioctl PIOCSTATUS. Yes, you have to mount procfs.
> > > > > > > >=20
> > > > > > > > The interface can be lifted to ptrace(2), but I think using=
 the capacity
> > > > > > > > of procfs is not wrong there.
> > > > > > >=20
> > > > > > > Hmm ok, I've been playing around with PIOCSTATUS but it doesn=
't seem to
> > > > > > > work, there's not much documentation about it either so I fig=
ured I'll
> > > > > > > just ask.
> > > > > > >=20
> > > > > > > The code is here: http://alip.github.com/code/piocstatus.c
> > > > > > >=20
> > > > > > > The traced child is stopped at the beginning of a system call=
. I await
> > > > > > > that the PIOCSTATUS request sets ps.why to S_SCE but it's alw=
ays zero.
> > > > > > > Can you help me figure out what I'm doing wrong? :)
> > > > > >=20
> > > > > > Apparently I missed the fact that S_PT_SCE and S_SCE are differ=
ent
> > > > > > flags. It seems you have to use procfs stop events (PIOCBIS) and
> > > > > > procfs-based loop to get p_step set to 1.
> > > > >=20
> > > > > So I can't use ptrace() together with ioctl() based tracing.
> > > > > Fair enough...
> > > > >=20
> > > > > I'm trying to write the ioctl() based equivalent of what I've sta=
rted
> > > > > but I can't figure out how to start tracing by forking a new chil=
d.
> > > > >=20
> > > > > Here's how I do it on Linux:
> > > > > fork()
> > > > >  child: call kill(getpid(), SIGSTOP) and wait for the parent to r=
esume.
> > > > >  parent: wait for the child, set up tracing options and start tra=
cing.
> > > > >=20
> > > > > I can directly use execve() so the child will stop too but I'm wr=
iting a
> > > > > library and for its unit tests I need to use the SIGSTOP method b=
ecause
> > > > > I won't do any exec'ing.
> > > > >=20
> > > > > I tried to do the same with ioctl(), it works most of the time bu=
t it
> > > > > hangs every now and then at PIOCWAIT. I'm inclined to think there=
's a
> > > > > race condition but I couldn't figure out why.
> > > > >=20
> > > > > The code is here: http://alip.github.com/code/piocstatus-2.c
> > > > >=20
> > > > > Fwiw this is about a library called
> > > > > pinktrace(http://dev.exherbo.org/~alip/pinktrace) I'm trying to w=
rite.
> > > > > Its aim is to be a lightweight portable tracing library with mult=
iple
> > > > > backends (like procfs and ptrace etc.) I think this could prove u=
seful
> > > > > for many people who need to do tracing and doesn't want to bother=
 with
> > > > > platform specific details.
> > > >=20
> > > > I see. You could try this patch. It requires HEAD or recent RELENG_8
> > > > to be applicable. I added PL_EVENT_SCE/SCX to PT_LWPINFO for i386 a=
nd
> > > > amd64. Please note that I did not tested it, only booted the kernel=
 to
> > > > make sure that it does not break too ugly.
> > > >=20
> > > > diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
> > > > index f3dba94..f97f875 100644
> > > <snip the nice patch>
> > >=20
> > > Looks great, I could only test it basically but it seems to work fine.
> > > If this is merged, truss can make use of this too.
> > >=20
> > > Another question is how hard is it to implement PL_EVENT_EXEC?
> > > This could be useful for truss as it updates the execution type of the
> > > process after successful execve() calls afaict.
> >=20
> > Is this needed ? The question is not rhetorical, I am trying to
> > understand what prevents use of PT_TO_SCE and checking the syscall
> > number ? You would screen for SYS_execve or SYS_fexecve and
> > reset the debugger state on SIGTRAP that is supplied to the debugger
> > before first instruction of new image is executed.
> >=20
>=20
> Not really needed, just cleaner imo. As system call numbers may be
> different for different execution types and you need to look it up from
> a table using a string as argument which is slow.
>=20
> > Can you, please, extract and provide me with the code you used to test
> > the PL_EVENT_SCE/SCX patch ?
>=20
> Sure, the code is below. It doesn't work though (Sorry to tell you it
> was working fine in my first post, too much vodka makes me see things
> differently as it seems). The PT_LWPINFO request returns
> PL_EVENT_SIGNAL in both cases.

Yes, this is a relief, since I realized that syscall enter/leave is reported
using SIGTRAP. I have to move the events to flags. Also, original patch
missed SCE on i386. Below is the updated change.

diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index f3dba94..f97f875 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -911,6 +911,7 @@ syscall(struct trapframe *frame)
 	if (p->p_flag & P_TRACED) {
 		PROC_LOCK(p);
 		td->td_dbgflags &=3D ~TDB_USERWR;
+		td->td_dbgflags |=3D TDB_SCE;
 		PROC_UNLOCK(p);
 	}
 	error =3D fetch_syscall_args(td, &sa);
@@ -965,6 +966,11 @@ syscall(struct trapframe *frame)
 #endif
 	}
  retval:
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCE;
+		PROC_UNLOCK(p);
+	}
 	cpu_set_syscall_retval(td, error);
=20
 	/*
@@ -1007,12 +1013,21 @@ syscall(struct trapframe *frame)
 		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
=20
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags |=3D TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 	/*
 	 * This works because errno is findable through the
 	 * 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, sa.code);
-
 	PTRACESTOP_SC(p, td, S_PT_SCX);
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 }
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
index aa1ae6c..300d1f6 100644
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -186,6 +186,7 @@ ia32_syscall(struct trapframe *frame)
 	if (p->p_flag & P_TRACED) {
 		PROC_LOCK(p);
 		td->td_dbgflags &=3D ~TDB_USERWR;
+		td->td_dbgflags |=3D TDB_SCE;
 		PROC_UNLOCK(p);
 	}
 	error =3D fetch_ia32_syscall_args(td, &sa);
@@ -218,6 +219,11 @@ ia32_syscall(struct trapframe *frame)
 		td->td_errno =3D error;
 	}
  retval:
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCE;
+		PROC_UNLOCK(p);
+	}
 	cpu_set_syscall_retval(td, error);
=20
 	/*
@@ -259,14 +265,23 @@ ia32_syscall(struct trapframe *frame)
 		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
=20
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags |=3D TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 	/*
 	 * This works because errno is findable through the
 	 * 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, sa.code);
-=20
 	PTRACESTOP_SC(p, td, S_PT_SCX);
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 }
=20
=20
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index a11daa6..44c8585 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -1074,6 +1074,7 @@ syscall(struct trapframe *frame)
 	if (p->p_flag & P_TRACED) {
 		PROC_LOCK(p);
 		td->td_dbgflags &=3D ~TDB_USERWR;
+		td->td_dbgflags |=3D TDB_SCE;
 		PROC_UNLOCK(p);
 	}
 	error =3D fetch_syscall_args(td, &sa);
@@ -1128,6 +1129,11 @@ syscall(struct trapframe *frame)
 #endif
 	}
  retval:
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCE;
+		PROC_UNLOCK(p);
+	}
 	cpu_set_syscall_retval(td, error);
=20
 	/*
@@ -1170,13 +1176,22 @@ syscall(struct trapframe *frame)
 		ktrsysret(sa.code, error, td->td_retval[0]);
 #endif
=20
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags |=3D TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 	/*
 	 * This works because errno is findable through the
 	 * 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, sa.code);
-
 	PTRACESTOP_SC(p, td, S_PT_SCX);
+	if (p->p_flag & P_TRACED) {
+		PROC_LOCK(p);
+		td->td_dbgflags &=3D ~TDB_SCX;
+		PROC_UNLOCK(p);
+	}
 }
=20
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index d8cc4f0..bc0dd24 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1105,9 +1105,11 @@ kern_ptrace(struct thread *td, int req, pid_t pid, v=
oid *addr, int data)
 		pl->pl_lwpid =3D td2->td_tid;
 		if (td2->td_dbgflags & TDB_XSIG)
 			pl->pl_event =3D PL_EVENT_SIGNAL;
-		else
-			pl->pl_event =3D 0;
 		pl->pl_flags =3D 0;
+		if (td2->td_dbgflags & TDB_SCE)
+			pl->pl_flags |=3D PL_FLAG_SCE;
+		else if (td2->td_dbgflags & TDB_SCX)
+			pl->pl_flags |=3D PL_FLAG_SCX;
 		pl->pl_sigmask =3D td2->td_sigmask;
 		pl->pl_siglist =3D td2->td_siglist;
 		break;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index e32e494..9457ad1 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -364,6 +364,8 @@ do {									\
 #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 */
+#define	TDB_SCE		0x00000008 /* Thread performs syscall enter */
+#define	TDB_SCX		0x00000010 /* Thread performs syscall exit */
=20
 /*
  * "Private" flags kept in td_pflags:
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index b30447c..8be0cae 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -99,6 +99,8 @@ struct ptrace_lwpinfo {
 	int	pl_flags;	/* LWP flags. */
 #define	PL_FLAG_SA	0x01	/* M:N thread */
 #define	PL_FLAG_BOUND	0x02	/* M:N bound thread */
+#define	PL_FLAG_SCE	0x04	/* syscall enter point */
+#define	PL_FLAG_SCX	0x08	/* syscall leave point */
 	sigset_t	pl_sigmask;	/* LWP signal mask */
 	sigset_t	pl_siglist;	/* LWP pending signal */
 };

--V4yrq4dHtCqH+JvC
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (FreeBSD)

iEYEARECAAYFAkvpSD4ACgkQC3+MBN1Mb4jdNQCdFJ07HNA1nRkHruSj/y2Lu0Yk
thkAoOizHMOOjouhN7HOJBItzJpVqcrL
=ahNQ
-----END PGP SIGNATURE-----

--V4yrq4dHtCqH+JvC--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100511120622.GU83316>