Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Jul 2010 15:45:58 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        David Xu <davidxu@freebsd.org>
Cc:        John Baldwin <john@baldwin.cx>, freebsd-arch@freebsd.org
Subject:   Re: Access to siginfo for the signal from debugger
Message-ID:  <20100702124555.GR13238@deviant.kiev.zoral.com.ua>
In-Reply-To: <4C2D4B65.8080708@freebsd.org>
References:  <20100701134217.GM13238@deviant.kiev.zoral.com.ua> <201007011705.26173.john@baldwin.cx> <20100701212710.GP13238@deviant.kiev.zoral.com.ua> <4C2D4B65.8080708@freebsd.org>

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

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

On Fri, Jul 02, 2010 at 10:13:57AM +0800, David Xu wrote:
> Kostik Belousov wrote:
> >On Thu, Jul 01, 2010 at 05:05:26PM -0400, John Baldwin wrote:
> >>On Thursday 01 July 2010 09:42:17 am Kostik Belousov wrote:
> >>>Hi,
> >>>below is the patch that provides the debugger with access to siginfo
> >>>of the signal that stopped the debuggee. This allows to see a lot more
> >>>details for the cause of the process stop. E.g. you can see a fault
> >>>address if process get SIGSEGV or SIGBUS, you can distinguish between
> >>>breakpoint-generated SIGTRAP and non-breakpoint, whether the signal
> >>>was send due to external event etc.
> >>>
> >>>The change to struct ptrace_lwpinfo is backward-compatible in the sense
> >>>that programs that were compiled with old definition for the struct wi=
ll
> >>>work on new kernels.
> >>Nice!  Does gdb "just work" with these changes or does it need patching=
=20
> >>as well?
> >It should "just work", and my testing seems to confirm this. gdb uses
> >PT_LWPINFO to enumerate the thread ids, and I checked it on mt process.
> >
> >As I said, the change is ABI backward-compatible, i.e. you do not need
> >even to recompile the old program for new kernel.
> >
> >Sure, gdb cannot show additional available information without
> >modifications.
>=20
> Yes, you can add new fields to ptrace_lwpinfo without any problem.
> To print new fields, you should change the function
> fbsd_thread_signal_cmd in file
> src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
> after change, you just type 'thread signal' command in gdb to
> show thread's signal info. The command is freebsd specific,
> others may or may not have it.

I did what you suggested. The drawback there is that "thread signal"
only works for the threaded processes.

diff --git a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c b/gnu/usr.bin/gdb/libgdb=
/fbsd-threads.c
index eb83f2e..6b424bc 100644
--- a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
+++ b/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
@@ -1299,6 +1299,7 @@ fbsd_thread_signal_cmd (char *exp, int from_tty)
   td_thrhandle_t th;
   td_thrinfo_t ti;
   td_err_e err;
+  const char *code;
=20
   if (!fbsd_thread_active || !IS_THREAD(inferior_ptid))
     return;
@@ -1315,6 +1316,40 @@ fbsd_thread_signal_cmd (char *exp, int from_tty)
   fbsd_print_sigset(&ti.ti_sigmask);
   printf_filtered("signal pending:\n");
   fbsd_print_sigset(&ti.ti_pending);
+  if (ti.ti_siginfo.si_signo !=3D 0) {
+    printf_filtered("si_signo %d\n", ti.ti_siginfo.si_signo);
+    printf_filtered("si_errno %d (%s)\n", ti.ti_siginfo.si_errno,
+      strerror(ti.ti_siginfo.si_errno));
+    switch (ti.ti_siginfo.si_code) {
+      case SI_NOINFO:
+	code =3D "NOINFO";
+	break;
+    case SI_USER:
+	code =3D "USER";
+	break;
+    case SI_QUEUE:
+	code =3D "QUEUE";
+	break;
+    case SI_TIMER:
+	code =3D "TIMER";
+	break;
+    case SI_ASYNCIO:
+	code =3D "ASYNCIO";
+	break;
+    case SI_MESGQ:
+	code =3D "MESGQ";
+	break;
+    case SI_KERNEL:
+	code =3D "KERNEL";
+	break;
+    default:
+	code =3D "UNKNOWN";
+	break;
+    }
+    printf_filtered("si_code %s si_pid %d si_uid %d si_status %x si_addr %=
p\n",
+      code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid, ti.ti_siginfo.si_s=
tatus,
+      ti.ti_siginfo.si_addr);
+  }
 }
=20
 static int
