xref: /titanic_41/usr/src/lib/libtnfctl/util.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 (c) 1994, by Sun Microsytems, Inc.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * Utility functions to initialize tnfctl handle, find functions that
30*7c478bd9Sstevel@tonic-gate  * can be plugged into probes, find trace file information, and create
31*7c478bd9Sstevel@tonic-gate  * a trace file for process tracing.
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #ifndef DEBUG
35*7c478bd9Sstevel@tonic-gate #define	NDEBUG	1
36*7c478bd9Sstevel@tonic-gate #endif
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #include "tnfctl_int.h"
39*7c478bd9Sstevel@tonic-gate #include "dbg.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <assert.h>
42*7c478bd9Sstevel@tonic-gate #include <errno.h>
43*7c478bd9Sstevel@tonic-gate #include <stdio.h>
44*7c478bd9Sstevel@tonic-gate #include <string.h>
45*7c478bd9Sstevel@tonic-gate #include <unistd.h>
46*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
47*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #include "tnf_buf.h"
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  * Defines - Project private interfaces in libtnfprobe.so
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #define	TRACEFILE_NAME		"tnf_trace_file_name"
56*7c478bd9Sstevel@tonic-gate #define	TRACEFILE_SIZE		"tnf_trace_file_size"
57*7c478bd9Sstevel@tonic-gate #define	TRACEFILE_MIN		"tnf_trace_file_min"
58*7c478bd9Sstevel@tonic-gate #define	TRACE_ERROR		"_tnfw_b_control"
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #define	TRACE_ALLOC		"tnf_trace_alloc"
61*7c478bd9Sstevel@tonic-gate #define	TRACE_COMMIT		"tnf_trace_commit"
62*7c478bd9Sstevel@tonic-gate #define	TRACE_ROLLBACK		"tnf_trace_rollback"
63*7c478bd9Sstevel@tonic-gate #define	DEBUG_ENTRY		"tnf_probe_debug"
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	PROBE_LIST_HEAD		"__tnf_probe_list_head"
66*7c478bd9Sstevel@tonic-gate #define	PROBE_LIST_VALID	"__tnf_probe_list_valid"
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate #define	NONTHREAD_TEST		"tnf_non_threaded_test_addr"
69*7c478bd9Sstevel@tonic-gate #define	THREAD_TEST		"tnf_threaded_test_addr"
70*7c478bd9Sstevel@tonic-gate #define	PROBE_THR_SYNC		"__tnf_probe_thr_sync"
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	MEMSEG_PTR		"__tnf_probe_memseg_p"
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /* Project private interfaces in libthread.so */
75*7c478bd9Sstevel@tonic-gate #define	LIBTHREAD_PRESENT	"thr_probe_getfunc_addr"
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate  * Local declarations
79*7c478bd9Sstevel@tonic-gate  */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t find_test_func(tnfctl_handle_t *hndl);
82*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t find_target_syms(tnfctl_handle_t *hndl);
83*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t find_trace_file_info(tnfctl_handle_t *hndl);
84*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t check_trace_error(tnfctl_handle_t *hndl);
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * _tnfctl_refresh_process() - search for new shared objects.  If any
88*7c478bd9Sstevel@tonic-gate  * found, discover probes in new shared objects.
89*7c478bd9Sstevel@tonic-gate  *	NOT to be called in kernel mode.
90*7c478bd9Sstevel@tonic-gate  */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t
_tnfctl_refresh_process(tnfctl_handle_t * hndl,boolean_t * lmap_ok,enum event_op_t * dl_evt)93*7c478bd9Sstevel@tonic-gate _tnfctl_refresh_process(tnfctl_handle_t *hndl, boolean_t *lmap_ok,
94*7c478bd9Sstevel@tonic-gate 			enum event_op_t *dl_evt)
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat = TNFCTL_ERR_NONE;
97*7c478bd9Sstevel@tonic-gate 	boolean_t	release_lock;
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	assert(hndl->mode != KERNEL_MODE);
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	/*LINTED statement has no consequent: else*/
102*7c478bd9Sstevel@tonic-gate 	LOCK(hndl, prexstat, release_lock);
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	prexstat = check_trace_error(hndl);
105*7c478bd9Sstevel@tonic-gate 	if (prexstat)
106*7c478bd9Sstevel@tonic-gate 		goto finish_func;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	/*
109*7c478bd9Sstevel@tonic-gate 	 * update the link map. caller decides what to do on
110*7c478bd9Sstevel@tonic-gate 	 * inconsistent link map
111*7c478bd9Sstevel@tonic-gate 	 */
112*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_lmap_update(hndl, lmap_ok, dl_evt);
113*7c478bd9Sstevel@tonic-gate 	if (prexstat)
114*7c478bd9Sstevel@tonic-gate 		goto finish_func;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	/* link map is ok now */
117*7c478bd9Sstevel@tonic-gate 	prexstat = find_test_func(hndl);
118*7c478bd9Sstevel@tonic-gate 	if (prexstat)
119*7c478bd9Sstevel@tonic-gate 		goto finish_func;
120*7c478bd9Sstevel@tonic-gate 	if (*dl_evt != EVT_NONE) {
121*7c478bd9Sstevel@tonic-gate 		prexstat = _tnfctl_find_all_probes(hndl);
122*7c478bd9Sstevel@tonic-gate 		if (prexstat)
123*7c478bd9Sstevel@tonic-gate 			goto finish_func;
124*7c478bd9Sstevel@tonic-gate 	}
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate finish_func:
127*7c478bd9Sstevel@tonic-gate 	/*LINTED statement has no consequent: else*/
128*7c478bd9Sstevel@tonic-gate 	UNLOCK(hndl, release_lock);
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	return (prexstat);
131*7c478bd9Sstevel@tonic-gate }
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate /*
134*7c478bd9Sstevel@tonic-gate  * initialize tnfctl handle for a new target
135*7c478bd9Sstevel@tonic-gate  */
136*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t
_tnfctl_set_state(tnfctl_handle_t * hndl)137*7c478bd9Sstevel@tonic-gate _tnfctl_set_state(tnfctl_handle_t *hndl)
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat = TNFCTL_ERR_NONE;
140*7c478bd9Sstevel@tonic-gate 	boolean_t	lmap_ok;
141*7c478bd9Sstevel@tonic-gate 	enum event_op_t	dl_evt;
142*7c478bd9Sstevel@tonic-gate 	boolean_t	release_lock;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	hndl->targ_pid = hndl->p_getpid(hndl->proc_p);
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 	/*LINTED statement has no consequent: else*/
147*7c478bd9Sstevel@tonic-gate 	LOCK(hndl, prexstat, release_lock);
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	/*
150*7c478bd9Sstevel@tonic-gate 	 * initialize the link map table. If link map is not ok, it is an
151*7c478bd9Sstevel@tonic-gate 	 * error.
152*7c478bd9Sstevel@tonic-gate 	 */
153*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_lmap_update(hndl, &lmap_ok, &dl_evt);
154*7c478bd9Sstevel@tonic-gate 	if (prexstat)
155*7c478bd9Sstevel@tonic-gate 		goto end_func;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/* find the needed target symbols */
158*7c478bd9Sstevel@tonic-gate 	prexstat = find_target_syms(hndl);
159*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
160*7c478bd9Sstevel@tonic-gate 		/* is libtnfprobe.so loaded in target ? */
161*7c478bd9Sstevel@tonic-gate 		goto end_func;
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	prexstat = find_trace_file_info(hndl);
165*7c478bd9Sstevel@tonic-gate 	if (prexstat)
166*7c478bd9Sstevel@tonic-gate 		goto end_func;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	prexstat = find_test_func(hndl);
169*7c478bd9Sstevel@tonic-gate 	if (prexstat)
170*7c478bd9Sstevel@tonic-gate 		goto end_func;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_find_all_probes(hndl);
173*7c478bd9Sstevel@tonic-gate 	if (prexstat)
174*7c478bd9Sstevel@tonic-gate 		goto end_func;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	prexstat = check_trace_error(hndl);
177*7c478bd9Sstevel@tonic-gate 	/* fall into end_func */
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate end_func:
180*7c478bd9Sstevel@tonic-gate 	/*LINTED statement has no consequent: else*/
181*7c478bd9Sstevel@tonic-gate 	UNLOCK(hndl, release_lock);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	return (prexstat);
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate  * find the test function for a probe.  The test function could change
188*7c478bd9Sstevel@tonic-gate  * with time, so we have to repeatedly check for the test function to use
189*7c478bd9Sstevel@tonic-gate  */
190*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
find_test_func(tnfctl_handle_t * hndl)191*7c478bd9Sstevel@tonic-gate find_test_func(tnfctl_handle_t *hndl)
192*7c478bd9Sstevel@tonic-gate {
193*7c478bd9Sstevel@tonic-gate 	long		thr_sync;
194*7c478bd9Sstevel@tonic-gate 	int		miscstat;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	if (hndl->mt_target == B_FALSE) {
197*7c478bd9Sstevel@tonic-gate 		/* no libthread linked in */
198*7c478bd9Sstevel@tonic-gate 		hndl->testfunc = hndl->nonthread_test;
199*7c478bd9Sstevel@tonic-gate 	} else {
200*7c478bd9Sstevel@tonic-gate 		/*
201*7c478bd9Sstevel@tonic-gate 		 * check whether libthread/libtnfw have synced up.
202*7c478bd9Sstevel@tonic-gate 		 * If not yet synced up, use non-threaded test function
203*7c478bd9Sstevel@tonic-gate 		 */
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 		/* assume we are going to use threaded test */
206*7c478bd9Sstevel@tonic-gate 		hndl->testfunc = hndl->thread_test;
207*7c478bd9Sstevel@tonic-gate 		miscstat = hndl->p_read(hndl->proc_p, hndl->thread_sync,
208*7c478bd9Sstevel@tonic-gate 			&thr_sync, sizeof (thr_sync));
209*7c478bd9Sstevel@tonic-gate 		if (miscstat != 0)
210*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
211*7c478bd9Sstevel@tonic-gate 		/* if not yet synced up, change test func to non-threaded one */
212*7c478bd9Sstevel@tonic-gate 		if (thr_sync == 0) {
213*7c478bd9Sstevel@tonic-gate 			hndl->testfunc = hndl->nonthread_test;
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	/*
218*7c478bd9Sstevel@tonic-gate 	 * Note: the testfunc in the target can change underneath us because
219*7c478bd9Sstevel@tonic-gate 	 * in an MT program the init section of libthread changes all the
220*7c478bd9Sstevel@tonic-gate 	 * test functions from the non-threaded one to the threaded one.
221*7c478bd9Sstevel@tonic-gate 	 * So, every time we write out a probe, we have to make sure that
222*7c478bd9Sstevel@tonic-gate 	 * we are using the correct test function by not trusting the test
223*7c478bd9Sstevel@tonic-gate 	 * function in our copy of the probe.  A more fool-proof solution
224*7c478bd9Sstevel@tonic-gate 	 * which will allow other fields in the probe to change internally
225*7c478bd9Sstevel@tonic-gate 	 * is to refresh every probe on a _tnfctl_refresh_process()
226*7c478bd9Sstevel@tonic-gate 	 */
227*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate /*
231*7c478bd9Sstevel@tonic-gate  * check_trace_error() - checks whether there was an error in tracing
232*7c478bd9Sstevel@tonic-gate  *	side effects trace_buf_state and trace_state in hndl
233*7c478bd9Sstevel@tonic-gate  *	note: call this function only after trace_file_name is set up
234*7c478bd9Sstevel@tonic-gate  *	in hndl
235*7c478bd9Sstevel@tonic-gate  */
236*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t
check_trace_error(tnfctl_handle_t * hndl)237*7c478bd9Sstevel@tonic-gate check_trace_error(tnfctl_handle_t *hndl)
238*7c478bd9Sstevel@tonic-gate {
239*7c478bd9Sstevel@tonic-gate 	int		miscstat;
240*7c478bd9Sstevel@tonic-gate 	uintptr_t	trace_error_ptr;
241*7c478bd9Sstevel@tonic-gate 	TNFW_B_CONTROL	trace_error_rec;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	/* read in the value of the control structure pointer */
244*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, hndl->trace_error,
245*7c478bd9Sstevel@tonic-gate 		&trace_error_ptr, sizeof (trace_error_ptr));
246*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
247*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	/* read in the value of the control structure */
250*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, trace_error_ptr, &trace_error_rec,
251*7c478bd9Sstevel@tonic-gate 		sizeof (trace_error_rec));
252*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
253*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	if (trace_error_rec.tnf_state == TNFW_B_NOBUFFER) {
256*7c478bd9Sstevel@tonic-gate 		/*
257*7c478bd9Sstevel@tonic-gate 		 * massage into correct state for caller - the target might
258*7c478bd9Sstevel@tonic-gate 		 * not have hit the first probe and hence we got "no buffer".
259*7c478bd9Sstevel@tonic-gate 		 * So, if the user had given a file name, return BUF_OK.
260*7c478bd9Sstevel@tonic-gate 		 */
261*7c478bd9Sstevel@tonic-gate 		if (hndl->trace_file_name == NULL)
262*7c478bd9Sstevel@tonic-gate 			hndl->trace_buf_state = TNFCTL_BUF_NONE;
263*7c478bd9Sstevel@tonic-gate 		else
264*7c478bd9Sstevel@tonic-gate 			hndl->trace_buf_state = TNFCTL_BUF_OK;
265*7c478bd9Sstevel@tonic-gate 	} else if (trace_error_rec.tnf_state == TNFW_B_BROKEN) {
266*7c478bd9Sstevel@tonic-gate 		hndl->trace_buf_state = TNFCTL_BUF_BROKEN;
267*7c478bd9Sstevel@tonic-gate 	} else {
268*7c478bd9Sstevel@tonic-gate 		hndl->trace_buf_state = TNFCTL_BUF_OK;
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	if (TNFW_B_IS_STOPPED(trace_error_rec.tnf_state))
272*7c478bd9Sstevel@tonic-gate 		hndl->trace_state = B_FALSE;
273*7c478bd9Sstevel@tonic-gate 	else
274*7c478bd9Sstevel@tonic-gate 		hndl->trace_state = B_TRUE;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate }				/* end find_alloc_func */
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate /*
281*7c478bd9Sstevel@tonic-gate  * find_target_syms() - finds needed target functions
282*7c478bd9Sstevel@tonic-gate  * 	sideffects allocfunc, commitfunc, endfunc, rollbackfunc in hndl
283*7c478bd9Sstevel@tonic-gate  */
284*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
find_target_syms(tnfctl_handle_t * hndl)285*7c478bd9Sstevel@tonic-gate find_target_syms(tnfctl_handle_t *hndl)
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat;
288*7c478bd9Sstevel@tonic-gate 	uintptr_t		temp_addr;
289*7c478bd9Sstevel@tonic-gate 	int			miscstat;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACE_ALLOC, &hndl->allocfunc);
292*7c478bd9Sstevel@tonic-gate 	if (prexstat)
293*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACE_COMMIT, &hndl->commitfunc);
296*7c478bd9Sstevel@tonic-gate 	if (prexstat)
297*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACE_END_FUNC, &hndl->endfunc);
300*7c478bd9Sstevel@tonic-gate 	if (prexstat)
301*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACE_ROLLBACK, &hndl->rollbackfunc);
304*7c478bd9Sstevel@tonic-gate 	if (prexstat)
305*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, PROBE_LIST_HEAD,
308*7c478bd9Sstevel@tonic-gate 					&hndl->probelist_head);
309*7c478bd9Sstevel@tonic-gate 	if (prexstat)
310*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACE_ERROR, &hndl->trace_error);
313*7c478bd9Sstevel@tonic-gate 	if (prexstat)
314*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, MEMSEG_PTR, &temp_addr);
317*7c478bd9Sstevel@tonic-gate 	if (prexstat)
318*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	/* dereference to get the actual address of structure */
321*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, temp_addr, &hndl->memseg_p,
322*7c478bd9Sstevel@tonic-gate 			sizeof (hndl->memseg_p));
323*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
324*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, PROBE_LIST_VALID,
327*7c478bd9Sstevel@tonic-gate 					&hndl->probelist_valid);
328*7c478bd9Sstevel@tonic-gate 	if (prexstat)
329*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, NONTHREAD_TEST, &temp_addr);
332*7c478bd9Sstevel@tonic-gate 	if (prexstat)
333*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	/* dereference to get the actual function address */
336*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, temp_addr, &hndl->nonthread_test,
337*7c478bd9Sstevel@tonic-gate 			sizeof (hndl->nonthread_test));
338*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
339*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, THREAD_TEST, &temp_addr);
342*7c478bd9Sstevel@tonic-gate 	if (prexstat)
343*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	/* dereference to get the actual function address */
346*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, temp_addr, &hndl->thread_test,
347*7c478bd9Sstevel@tonic-gate 			sizeof (hndl->thread_test));
348*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
349*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, PROBE_THR_SYNC, &hndl->thread_sync);
352*7c478bd9Sstevel@tonic-gate 	if (prexstat)
353*7c478bd9Sstevel@tonic-gate 		goto end_of_func;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, LIBTHREAD_PRESENT, &temp_addr);
356*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
357*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG) {
358*7c478bd9Sstevel@tonic-gate 			/* no libthread linked in */
359*7c478bd9Sstevel@tonic-gate 			hndl->mt_target = B_FALSE;
360*7c478bd9Sstevel@tonic-gate 			/* this is not an error condition */
361*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_NONE;
362*7c478bd9Sstevel@tonic-gate 		} else {
363*7c478bd9Sstevel@tonic-gate 			return (prexstat);
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 	} else {
366*7c478bd9Sstevel@tonic-gate 		hndl->mt_target = B_TRUE;
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate end_of_func:
370*7c478bd9Sstevel@tonic-gate 	if (prexstat == TNFCTL_ERR_BADARG)
371*7c478bd9Sstevel@tonic-gate 		prexstat = TNFCTL_ERR_NOLIBTNFPROBE;
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	return (prexstat);
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate /*
377*7c478bd9Sstevel@tonic-gate  * _tnfctl_create_tracefile() - initializes tracefile, sets the tracefile name
378*7c478bd9Sstevel@tonic-gate  *	and size
379*7c478bd9Sstevel@tonic-gate  *	side effects trace_file_name and trace_buf_size in hndl
380*7c478bd9Sstevel@tonic-gate  */
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate #define	ZBUFSZ		(64 * 1024)
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t
_tnfctl_create_tracefile(tnfctl_handle_t * hndl,const char * trace_file_name,uint_t trace_file_size)385*7c478bd9Sstevel@tonic-gate _tnfctl_create_tracefile(tnfctl_handle_t *hndl, const char *trace_file_name,
386*7c478bd9Sstevel@tonic-gate 			uint_t trace_file_size)
387*7c478bd9Sstevel@tonic-gate {
388*7c478bd9Sstevel@tonic-gate 	char		*preexisting;
389*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat;
390*7c478bd9Sstevel@tonic-gate 	int		miscstat;
391*7c478bd9Sstevel@tonic-gate 	char		path[MAXPATHLEN];
392*7c478bd9Sstevel@tonic-gate 	uintptr_t	name_addr, size_addr;
393*7c478bd9Sstevel@tonic-gate 	uint_t		outsize;
394*7c478bd9Sstevel@tonic-gate 	char		zerobuf[ZBUFSZ];
395*7c478bd9Sstevel@tonic-gate 	int		fd, sz, i;
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	/* find the neccessary symbols in the target */
398*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACEFILE_NAME, &name_addr);
399*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
400*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG)
401*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_INTERNAL;
402*7c478bd9Sstevel@tonic-gate 		return (prexstat);
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACEFILE_SIZE, &size_addr);
405*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
406*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG)
407*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_INTERNAL;
408*7c478bd9Sstevel@tonic-gate 		return (prexstat);
409*7c478bd9Sstevel@tonic-gate 	}
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	/* Double check that a file name doesn't already exist */
412*7c478bd9Sstevel@tonic-gate 	preexisting = NULL;
413*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_readstr_targ(hndl, name_addr, &preexisting);
414*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
415*7c478bd9Sstevel@tonic-gate 		if (preexisting)
416*7c478bd9Sstevel@tonic-gate 			free(preexisting);
417*7c478bd9Sstevel@tonic-gate 		return (prexstat);
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	/* There better not be a file name there yet */
421*7c478bd9Sstevel@tonic-gate 	assert(preexisting[0] == '\0');
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	/* paranoia - for optimized compilation */
424*7c478bd9Sstevel@tonic-gate 	if (preexisting[0] != '\0')
425*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_BUFEXISTS);
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	/* free memory in preexisting string */
428*7c478bd9Sstevel@tonic-gate 	if (preexisting)
429*7c478bd9Sstevel@tonic-gate 		free(preexisting);
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	if (trace_file_size < hndl->trace_min_size) {
432*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_SIZETOOSMALL);
433*7c478bd9Sstevel@tonic-gate 	}
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	/* do we have an absolute, relative or no pathname specified? */
436*7c478bd9Sstevel@tonic-gate 	if (trace_file_name == NULL) {
437*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_BADARG);
438*7c478bd9Sstevel@tonic-gate 	}
439*7c478bd9Sstevel@tonic-gate 	if (trace_file_name[0] == '/') {
440*7c478bd9Sstevel@tonic-gate 		/* absolute path to tracefile specified */
441*7c478bd9Sstevel@tonic-gate 		if ((strlen(trace_file_name) + 1) > (size_t) MAXPATHLEN) {
442*7c478bd9Sstevel@tonic-gate 			/* directory specification too long */
443*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_BADARG);
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 		(void) strcpy(path, trace_file_name);
446*7c478bd9Sstevel@tonic-gate 	} else {
447*7c478bd9Sstevel@tonic-gate 		char		   *cwd;
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 		/* relative path to tracefile specified */
450*7c478bd9Sstevel@tonic-gate 		cwd = getcwd(NULL, MAXPATHLEN);
451*7c478bd9Sstevel@tonic-gate 		if (!cwd) {
452*7c478bd9Sstevel@tonic-gate 			return (tnfctl_status_map(errno));
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 		if ((strlen(cwd) + 1 + strlen(trace_file_name) + 1) >
455*7c478bd9Sstevel@tonic-gate 			(size_t) MAXPATHLEN) {
456*7c478bd9Sstevel@tonic-gate 			/* path name too long */
457*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_BADARG);
458*7c478bd9Sstevel@tonic-gate 		}
459*7c478bd9Sstevel@tonic-gate 		(void) sprintf(path, "%s/%s", cwd, trace_file_name);
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 		free(cwd);
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 	outsize = trace_file_size;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	DBG_TNF_PROBE_2(_tnfctl_create_tracefile_1, "libtnfctl",
467*7c478bd9Sstevel@tonic-gate 		"sunw%verbosity 1; sunw%debug 'setting trace file name'",
468*7c478bd9Sstevel@tonic-gate 		tnf_string, tracefile_name, path,
469*7c478bd9Sstevel@tonic-gate 		tnf_long, tracefile_size, outsize);
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	/* unlink a previous tracefile (if one exists) */
472*7c478bd9Sstevel@tonic-gate 	(void) unlink(path);
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	/* create the new tracefile */
475*7c478bd9Sstevel@tonic-gate 	fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
476*7c478bd9Sstevel@tonic-gate 	if (fd < 0)	{
477*7c478bd9Sstevel@tonic-gate 		return (tnfctl_status_map(errno));
478*7c478bd9Sstevel@tonic-gate 	}
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	/* zero fill the file */
481*7c478bd9Sstevel@tonic-gate 	(void) memset(zerobuf, 0, ZBUFSZ);
482*7c478bd9Sstevel@tonic-gate 	sz = ZBUFSZ;
483*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < outsize; i += sz) {
484*7c478bd9Sstevel@tonic-gate 		ulong_t		retval;
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 		sz = ((outsize - i) > ZBUFSZ) ? ZBUFSZ : (outsize - i);
487*7c478bd9Sstevel@tonic-gate 		retval = write(fd, zerobuf, sz);
488*7c478bd9Sstevel@tonic-gate 		if (retval != sz) {
489*7c478bd9Sstevel@tonic-gate 			/* trouble zeroing tracefile */
490*7c478bd9Sstevel@tonic-gate 			return (tnfctl_status_map(errno));
491*7c478bd9Sstevel@tonic-gate 		}
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	/* close the file */
495*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	/* write the tracefile name and size into the target process */
498*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_write(hndl->proc_p, name_addr, path,
499*7c478bd9Sstevel@tonic-gate 					strlen(path) + 1);
500*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
501*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
502*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_write(hndl->proc_p, size_addr, &outsize,
503*7c478bd9Sstevel@tonic-gate 					sizeof (outsize));
504*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
505*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	hndl->trace_file_name = strdup(path);
508*7c478bd9Sstevel@tonic-gate 	if (hndl->trace_file_name == NULL)
509*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_ALLOCFAIL);
510*7c478bd9Sstevel@tonic-gate 	hndl->trace_buf_size = outsize;
511*7c478bd9Sstevel@tonic-gate 	hndl->trace_buf_state = TNFCTL_BUF_OK;
512*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
513*7c478bd9Sstevel@tonic-gate }				/* end _tnfctl_create_tracefile */
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate /*
516*7c478bd9Sstevel@tonic-gate  * find_trace_file_info()
517*7c478bd9Sstevel@tonic-gate  *	finds out information about the trace file.
518*7c478bd9Sstevel@tonic-gate  *	side effects trace_buf_size, trace_min_size, trace_file_name in hndl
519*7c478bd9Sstevel@tonic-gate  */
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
find_trace_file_info(tnfctl_handle_t * hndl)522*7c478bd9Sstevel@tonic-gate find_trace_file_info(tnfctl_handle_t *hndl)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	prexstat;
525*7c478bd9Sstevel@tonic-gate 	int		miscstat;
526*7c478bd9Sstevel@tonic-gate 	char		*preexisting;
527*7c478bd9Sstevel@tonic-gate 	uintptr_t	name_addr, size_addr, min_addr;
528*7c478bd9Sstevel@tonic-gate 	uint_t		outsize, minoutsize;
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 	/* find the neccessary symbols in the target */
531*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACEFILE_NAME, &name_addr);
532*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
533*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG)
534*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_INTERNAL;
535*7c478bd9Sstevel@tonic-gate 		return (prexstat);
536*7c478bd9Sstevel@tonic-gate 	}
537*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACEFILE_SIZE, &size_addr);
538*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
539*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG)
540*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_INTERNAL;
541*7c478bd9Sstevel@tonic-gate 		return (prexstat);
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_sym_find(hndl, TRACEFILE_MIN, &min_addr);
544*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
545*7c478bd9Sstevel@tonic-gate 		if (prexstat == TNFCTL_ERR_BADARG)
546*7c478bd9Sstevel@tonic-gate 			prexstat = TNFCTL_ERR_INTERNAL;
547*7c478bd9Sstevel@tonic-gate 		return (prexstat);
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	/* read file name */
551*7c478bd9Sstevel@tonic-gate 	preexisting = NULL;
552*7c478bd9Sstevel@tonic-gate 	prexstat = _tnfctl_readstr_targ(hndl, name_addr, &preexisting);
553*7c478bd9Sstevel@tonic-gate 	if (prexstat) {
554*7c478bd9Sstevel@tonic-gate 		if (preexisting)
555*7c478bd9Sstevel@tonic-gate 			free(preexisting);
556*7c478bd9Sstevel@tonic-gate 		return (prexstat);
557*7c478bd9Sstevel@tonic-gate 	}
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	/* read the minimum file size from the target */
560*7c478bd9Sstevel@tonic-gate 	miscstat = hndl->p_read(hndl->proc_p, min_addr, &minoutsize,
561*7c478bd9Sstevel@tonic-gate 							sizeof (minoutsize));
562*7c478bd9Sstevel@tonic-gate 	if (miscstat != 0)
563*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_INTERNAL);
564*7c478bd9Sstevel@tonic-gate 	hndl->trace_min_size = minoutsize;
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	/* if there is no filename, we are done */
567*7c478bd9Sstevel@tonic-gate 	if (preexisting[0] == '\0') {
568*7c478bd9Sstevel@tonic-gate 		hndl->trace_file_name = NULL;
569*7c478bd9Sstevel@tonic-gate 		hndl->trace_buf_size = 0;
570*7c478bd9Sstevel@tonic-gate 	} else {
571*7c478bd9Sstevel@tonic-gate 		hndl->trace_file_name = preexisting;
572*7c478bd9Sstevel@tonic-gate 		/* read size of file */
573*7c478bd9Sstevel@tonic-gate 		miscstat = hndl->p_read(hndl->proc_p, size_addr,
574*7c478bd9Sstevel@tonic-gate 				&outsize, sizeof (outsize));
575*7c478bd9Sstevel@tonic-gate 		if (miscstat != 0)
576*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
577*7c478bd9Sstevel@tonic-gate 		hndl->trace_buf_size = outsize;
578*7c478bd9Sstevel@tonic-gate 	}
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
581*7c478bd9Sstevel@tonic-gate }				/* end find_trace_file_info */
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate /*
584*7c478bd9Sstevel@tonic-gate  * wrapper functions over native /proc functions implemented by proc
585*7c478bd9Sstevel@tonic-gate  * layer
586*7c478bd9Sstevel@tonic-gate  */
587*7c478bd9Sstevel@tonic-gate int
_tnfctl_read_targ(void * proc_p,uintptr_t addr,void * buf,size_t size)588*7c478bd9Sstevel@tonic-gate _tnfctl_read_targ(void *proc_p, uintptr_t addr, void *buf, size_t size)
589*7c478bd9Sstevel@tonic-gate {
590*7c478bd9Sstevel@tonic-gate 	return (prb_proc_read(proc_p, addr, buf, size));
591*7c478bd9Sstevel@tonic-gate }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate int
_tnfctl_write_targ(void * proc_p,uintptr_t addr,void * buf,size_t size)594*7c478bd9Sstevel@tonic-gate _tnfctl_write_targ(void *proc_p, uintptr_t addr, void *buf, size_t size)
595*7c478bd9Sstevel@tonic-gate {
596*7c478bd9Sstevel@tonic-gate 	return (prb_proc_write(proc_p, addr, buf, size));
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate int
_tnfctl_loadobj_iter(void * proc_p,tnfctl_ind_obj_f * func,void * client_data)600*7c478bd9Sstevel@tonic-gate _tnfctl_loadobj_iter(void *proc_p, tnfctl_ind_obj_f *func, void *client_data)
601*7c478bd9Sstevel@tonic-gate {
602*7c478bd9Sstevel@tonic-gate 	prb_loadobj_f *same_func = (prb_loadobj_f *) func;
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 	return (prb_loadobj_iter(proc_p, same_func, client_data));
605*7c478bd9Sstevel@tonic-gate }
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate pid_t
_tnfctl_pid_get(void * proc_p)608*7c478bd9Sstevel@tonic-gate _tnfctl_pid_get(void *proc_p)
609*7c478bd9Sstevel@tonic-gate {
610*7c478bd9Sstevel@tonic-gate 	return (prb_proc_pid_get(proc_p));
611*7c478bd9Sstevel@tonic-gate }
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate /*
614*7c478bd9Sstevel@tonic-gate  * _tnfctl_readstr_targ() - dereferences a string in the target
615*7c478bd9Sstevel@tonic-gate  * 	NOTE: There is a similar routine called prb_proc_readstr()
616*7c478bd9Sstevel@tonic-gate  *	      used by proc layer.  It would be better if there was only
617*7c478bd9Sstevel@tonic-gate  *	      one of these functions defined.
618*7c478bd9Sstevel@tonic-gate  */
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate #define	BUFSZ	256
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t
_tnfctl_readstr_targ(tnfctl_handle_t * hndl,uintptr_t addr,char ** outstr_pp)623*7c478bd9Sstevel@tonic-gate _tnfctl_readstr_targ(tnfctl_handle_t *hndl, uintptr_t addr, char **outstr_pp)
624*7c478bd9Sstevel@tonic-gate {
625*7c478bd9Sstevel@tonic-gate 	int		retstat;
626*7c478bd9Sstevel@tonic-gate 	int		bufsz = BUFSZ;
627*7c478bd9Sstevel@tonic-gate 	char		buffer[BUFSZ + 1];
628*7c478bd9Sstevel@tonic-gate 	offset_t	offset;
629*7c478bd9Sstevel@tonic-gate 	char		*ptr, *orig_ptr;
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	*outstr_pp = NULL;
632*7c478bd9Sstevel@tonic-gate 	offset = 0;
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	/* allocate an inital return buffer */
635*7c478bd9Sstevel@tonic-gate 	ptr = (char *) malloc(BUFSZ);
636*7c478bd9Sstevel@tonic-gate 	if (!ptr) {
637*7c478bd9Sstevel@tonic-gate 		DBG((void) fprintf(stderr,
638*7c478bd9Sstevel@tonic-gate 			"_tnfctl_readstr_targ: malloc failed\n"));
639*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_ALLOCFAIL);
640*7c478bd9Sstevel@tonic-gate 	}
641*7c478bd9Sstevel@tonic-gate 	/*LINTED constant in conditional context*/
642*7c478bd9Sstevel@tonic-gate 	while (1) {
643*7c478bd9Sstevel@tonic-gate 		int			 i;
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 		/* read a chunk into our buffer */
646*7c478bd9Sstevel@tonic-gate 		retstat = hndl->p_read(hndl->proc_p, addr + offset, buffer,
647*7c478bd9Sstevel@tonic-gate 								bufsz);
648*7c478bd9Sstevel@tonic-gate 		if (retstat != 0) {
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 			/*
651*7c478bd9Sstevel@tonic-gate 			 * if we get into trouble with a large read, try again
652*7c478bd9Sstevel@tonic-gate 			 * with a single byte.  Subsequent failiure is real ...
653*7c478bd9Sstevel@tonic-gate 			 */
654*7c478bd9Sstevel@tonic-gate 			if (bufsz > 1) {
655*7c478bd9Sstevel@tonic-gate 				bufsz = 1;
656*7c478bd9Sstevel@tonic-gate 				continue;
657*7c478bd9Sstevel@tonic-gate 			}
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 			DBG((void) fprintf(stderr,
660*7c478bd9Sstevel@tonic-gate 			    "_tnfctl_readstr_targ: target read failed: \n"));
661*7c478bd9Sstevel@tonic-gate 			free(ptr);
662*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
663*7c478bd9Sstevel@tonic-gate 		}
664*7c478bd9Sstevel@tonic-gate 		/* copy the chracters into the return buffer */
665*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < bufsz; i++) {
666*7c478bd9Sstevel@tonic-gate 			char			c = buffer[i];
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 			ptr[offset + i] = c;
669*7c478bd9Sstevel@tonic-gate 			if (c == '\0') {
670*7c478bd9Sstevel@tonic-gate 				/* hooray! we saw the end of the string */
671*7c478bd9Sstevel@tonic-gate 				*outstr_pp = ptr;
672*7c478bd9Sstevel@tonic-gate 				return (TNFCTL_ERR_NONE);
673*7c478bd9Sstevel@tonic-gate 			}
674*7c478bd9Sstevel@tonic-gate 		}
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 		/* bummer, need to grab another bufsz characters */
677*7c478bd9Sstevel@tonic-gate 		offset += bufsz;
678*7c478bd9Sstevel@tonic-gate 		orig_ptr = ptr;
679*7c478bd9Sstevel@tonic-gate 		ptr = (char *) realloc(ptr, offset + bufsz);
680*7c478bd9Sstevel@tonic-gate 		if (!ptr) {
681*7c478bd9Sstevel@tonic-gate 			free(orig_ptr);
682*7c478bd9Sstevel@tonic-gate 			DBG((void) fprintf(stderr,
683*7c478bd9Sstevel@tonic-gate 				"_tnfctl_readstr_targ: realloc failed\n"));
684*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_ALLOCFAIL);
685*7c478bd9Sstevel@tonic-gate 		}
686*7c478bd9Sstevel@tonic-gate 	}
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate #if defined(lint)
689*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
690*7c478bd9Sstevel@tonic-gate #endif
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate }
693