xref: /titanic_41/usr/src/lib/libtnfctl/continue.c (revision 8fd04b8338ed5093ec2d1e668fa620b7de44c177)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5657b1f3dSraf  * Common Development and Distribution License (the "License").
6657b1f3dSraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21657b1f3dSraf 
227c478bd9Sstevel@tonic-gate /*
23*8fd04b83SRoger A. Faulkner  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * interface to continue a target process (DIRECT_MODE) and helper
297c478bd9Sstevel@tonic-gate  * functions needed by this routine.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "tnfctl_int.h"
337c478bd9Sstevel@tonic-gate #include "prb_proc.h"
347c478bd9Sstevel@tonic-gate #include "dbg.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate static tnfctl_errcode_t _tnfctl_continue(tnfctl_handle_t *hndl,
417c478bd9Sstevel@tonic-gate     tnfctl_event_t *evt, sigset_t *oldmask, boolean_t watch_forks);
427c478bd9Sstevel@tonic-gate static tnfctl_errcode_t enable_target_state(tnfctl_handle_t *hndl,
437c478bd9Sstevel@tonic-gate     boolean_t watch_forks);
447c478bd9Sstevel@tonic-gate static tnfctl_errcode_t disable_target_state(tnfctl_handle_t *hndl);
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * continue the target process and return the evt it stopped on.
487c478bd9Sstevel@tonic-gate  * If child_hndl is set and we see a fork, return a handle on child
497c478bd9Sstevel@tonic-gate  * process.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate tnfctl_errcode_t
tnfctl_continue(tnfctl_handle_t * hndl,tnfctl_event_t * evt,tnfctl_handle_t ** child_hndl)527c478bd9Sstevel@tonic-gate tnfctl_continue(tnfctl_handle_t *hndl, tnfctl_event_t *evt,
537c478bd9Sstevel@tonic-gate 		tnfctl_handle_t **child_hndl)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat;
567c478bd9Sstevel@tonic-gate 	prb_status_t		prbstat;
577c478bd9Sstevel@tonic-gate 	boolean_t		lmapok = B_FALSE;
587c478bd9Sstevel@tonic-gate 	boolean_t		watch_forks;
597c478bd9Sstevel@tonic-gate 	/* set my_evt to something other than TNFCTL_EVENT_TARGGONE */
607c478bd9Sstevel@tonic-gate 	tnfctl_event_t		my_evt = TNFCTL_EVENT_EINTR;
617c478bd9Sstevel@tonic-gate 	enum event_op_t		dl_evt;
627c478bd9Sstevel@tonic-gate 	sigset_t		newmask, oldmask;
637c478bd9Sstevel@tonic-gate 	prb_proc_ctl_t		*proc_p;
647c478bd9Sstevel@tonic-gate 	prgreg_t		reg0, reg1;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	/* this interface only works for DIRECT_MODE clients */
677c478bd9Sstevel@tonic-gate 	if (hndl->mode != DIRECT_MODE)
687c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_BADARG);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	proc_p = hndl->proc_p;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	if (sigfillset(&newmask) == -1)
737c478bd9Sstevel@tonic-gate 		return (tnfctl_status_map(errno));
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	watch_forks = (child_hndl != NULL);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	/*
787c478bd9Sstevel@tonic-gate 	 * XXXX block all signals.  Synchronous signals like SEGV that
797c478bd9Sstevel@tonic-gate 	 * the user could catch and handle will now result in a core dump.
807c478bd9Sstevel@tonic-gate 	 * But, this is very unlikely for 2 reasons - most users don't try
817c478bd9Sstevel@tonic-gate 	 * to handle synchronous signals - it usually just aborts the process.
827c478bd9Sstevel@tonic-gate 	 * And, secondly, the code until we return the original mask is the
837c478bd9Sstevel@tonic-gate 	 * place where this synchronous signal would be generated - and, it
847c478bd9Sstevel@tonic-gate 	 * is not very much code.
857c478bd9Sstevel@tonic-gate 	 */
867c478bd9Sstevel@tonic-gate 	if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) == -1)
877c478bd9Sstevel@tonic-gate 		return (tnfctl_status_map(errno));
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	/*
907c478bd9Sstevel@tonic-gate 	 * Target is stopped on entry because tnfctl_continue()
917c478bd9Sstevel@tonic-gate 	 * only returns with a stopped target.
927c478bd9Sstevel@tonic-gate 	 */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	/* target process shouldn't be stopped when link maps are incosistent */
957c478bd9Sstevel@tonic-gate 	while (lmapok == B_FALSE) {
967c478bd9Sstevel@tonic-gate 		prexstat = _tnfctl_continue(hndl, &my_evt, &oldmask,
977c478bd9Sstevel@tonic-gate 		    watch_forks);
987c478bd9Sstevel@tonic-gate 		if (prexstat) {
997c478bd9Sstevel@tonic-gate 			if (my_evt == TNFCTL_EVENT_TARGGONE ||
1007c478bd9Sstevel@tonic-gate 			    my_evt == TNFCTL_EVENT_EXIT) {
1017c478bd9Sstevel@tonic-gate 				/*
1027c478bd9Sstevel@tonic-gate 				 * target exited - free obj list and probe
1037c478bd9Sstevel@tonic-gate 				 * list so that we keep our internal state
1047c478bd9Sstevel@tonic-gate 				 * correct, else probe control interfaces will
1057c478bd9Sstevel@tonic-gate 				 * have wrong information.
1067c478bd9Sstevel@tonic-gate 				 */
1077c478bd9Sstevel@tonic-gate 			    DBG(fprintf(stderr, "target is gone\n"));
1087c478bd9Sstevel@tonic-gate 				_tnfctl_free_objs_and_probes(hndl);
1097c478bd9Sstevel@tonic-gate 				*evt = my_evt;
1107c478bd9Sstevel@tonic-gate 				return (TNFCTL_ERR_NONE);
1117c478bd9Sstevel@tonic-gate 			} else if (my_evt == TNFCTL_EVENT_EXEC) {
1127c478bd9Sstevel@tonic-gate 				*evt = my_evt;
1137c478bd9Sstevel@tonic-gate 				return (TNFCTL_ERR_NONE);
1147c478bd9Sstevel@tonic-gate 			} else if (prexstat == TNFCTL_ERR_FILENOTFOUND) {
1157c478bd9Sstevel@tonic-gate 				return (TNFCTL_ERR_NOPROCESS);
1167c478bd9Sstevel@tonic-gate 			} else {
1177c478bd9Sstevel@tonic-gate 				return (prexstat);
1187c478bd9Sstevel@tonic-gate 			}
1197c478bd9Sstevel@tonic-gate 		}
1207c478bd9Sstevel@tonic-gate 		if (my_evt == TNFCTL_EVENT_FORK) {
1217c478bd9Sstevel@tonic-gate 	/*
1227c478bd9Sstevel@tonic-gate 	 * sanity check.  we should only get here if child_hndl is set
1237c478bd9Sstevel@tonic-gate 	 */
1247c478bd9Sstevel@tonic-gate 		    if (child_hndl) {
1257c478bd9Sstevel@tonic-gate 			    *evt = my_evt;
1267c478bd9Sstevel@tonic-gate 			    prbstat = prb_proc_get_r0_r1(proc_p,
1277c478bd9Sstevel@tonic-gate 				&reg0, &reg1);
1287c478bd9Sstevel@tonic-gate 			    if (prbstat) {
1297c478bd9Sstevel@tonic-gate 				prexstat = _tnfctl_map_to_errcode(prbstat);
1307c478bd9Sstevel@tonic-gate 				return (prexstat);
1317c478bd9Sstevel@tonic-gate 			    }
1327c478bd9Sstevel@tonic-gate 			    prexstat = tnfctl_pid_open((pid_t)reg0,
1337c478bd9Sstevel@tonic-gate 						child_hndl);
1347c478bd9Sstevel@tonic-gate 			    disable_target_state(*child_hndl);
1357c478bd9Sstevel@tonic-gate 			    return (prexstat);
1367c478bd9Sstevel@tonic-gate 			}
1377c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_NONE);
1387c478bd9Sstevel@tonic-gate 		}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 		/*
1417c478bd9Sstevel@tonic-gate 		 * update state in handle
1427c478bd9Sstevel@tonic-gate 		 * REMIND: Only need to call _tnfctl_refresh_process on
1437c478bd9Sstevel@tonic-gate 		 * dlopen or dlclose.  Need to take out other functionality
1447c478bd9Sstevel@tonic-gate 		 * of refresh_process into a separate function that should
1457c478bd9Sstevel@tonic-gate 		 * be called here.
1467c478bd9Sstevel@tonic-gate 		 */
1477c478bd9Sstevel@tonic-gate 		prexstat = _tnfctl_refresh_process(hndl, &lmapok, &dl_evt);
1487c478bd9Sstevel@tonic-gate 		if (prexstat && (lmapok == B_TRUE))
1497c478bd9Sstevel@tonic-gate 			return (prexstat);
1507c478bd9Sstevel@tonic-gate 		prexstat = TNFCTL_ERR_NONE;
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	*evt = my_evt;
1537c478bd9Sstevel@tonic-gate 	/* see if we have more detail about the event */
1547c478bd9Sstevel@tonic-gate 	if (dl_evt == EVT_OPEN)
1557c478bd9Sstevel@tonic-gate 		*evt = TNFCTL_EVENT_DLOPEN;
1567c478bd9Sstevel@tonic-gate 	else if (dl_evt == EVT_CLOSE)
1577c478bd9Sstevel@tonic-gate 		*evt = TNFCTL_EVENT_DLCLOSE;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate  * Continues target and waits for it to stop.
1647c478bd9Sstevel@tonic-gate  *	warning: This routine returns TNFCTL_EVENT_DLOPEN for any kind of
1657c478bd9Sstevel@tonic-gate  *	dl activity.  Up to the caller to determine the actual DL event.
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
_tnfctl_continue(tnfctl_handle_t * hndl,tnfctl_event_t * evt,sigset_t * oldmask,boolean_t watch_forks)1687c478bd9Sstevel@tonic-gate _tnfctl_continue(tnfctl_handle_t *hndl, tnfctl_event_t *evt, sigset_t *oldmask,
1697c478bd9Sstevel@tonic-gate     boolean_t watch_forks)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat;
1727c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	ret_prexstat = TNFCTL_ERR_NONE;
1737c478bd9Sstevel@tonic-gate 	prb_status_t		prbstat, prbstat2;
1747c478bd9Sstevel@tonic-gate 	prb_proc_ctl_t		*proc_p;
1757c478bd9Sstevel@tonic-gate 	prb_proc_state_t 	state;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	proc_p = hndl->proc_p;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	/* set up state before we run process */
1807c478bd9Sstevel@tonic-gate 	prexstat = enable_target_state(hndl, watch_forks);
1817c478bd9Sstevel@tonic-gate 	if (prexstat)
1827c478bd9Sstevel@tonic-gate 		return (prexstat);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate again:
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/* resume target */
1877c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_cont(proc_p);
1887c478bd9Sstevel@tonic-gate 	if (prbstat) {
1897c478bd9Sstevel@tonic-gate 		ret_prexstat = _tnfctl_map_to_errcode(prbstat);
1907c478bd9Sstevel@tonic-gate 		goto end_of_func;
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	/* wait on target to stop (standby) */
1947c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_wait(proc_p, B_TRUE, oldmask);
1957c478bd9Sstevel@tonic-gate 	if (prbstat) {
1967c478bd9Sstevel@tonic-gate 		if (prbstat == EINTR) {
1977c478bd9Sstevel@tonic-gate 			*evt = TNFCTL_EVENT_EINTR;
1987c478bd9Sstevel@tonic-gate 			prbstat2 = prb_proc_stop(proc_p);
1997c478bd9Sstevel@tonic-gate 			if (prbstat2) {
2007c478bd9Sstevel@tonic-gate 				ret_prexstat = _tnfctl_map_to_errcode(prbstat2);
2017c478bd9Sstevel@tonic-gate 				goto end_of_func;
2027c478bd9Sstevel@tonic-gate 			}
2037c478bd9Sstevel@tonic-gate 		} else if (prbstat == ENOENT) {
2047c478bd9Sstevel@tonic-gate 			/* target process finished */
2057c478bd9Sstevel@tonic-gate 			if (hndl->called_exit)
2067c478bd9Sstevel@tonic-gate 				*evt = TNFCTL_EVENT_EXIT;
2077c478bd9Sstevel@tonic-gate 			else
2087c478bd9Sstevel@tonic-gate 				*evt = TNFCTL_EVENT_TARGGONE;
2097c478bd9Sstevel@tonic-gate 			/* return directly - process no longer around */
2107c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
2117c478bd9Sstevel@tonic-gate 		} else {
2127c478bd9Sstevel@tonic-gate 			ret_prexstat = _tnfctl_map_to_errcode(prbstat);
2137c478bd9Sstevel@tonic-gate 			goto end_of_func;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_state(proc_p, &state);
2187c478bd9Sstevel@tonic-gate 	if (prbstat) {
2197c478bd9Sstevel@tonic-gate 		ret_prexstat = _tnfctl_map_to_errcode(prbstat);
2207c478bd9Sstevel@tonic-gate 		goto end_of_func;
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	if (state.ps_isbptfault) {
2237c478bd9Sstevel@tonic-gate 		/* dlopen or dlclose */
2247c478bd9Sstevel@tonic-gate 		prbstat = prb_rtld_advance(proc_p);
2257c478bd9Sstevel@tonic-gate 		if (prbstat) {
2267c478bd9Sstevel@tonic-gate 			ret_prexstat = _tnfctl_map_to_errcode(prbstat);
2277c478bd9Sstevel@tonic-gate 			goto end_of_func;
2287c478bd9Sstevel@tonic-gate 		}
2297c478bd9Sstevel@tonic-gate 		/*
2307c478bd9Sstevel@tonic-gate 		 * actually don't know if it is a dlopen or dlclose yet.
2317c478bd9Sstevel@tonic-gate 		 * But, we return dlopen here.  Up to the caller to determine
2327c478bd9Sstevel@tonic-gate 		 * which one it actually is.
2337c478bd9Sstevel@tonic-gate 		 */
2347c478bd9Sstevel@tonic-gate 		*evt = TNFCTL_EVENT_DLOPEN;
2357c478bd9Sstevel@tonic-gate 	} else
2367c478bd9Sstevel@tonic-gate 	    if (state.ps_issysentry) {
2377c478bd9Sstevel@tonic-gate 		switch (state.ps_syscallnum) {
2387c478bd9Sstevel@tonic-gate 		case SYS_execve:
2397c478bd9Sstevel@tonic-gate 		    *evt = TNFCTL_EVENT_EXEC;
2407c478bd9Sstevel@tonic-gate 		    ret_prexstat = TNFCTL_ERR_INTERNAL;
2417c478bd9Sstevel@tonic-gate 		    break;
2427c478bd9Sstevel@tonic-gate 		case SYS_exit:
2437c478bd9Sstevel@tonic-gate 		    hndl->called_exit = B_TRUE;
2447c478bd9Sstevel@tonic-gate 		    goto again;
2457c478bd9Sstevel@tonic-gate 		default:
2467c478bd9Sstevel@tonic-gate 		    break;
2477c478bd9Sstevel@tonic-gate 		}
2487c478bd9Sstevel@tonic-gate 	    } else if (state.ps_issysexit) {
2497c478bd9Sstevel@tonic-gate 		    switch (state.ps_syscallnum) {
2507c478bd9Sstevel@tonic-gate 		    case SYS_vfork:
251657b1f3dSraf 		    case SYS_forksys:
2527c478bd9Sstevel@tonic-gate 			*evt = TNFCTL_EVENT_FORK;
2537c478bd9Sstevel@tonic-gate 			break;
2547c478bd9Sstevel@tonic-gate 		    default:
2557c478bd9Sstevel@tonic-gate 			break;
2567c478bd9Sstevel@tonic-gate 		    }
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate end_of_func:
2597c478bd9Sstevel@tonic-gate 	/*
2607c478bd9Sstevel@tonic-gate 	 * disable all our sycall tracing and bpt setup in process when it
2617c478bd9Sstevel@tonic-gate 	 * is stopped, so that even if the controlling process aborts,
2627c478bd9Sstevel@tonic-gate 	 * the target could continue running
2637c478bd9Sstevel@tonic-gate 	 */
2647c478bd9Sstevel@tonic-gate 	prexstat = disable_target_state(hndl);
2657c478bd9Sstevel@tonic-gate 	if (prexstat)
2667c478bd9Sstevel@tonic-gate 		return (prexstat);
2677c478bd9Sstevel@tonic-gate 	return (ret_prexstat);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  * enable the system call tracing and dl activity tracing
2727c478bd9Sstevel@tonic-gate  */
2737c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
enable_target_state(tnfctl_handle_t * hndl,boolean_t watch_forks)2747c478bd9Sstevel@tonic-gate enable_target_state(tnfctl_handle_t *hndl, boolean_t watch_forks)
2757c478bd9Sstevel@tonic-gate {
2767c478bd9Sstevel@tonic-gate 	prb_status_t	prbstat;
2777c478bd9Sstevel@tonic-gate 	prb_proc_ctl_t	*proc_p;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	proc_p = hndl->proc_p;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	/* trace exec */
2827c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, SYS_execve, PRB_SYS_ADD);
2837c478bd9Sstevel@tonic-gate 	if (prbstat)
2847c478bd9Sstevel@tonic-gate 		return (_tnfctl_map_to_errcode(prbstat));
2857c478bd9Sstevel@tonic-gate 	/* trace exit */
2867c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_ADD);
2877c478bd9Sstevel@tonic-gate 	if (prbstat)
2887c478bd9Sstevel@tonic-gate 		return (_tnfctl_map_to_errcode(prbstat));
2897c478bd9Sstevel@tonic-gate 	/* trace fork if the caller requests */
2907c478bd9Sstevel@tonic-gate 	if (watch_forks) {
2917c478bd9Sstevel@tonic-gate 		prbstat = prb_proc_exit(proc_p, SYS_vfork, PRB_SYS_ADD);
2927c478bd9Sstevel@tonic-gate 		if (prbstat)
2937c478bd9Sstevel@tonic-gate 			return (_tnfctl_map_to_errcode(prbstat));
2947c478bd9Sstevel@tonic-gate 
295657b1f3dSraf 		prbstat = prb_proc_exit(proc_p, SYS_forksys, PRB_SYS_ADD);
296657b1f3dSraf 		if (prbstat)
297657b1f3dSraf 			return (_tnfctl_map_to_errcode(prbstat));
298657b1f3dSraf 
2997c478bd9Sstevel@tonic-gate 		prbstat = prb_proc_setfork(proc_p, B_TRUE);
3007c478bd9Sstevel@tonic-gate 		if (prbstat)
3017c478bd9Sstevel@tonic-gate 			return (_tnfctl_map_to_errcode(prbstat));
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 	/*
3047c478bd9Sstevel@tonic-gate 	 * tracing flags for fork and exec will get unset when
3057c478bd9Sstevel@tonic-gate 	 * process stops. see disable_target_state()
3067c478bd9Sstevel@tonic-gate 	 */
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	/* setup process to stop during dlopen() or dlclose() */
3097c478bd9Sstevel@tonic-gate 	prbstat = prb_rtld_stalk(proc_p);
3107c478bd9Sstevel@tonic-gate 	return (_tnfctl_map_to_errcode(prbstat));
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate  * disable the system call tracing and dl activity tracing
3157c478bd9Sstevel@tonic-gate  */
3167c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
disable_target_state(tnfctl_handle_t * hndl)3177c478bd9Sstevel@tonic-gate disable_target_state(tnfctl_handle_t *hndl)
3187c478bd9Sstevel@tonic-gate {
3197c478bd9Sstevel@tonic-gate 	prb_status_t	prbstat;
3207c478bd9Sstevel@tonic-gate 	prb_proc_ctl_t	*proc_p;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	proc_p = hndl->proc_p;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	/* remove the stalking breakpoint while the process is stopped */
3257c478bd9Sstevel@tonic-gate 	prbstat = prb_rtld_unstalk(proc_p);
3267c478bd9Sstevel@tonic-gate 	if (prbstat)
3277c478bd9Sstevel@tonic-gate 		return (_tnfctl_map_to_errcode(prbstat));
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/* remove the exec, exit and fork tracing while stopped */
3307c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, SYS_execve, PRB_SYS_DEL);
3317c478bd9Sstevel@tonic-gate 	if (prbstat)
3327c478bd9Sstevel@tonic-gate 		return (_tnfctl_map_to_errcode(prbstat));
3337c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_DEL);
3347c478bd9Sstevel@tonic-gate 	if (prbstat)
3357c478bd9Sstevel@tonic-gate 		return (_tnfctl_map_to_errcode(prbstat));
3367c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_exit(proc_p, SYS_vfork, PRB_SYS_DEL);
3377c478bd9Sstevel@tonic-gate 	if (prbstat)
3387c478bd9Sstevel@tonic-gate 	    return (_tnfctl_map_to_errcode(prbstat));
339657b1f3dSraf 	prbstat = prb_proc_exit(proc_p, SYS_forksys, PRB_SYS_DEL);
340657b1f3dSraf 	if (prbstat)
341657b1f3dSraf 	    return (_tnfctl_map_to_errcode(prbstat));
3427c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_setfork(proc_p, B_FALSE);
3437c478bd9Sstevel@tonic-gate 	if (prbstat)
3447c478bd9Sstevel@tonic-gate 	    return (_tnfctl_map_to_errcode(prbstat));
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
3477c478bd9Sstevel@tonic-gate }
348