From owner-freebsd-hackers@FreeBSD.ORG Sun May 9 21:44:05 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id BDC10106566B for ; Sun, 9 May 2010 21:44:05 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (mx0.zoral.com.ua [91.193.166.200]) by mx1.freebsd.org (Postfix) with ESMTP id 264508FC08 for ; Sun, 9 May 2010 21:44:04 +0000 (UTC) Received: from deviant.kiev.zoral.com.ua (root@deviant.kiev.zoral.com.ua [10.1.1.148]) by mail.zoral.com.ua (8.14.2/8.14.2) with ESMTP id o49Li0gN011800 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 10 May 2010 00:44:00 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: from deviant.kiev.zoral.com.ua (kostik@localhost [127.0.0.1]) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4) with ESMTP id o49Li03a006442; Mon, 10 May 2010 00:44:00 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4/Submit) id o49LhxV7006441; Mon, 10 May 2010 00:43:59 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: deviant.kiev.zoral.com.ua: kostik set sender to kostikbel@gmail.com using -f Date: Mon, 10 May 2010 00:43:59 +0300 From: Kostik Belousov To: Ali Polatel Message-ID: <20100509214359.GJ83316@deviant.kiev.zoral.com.ua> References: <20100508111509.GB8186@harikalardiyari> <20100508123626.GC83316@deviant.kiev.zoral.com.ua> <20100509053303.GD8186@harikalardiyari> <20100509135807.GH83316@deviant.kiev.zoral.com.ua> <20100509182851.GE8186@harikalardiyari> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="C7PTD44AewjTsiSV" Content-Disposition: inline In-Reply-To: <20100509182851.GE8186@harikalardiyari> User-Agent: Mutt/1.4.2.3i X-Virus-Scanned: clamav-milter 0.95.2 at skuns.kiev.zoral.com.ua X-Virus-Status: Clean X-Spam-Status: No, score=-2.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_50, DNS_FROM_OPENWHOIS autolearn=no version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: freebsd-hackers@freebsd.org Subject: Re: Ability to tell the difference between normal and syscall traps X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 May 2010 21:44:05 -0000 --C7PTD44AewjTsiSV Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable 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 between n= ormal > > > > > traps and those caused by a system call? > > > > >=20 > > > > > On Linux? this is possible by passing PTRACE_O_TRACESYSGOOD optio= n to the > > > > > ptrace request PTRACE_SETOPTIONS which makes the kernel set 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 request l= ooks > > > > > 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 cap= acity > > > > 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 figured 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 always 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 different > > 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 started > but I can't figure out how to start tracing by forking a new child. >=20 > Here's how I do it on Linux: > fork() > child: call kill(getpid(), SIGSTOP) and wait for the parent to resume. > parent: wait for the child, set up tracing options and start tracing. >=20 > I can directly use execve() so the child will stop too but I'm writing a > library and for its unit tests I need to use the SIGSTOP method because > I won't do any exec'ing. >=20 > I tried to do the same with ioctl(), it works most of the time but 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 write. > Its aim is to be a lightweight portable tracing library with multiple > backends (like procfs and ptrace etc.) I think this could prove useful > for many people who need to do tracing and doesn't want to bother with > platform specific details. 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 and amd64. Please note that I did not tested it, only booted the kernel to make sure that it does not break too ugly. 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..2550d34 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -1170,13 +1170,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..a6b88c3 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1105,6 +1105,10 @@ 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 if (td2->td_dbgflags & TDB_SCE) + pl->pl_event =3D PL_EVENT_SCE; + else if (td2->td_dbgflags & TDB_SCX) + pl->pl_event =3D PL_EVENT_SCX; else pl->pl_event =3D 0; pl->pl_flags =3D 0; 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..3265e63 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -96,6 +96,8 @@ struct ptrace_lwpinfo { int pl_event; /* Event that stopped the LWP. */ #define PL_EVENT_NONE 0 #define PL_EVENT_SIGNAL 1 +#define PL_EVENT_SCE 2 +#define PL_EVENT_SCX 3 int pl_flags; /* LWP flags. */ #define PL_FLAG_SA 0x01 /* M:N thread */ #define PL_FLAG_BOUND 0x02 /* M:N bound thread */ --C7PTD44AewjTsiSV Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (FreeBSD) iEYEARECAAYFAkvnLJ8ACgkQC3+MBN1Mb4g9SgCfddSBqrVeOWqlXjLuRrKWvwAK nnwAn3YOWzugd7p3ViKHwNZEIXE0YlJz =JhPv -----END PGP SIGNATURE----- --C7PTD44AewjTsiSV--