diff --git a/lib/libthread_db/Symbol.map b/lib/libthread_db/Symbol.map
index 65e78d4..4e690f9 100644
--- a/lib/libthread_db/Symbol.map
+++ b/lib/libthread_db/Symbol.map
@@ -19,7 +19,6 @@ FBSD_1.0 {
 	td_thr_dbsuspend;
 	td_thr_event_enable;
 	td_thr_event_getmsg;
-	td_thr_get_info;
 	td_thr_getfpregs;
 	td_thr_getgregs;
 #if defined(i386)
@@ -33,3 +32,7 @@ FBSD_1.0 {
 	td_thr_tls_get_addr;
 	td_thr_validate;
 };
+
+FBSD_1.2 {
+	td_thr_get_info;
+};
diff --git a/lib/libthread_db/libpthread_db.c b/lib/libthread_db/libpthread=
_db.c
index 65478a7..31ea15d 100644
--- a/lib/libthread_db/libpthread_db.c
+++ b/lib/libthread_db/libpthread_db.c
@@ -570,7 +570,7 @@ pt_thr_validate(const td_thrhandle_t *th)
 }
=20
 static td_err_e
-pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
+pt_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info)
 {
 	const td_thragent_t *ta =3D th->th_ta;
 	struct ptrace_lwpinfo linfo;
@@ -659,6 +659,16 @@ pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t=
 *info)
 	return (0);
 }
=20
+static td_err_e
+pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
+{
+	td_err_e e;
+
+	e =3D pt_thr_old_get_info(th, (td_old_thrinfo_t *)info);
+	bzero(&info->ti_siginfo, sizeof(info->ti_siginfo));
+	return (e);
+}
+
 #ifdef __i386__
 static td_err_e
 pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
@@ -1114,6 +1124,7 @@ struct ta_ops libpthread_db_ops =3D {
 	.to_thr_dbsuspend	=3D pt_thr_dbsuspend,
 	.to_thr_event_enable	=3D pt_thr_event_enable,
 	.to_thr_event_getmsg	=3D pt_thr_event_getmsg,
+	.to_thr_old_get_info	=3D pt_thr_old_get_info,
 	.to_thr_get_info	=3D pt_thr_get_info,
 	.to_thr_getfpregs	=3D pt_thr_getfpregs,
 	.to_thr_getgregs	=3D pt_thr_getgregs,
diff --git a/lib/libthread_db/libthr_db.c b/lib/libthread_db/libthr_db.c
index f79facb..33225f4 100644
--- a/lib/libthread_db/libthr_db.c
+++ b/lib/libthread_db/libthr_db.c
@@ -453,7 +453,7 @@ pt_thr_validate(const td_thrhandle_t *th)
 }
=20
 static td_err_e
-pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
+pt_thr_get_info_common(const td_thrhandle_t *th, td_thrinfo_t *info, int o=
ld)
 {
 	const td_thragent_t *ta =3D th->th_ta;
 	struct ptrace_lwpinfo linfo;
@@ -489,6 +489,13 @@ pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t=
 *info)
 	if (ret =3D=3D PS_OK) {
 		info->ti_sigmask =3D linfo.pl_sigmask;
 		info->ti_pending =3D linfo.pl_siglist;
+		if (!old) {
+			if ((linfo.pl_flags & PL_FLAG_SI) !=3D 0)
+				info->ti_siginfo =3D linfo.pl_siginfo;
+			else
+				bzero(&info->ti_siginfo,
+				    sizeof(info->ti_siginfo));
+		}
 	} else
 		return (ret);
 	if (state =3D=3D ta->thread_state_running)
@@ -501,6 +508,20 @@ pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t=
 *info)
 	return (0);
 }
=20
+static td_err_e
+pt_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info)
+{
+
+	return (pt_thr_get_info_common(th, (td_thrinfo_t *)info, 1));
+}
+
+static td_err_e
+pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
+{
+
+	return (pt_thr_get_info_common(th, info, 0));
+}
+
 #ifdef __i386__
 static td_err_e
 pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
@@ -761,6 +782,7 @@ struct ta_ops libthr_db_ops =3D {
 	.to_thr_dbsuspend	=3D pt_thr_dbsuspend,
 	.to_thr_event_enable	=3D pt_thr_event_enable,
 	.to_thr_event_getmsg	=3D pt_thr_event_getmsg,
+	.to_thr_old_get_info	=3D pt_thr_old_get_info,
 	.to_thr_get_info	=3D pt_thr_get_info,
 	.to_thr_getfpregs	=3D pt_thr_getfpregs,
 	.to_thr_getgregs	=3D pt_thr_getgregs,
diff --git a/lib/libthread_db/thread_db.c b/lib/libthread_db/thread_db.c
index dc8195d..121855b 100644
--- a/lib/libthread_db/thread_db.c
+++ b/lib/libthread_db/thread_db.c
@@ -176,6 +176,14 @@ td_thr_event_getmsg(const td_thrhandle_t *th, td_event=
_msg_t *msg)
 }
