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