1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1994,2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * interface to continue a target process (DIRECT_MODE) and helper 31*7c478bd9Sstevel@tonic-gate * functions needed by this routine. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "tnfctl_int.h" 35*7c478bd9Sstevel@tonic-gate #include "prb_proc.h" 36*7c478bd9Sstevel@tonic-gate #include "dbg.h" 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t _tnfctl_continue(tnfctl_handle_t *hndl, 43*7c478bd9Sstevel@tonic-gate tnfctl_event_t *evt, sigset_t *oldmask, boolean_t watch_forks); 44*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t enable_target_state(tnfctl_handle_t *hndl, 45*7c478bd9Sstevel@tonic-gate boolean_t watch_forks); 46*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t disable_target_state(tnfctl_handle_t *hndl); 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * continue the target process and return the evt it stopped on. 50*7c478bd9Sstevel@tonic-gate * If child_hndl is set and we see a fork, return a handle on child 51*7c478bd9Sstevel@tonic-gate * process. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t 54*7c478bd9Sstevel@tonic-gate tnfctl_continue(tnfctl_handle_t *hndl, tnfctl_event_t *evt, 55*7c478bd9Sstevel@tonic-gate tnfctl_handle_t **child_hndl) 56*7c478bd9Sstevel@tonic-gate { 57*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 58*7c478bd9Sstevel@tonic-gate prb_status_t prbstat; 59*7c478bd9Sstevel@tonic-gate boolean_t lmapok = B_FALSE; 60*7c478bd9Sstevel@tonic-gate boolean_t watch_forks; 61*7c478bd9Sstevel@tonic-gate /* set my_evt to something other than TNFCTL_EVENT_TARGGONE */ 62*7c478bd9Sstevel@tonic-gate tnfctl_event_t my_evt = TNFCTL_EVENT_EINTR; 63*7c478bd9Sstevel@tonic-gate enum event_op_t dl_evt; 64*7c478bd9Sstevel@tonic-gate sigset_t newmask, oldmask; 65*7c478bd9Sstevel@tonic-gate prb_proc_ctl_t *proc_p; 66*7c478bd9Sstevel@tonic-gate prgreg_t reg0, reg1; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* this interface only works for DIRECT_MODE clients */ 69*7c478bd9Sstevel@tonic-gate if (hndl->mode != DIRECT_MODE) 70*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_BADARG); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate proc_p = hndl->proc_p; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate if (sigfillset(&newmask) == -1) 75*7c478bd9Sstevel@tonic-gate return (tnfctl_status_map(errno)); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate watch_forks = (child_hndl != NULL); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate * XXXX block all signals. Synchronous signals like SEGV that 81*7c478bd9Sstevel@tonic-gate * the user could catch and handle will now result in a core dump. 82*7c478bd9Sstevel@tonic-gate * But, this is very unlikely for 2 reasons - most users don't try 83*7c478bd9Sstevel@tonic-gate * to handle synchronous signals - it usually just aborts the process. 84*7c478bd9Sstevel@tonic-gate * And, secondly, the code until we return the original mask is the 85*7c478bd9Sstevel@tonic-gate * place where this synchronous signal would be generated - and, it 86*7c478bd9Sstevel@tonic-gate * is not very much code. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) == -1) 89*7c478bd9Sstevel@tonic-gate return (tnfctl_status_map(errno)); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate /* 92*7c478bd9Sstevel@tonic-gate * Target is stopped on entry because tnfctl_continue() 93*7c478bd9Sstevel@tonic-gate * only returns with a stopped target. 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* target process shouldn't be stopped when link maps are incosistent */ 97*7c478bd9Sstevel@tonic-gate while (lmapok == B_FALSE) { 98*7c478bd9Sstevel@tonic-gate prexstat = _tnfctl_continue(hndl, &my_evt, &oldmask, 99*7c478bd9Sstevel@tonic-gate watch_forks); 100*7c478bd9Sstevel@tonic-gate if (prexstat) { 101*7c478bd9Sstevel@tonic-gate if (my_evt == TNFCTL_EVENT_TARGGONE || 102*7c478bd9Sstevel@tonic-gate my_evt == TNFCTL_EVENT_EXIT) { 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * target exited - free obj list and probe 105*7c478bd9Sstevel@tonic-gate * list so that we keep our internal state 106*7c478bd9Sstevel@tonic-gate * correct, else probe control interfaces will 107*7c478bd9Sstevel@tonic-gate * have wrong information. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate DBG(fprintf(stderr, "target is gone\n")); 110*7c478bd9Sstevel@tonic-gate _tnfctl_free_objs_and_probes(hndl); 111*7c478bd9Sstevel@tonic-gate *evt = my_evt; 112*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 113*7c478bd9Sstevel@tonic-gate } else if (my_evt == TNFCTL_EVENT_EXEC) { 114*7c478bd9Sstevel@tonic-gate *evt = my_evt; 115*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 116*7c478bd9Sstevel@tonic-gate } else if (prexstat == TNFCTL_ERR_FILENOTFOUND) { 117*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NOPROCESS); 118*7c478bd9Sstevel@tonic-gate } else { 119*7c478bd9Sstevel@tonic-gate return (prexstat); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate if (my_evt == TNFCTL_EVENT_FORK) { 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * sanity check. we should only get here if child_hndl is set 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate if (child_hndl) { 127*7c478bd9Sstevel@tonic-gate *evt = my_evt; 128*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_get_r0_r1(proc_p, 129*7c478bd9Sstevel@tonic-gate ®0, ®1); 130*7c478bd9Sstevel@tonic-gate if (prbstat) { 131*7c478bd9Sstevel@tonic-gate prexstat = _tnfctl_map_to_errcode(prbstat); 132*7c478bd9Sstevel@tonic-gate return (prexstat); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate prexstat = tnfctl_pid_open((pid_t)reg0, 135*7c478bd9Sstevel@tonic-gate child_hndl); 136*7c478bd9Sstevel@tonic-gate disable_target_state(*child_hndl); 137*7c478bd9Sstevel@tonic-gate return (prexstat); 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * update state in handle 144*7c478bd9Sstevel@tonic-gate * REMIND: Only need to call _tnfctl_refresh_process on 145*7c478bd9Sstevel@tonic-gate * dlopen or dlclose. Need to take out other functionality 146*7c478bd9Sstevel@tonic-gate * of refresh_process into a separate function that should 147*7c478bd9Sstevel@tonic-gate * be called here. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate prexstat = _tnfctl_refresh_process(hndl, &lmapok, &dl_evt); 150*7c478bd9Sstevel@tonic-gate if (prexstat && (lmapok == B_TRUE)) 151*7c478bd9Sstevel@tonic-gate return (prexstat); 152*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_NONE; 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate *evt = my_evt; 155*7c478bd9Sstevel@tonic-gate /* see if we have more detail about the event */ 156*7c478bd9Sstevel@tonic-gate if (dl_evt == EVT_OPEN) 157*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_DLOPEN; 158*7c478bd9Sstevel@tonic-gate else if (dl_evt == EVT_CLOSE) 159*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_DLCLOSE; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * Continues target and waits for it to stop. 166*7c478bd9Sstevel@tonic-gate * warning: This routine returns TNFCTL_EVENT_DLOPEN for any kind of 167*7c478bd9Sstevel@tonic-gate * dl activity. Up to the caller to determine the actual DL event. 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 170*7c478bd9Sstevel@tonic-gate _tnfctl_continue(tnfctl_handle_t *hndl, tnfctl_event_t *evt, sigset_t *oldmask, 171*7c478bd9Sstevel@tonic-gate boolean_t watch_forks) 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 174*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t ret_prexstat = TNFCTL_ERR_NONE; 175*7c478bd9Sstevel@tonic-gate prb_status_t prbstat, prbstat2; 176*7c478bd9Sstevel@tonic-gate prb_proc_ctl_t *proc_p; 177*7c478bd9Sstevel@tonic-gate prb_proc_state_t state; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate proc_p = hndl->proc_p; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* set up state before we run process */ 182*7c478bd9Sstevel@tonic-gate prexstat = enable_target_state(hndl, watch_forks); 183*7c478bd9Sstevel@tonic-gate if (prexstat) 184*7c478bd9Sstevel@tonic-gate return (prexstat); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate again: 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* resume target */ 189*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_cont(proc_p); 190*7c478bd9Sstevel@tonic-gate if (prbstat) { 191*7c478bd9Sstevel@tonic-gate ret_prexstat = _tnfctl_map_to_errcode(prbstat); 192*7c478bd9Sstevel@tonic-gate goto end_of_func; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate /* wait on target to stop (standby) */ 196*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_wait(proc_p, B_TRUE, oldmask); 197*7c478bd9Sstevel@tonic-gate if (prbstat) { 198*7c478bd9Sstevel@tonic-gate if (prbstat == EINTR) { 199*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_EINTR; 200*7c478bd9Sstevel@tonic-gate prbstat2 = prb_proc_stop(proc_p); 201*7c478bd9Sstevel@tonic-gate if (prbstat2) { 202*7c478bd9Sstevel@tonic-gate ret_prexstat = _tnfctl_map_to_errcode(prbstat2); 203*7c478bd9Sstevel@tonic-gate goto end_of_func; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } else if (prbstat == ENOENT) { 206*7c478bd9Sstevel@tonic-gate /* target process finished */ 207*7c478bd9Sstevel@tonic-gate if (hndl->called_exit) 208*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_EXIT; 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_TARGGONE; 211*7c478bd9Sstevel@tonic-gate /* return directly - process no longer around */ 212*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_INTERNAL); 213*7c478bd9Sstevel@tonic-gate } else { 214*7c478bd9Sstevel@tonic-gate ret_prexstat = _tnfctl_map_to_errcode(prbstat); 215*7c478bd9Sstevel@tonic-gate goto end_of_func; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_state(proc_p, &state); 220*7c478bd9Sstevel@tonic-gate if (prbstat) { 221*7c478bd9Sstevel@tonic-gate ret_prexstat = _tnfctl_map_to_errcode(prbstat); 222*7c478bd9Sstevel@tonic-gate goto end_of_func; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate if (state.ps_isbptfault) { 225*7c478bd9Sstevel@tonic-gate /* dlopen or dlclose */ 226*7c478bd9Sstevel@tonic-gate prbstat = prb_rtld_advance(proc_p); 227*7c478bd9Sstevel@tonic-gate if (prbstat) { 228*7c478bd9Sstevel@tonic-gate ret_prexstat = _tnfctl_map_to_errcode(prbstat); 229*7c478bd9Sstevel@tonic-gate goto end_of_func; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate /* 232*7c478bd9Sstevel@tonic-gate * actually don't know if it is a dlopen or dlclose yet. 233*7c478bd9Sstevel@tonic-gate * But, we return dlopen here. Up to the caller to determine 234*7c478bd9Sstevel@tonic-gate * which one it actually is. 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_DLOPEN; 237*7c478bd9Sstevel@tonic-gate } else 238*7c478bd9Sstevel@tonic-gate if (state.ps_issysentry) { 239*7c478bd9Sstevel@tonic-gate switch (state.ps_syscallnum) { 240*7c478bd9Sstevel@tonic-gate case SYS_exec: 241*7c478bd9Sstevel@tonic-gate case SYS_execve: 242*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_EXEC; 243*7c478bd9Sstevel@tonic-gate ret_prexstat = TNFCTL_ERR_INTERNAL; 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate case SYS_exit: 246*7c478bd9Sstevel@tonic-gate hndl->called_exit = B_TRUE; 247*7c478bd9Sstevel@tonic-gate goto again; 248*7c478bd9Sstevel@tonic-gate default: 249*7c478bd9Sstevel@tonic-gate break; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate } else if (state.ps_issysexit) { 252*7c478bd9Sstevel@tonic-gate switch (state.ps_syscallnum) { 253*7c478bd9Sstevel@tonic-gate case SYS_forkall: 254*7c478bd9Sstevel@tonic-gate case SYS_vfork: 255*7c478bd9Sstevel@tonic-gate case SYS_fork1: 256*7c478bd9Sstevel@tonic-gate *evt = TNFCTL_EVENT_FORK; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate default: 259*7c478bd9Sstevel@tonic-gate break; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate end_of_func: 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * disable all our sycall tracing and bpt setup in process when it 265*7c478bd9Sstevel@tonic-gate * is stopped, so that even if the controlling process aborts, 266*7c478bd9Sstevel@tonic-gate * the target could continue running 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate prexstat = disable_target_state(hndl); 269*7c478bd9Sstevel@tonic-gate if (prexstat) 270*7c478bd9Sstevel@tonic-gate return (prexstat); 271*7c478bd9Sstevel@tonic-gate return (ret_prexstat); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * enable the system call tracing and dl activity tracing 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 278*7c478bd9Sstevel@tonic-gate enable_target_state(tnfctl_handle_t *hndl, boolean_t watch_forks) 279*7c478bd9Sstevel@tonic-gate { 280*7c478bd9Sstevel@tonic-gate prb_status_t prbstat; 281*7c478bd9Sstevel@tonic-gate prb_proc_ctl_t *proc_p; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate proc_p = hndl->proc_p; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* trace exec */ 286*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_execve, PRB_SYS_ADD); 287*7c478bd9Sstevel@tonic-gate if (prbstat) 288*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 289*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_exec, PRB_SYS_ADD); 290*7c478bd9Sstevel@tonic-gate if (prbstat) 291*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 292*7c478bd9Sstevel@tonic-gate /* trace exit */ 293*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_ADD); 294*7c478bd9Sstevel@tonic-gate if (prbstat) 295*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 296*7c478bd9Sstevel@tonic-gate /* trace fork if the caller requests */ 297*7c478bd9Sstevel@tonic-gate if (watch_forks) { 298*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_forkall, PRB_SYS_ADD); 299*7c478bd9Sstevel@tonic-gate if (prbstat) 300*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_vfork, PRB_SYS_ADD); 303*7c478bd9Sstevel@tonic-gate if (prbstat) 304*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_fork1, PRB_SYS_ADD); 307*7c478bd9Sstevel@tonic-gate if (prbstat) 308*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 309*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_setfork(proc_p, B_TRUE); 310*7c478bd9Sstevel@tonic-gate if (prbstat) 311*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * tracing flags for fork and exec will get unset when 315*7c478bd9Sstevel@tonic-gate * process stops. see disable_target_state() 316*7c478bd9Sstevel@tonic-gate */ 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* setup process to stop during dlopen() or dlclose() */ 319*7c478bd9Sstevel@tonic-gate prbstat = prb_rtld_stalk(proc_p); 320*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * disable the system call tracing and dl activity tracing 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 327*7c478bd9Sstevel@tonic-gate disable_target_state(tnfctl_handle_t *hndl) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate prb_status_t prbstat; 330*7c478bd9Sstevel@tonic-gate prb_proc_ctl_t *proc_p; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate proc_p = hndl->proc_p; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* remove the stalking breakpoint while the process is stopped */ 335*7c478bd9Sstevel@tonic-gate prbstat = prb_rtld_unstalk(proc_p); 336*7c478bd9Sstevel@tonic-gate if (prbstat) 337*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* remove the exec, exit and fork tracing while stopped */ 340*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_execve, PRB_SYS_DEL); 341*7c478bd9Sstevel@tonic-gate if (prbstat) 342*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 343*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_exec, PRB_SYS_DEL); 344*7c478bd9Sstevel@tonic-gate if (prbstat) 345*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 346*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_DEL); 347*7c478bd9Sstevel@tonic-gate if (prbstat) 348*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 349*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_forkall, PRB_SYS_DEL); 350*7c478bd9Sstevel@tonic-gate if (prbstat) 351*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 352*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_vfork, PRB_SYS_DEL); 353*7c478bd9Sstevel@tonic-gate if (prbstat) 354*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 355*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_exit(proc_p, SYS_fork1, PRB_SYS_DEL); 356*7c478bd9Sstevel@tonic-gate if (prbstat) 357*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 358*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_setfork(proc_p, B_FALSE); 359*7c478bd9Sstevel@tonic-gate if (prbstat) 360*7c478bd9Sstevel@tonic-gate return (_tnfctl_map_to_errcode(prbstat)); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 363*7c478bd9Sstevel@tonic-gate } 364