=20
 td_err_e
+td_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info)
+{
+	const td_thragent_t *ta =3D th->th_ta;
+	return (ta->ta_ops->to_thr_old_get_info(th, info));
+}
+__sym_compat(td_thr_get_info, td_thr_old_get_info, FBSD_1.0);
+
+td_err_e
 td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
 {
 	const td_thragent_t *ta =3D th->th_ta;
diff --git a/lib/libthread_db/thread_db.h b/lib/libthread_db/thread_db.h
index 44ddea4..8c30812 100644
--- a/lib/libthread_db/thread_db.h
+++ b/lib/libthread_db/thread_db.h
@@ -191,6 +191,7 @@ typedef struct {
 	psaddr_t	ti_startfunc;
 	psaddr_t	ti_stkbase;
 	size_t		ti_stksize;
+	siginfo_t	ti_siginfo;
 } td_thrinfo_t;
=20
 /*
diff --git a/lib/libthread_db/thread_db_int.h b/lib/libthread_db/thread_db_=
int.h
index 3b03062..92ba6e5 100644
--- a/lib/libthread_db/thread_db_int.h
+++ b/lib/libthread_db/thread_db_int.h
@@ -32,6 +32,25 @@
 #include <sys/types.h>
 #include <sys/queue.h>
=20
+typedef struct {
+	const td_thragent_t *ti_ta_p;
+	thread_t	ti_tid;
+	psaddr_t	ti_thread;
+	td_thr_state_e	ti_state;
+	td_thr_type_e	ti_type;
+	td_thr_events_t	ti_events;
+	int		ti_pri;
+	lwpid_t		ti_lid;
+	char		ti_db_suspended;
+	char		ti_traceme;
+	sigset_t	ti_sigmask;
+	sigset_t	ti_pending;
+	psaddr_t	ti_tls;
+	psaddr_t	ti_startfunc;
+	psaddr_t	ti_stkbase;
+	size_t		ti_stksize;
+} td_old_thrinfo_t;
+
 #define	TD_THRAGENT_FIELDS			\
 	struct ta_ops		*ta_ops;	\
 	TAILQ_ENTRY(td_thragent) ta_next;	\
@@ -65,6 +84,8 @@ struct ta_ops {
 	td_err_e (*to_thr_event_enable)(const td_thrhandle_t *, int);
 	td_err_e (*to_thr_event_getmsg)(const td_thrhandle_t *,
 	    td_event_msg_t *);
+	td_err_e (*to_thr_old_get_info)(const td_thrhandle_t *,
+	    td_old_thrinfo_t *);
 	td_err_e (*to_thr_get_info)(const td_thrhandle_t *, td_thrinfo_t *);
 	td_err_e (*to_thr_getfpregs)(const td_thrhandle_t *, prfpregset_t *);
 	td_err_e (*to_thr_getgregs)(const td_thrhandle_t *, prgregset_t);
@@ -103,4 +124,6 @@ int thr_pwrite_int(const struct td_thragent *, psaddr_t=
, uint32_t);
 int thr_pwrite_long(const struct td_thragent *, psaddr_t, uint64_t);
 int thr_pwrite_ptr(const struct td_thragent *, psaddr_t, psaddr_t);
=20
+td_err_e td_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *i=
nfo);
+
 #endif /* _THREAD_DB_INT_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/f=
reebsd32_misc.c
index f0fde2b..1d60ed4 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2208,7 +2208,7 @@ freebsd32_thr_suspend(struct thread *td, struct freeb=
sd32_thr_suspend_args *uap)
 }
=20
 void
-siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
+siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst)
 {
 	bzero(dst, sizeof(*dst));
 	dst->si_signo =3D src->si_signo;
diff --git a/sys/compat/freebsd32/freebsd32_signal.h b/sys/compat/freebsd32=
/freebsd32_signal.h
index ba0922a..2669581 100644
--- a/sys/compat/freebsd32/freebsd32_signal.h
+++ b/sys/compat/freebsd32/freebsd32_signal.h
@@ -96,6 +96,6 @@ struct sigevent32 {
 	} _sigev_un;
 };
=20
-void siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst);
+void siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst);
=20
 #endif /* !_COMPAT_FREEBSD32_SIGNAL_H_ */
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 04c2ba7..af3c7da 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2522,7 +2522,6 @@ issignal(struct thread *td, int stop_allowed)
 	struct sigacts *ps;
 	struct sigqueue *queue;
 	sigset_t sigpending;
-	ksiginfo_t ksi;
 	int sig, prop, newsig;
=20
 	p =3D td->td_proc;
@@ -2565,10 +2564,10 @@ issignal(struct thread *td, int stop_allowed)
 			 * be thrown away.
 			 */
 			queue =3D &td->td_sigqueue;
-			ksi.ksi_signo =3D 0;
-			if (sigqueue_get(queue, sig, &ksi) =3D=3D 0) {
+			td->td_dbgksi.ksi_signo =3D 0;
+			if (sigqueue_get(queue, sig, &td->td_dbgksi) =3D=3D 0) {
 				queue =3D &p->p_sigqueue;
-				sigqueue_get(queue, sig, &ksi);
+				sigqueue_get(queue, sig, &td->td_dbgksi);
 			}
=20
 			mtx_unlock(&ps->ps_mtx);
@@ -2595,13 +2594,13 @@ issignal(struct thread *td, int stop_allowed)
 					continue;
 				signotify(td);
 			} else {
-				if (ksi.ksi_signo !=3D 0) {
-					ksi.ksi_flags |=3D KSI_HEAD;
+				if (td->td_dbgksi.ksi_signo !=3D 0) {
+					td->td_dbgksi.ksi_flags |=3D KSI_HEAD;
 					if (sigqueue_add(&td->td_sigqueue, sig,
-					    &ksi) !=3D 0)
-						ksi.ksi_signo =3D 0;
+					    &td->td_dbgksi) !=3D 0)
+						td->td_dbgksi.ksi_signo =3D 0;
 				}
-				if (ksi.ksi_signo =3D=3D 0)
+				if (td->td_dbgksi.ksi_signo =3D=3D 0)
 					sigqueue_add(&td->td_sigqueue, sig,
 					    NULL);
 			}
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 40c861b..525c0e2 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
=20
 #ifdef COMPAT_FREEBSD32
 #include <sys/procfs.h>
