4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
49 /* Various list pointers */
50 static char *fromlist
;
51 static char *fromexcl
;
60 /* The supported options */
61 static char const *optlet
= "F:fo:T:t:v:";
62 /* basename(argv[0]) */
63 static char const *command
;
65 /* The environment variables that'll get picked up by apptrace.so.1 */
66 static char const *APPTRACE_BINDTO
= "APPTRACE_BINDTO=";
67 static char const *APPTRACE_BINDTO_EXCLUDE
= "APPTRACE_BINDTO_EXCLUDE=";
68 static char const *APPTRACE_BINDFROM
= "APPTRACE_BINDFROM=";
69 static char const *APPTRACE_BINDFROM_EXCLUDE
= "APPTRACE_BINDFROM_EXCLUDE=";
70 static char const *APPTRACE_OUTPUT
= "APPTRACE_OUTPUT=";
71 static char const *APPTRACE_PID
= "APPTRACE_PID=";
72 static char const *APPTRACE_INTERFACES
= "APPTRACE_INTERFACES=";
73 static char const *APPTRACE_INTERFACES_EXCLUDE
= "APPTRACE_INTERFACES_EXCLUDE=";
74 static char const *APPTRACE_VERBOSE
= "APPTRACE_VERBOSE=";
75 static char const *APPTRACE_VERBOSE_EXCLUDE
= "APPTRACE_VERBOSE_EXCLUDE=";
77 /* Some default values for the above */
78 static char *LD_AUDIT
= "LD_AUDIT=/usr/lib/abi/apptrace.so.1";
79 #if defined(sparc) || defined(__sparcv9)
80 static char *LD_AUDIT_64
=
81 "LD_AUDIT_64=/usr/lib/abi/sparcv9/apptrace.so.1";
82 #elif defined(i386) || defined(__amd64)
83 static char *LD_AUDIT_64
=
84 "LD_AUDIT_64=/usr/lib/abi/amd64/apptrace.so.1";
86 #error Unsupported Platform
89 static char const *one
= "1";
91 /* The local support functions */
92 static void usage(char const *);
93 static void stuffenv(char const *, char const *);
94 static char *buildlist(char **, char const *);
97 main(int argc
, char **argv
)
102 char *outfile
= NULL
;
106 (void) setlocale(LC_ALL
, "");
107 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
108 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
110 (void) textdomain(TEXT_DOMAIN
);
113 /* Squirrel the basename of the command name away. */
114 if ((command
= strrchr(argv
[0], '/')) != NULL
)
119 while ((opt
= getopt(argc
, argv
, optlet
)) != EOF
) {
123 (void) buildlist(&fromexcl
, optarg
+ 1);
125 (void) buildlist(&fromlist
, optarg
);
135 (void) buildlist(&toexcl
, optarg
+ 1);
137 (void) buildlist(&tolist
, optarg
);
141 (void) buildlist(&ifexcl
, optarg
+ 1);
143 (void) buildlist(&iflist
, optarg
);
147 (void) buildlist(&vifexcl
, optarg
+ 1);
149 (void) buildlist(&viflist
, optarg
);
158 * Whack the argument vector so that the remainder will be
159 * ready for passing to exec
165 * If there was a problem with the options, or there was no command
166 * to be run, then give the usage message and bugout.
168 if (errflg
|| argc
<= 0) {
174 * This is where the environment gets setup.
177 stuffenv(APPTRACE_PID
, one
);
179 if (fromexcl
!= NULL
)
180 stuffenv(APPTRACE_BINDFROM_EXCLUDE
, fromexcl
);
181 if (fromlist
!= NULL
)
182 stuffenv(APPTRACE_BINDFROM
, fromlist
);
185 stuffenv(APPTRACE_BINDTO
, tolist
);
187 stuffenv(APPTRACE_BINDTO_EXCLUDE
, toexcl
);
190 stuffenv(APPTRACE_INTERFACES
, iflist
);
192 stuffenv(APPTRACE_INTERFACES_EXCLUDE
, ifexcl
);
195 stuffenv(APPTRACE_VERBOSE
, viflist
);
197 stuffenv(APPTRACE_VERBOSE_EXCLUDE
, vifexcl
);
200 stuffenv(APPTRACE_OUTPUT
, outfile
);
203 * It is the setting of the LD_AUDIT environment variable
204 * that tells ld.so.1 to enable link auditing when the child
207 (void) putenv(LD_AUDIT
);
208 (void) putenv(LD_AUDIT_64
);
211 * The environment is now all setup.
212 * For those about to rock, we salute you!
218 (void) fprintf(stderr
, gettext("%s: fork failed: %s\n"),
219 command
, strerror(errno
));
225 * Usual failure is argv[0] does not exist or is
228 if (execvp(argv
[0], argv
)) {
229 (void) fprintf(stderr
, gettext("%s: %s: %s\n"),
230 command
, argv
[0], strerror(errno
));
236 wret
= waitpid(pid
, &stat_loc
, 0);
238 (void) fprintf(stderr
,
239 gettext("%s: waitpid failed: %s\n"),
240 command
, strerror(errno
));
245 (void) fprintf(stderr
,
247 "waitpid returned %ld when child pid was %ld\n"),
252 if (WIFSIGNALED(stat_loc
)) {
253 (void) fprintf(stderr
, gettext("\n%s: %s: %s"),
254 command
, argv
[0], strsignal(WTERMSIG(stat_loc
)));
255 if (WCOREDUMP(stat_loc
)) {
256 (void) fputs(gettext("(Core dump)"), stderr
);
258 (void) fputs(gettext("\nRunning pstack:\n"),
260 (void) putenv("LD_AUDIT=");
261 (void) putenv("LD_AUDIT_64=");
262 (void) system("/usr/proc/bin/pstack core");
265 (void) putc('\n', stderr
);
268 /* Normal return from main() */
269 return (WEXITSTATUS(stat_loc
));
276 * Take a string in the form "VAR=" and another in the
277 * form "value" and paste them together.
280 stuffenv(char const *var
, char const *val
)
285 lenvar
= strlen(var
);
286 lenval
= strlen(val
);
288 if ((stuff
= malloc(lenvar
+ lenval
+ 1)) == NULL
) {
289 (void) fprintf(stderr
, gettext("%s: malloc failed\n"), command
);
292 (void) sprintf(stuff
, "%s%s", var
, val
);
293 (void) putenv(stuff
);
297 * If *dst is empty, use strdup to duplicate src.
298 * Otherwise: dst = dst + "," + src;
301 buildlist(char **dst
, char const *src
)
307 * If dst is still empty then dup,
308 * if dup succeeds set dst.
320 /* +2 because of the comma we add below */
321 if ((p
= realloc(*dst
, len
+ strlen(src
) + 2)) == NULL
)
327 (void) strcpy((*dst
+ len
+ 1), src
);
332 (void) fprintf(stderr
, gettext("%s: allocation failed: %s\n"),
333 command
, strerror(errno
));
339 usage(char const *prog
)
341 (void) fprintf(stderr
, gettext("Usage: %s [-f][-F [!]tracefromlist]"
342 "[-T [!]tracetolist][-o outputfile]\n"
343 " [-t calls][-v calls] prog [prog arguments]\n"
345 " -F <bindfromlist>\n"
346 " A comma separated list of libraries that are to be\n"
347 " traced. Only calls from these libraries will be\n"
348 " traced. The default is to trace calls from the\n"
349 " main executable.\n"
350 " If <bindfromlist> begins with a ! then it defines\n"
351 " a list of libraries to exclude from the trace.\n"
353 " A comma separated list of libraries that are to be\n"
354 " traced. Only calls to these libraries will be\n"
355 " traced. The default is to trace all calls.\n"
356 " If <bindtolist> begins with a ! then it defines\n"
357 " a list of libraries to exclude from the trace.\n"
359 " %s output will be directed to 'outputfile'.\n"
360 " by default it is placed on stderr\n"
362 " Follow all children created by fork() and also\n"
363 " print apptrace output for the children. This also\n"
364 " causes a 'pid' to be added to each output line\n"
366 " A comma separated list of interfaces to trace.\n"
367 " A list preceded by ! is an exlusion list.\n"
368 " -v <verboselist>\n"
369 " A comma separated list of interfaces to trace\n"
371 " A list preceded by ! is an exclusion list.\n"
372 " Interfaces matched in -v do not also need to be\n"
374 " All lists may use shell style wild cards.\n"
375 " Leading path components or suffixes are not required when\n"
376 " listing libraries (ie. libc will match /usr/lib/libc.so.1).\n"),