xref: /titanic_54/usr/src/cmd/tnf/prex/main.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 2004 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  * Includes
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <signal.h>
38*7c478bd9Sstevel@tonic-gate #include <errno.h>
39*7c478bd9Sstevel@tonic-gate #include <locale.h>
40*7c478bd9Sstevel@tonic-gate #include <libintl.h>
41*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
42*7c478bd9Sstevel@tonic-gate #include <limits.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
47*7c478bd9Sstevel@tonic-gate #include <libelf.h>
48*7c478bd9Sstevel@tonic-gate #include <gelf.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <tnf/tnfctl.h>
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #include "set.h"
54*7c478bd9Sstevel@tonic-gate #include "cmd.h"
55*7c478bd9Sstevel@tonic-gate #include "spec.h"
56*7c478bd9Sstevel@tonic-gate #include "expr.h"
57*7c478bd9Sstevel@tonic-gate #include "source.h"
58*7c478bd9Sstevel@tonic-gate #include "list.h"
59*7c478bd9Sstevel@tonic-gate #include "prbk.h"
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate  * Defines - Project private interfaces
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	DEBUG_ENTRY		"tnf_probe_debug"
66*7c478bd9Sstevel@tonic-gate #ifdef TESTING
67*7c478bd9Sstevel@tonic-gate #define	EMPTY_ENTRY		"tnf_probe_empty"
68*7c478bd9Sstevel@tonic-gate #endif
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #define	USER_OUTSIZE		(4*1024*1024)
71*7c478bd9Sstevel@tonic-gate #define	KERNEL_OUTSIZE		(384*1024)
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate #if defined(__sparc)
74*7c478bd9Sstevel@tonic-gate #define	PREX32DIR	"/sparcv7/"
75*7c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64)
76*7c478bd9Sstevel@tonic-gate #define	PREX32DIR	"/i86/"
77*7c478bd9Sstevel@tonic-gate #endif
78*7c478bd9Sstevel@tonic-gate #define	PREX32EXEC	"/usr/bin" PREX32DIR "prex"
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /*
81*7c478bd9Sstevel@tonic-gate  * Globals
82*7c478bd9Sstevel@tonic-gate  */
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate char			**g_argv;	/* copy of argv pointer */
85*7c478bd9Sstevel@tonic-gate tnfctl_handle_t		*g_hndl;	/* handle on target or kernel */
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate static int		g_verbose;	/* debugging to stderr */
88*7c478bd9Sstevel@tonic-gate static char		*g_cmdname;	/* target command name */
89*7c478bd9Sstevel@tonic-gate static char		**g_cmdargs;	/* target command args */
90*7c478bd9Sstevel@tonic-gate static pid_t		g_targetpid;	/* target process id */
91*7c478bd9Sstevel@tonic-gate static volatile boolean_t g_getcmds;	/* accept input flag */
92*7c478bd9Sstevel@tonic-gate static boolean_t	g_testflag;	/* asserted in test mode */
93*7c478bd9Sstevel@tonic-gate static char		*g_preload;	/* objects to preload */
94*7c478bd9Sstevel@tonic-gate static char		*g_outname;	/* tracefile name */
95*7c478bd9Sstevel@tonic-gate static char		*tracefile;	/* tracefile name used by list cmd */
96*7c478bd9Sstevel@tonic-gate int			g_outsize;	/* tracefile size */
97*7c478bd9Sstevel@tonic-gate boolean_t		g_kernelmode;	/* -k flag: kernel mode */
98*7c478bd9Sstevel@tonic-gate static int		prex_dmodel;	/* prex data model */
99*7c478bd9Sstevel@tonic-gate /*
100*7c478bd9Sstevel@tonic-gate  * Local Declarations
101*7c478bd9Sstevel@tonic-gate  */
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate static void usage(char **argv, const char *msg);
104*7c478bd9Sstevel@tonic-gate static void scanargs(int argc, char **argv);
105*7c478bd9Sstevel@tonic-gate static int set_signal(void);
106*7c478bd9Sstevel@tonic-gate static int get_data_model(pid_t pid);
107*7c478bd9Sstevel@tonic-gate static int get_elf_class(char *filename);
108*7c478bd9Sstevel@tonic-gate static int get_executable(char *);
109*7c478bd9Sstevel@tonic-gate static void prex_isaexec(char **argv, char **envp);
110*7c478bd9Sstevel@tonic-gate static void check_pid_model(char **argv, char **envp);
111*7c478bd9Sstevel@tonic-gate static void check_exec_model(char **argv, char **envp);
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /* #### - FIXME - need to put this in a private header file */
114*7c478bd9Sstevel@tonic-gate extern void err_fatal(char *s, ...);
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate extern int	  yyparse(void);
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t check_trace_error(tnfctl_handle_t *hndl);
119*7c478bd9Sstevel@tonic-gate static void set_default_cmd(void);
120*7c478bd9Sstevel@tonic-gate static void get_commands(void);
121*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t set_tracefile(tnfctl_handle_t *hndl);
122*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t set_probe_discovery_callback(tnfctl_handle_t *hndl);
123*7c478bd9Sstevel@tonic-gate static void * perprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p);
124*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t perprobe2(tnfctl_handle_t *hndl,
125*7c478bd9Sstevel@tonic-gate 	tnfctl_probe_t *probe_p, void *ignored);
126*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t percmd(expr_t *expr_p, cmd_kind_t kind, fcn_t *fcn_p,
127*7c478bd9Sstevel@tonic-gate 	boolean_t isnew, void *calldata_p);
128*7c478bd9Sstevel@tonic-gate void quit(boolean_t killtarget, boolean_t runtarget);
129*7c478bd9Sstevel@tonic-gate void cmd_listtracefile();
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate /*
133*7c478bd9Sstevel@tonic-gate  * usage() - gives a description of the arguments, and exits
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate static void
137*7c478bd9Sstevel@tonic-gate usage(char *argv[], const char *msg)
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	if (msg)
140*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
141*7c478bd9Sstevel@tonic-gate 			gettext("%s: %s\n"), argv[0], msg);
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
144*7c478bd9Sstevel@tonic-gate 		"usage: %s [options] <cmd> [cmd-args...]\n"), argv[0]);
145*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
146*7c478bd9Sstevel@tonic-gate 		"usage: %s [options] -p <pid>\n"), argv[0]);
147*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
148*7c478bd9Sstevel@tonic-gate 		"usage: %s -s <kbytes-size> -k\n"), argv[0]);
149*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
150*7c478bd9Sstevel@tonic-gate 		"options:\n"));
151*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
152*7c478bd9Sstevel@tonic-gate 		"	-o <outfilename>   set trace output file name\n"));
153*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
154*7c478bd9Sstevel@tonic-gate 		"	-s <kbytes-size>   set trace file size\n"));
155*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
156*7c478bd9Sstevel@tonic-gate 		"	-l <sharedobjs>    shared objects to "
157*7c478bd9Sstevel@tonic-gate 		"be preloaded (cmd only)\n"));
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	exit(1);
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /*
164*7c478bd9Sstevel@tonic-gate  * main() -
165*7c478bd9Sstevel@tonic-gate  */
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate int
168*7c478bd9Sstevel@tonic-gate main(int argc, char **argv, char **envp)
169*7c478bd9Sstevel@tonic-gate {
170*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err = TNFCTL_ERR_NONE;
171*7c478bd9Sstevel@tonic-gate 	int			sys_err;
172*7c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	trace_attrs;
173*7c478bd9Sstevel@tonic-gate 	tnfctl_event_t		event = TNFCTL_EVENT_EINTR;
174*7c478bd9Sstevel@tonic-gate 	pid_t			prex_pid;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	/* internationalization stuff */
177*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
178*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
179*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
180*7c478bd9Sstevel@tonic-gate #endif
181*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	g_argv = argv;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	prex_pid = getpid();
186*7c478bd9Sstevel@tonic-gate #if defined(DEBUG)
187*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "### prex_pid = %d ###\n", prex_pid);
188*7c478bd9Sstevel@tonic-gate #endif
189*7c478bd9Sstevel@tonic-gate 	prex_dmodel = get_data_model(prex_pid);
190*7c478bd9Sstevel@tonic-gate #if defined(DEBUG)
191*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "### prex_dmodel = %d ###\n", prex_dmodel);
192*7c478bd9Sstevel@tonic-gate #endif
193*7c478bd9Sstevel@tonic-gate 	scanargs(argc, argv);
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
196*7c478bd9Sstevel@tonic-gate 		/* prexing the kernel */
197*7c478bd9Sstevel@tonic-gate 		err = tnfctl_kernel_open(&g_hndl);
198*7c478bd9Sstevel@tonic-gate 		if (err) {
199*7c478bd9Sstevel@tonic-gate 			err_fatal(gettext(
200*7c478bd9Sstevel@tonic-gate 				"%s: trouble attaching to the kernel: %s\n"),
201*7c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
202*7c478bd9Sstevel@tonic-gate 		}
203*7c478bd9Sstevel@tonic-gate 	} else {
204*7c478bd9Sstevel@tonic-gate 		/* prexing a user process */
205*7c478bd9Sstevel@tonic-gate 		if (g_targetpid != 0) {
206*7c478bd9Sstevel@tonic-gate 			/* check data model */
207*7c478bd9Sstevel@tonic-gate 			check_pid_model(argv, envp);
208*7c478bd9Sstevel@tonic-gate 			/* attach case */
209*7c478bd9Sstevel@tonic-gate 			err = tnfctl_pid_open(g_targetpid, &g_hndl);
210*7c478bd9Sstevel@tonic-gate 			if (err == TNFCTL_ERR_NOLIBTNFPROBE) {
211*7c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
212*7c478bd9Sstevel@tonic-gate 					"%s: missing symbols, is "
213*7c478bd9Sstevel@tonic-gate 					"libtnfprobe.so loaded in target?\n"),
214*7c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
215*7c478bd9Sstevel@tonic-gate 			} else if (err) {
216*7c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
217*7c478bd9Sstevel@tonic-gate 					"%s: trouble attaching to target "
218*7c478bd9Sstevel@tonic-gate 					"process: %s\n"),
219*7c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
220*7c478bd9Sstevel@tonic-gate 			}
221*7c478bd9Sstevel@tonic-gate 		} else {
222*7c478bd9Sstevel@tonic-gate 			/* check elf class model */
223*7c478bd9Sstevel@tonic-gate 			check_exec_model(argv, envp);
224*7c478bd9Sstevel@tonic-gate 			/* exec case */
225*7c478bd9Sstevel@tonic-gate 			err = tnfctl_exec_open(g_cmdname, g_cmdargs, NULL,
226*7c478bd9Sstevel@tonic-gate 					g_preload, NULL, &g_hndl);
227*7c478bd9Sstevel@tonic-gate 			if (err == TNFCTL_ERR_NONE)
228*7c478bd9Sstevel@tonic-gate 				err = tnfctl_trace_attrs_get(g_hndl,
229*7c478bd9Sstevel@tonic-gate 						&trace_attrs);
230*7c478bd9Sstevel@tonic-gate 			if (err) {
231*7c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
232*7c478bd9Sstevel@tonic-gate 					"%s: trouble creating target process: "
233*7c478bd9Sstevel@tonic-gate 					"%s\n"),
234*7c478bd9Sstevel@tonic-gate 					argv[0], tnfctl_strerror(err));
235*7c478bd9Sstevel@tonic-gate 			}
236*7c478bd9Sstevel@tonic-gate 			g_targetpid = trace_attrs.targ_pid;
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		sys_err = set_signal();
240*7c478bd9Sstevel@tonic-gate 		if (sys_err)
241*7c478bd9Sstevel@tonic-gate 			err_fatal(gettext(
242*7c478bd9Sstevel@tonic-gate 				"%s: trouble setting up signal handler: %s\n"),
243*7c478bd9Sstevel@tonic-gate 				argv[0], strerror(err));
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	/* initialize the source stack for the parser */
247*7c478bd9Sstevel@tonic-gate 	source_init();
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	if (!g_kernelmode) {
250*7c478bd9Sstevel@tonic-gate 		/* set the tracefile name and size */
251*7c478bd9Sstevel@tonic-gate 		err = set_tracefile(g_hndl);
252*7c478bd9Sstevel@tonic-gate 		if (err) {
253*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
254*7c478bd9Sstevel@tonic-gate 				"%s: trouble initializing tracefile: %s\n"),
255*7c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
256*7c478bd9Sstevel@tonic-gate 			goto Cleanup;
257*7c478bd9Sstevel@tonic-gate 		}
258*7c478bd9Sstevel@tonic-gate 		err = check_trace_error(g_hndl);
259*7c478bd9Sstevel@tonic-gate 		if (err) {
260*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
261*7c478bd9Sstevel@tonic-gate 				"%s: cannot read tracing status : %s\n"),
262*7c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
263*7c478bd9Sstevel@tonic-gate 			goto Cleanup;
264*7c478bd9Sstevel@tonic-gate 		}
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	/* accept commands from stdin the first time through */
268*7c478bd9Sstevel@tonic-gate 	g_getcmds = B_TRUE;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	/* set up default aliases */
271*7c478bd9Sstevel@tonic-gate 	set_default_cmd();
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	/* set up creator/destructor function to call for new probes */
274*7c478bd9Sstevel@tonic-gate 	err = set_probe_discovery_callback(g_hndl);
275*7c478bd9Sstevel@tonic-gate 	if (err) {
276*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
277*7c478bd9Sstevel@tonic-gate 			"%s: error in probe discovery : %s\n"),
278*7c478bd9Sstevel@tonic-gate 			argv[0], tnfctl_strerror(err));
279*7c478bd9Sstevel@tonic-gate 		goto Cleanup;
280*7c478bd9Sstevel@tonic-gate 	}
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
283*7c478bd9Sstevel@tonic-gate 		prbk_warn_pfilter_empty();
284*7c478bd9Sstevel@tonic-gate 	}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	while (err == TNFCTL_ERR_NONE) {
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 		if (g_kernelmode || g_getcmds) {
289*7c478bd9Sstevel@tonic-gate 			g_getcmds = B_FALSE;
290*7c478bd9Sstevel@tonic-gate 			get_commands();
291*7c478bd9Sstevel@tonic-gate 		}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		if (!g_kernelmode && (g_getcmds == B_FALSE)) {
294*7c478bd9Sstevel@tonic-gate 		    err = tnfctl_continue(g_hndl, &event, NULL);
295*7c478bd9Sstevel@tonic-gate 		    if (err) {
296*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
297*7c478bd9Sstevel@tonic-gate 				"%s: cannot continue target : %s\n"),
298*7c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
299*7c478bd9Sstevel@tonic-gate 			goto Cleanup;
300*7c478bd9Sstevel@tonic-gate 		    }
301*7c478bd9Sstevel@tonic-gate 		}
302*7c478bd9Sstevel@tonic-gate 		err = check_trace_error(g_hndl);
303*7c478bd9Sstevel@tonic-gate 		if (err) {
304*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
305*7c478bd9Sstevel@tonic-gate 				"%s: cannot read tracing status : %s\n"),
306*7c478bd9Sstevel@tonic-gate 				argv[0], tnfctl_strerror(err));
307*7c478bd9Sstevel@tonic-gate 			goto Cleanup;
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 		if (!g_kernelmode) {
310*7c478bd9Sstevel@tonic-gate 			if (event == TNFCTL_EVENT_EXEC) {
311*7c478bd9Sstevel@tonic-gate 			    (void) printf(gettext(
312*7c478bd9Sstevel@tonic-gate 				"Target process exec'd\n"));
313*7c478bd9Sstevel@tonic-gate 			    quit(B_FALSE, B_TRUE);	/* quit resume */
314*7c478bd9Sstevel@tonic-gate 			} else if (event == TNFCTL_EVENT_EXIT) {
315*7c478bd9Sstevel@tonic-gate 			    /* target exited */
316*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr, gettext(
317*7c478bd9Sstevel@tonic-gate 				"%s: target process exited\n"),
318*7c478bd9Sstevel@tonic-gate 				g_argv[0]);
319*7c478bd9Sstevel@tonic-gate 			    goto Cleanup;
320*7c478bd9Sstevel@tonic-gate 			} else if (event == TNFCTL_EVENT_TARGGONE) {
321*7c478bd9Sstevel@tonic-gate 				/* target terminated */
322*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
323*7c478bd9Sstevel@tonic-gate 	gettext("%s: target process disappeared (without calling exit)\n"),
324*7c478bd9Sstevel@tonic-gate 				g_argv[0]);
325*7c478bd9Sstevel@tonic-gate 			    goto Cleanup;
326*7c478bd9Sstevel@tonic-gate 			}
327*7c478bd9Sstevel@tonic-gate 		}
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate Cleanup:
331*7c478bd9Sstevel@tonic-gate 	err = tnfctl_close(g_hndl, TNFCTL_TARG_DEFAULT);
332*7c478bd9Sstevel@tonic-gate 	if (err)
333*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
334*7c478bd9Sstevel@tonic-gate 			"%s: error on closing : %s\n"),
335*7c478bd9Sstevel@tonic-gate 			argv[0], tnfctl_strerror(err));
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	exit(0);
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	return (0);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate }
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate /*
344*7c478bd9Sstevel@tonic-gate  * check_trace_error() - checks whether there was an error in tracing
345*7c478bd9Sstevel@tonic-gate  */
346*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
347*7c478bd9Sstevel@tonic-gate check_trace_error(tnfctl_handle_t *hndl)
348*7c478bd9Sstevel@tonic-gate {
349*7c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	trace_attrs;
350*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	err = tnfctl_trace_attrs_get(hndl, &trace_attrs);
353*7c478bd9Sstevel@tonic-gate 	if (err)
354*7c478bd9Sstevel@tonic-gate 		return (err);
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	if (trace_attrs.trace_buf_state == TNFCTL_BUF_BROKEN) {
357*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Tracing shut down in target program "
358*7c478bd9Sstevel@tonic-gate 			"due to an internal error - Please restart prex "
359*7c478bd9Sstevel@tonic-gate 			"and target\n"));
360*7c478bd9Sstevel@tonic-gate 	}
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
363*7c478bd9Sstevel@tonic-gate }
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate /*
366*7c478bd9Sstevel@tonic-gate  * set_default_cmd() - set the default debug entry and $all
367*7c478bd9Sstevel@tonic-gate  */
368*7c478bd9Sstevel@tonic-gate static void
369*7c478bd9Sstevel@tonic-gate set_default_cmd(void)
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate 	if (!g_kernelmode)
372*7c478bd9Sstevel@tonic-gate 		fcn(strdup("debug"), DEBUG_ENTRY);
373*7c478bd9Sstevel@tonic-gate #ifdef TESTING
374*7c478bd9Sstevel@tonic-gate 	fcn(strdup("empty"), EMPTY_ENTRY);
375*7c478bd9Sstevel@tonic-gate #endif
376*7c478bd9Sstevel@tonic-gate 	(void) set(strdup("all"), expr(spec(strdup("keys"), SPEC_EXACT),
377*7c478bd9Sstevel@tonic-gate 				spec(strdup(".*"), SPEC_REGEXP)));
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate }
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate /*
382*7c478bd9Sstevel@tonic-gate  * process() - enable and disable selected probes
383*7c478bd9Sstevel@tonic-gate  */
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate typedef struct {
386*7c478bd9Sstevel@tonic-gate 	tnfctl_probe_t	*probe_p;
387*7c478bd9Sstevel@tonic-gate 	tnfctl_handle_t	*hndl;
388*7c478bd9Sstevel@tonic-gate } process_args_t;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
391*7c478bd9Sstevel@tonic-gate percmd(expr_t *expr_p, cmd_kind_t kind, fcn_t *fcn_p, boolean_t isnew,
392*7c478bd9Sstevel@tonic-gate 	void *calldata_p)
393*7c478bd9Sstevel@tonic-gate {
394*7c478bd9Sstevel@tonic-gate 	process_args_t *args_p = (process_args_t *)calldata_p;
395*7c478bd9Sstevel@tonic-gate 	tnfctl_handle_t	*hndl = args_p->hndl;
396*7c478bd9Sstevel@tonic-gate 	tnfctl_probe_t	*probe_p = args_p->probe_p;
397*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err = TNFCTL_ERR_NONE;
398*7c478bd9Sstevel@tonic-gate 	char *attrs;
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	attrs = list_getattrs(probe_p);
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	if (expr_match(expr_p, attrs)) {
403*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
404*7c478bd9Sstevel@tonic-gate 		if (g_verbose) {
405*7c478bd9Sstevel@tonic-gate 			char		   *cmdstr[] = {
406*7c478bd9Sstevel@tonic-gate 				"enable", "disable",
407*7c478bd9Sstevel@tonic-gate 				"connect", "clear",
408*7c478bd9Sstevel@tonic-gate 				"trace", "untrace"};
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, ": %s command: %s ",
411*7c478bd9Sstevel@tonic-gate 				(isnew) ? "new" : "old", cmdstr[kind]);
412*7c478bd9Sstevel@tonic-gate 			expr_print(stderr, expr_p);
413*7c478bd9Sstevel@tonic-gate 		}
414*7c478bd9Sstevel@tonic-gate #endif
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 		switch (kind) {
417*7c478bd9Sstevel@tonic-gate 		case CMD_ENABLE:
418*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_enable(hndl, probe_p, NULL);
419*7c478bd9Sstevel@tonic-gate 			break;
420*7c478bd9Sstevel@tonic-gate 		case CMD_DISABLE:
421*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_disable(hndl, probe_p, NULL);
422*7c478bd9Sstevel@tonic-gate 			break;
423*7c478bd9Sstevel@tonic-gate 		case CMD_TRACE:
424*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_trace(hndl, probe_p, NULL);
425*7c478bd9Sstevel@tonic-gate 			break;
426*7c478bd9Sstevel@tonic-gate 		case CMD_UNTRACE:
427*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_untrace(hndl, probe_p, NULL);
428*7c478bd9Sstevel@tonic-gate 			break;
429*7c478bd9Sstevel@tonic-gate 		case CMD_CONNECT:
430*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_connect(hndl, probe_p, NULL,
431*7c478bd9Sstevel@tonic-gate 				fcn_p->entry_name_p);
432*7c478bd9Sstevel@tonic-gate 			break;
433*7c478bd9Sstevel@tonic-gate 		case CMD_CLEAR:
434*7c478bd9Sstevel@tonic-gate 			err = tnfctl_probe_disconnect_all(hndl, probe_p, NULL);
435*7c478bd9Sstevel@tonic-gate 			break;
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
439*7c478bd9Sstevel@tonic-gate 		if (g_verbose)
440*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\n");
441*7c478bd9Sstevel@tonic-gate #endif
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate 	if (attrs)
445*7c478bd9Sstevel@tonic-gate 		free(attrs);
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	return (err);
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
452*7c478bd9Sstevel@tonic-gate static void *
453*7c478bd9Sstevel@tonic-gate perprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p)
454*7c478bd9Sstevel@tonic-gate {
455*7c478bd9Sstevel@tonic-gate 	process_args_t  args;
456*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	args.probe_p = probe_p;
459*7c478bd9Sstevel@tonic-gate 	args.hndl = hndl;
460*7c478bd9Sstevel@tonic-gate 	err = cmd_traverse(percmd, &args);
461*7c478bd9Sstevel@tonic-gate 	if (err) {
462*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
463*7c478bd9Sstevel@tonic-gate 				"%s: error on new (dlopened) probe : %s\n"),
464*7c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
465*7c478bd9Sstevel@tonic-gate 	}
466*7c478bd9Sstevel@tonic-gate 	return (NULL);
467*7c478bd9Sstevel@tonic-gate }
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
470*7c478bd9Sstevel@tonic-gate set_probe_discovery_callback(tnfctl_handle_t *hndl)
471*7c478bd9Sstevel@tonic-gate {
472*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	err = tnfctl_register_funcs(hndl, perprobe, NULL);
475*7c478bd9Sstevel@tonic-gate 	if (err)
476*7c478bd9Sstevel@tonic-gate 		return (err);
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	return (TNFCTL_ERR_NONE);
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
482*7c478bd9Sstevel@tonic-gate perprobe2(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_p, void *cd)
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate 	cmd_t		*cmd = cd;
485*7c478bd9Sstevel@tonic-gate 	process_args_t  args;
486*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	args.probe_p = probe_p;
489*7c478bd9Sstevel@tonic-gate 	args.hndl = hndl;
490*7c478bd9Sstevel@tonic-gate 	err = cmd_callback(cmd, percmd, &args);
491*7c478bd9Sstevel@tonic-gate 	if (err) {
492*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
493*7c478bd9Sstevel@tonic-gate 				"%s: error on probe operation: %s\n"),
494*7c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
495*7c478bd9Sstevel@tonic-gate 	}
496*7c478bd9Sstevel@tonic-gate 	return (err);
497*7c478bd9Sstevel@tonic-gate }
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate void
500*7c478bd9Sstevel@tonic-gate process_cmd(tnfctl_handle_t *hndl, cmd_t *cmd)
501*7c478bd9Sstevel@tonic-gate {
502*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
503*7c478bd9Sstevel@tonic-gate 	if (g_verbose)
504*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "processing commands\n");
505*7c478bd9Sstevel@tonic-gate #endif
506*7c478bd9Sstevel@tonic-gate 	(void) tnfctl_probe_apply(hndl, perprobe2, cmd);
507*7c478bd9Sstevel@tonic-gate }
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate /*
510*7c478bd9Sstevel@tonic-gate  * get_commands() - process commands from stdin
511*7c478bd9Sstevel@tonic-gate  */
512*7c478bd9Sstevel@tonic-gate static void
513*7c478bd9Sstevel@tonic-gate get_commands(void)
514*7c478bd9Sstevel@tonic-gate {
515*7c478bd9Sstevel@tonic-gate 	/* Read commands from STDIN */
516*7c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
517*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Type \"help\" for help ...\n"));
518*7c478bd9Sstevel@tonic-gate 	} else {
519*7c478bd9Sstevel@tonic-gate 		if (g_testflag)
520*7c478bd9Sstevel@tonic-gate 			(void) printf("prex(%ld), target(%ld): ",
521*7c478bd9Sstevel@tonic-gate 					getpid(), g_targetpid);
522*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Target process stopped\n"));
523*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
524*7c478bd9Sstevel@tonic-gate 			"Type \"continue\" to resume the target, "
525*7c478bd9Sstevel@tonic-gate 			"\"help\" for help ...\n"));
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	while (yyparse());
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate /*
533*7c478bd9Sstevel@tonic-gate  * quit() - called to quit the controlling process. The boolean argument
534*7c478bd9Sstevel@tonic-gate  * specifies whether to terminate the target as well.
535*7c478bd9Sstevel@tonic-gate  */
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate void
538*7c478bd9Sstevel@tonic-gate quit(boolean_t killtarget, boolean_t runtarget)
539*7c478bd9Sstevel@tonic-gate {
540*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t err;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	if (killtarget && runtarget)
543*7c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_DEFAULT);
544*7c478bd9Sstevel@tonic-gate 	else if (killtarget && !runtarget)
545*7c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_KILL);
546*7c478bd9Sstevel@tonic-gate 	else if (!killtarget && runtarget)
547*7c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_RESUME);
548*7c478bd9Sstevel@tonic-gate 	else if (!killtarget && !runtarget)
549*7c478bd9Sstevel@tonic-gate 		err = tnfctl_close(g_hndl, TNFCTL_TARG_SUSPEND);
550*7c478bd9Sstevel@tonic-gate 	if (err) {
551*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
552*7c478bd9Sstevel@tonic-gate 				"%s: trouble quitting : %s\n"),
553*7c478bd9Sstevel@tonic-gate 				g_argv[0], tnfctl_strerror(err));
554*7c478bd9Sstevel@tonic-gate 		exit(1);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 	exit(0);
557*7c478bd9Sstevel@tonic-gate }
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate /*
561*7c478bd9Sstevel@tonic-gate  * scanargs() - processes the command line arguments
562*7c478bd9Sstevel@tonic-gate  */
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate #define	strneq(s1, s2, n) 	(strncmp(s1, s2, n) == 0)
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate static void
567*7c478bd9Sstevel@tonic-gate scanargs(int argc,
568*7c478bd9Sstevel@tonic-gate 	char **argv)
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	int			 c;
571*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
572*7c478bd9Sstevel@tonic-gate 	char		   *optstr = "l:o:p:s:tkv:";	/* debugging options */
573*7c478bd9Sstevel@tonic-gate #else
574*7c478bd9Sstevel@tonic-gate 	char		   *optstr = "l:o:p:s:tk";	/* production options */
575*7c478bd9Sstevel@tonic-gate #endif
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	/* set up some defaults */
578*7c478bd9Sstevel@tonic-gate 	g_targetpid = 0;
579*7c478bd9Sstevel@tonic-gate 	g_cmdname = NULL;
580*7c478bd9Sstevel@tonic-gate 	g_cmdargs = NULL;
581*7c478bd9Sstevel@tonic-gate 	g_preload = NULL;
582*7c478bd9Sstevel@tonic-gate 	g_outname = NULL;
583*7c478bd9Sstevel@tonic-gate 	g_outsize = -1;
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, optstr)) != EOF) {
586*7c478bd9Sstevel@tonic-gate 		switch (c) {
587*7c478bd9Sstevel@tonic-gate 		case 'l':	/* preload objects */
588*7c478bd9Sstevel@tonic-gate 			g_preload = optarg;
589*7c478bd9Sstevel@tonic-gate 			break;
590*7c478bd9Sstevel@tonic-gate 		case 'o':	/* tracefile name */
591*7c478bd9Sstevel@tonic-gate 			g_outname = optarg;
592*7c478bd9Sstevel@tonic-gate 			break;
593*7c478bd9Sstevel@tonic-gate 		case 'p':	/* target pid (attach case) */
594*7c478bd9Sstevel@tonic-gate 			g_targetpid = atoi(optarg);
595*7c478bd9Sstevel@tonic-gate 			break;
596*7c478bd9Sstevel@tonic-gate 		case 's':	/* tracefile size */
597*7c478bd9Sstevel@tonic-gate 			g_outsize = atoi(optarg) * 1024;
598*7c478bd9Sstevel@tonic-gate 			break;
599*7c478bd9Sstevel@tonic-gate 		case 't':	/* test flag */
600*7c478bd9Sstevel@tonic-gate 			g_testflag = B_TRUE;
601*7c478bd9Sstevel@tonic-gate 			(void) setvbuf(stdout, NULL, _IOLBF, 0);
602*7c478bd9Sstevel@tonic-gate 			break;
603*7c478bd9Sstevel@tonic-gate 		case 'k':	/* kernel mode */
604*7c478bd9Sstevel@tonic-gate 			g_kernelmode = B_TRUE;
605*7c478bd9Sstevel@tonic-gate 			break;
606*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
607*7c478bd9Sstevel@tonic-gate 		case 'v':	/* verbose flag */
608*7c478bd9Sstevel@tonic-gate 			g_verbose = atoi(optarg);
609*7c478bd9Sstevel@tonic-gate 			break;
610*7c478bd9Sstevel@tonic-gate #endif
611*7c478bd9Sstevel@tonic-gate 		case '?':	/* error case */
612*7c478bd9Sstevel@tonic-gate 			usage(argv, gettext("unrecognized argument"));
613*7c478bd9Sstevel@tonic-gate 		}
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	if (optind < argc) {
617*7c478bd9Sstevel@tonic-gate 		g_cmdname = strdup(argv[optind]);
618*7c478bd9Sstevel@tonic-gate 		g_cmdargs = &argv[optind];
619*7c478bd9Sstevel@tonic-gate 	}
620*7c478bd9Sstevel@tonic-gate 	/* sanity clause */
621*7c478bd9Sstevel@tonic-gate 	if (!g_kernelmode && (g_cmdname == NULL && g_targetpid == 0))
622*7c478bd9Sstevel@tonic-gate 		usage(argv, gettext("need to specify cmd or pid"));
623*7c478bd9Sstevel@tonic-gate 	if (g_cmdname != NULL && g_targetpid != 0)
624*7c478bd9Sstevel@tonic-gate 		usage(argv, gettext("can't specify both cmd and pid"));
625*7c478bd9Sstevel@tonic-gate 	if (g_targetpid && g_preload)
626*7c478bd9Sstevel@tonic-gate 		usage(argv, gettext("can't use preload option with attach"));
627*7c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
628*7c478bd9Sstevel@tonic-gate 		if (g_outname)
629*7c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify a filename in kernel mode");
630*7c478bd9Sstevel@tonic-gate 		if (g_cmdname)
631*7c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify a command in kernel mode");
632*7c478bd9Sstevel@tonic-gate 		if (g_targetpid)
633*7c478bd9Sstevel@tonic-gate 			usage(argv, "can't specify pid in kernel mode");
634*7c478bd9Sstevel@tonic-gate 		if (g_preload)
635*7c478bd9Sstevel@tonic-gate 			usage(argv, "can't use preload option in kernel mode");
636*7c478bd9Sstevel@tonic-gate 	}
637*7c478bd9Sstevel@tonic-gate 	/* default output size */
638*7c478bd9Sstevel@tonic-gate 	if (g_outsize == -1)
639*7c478bd9Sstevel@tonic-gate 		g_outsize = g_kernelmode ? KERNEL_OUTSIZE : USER_OUTSIZE;
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate #ifdef OLD
642*7c478bd9Sstevel@tonic-gate 	int			 i;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	for (i = 1; i < argc; i++) {
645*7c478bd9Sstevel@tonic-gate 		if (strneq(argv[i], "-v", 2)) {
646*7c478bd9Sstevel@tonic-gate 			int			 vlevel;
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 			vlevel = (strlen(argv[i]) > 2)? atoi(&argv[i][2]) : 1;
649*7c478bd9Sstevel@tonic-gate 			g_verbose = B_TRUE;
650*7c478bd9Sstevel@tonic-gate 			prb_verbose_set(vlevel);
651*7c478bd9Sstevel@tonic-gate 		} else if (strneq(argv[i], "-pid", 2)) {
652*7c478bd9Sstevel@tonic-gate 			if (++i >= argc)
653*7c478bd9Sstevel@tonic-gate 				usage(argv, gettext("missing pid argument"));
654*7c478bd9Sstevel@tonic-gate 			g_targetpid = atoi(argv[i]);
655*7c478bd9Sstevel@tonic-gate 		} else if (strneq(argv[i], "-t", 2)) {
656*7c478bd9Sstevel@tonic-gate 			g_testflag = B_TRUE;
657*7c478bd9Sstevel@tonic-gate 			(void) setvbuf(stdout, NULL, _IOLBF, 0);
658*7c478bd9Sstevel@tonic-gate 		} else if (argv[i][0] != '-') {
659*7c478bd9Sstevel@tonic-gate 			g_cmdname = strdup(argv[i]);
660*7c478bd9Sstevel@tonic-gate 			if (!g_cmdname) {
661*7c478bd9Sstevel@tonic-gate 				err_fatal(gettext(
662*7c478bd9Sstevel@tonic-gate 					"%s: out of memory"), argv[0]);
663*7c478bd9Sstevel@tonic-gate 			}
664*7c478bd9Sstevel@tonic-gate 			if (g_verbose >= 2) {
665*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
666*7c478bd9Sstevel@tonic-gate 					"cmdname=%s\n", g_cmdname);
667*7c478bd9Sstevel@tonic-gate 			}
668*7c478bd9Sstevel@tonic-gate 			/*
669*7c478bd9Sstevel@tonic-gate 			 * rest of arguments are the args to the executable -
670*7c478bd9Sstevel@tonic-gate 			 * by convention argv[0] should be name of
671*7c478bd9Sstevel@tonic-gate 			 * executable, so we don't increment i
672*7c478bd9Sstevel@tonic-gate 			 */
673*7c478bd9Sstevel@tonic-gate 			g_cmdargs = &argv[i];
674*7c478bd9Sstevel@tonic-gate 			break;
675*7c478bd9Sstevel@tonic-gate 		} else {
676*7c478bd9Sstevel@tonic-gate 			usage(argv, gettext("unrecognized argument"));
677*7c478bd9Sstevel@tonic-gate 		}
678*7c478bd9Sstevel@tonic-gate 	}
679*7c478bd9Sstevel@tonic-gate #endif
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate }				/* end scanargs */
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate /*
685*7c478bd9Sstevel@tonic-gate  * sig_handler() - cleans up if a signal is received
686*7c478bd9Sstevel@tonic-gate  */
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
689*7c478bd9Sstevel@tonic-gate static void
690*7c478bd9Sstevel@tonic-gate sig_handler(int signo)
691*7c478bd9Sstevel@tonic-gate {
692*7c478bd9Sstevel@tonic-gate 	g_getcmds = B_TRUE;
693*7c478bd9Sstevel@tonic-gate }				/* end sig_handler */
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate /*
697*7c478bd9Sstevel@tonic-gate  * set_signal() -  sets up function to call for clean up
698*7c478bd9Sstevel@tonic-gate  */
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate static int
701*7c478bd9Sstevel@tonic-gate set_signal(void)
702*7c478bd9Sstevel@tonic-gate {
703*7c478bd9Sstevel@tonic-gate 	struct sigaction newact;
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	newact.sa_handler = sig_handler;
706*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&newact.sa_mask);
707*7c478bd9Sstevel@tonic-gate 	newact.sa_flags = 0;
708*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &newact, NULL) < 0) {
709*7c478bd9Sstevel@tonic-gate 		return (errno);
710*7c478bd9Sstevel@tonic-gate 	}
711*7c478bd9Sstevel@tonic-gate 	return (0);
712*7c478bd9Sstevel@tonic-gate }
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate /*
716*7c478bd9Sstevel@tonic-gate  * set_tracefile() - initializes tracefile, sets the tracefile name and size
717*7c478bd9Sstevel@tonic-gate  */
718*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t
719*7c478bd9Sstevel@tonic-gate set_tracefile(tnfctl_handle_t *hndl)
720*7c478bd9Sstevel@tonic-gate {
721*7c478bd9Sstevel@tonic-gate 	tnfctl_errcode_t	err;
722*7c478bd9Sstevel@tonic-gate 	tnfctl_trace_attrs_t	attrs;
723*7c478bd9Sstevel@tonic-gate 	size_t			minoutsize;
724*7c478bd9Sstevel@tonic-gate 	char			path[MAXPATHLEN];
725*7c478bd9Sstevel@tonic-gate 	char			*outfile_name;
726*7c478bd9Sstevel@tonic-gate 	char			*tmpdir;
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate 	/* Init tracefile name used by list cmd */
729*7c478bd9Sstevel@tonic-gate 	tracefile = NULL;
730*7c478bd9Sstevel@tonic-gate 	err = tnfctl_trace_attrs_get(hndl, &attrs);
731*7c478bd9Sstevel@tonic-gate 	if (err)
732*7c478bd9Sstevel@tonic-gate 		return (err);
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 	if (attrs.trace_buf_state == TNFCTL_BUF_BROKEN)
735*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_BUFBROKEN);
736*7c478bd9Sstevel@tonic-gate 	if (attrs.trace_buf_state == TNFCTL_BUF_OK) {
737*7c478bd9Sstevel@tonic-gate 		/* trace file set already - can't change it */
738*7c478bd9Sstevel@tonic-gate 		return (TNFCTL_ERR_NONE);
739*7c478bd9Sstevel@tonic-gate 	}
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	minoutsize = attrs.trace_min_size;
742*7c478bd9Sstevel@tonic-gate 	if (g_outsize < minoutsize)	{
743*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
744*7c478bd9Sstevel@tonic-gate 			gettext("specified tracefile size smaller then "
745*7c478bd9Sstevel@tonic-gate 				"minimum; setting to %d kbytes\n"),
746*7c478bd9Sstevel@tonic-gate 				minoutsize / 1024);
747*7c478bd9Sstevel@tonic-gate 		g_outsize = minoutsize;
748*7c478bd9Sstevel@tonic-gate 	}
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	/* where is $TMPDIR? */
751*7c478bd9Sstevel@tonic-gate 	tmpdir = getenv("TMPDIR");
752*7c478bd9Sstevel@tonic-gate 	if (!tmpdir || *tmpdir == '\0') {
753*7c478bd9Sstevel@tonic-gate 		tmpdir = "/tmp";
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 	/* do we have an absolute, relative or no pathname specified? */
757*7c478bd9Sstevel@tonic-gate 	if (g_outname == NULL) {
758*7c478bd9Sstevel@tonic-gate 		/* default, no tracefile specified */
759*7c478bd9Sstevel@tonic-gate 		if ((strlen(tmpdir) + 1 + 20) > (size_t)MAXPATHLEN) {
760*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
761*7c478bd9Sstevel@tonic-gate 				"%s: $TMPDIR too long\n"), g_argv[0]);
762*7c478bd9Sstevel@tonic-gate 			exit(1);
763*7c478bd9Sstevel@tonic-gate 		}
764*7c478bd9Sstevel@tonic-gate 		(void) sprintf(path, "%s/trace-%ld", tmpdir, g_targetpid);
765*7c478bd9Sstevel@tonic-gate 		outfile_name = path;
766*7c478bd9Sstevel@tonic-gate 	} else {
767*7c478bd9Sstevel@tonic-gate 		/* filename specified */
768*7c478bd9Sstevel@tonic-gate 		outfile_name = g_outname;
769*7c478bd9Sstevel@tonic-gate 	}
770*7c478bd9Sstevel@tonic-gate 	tracefile = strdup(outfile_name);
771*7c478bd9Sstevel@tonic-gate 	if (tracefile == NULL) {
772*7c478bd9Sstevel@tonic-gate 		if ((errno == ENOMEM) || (errno == EAGAIN)) {
773*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_ALLOCFAIL);
774*7c478bd9Sstevel@tonic-gate 		} else {
775*7c478bd9Sstevel@tonic-gate 			return (TNFCTL_ERR_INTERNAL);
776*7c478bd9Sstevel@tonic-gate 		}
777*7c478bd9Sstevel@tonic-gate 	}
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) || defined(lint)
780*7c478bd9Sstevel@tonic-gate 	if (g_verbose)
781*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
782*7c478bd9Sstevel@tonic-gate 			"setting tracefile name=\"%s\", size=%d\n",
783*7c478bd9Sstevel@tonic-gate 			path, g_outsize);
784*7c478bd9Sstevel@tonic-gate #endif
785*7c478bd9Sstevel@tonic-gate 	err = tnfctl_buffer_alloc(hndl, outfile_name, g_outsize);
786*7c478bd9Sstevel@tonic-gate 	return (err);
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate /*
789*7c478bd9Sstevel@tonic-gate  * get_data_model() - get the process data model from psinfo
790*7c478bd9Sstevel@tonic-gate  *		      structure.
791*7c478bd9Sstevel@tonic-gate  */
792*7c478bd9Sstevel@tonic-gate #define	PROCFORMAT	"/proc/%d"
793*7c478bd9Sstevel@tonic-gate static int
794*7c478bd9Sstevel@tonic-gate get_data_model(pid_t pid)
795*7c478bd9Sstevel@tonic-gate {
796*7c478bd9Sstevel@tonic-gate 	char	path[MAXPATHLEN];
797*7c478bd9Sstevel@tonic-gate 	int	fd, dmodel = -1;
798*7c478bd9Sstevel@tonic-gate 	prpsinfo_t	psinfo;
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	(void) sprintf(path, PROCFORMAT, (int)pid);
801*7c478bd9Sstevel@tonic-gate 	fd = open(path, O_RDONLY);
802*7c478bd9Sstevel@tonic-gate 	if (fd == -1)
803*7c478bd9Sstevel@tonic-gate 	    return (dmodel);
804*7c478bd9Sstevel@tonic-gate 	if ((dmodel = ioctl(fd, PIOCPSINFO, &psinfo)) == -1)
805*7c478bd9Sstevel@tonic-gate 	    return (dmodel);
806*7c478bd9Sstevel@tonic-gate 	return ((int)psinfo.pr_dmodel);
807*7c478bd9Sstevel@tonic-gate }
808*7c478bd9Sstevel@tonic-gate /*
809*7c478bd9Sstevel@tonic-gate  * get_executable - return file descriptor for PATH-resolved
810*7c478bd9Sstevel@tonic-gate  *		    target file.
811*7c478bd9Sstevel@tonic-gate  *
812*7c478bd9Sstevel@tonic-gate  */
813*7c478bd9Sstevel@tonic-gate static int
814*7c478bd9Sstevel@tonic-gate get_executable(char *name) {
815*7c478bd9Sstevel@tonic-gate     int fd = -1;
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate     if (name != NULL) {
818*7c478bd9Sstevel@tonic-gate 	char path[PATH_MAX + 1];
819*7c478bd9Sstevel@tonic-gate 	char line[MAX_INPUT + 1];
820*7c478bd9Sstevel@tonic-gate 	char *p = line;
821*7c478bd9Sstevel@tonic-gate 	char *fname = name;
822*7c478bd9Sstevel@tonic-gate 	int N = sizeof (line);
823*7c478bd9Sstevel@tonic-gate 	struct stat file_att;
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 	while (*fname == ' ') fname++;
826*7c478bd9Sstevel@tonic-gate 	if (fname[0] == '-' || strchr(fname, '/')) {
827*7c478bd9Sstevel@tonic-gate 	    fd = open(fname, O_RDONLY);
828*7c478bd9Sstevel@tonic-gate 	} else {
829*7c478bd9Sstevel@tonic-gate 	    int len = strlen(fname);
830*7c478bd9Sstevel@tonic-gate 	    char *dirlist = getenv("PATH");
831*7c478bd9Sstevel@tonic-gate 	    char *dir = NULL;
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 	    if (dirlist != NULL) {
834*7c478bd9Sstevel@tonic-gate 		dirlist = strdup(dirlist);
835*7c478bd9Sstevel@tonic-gate 		dir = strtok(dirlist, ":");
836*7c478bd9Sstevel@tonic-gate 	    }
837*7c478bd9Sstevel@tonic-gate 	    while (fd < 0 && dir != NULL) {
838*7c478bd9Sstevel@tonic-gate 		if ((strlen(dir) + len + 1) < sizeof (path)) {
839*7c478bd9Sstevel@tonic-gate 		    strcat(strcat(strcpy(path, dir), "/"), fname);
840*7c478bd9Sstevel@tonic-gate 		    fd = open(path, O_RDONLY);
841*7c478bd9Sstevel@tonic-gate 		}
842*7c478bd9Sstevel@tonic-gate 		dir = strtok(NULL, ":");
843*7c478bd9Sstevel@tonic-gate 	    }
844*7c478bd9Sstevel@tonic-gate 	    if (dirlist != NULL) free(dirlist);
845*7c478bd9Sstevel@tonic-gate 	}
846*7c478bd9Sstevel@tonic-gate 	if (fstat(fd, &file_att) || !S_ISREG(file_att.st_mode)) {
847*7c478bd9Sstevel@tonic-gate 	    if (fd >= 0)
848*7c478bd9Sstevel@tonic-gate 		close(fd);
849*7c478bd9Sstevel@tonic-gate 	    return (-1);
850*7c478bd9Sstevel@tonic-gate 	}
851*7c478bd9Sstevel@tonic-gate 	if (read(fd, p, 2) && p[0] == '#' && p[1] == '!') {
852*7c478bd9Sstevel@tonic-gate 	    while (N-- > 1 && read(fd, p, 1) && *p != '\n')
853*7c478bd9Sstevel@tonic-gate 		p++;
854*7c478bd9Sstevel@tonic-gate 	    *p = '\0';
855*7c478bd9Sstevel@tonic-gate 	    close(fd);
856*7c478bd9Sstevel@tonic-gate 	    return (get_executable(line));
857*7c478bd9Sstevel@tonic-gate 	}
858*7c478bd9Sstevel@tonic-gate 	if (fd >= 0) lseek(fd, 0, SEEK_SET);
859*7c478bd9Sstevel@tonic-gate 	} /* %$#@! cstyle complaint */
860*7c478bd9Sstevel@tonic-gate     return (fd);
861*7c478bd9Sstevel@tonic-gate }
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate /*
864*7c478bd9Sstevel@tonic-gate  * get_elf_class - get the target executable elf class
865*7c478bd9Sstevel@tonic-gate  *                 i.e. ELFCLASS64 or ELFCLASS32.
866*7c478bd9Sstevel@tonic-gate  */
867*7c478bd9Sstevel@tonic-gate static int
868*7c478bd9Sstevel@tonic-gate get_elf_class(char *filename)
869*7c478bd9Sstevel@tonic-gate {
870*7c478bd9Sstevel@tonic-gate 	int	elfclass = -1;
871*7c478bd9Sstevel@tonic-gate 	int	elffd = get_executable(filename);
872*7c478bd9Sstevel@tonic-gate 	Elf	*elf;
873*7c478bd9Sstevel@tonic-gate 	size_t	size;
874*7c478bd9Sstevel@tonic-gate 	char	*ident;
875*7c478bd9Sstevel@tonic-gate 	GElf_Ehdr	ehdr;
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 	if (elffd < 0)
878*7c478bd9Sstevel@tonic-gate 		return (elfclass);
879*7c478bd9Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
880*7c478bd9Sstevel@tonic-gate 		(void) close(elffd);
881*7c478bd9Sstevel@tonic-gate 		return (elfclass);
882*7c478bd9Sstevel@tonic-gate 	}
883*7c478bd9Sstevel@tonic-gate 	elf = elf_begin(elffd, ELF_C_READ, (Elf *) 0);
884*7c478bd9Sstevel@tonic-gate 	/*
885*7c478bd9Sstevel@tonic-gate 	 * verify information in file header
886*7c478bd9Sstevel@tonic-gate 	 */
887*7c478bd9Sstevel@tonic-gate 	if (gelf_getehdr(elf, &ehdr) == (GElf_Ehdr *) 0) {
888*7c478bd9Sstevel@tonic-gate 		close(elffd);
889*7c478bd9Sstevel@tonic-gate 		return (elfclass);
890*7c478bd9Sstevel@tonic-gate 	}
891*7c478bd9Sstevel@tonic-gate 	ident = elf_getident(elf, &size);
892*7c478bd9Sstevel@tonic-gate 	if (ident[EI_CLASS] == ELFCLASS32)
893*7c478bd9Sstevel@tonic-gate 		elfclass = ELFCLASS32;
894*7c478bd9Sstevel@tonic-gate 	if (ident[EI_CLASS] == ELFCLASS64)
895*7c478bd9Sstevel@tonic-gate 		elfclass = ELFCLASS64;
896*7c478bd9Sstevel@tonic-gate 	close(elffd);
897*7c478bd9Sstevel@tonic-gate 	return (elfclass);
898*7c478bd9Sstevel@tonic-gate }
899*7c478bd9Sstevel@tonic-gate /*
900*7c478bd9Sstevel@tonic-gate  * check_exec_model() - check the consistency between prex data model
901*7c478bd9Sstevel@tonic-gate  *                      and target elf class and act accordingly
902*7c478bd9Sstevel@tonic-gate  */
903*7c478bd9Sstevel@tonic-gate static void
904*7c478bd9Sstevel@tonic-gate check_exec_model(char **argv, char **envp)
905*7c478bd9Sstevel@tonic-gate {
906*7c478bd9Sstevel@tonic-gate 	int	elfclass;
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate 	elfclass = get_elf_class(g_cmdname);
909*7c478bd9Sstevel@tonic-gate 	if (((elfclass == ELFCLASS32) && (prex_dmodel == PR_MODEL_ILP32)) ||
910*7c478bd9Sstevel@tonic-gate 	    ((elfclass == ELFCLASS64) && (prex_dmodel == PR_MODEL_LP64)))
911*7c478bd9Sstevel@tonic-gate 	    return;
912*7c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_ILP32) &&
913*7c478bd9Sstevel@tonic-gate 	    (elfclass == ELFCLASS64)) {
914*7c478bd9Sstevel@tonic-gate 	    (void) fprintf(stderr, gettext(
915*7c478bd9Sstevel@tonic-gate 		"Error: 32 bit prex can not exec 64 bit target\n"));
916*7c478bd9Sstevel@tonic-gate 	    exit(1);
917*7c478bd9Sstevel@tonic-gate 	}
918*7c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_LP64) &&
919*7c478bd9Sstevel@tonic-gate 	    (elfclass == ELFCLASS32))
920*7c478bd9Sstevel@tonic-gate 	    prex_isaexec(argv, envp);
921*7c478bd9Sstevel@tonic-gate }
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate /*
924*7c478bd9Sstevel@tonic-gate  * check_pid_model() - check the consistency between prex data model
925*7c478bd9Sstevel@tonic-gate  *                     and target data model and act accordingly
926*7c478bd9Sstevel@tonic-gate  */
927*7c478bd9Sstevel@tonic-gate static void
928*7c478bd9Sstevel@tonic-gate check_pid_model(char **argv, char **envp)
929*7c478bd9Sstevel@tonic-gate {
930*7c478bd9Sstevel@tonic-gate 	int	dmodel;
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	dmodel = get_data_model(g_targetpid);
933*7c478bd9Sstevel@tonic-gate 	if (prex_dmodel == dmodel)
934*7c478bd9Sstevel@tonic-gate 		return;
935*7c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_ILP32) &&
936*7c478bd9Sstevel@tonic-gate 		(dmodel == PR_MODEL_LP64)) {
937*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
938*7c478bd9Sstevel@tonic-gate 		    "Error: 32 bit prex can not exec 64 bit target\n"));
939*7c478bd9Sstevel@tonic-gate 		exit(1);
940*7c478bd9Sstevel@tonic-gate 	}
941*7c478bd9Sstevel@tonic-gate 	if ((prex_dmodel == PR_MODEL_LP64) &&
942*7c478bd9Sstevel@tonic-gate 		(dmodel == PR_MODEL_ILP32))
943*7c478bd9Sstevel@tonic-gate 		prex_isaexec(argv, envp);
944*7c478bd9Sstevel@tonic-gate }
945*7c478bd9Sstevel@tonic-gate /*
946*7c478bd9Sstevel@tonic-gate  * prex_isaexec() - there is only one case this function get called
947*7c478bd9Sstevel@tonic-gate  *                  64 bit prex, 32 bit target, need to exec 32 bit
948*7c478bd9Sstevel@tonic-gate  *                  prex here.
949*7c478bd9Sstevel@tonic-gate  */
950*7c478bd9Sstevel@tonic-gate static void
951*7c478bd9Sstevel@tonic-gate prex_isaexec(char **argv, char **envp)
952*7c478bd9Sstevel@tonic-gate {
953*7c478bd9Sstevel@tonic-gate 	char path[PATH_MAX + sizeof (PREX32DIR)];
954*7c478bd9Sstevel@tonic-gate 	strcat(strcat(strcpy(path, dirname(dirname(argv[0]))), PREX32DIR),
955*7c478bd9Sstevel@tonic-gate 	    basename(argv[0]));
956*7c478bd9Sstevel@tonic-gate 	if (get_elf_class(path) != ELFCLASS32)
957*7c478bd9Sstevel@tonic-gate 	    strcpy(path, PREX32EXEC);
958*7c478bd9Sstevel@tonic-gate 	argv[0] = path;
959*7c478bd9Sstevel@tonic-gate 	(void) execve(path, argv, envp);
960*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
961*7c478bd9Sstevel@tonic-gate 	    gettext("%s: execve(\"%s\") failed\n"),
962*7c478bd9Sstevel@tonic-gate 	    argv[0], path);
963*7c478bd9Sstevel@tonic-gate }
964*7c478bd9Sstevel@tonic-gate void
965*7c478bd9Sstevel@tonic-gate cmd_listtracefile()
966*7c478bd9Sstevel@tonic-gate {
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	if (g_kernelmode) {
969*7c478bd9Sstevel@tonic-gate 	    (void) fprintf(stderr,
970*7c478bd9Sstevel@tonic-gate 		    gettext("There is no trace file in kernel mode!\n"));
971*7c478bd9Sstevel@tonic-gate 	} else {
972*7c478bd9Sstevel@tonic-gate 	    (void) printf(gettext("Current trace file is: %s\n"), tracefile);
973*7c478bd9Sstevel@tonic-gate 	}
974*7c478bd9Sstevel@tonic-gate }
975