+#include <compat/freebsd32/freebsd32_signal.h>
=20
 struct ptrace_io_desc32 {
 	int		piod_op;
@@ -85,6 +86,15 @@ struct ptrace_vm_entry32 {
 	uint32_t	pve_path;
 };
=20
+struct ptrace_lwpinfo32 {
+	lwpid_t	pl_lwpid;	/* LWP described. */
+	int	pl_event;	/* Event that stopped the LWP. */
+	int	pl_flags;	/* LWP flags. */
+	sigset_t	pl_sigmask;	/* LWP signal mask */
+	sigset_t	pl_siglist;	/* LWP pending signal */
+	struct siginfo32 pl_siginfo;	/* siginfo for signal */
+};
+
 #endif
=20
 /*
@@ -498,6 +508,19 @@ ptrace_vm_entry32(struct thread *td, struct proc *p,
 	pve32->pve_pathlen =3D pve.pve_pathlen;
 	return (error);
 }
+
+static void
+ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
+    struct ptrace_lwpinfo32 *pl32)
+{
+
+	pl32->pl_lwpid =3D pl->pl_lwpid;
+	pl32->pl_event =3D pl->pl_event;
+	pl32->pl_flags =3D pl->pl_flags;
+	pl32->pl_sigmask =3D pl->pl_sigmask;
+	pl32->pl_siglist =3D pl->pl_siglist;
+	siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
+}
 #endif /* COMPAT_FREEBSD32 */
=20
 /*
@@ -552,6 +575,7 @@ ptrace(struct thread *td, struct ptrace_args *uap)
 		struct fpreg32 fpreg32;
 		struct reg32 reg32;
 		struct ptrace_io_desc32 piod32;
+		struct ptrace_lwpinfo32 pl32;
 		struct ptrace_vm_entry32 pve32;
 #endif
 	} r;
@@ -662,6 +686,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void=
 *addr, int data)
 #ifdef COMPAT_FREEBSD32
 	int wrap32 =3D 0, safe =3D 0;
 	struct ptrace_io_desc32 *piod32 =3D NULL;
+	struct ptrace_lwpinfo32 *pl32 =3D NULL;
+	struct ptrace_lwpinfo plr;
 #endif
=20
 	curp =3D td->td_proc;
@@ -1103,15 +1129,44 @@ kern_ptrace(struct thread *td, int req, pid_t pid, =
void *addr, int data)
 		break;
=20
 	case PT_LWPINFO:
-		if (data <=3D 0 || data > sizeof(*pl)) {
+		if (data <=3D 0 ||
+#ifdef COMPAT_FREEBSD32
+		    (!wrap32 && data > sizeof(*pl)) ||
+		    (wrap32 && data > sizeof(*pl32))) {
+#else
+		    data > sizeof(*pl)) {
+#endif
 			error =3D EINVAL;
 			break;
 		}
+#ifdef COMPAT_FREEBSD32
+		if (wrap32) {
+			pl =3D &plr;
+			pl32 =3D addr;
+		} else
+#endif
 		pl =3D addr;
 		pl->pl_lwpid =3D td2->td_tid;
-		if (td2->td_dbgflags & TDB_XSIG)
-			pl->pl_event =3D PL_EVENT_SIGNAL;
 		pl->pl_flags =3D 0;
+		if (td2->td_dbgflags & TDB_XSIG) {
+			pl->pl_event =3D PL_EVENT_SIGNAL;
+			if (td2->td_dbgksi.ksi_signo !=3D 0 &&
+#ifdef COMPAT_FREEBSD32
+			    ((!wrap32 && data >=3D offsetof(struct ptrace_lwpinfo,
+			    pl_siginfo) + sizeof(pl->pl_siginfo)) ||
+			    (wrap32 && data >=3D offsetof(struct ptrace_lwpinfo32,
+			    pl_siginfo) + sizeof(struct siginfo32)))
+#else
+			    data >=3D offsetof(struct ptrace_lwpinfo, pl_siginfo)
+			    + sizeof(pl->pl_siginfo)
+#endif
+			){
+				pl->pl_flags |=3D PL_FLAG_SI;
+				pl->pl_siginfo =3D td2->td_dbgksi.ksi_info;
+			}
+		}
+		if ((pl->pl_flags & PL_FLAG_SI) =3D=3D 0)
+			bzero(&pl->pl_siginfo, sizeof(pl->pl_siginfo));
 		if (td2->td_dbgflags & TDB_SCE)
 			pl->pl_flags |=3D PL_FLAG_SCE;
 		else if (td2->td_dbgflags & TDB_SCX)
@@ -1120,6 +1175,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, v=
oid *addr, int data)
 			pl->pl_flags |=3D PL_FLAG_EXEC;
 		pl->pl_sigmask =3D td2->td_sigmask;
 		pl->pl_siglist =3D td2->td_siglist;
+#ifdef COMPAT_FREEBSD32
+		if (wrap32)
+			ptrace_lwpinfo_to32(pl, pl32);
+#endif
 		break;
=20
 	case PT_GETNUMLWPS:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 3c9a2de..cd00550 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -259,6 +259,7 @@ struct thread {
 	char		td_name[MAXCOMLEN + 1];	/* (*) Thread name. */
 	struct file	*td_fpop;	/* (k) file referencing cdev under op */
 	int		td_dbgflags;	/* (c) Userland debugger flags */
+	struct ksiginfo td_dbgksi;	/* (c) ksi reflected to debugger. */
 	int		td_ng_outbound;	/* (k) Thread entered ng from above. */
 	struct osd	td_osd;		/* (k) Object specific data. */
 #define	td_endzero td_base_pri
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index a6dbe2c..f4b25d4 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -33,7 +33,7 @@
 #ifndef	_SYS_PTRACE_H_
 #define	_SYS_PTRACE_H_
=20
-#include <sys/_sigset.h>
+#include <sys/signal.h>
 #include <machine/reg.h>
=20
 #define	PT_TRACE_ME	0	/* child declares it's being traced */
@@ -102,8 +102,10 @@ struct ptrace_lwpinfo {
 #define	PL_FLAG_SCE	0x04	/* syscall enter point */
 #define	PL_FLAG_SCX	0x08	/* syscall leave point */
 #define	PL_FLAG_EXEC	0x10	/* exec(2) succeeded */
+#define	PL_FLAG_SI	0x20	/* siginfo is valid */
 	sigset_t	pl_sigmask;	/* LWP signal mask */
 	sigset_t	pl_siglist;	/* LWP pending signal */
+	struct __siginfo pl_siginfo;	/* siginfo for signal */
 };
=20
 /* Argument structure for PT_VM_ENTRY. */

--BVBPRygDtbGal1Jh
Content-Type: application/pgp-signature
Content-Disposition: inline

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

iEYEARECAAYFAkwt34MACgkQC3+MBN1Mb4joeACg7pW50dhj6VJydth3NzvYokkc
2AEAoMzQHDtP0Y0PdOIFhoGLFWdweaNa
=1YSI
-----END PGP SIGNATURE-----

--BVBPRygDtbGal1Jh--



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