4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
35 #include <sys/types.h>
42 /* XXX A bug in the <string.h> header file requires this */
43 extern char *strtok_r(char *s1
, const char *s2
, char **lasts
);
46 * option procesing ---
47 * Routines for scanning syscall, signal, fault
48 * and file descriptor lists.
52 * Function prototypes for static routines in this module.
56 const char white
[] = " \t\n"; /* white space characters */
57 const char sepr
[] = " ,\t\n"; /* list separator characters */
58 const char csepr
[] = " :,\t\n"; /* same, with ':' added */
61 * Scan list of syscall names.
62 * Return 0 on success, != 0 on any failure.
65 syslist(char *str
, /* string of syscall names */
66 sysset_t
*setp
, /* syscall set */
67 int *fp
) /* first-time flag */
74 name
= strtok_r(str
, sepr
, &lasts
);
76 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
79 name
= strtok_r(NULL
, sepr
, &lasts
);
80 } else if (!*fp
) { /* first time, clear the set */
85 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
90 if (*name
== '!') { /* exclude remainder from set */
92 while (*++name
== '!')
98 sys
= strtol(name
, &next
, 0);
100 if (sys
< 0 || sys
> PRMAXSYS
|| *next
!= '\0')
103 const struct systable
*stp
= systable
;
104 for (; sys
== 0 && stp
->nargs
>= 0; stp
++)
105 if (stp
->name
&& strcmp(stp
->name
, name
) == 0)
109 const struct sysalias
*sap
= sysalias
;
110 for (; sys
== 0 && sap
->name
; sap
++)
111 if (strcmp(sap
->name
, name
) == 0)
114 if (sys
> 0 && sys
<= PRMAXSYS
) {
173 case SYS_forksys
: /* set both if either */
179 case SYS_sigprocmask
: /* set both if either */
180 case SYS_lwp_sigmask
:
181 sysx
= SYS_sigprocmask
;
182 sys
= SYS_lwp_sigmask
;
185 case SYS_lseek
: /* set both if either */
191 case SYS_rename
: /* set both */
195 case SYS_link
: /* set both */
199 case SYS_unlink
: /* set both */
200 case SYS_rmdir
: /* set both */
204 case SYS_symlink
: /* set both */
205 sysx
= SYS_symlinkat
;
208 case SYS_readlink
: /* set both */
209 sysx
= SYS_readlinkat
;
212 case SYS_chmod
: /* set both */
213 case SYS_fchmod
: /* set both */
217 case SYS_chown
: /* set both */
218 case SYS_lchown
: /* set both */
219 case SYS_fchown
: /* set both */
223 case SYS_mkdir
: /* set both */
227 case SYS_mknod
: /* set both */
231 case SYS_access
: /* set both */
232 sysx
= SYS_faccessat
;
240 prdelset(setp
, sysx
);
244 praddset(setp
, sysx
);
248 } else if (strcmp(name
, "all") == 0 ||
249 strcmp(name
, "ALL") == 0) {
256 (void) fprintf(stderr
,
257 "%s: unrecognized syscall: %s\n",
267 * List of signals to trace.
268 * Return 0 on success, != 0 on any failure.
271 siglist(private_t
*pri
,
272 char *str
, /* string of signal names */
273 sigset_t
*setp
, /* signal set */
274 int *fp
) /* first-time flag */
282 name
= strtok_r(str
, sepr
, &lasts
);
284 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
287 name
= strtok_r(NULL
, sepr
, &lasts
);
288 } else if (!*fp
) { /* first time, clear the set */
293 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
297 if (*name
== '!') { /* exclude remainder from set */
299 while (*++name
== '!')
305 sig
= strtol(name
, &next
, 0);
306 if (sig
<= 0 || sig
> PRMAXSIG
|| *next
!= '\0') {
307 for (sig
= 1; sig
<= PRMAXSIG
; sig
++) {
308 const char *sname
= rawsigname(pri
, sig
);
311 if (strcmp(sname
, name
) == 0 ||
312 strcmp(sname
+3, name
) == 0)
318 if (sig
> 0 && sig
<= PRMAXSIG
) {
324 } else if (strcmp(name
, "ALL") == 0) {
331 (void) fprintf(stderr
,
332 "%s: unrecognized signal name/number: %s\n",
342 * List of faults to trace.
343 * return 0 on success, != 0 on any failure.
346 fltlist(char *str
, /* string of fault names */
347 fltset_t
*setp
, /* fault set */
348 int *fp
) /* first-time flag */
356 name
= strtok_r(str
, sepr
, &lasts
);
358 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
361 name
= strtok_r(NULL
, sepr
, &lasts
);
362 } else if (!*fp
) { /* first time, clear the set */
367 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
371 if (*name
== '!') { /* exclude remainder from set */
373 while (*++name
== '!')
379 flt
= strtol(name
, &next
, 0);
380 if (flt
<= 0 || flt
> PRMAXFAULT
|| *next
!= '\0') {
381 for (flt
= 1; flt
<= PRMAXFAULT
; flt
++) {
384 if (proc_fltname(flt
, fname
,
385 sizeof (fname
)) == NULL
)
388 if (strcmp(fname
, name
) == 0 ||
389 strcmp(fname
+3, name
) == 0)
392 if (flt
> PRMAXFAULT
)
395 if (flt
> 0 && flt
<= PRMAXFAULT
) {
401 } else if (strcmp(name
, "ALL") == 0) {
408 (void) fprintf(stderr
,
409 "%s: unrecognized fault name/number: %s\n",
419 * Gather file descriptors to dump.
420 * Return 0 on success, != 0 on any failure.
423 fdlist(char *str
, /* string of filedescriptors */
424 fileset_t
*setp
) /* set of boolean flags */
432 name
= strtok_r(str
, sepr
, &lasts
);
434 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
437 name
= strtok_r(NULL
, sepr
, &lasts
);
440 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
444 if (*name
== '!') { /* exclude remainder from set */
446 while (*++name
== '!')
452 fd
= strtol(name
, &next
, 0);
453 if (fd
>= 0 && fd
< NOFILES_MAX
&& *next
== '\0') {
460 } else if (strcmp(name
, "ALL") == 0) {
467 (void) fprintf(stderr
,
468 "%s: filedescriptor not in range[0..%d]: %s\n",
469 command
, NOFILES_MAX
-1, name
);
482 while ((c
= *str
) != '\0')
487 * 'arg' points to a string like:
488 * libc,libnsl,... : printf,read,write,...
490 * libc,libnsl,... :: printf,read,write,...
491 * with possible filename pattern-matching metacharacters.
493 * Assumption: No library or function name can contain ',' or ':'.
496 liblist(char *arg
, int hang
)
498 const char *star
= "*";
505 /* append a new dynpat structure to the end of the Dynpat list */
506 Dyp
= my_malloc(sizeof (struct dynpat
), NULL
);
509 Dynpat
= Lastpat
= Dyp
;
514 Dyp
->flag
= hang
? BPT_HANG
: 0;
515 Dyp
->exclude_lib
= 0;
521 * Find the beginning of the filename patterns
522 * and null-terminate the library name patterns.
524 if ((fpat
= strchr(arg
, ':')) != NULL
)
528 * Library name patterns.
530 pat
= strtok_r(arg
, sepr
, &lasts
);
532 /* '!' introduces an exclusion list */
533 if (pat
!= NULL
&& *pat
== '!') {
534 Dyp
->exclude_lib
= 1;
535 pat
+= strspn(pat
, "!");
537 pat
= strtok_r(NULL
, sepr
, &lasts
);
538 /* force exclusion of all functions as well */
545 /* empty list means all libraries */
546 Dyp
->libpat
= my_malloc(sizeof (char *), NULL
);
547 Dyp
->libpat
[0] = star
;
551 * We are now at the library list.
552 * Generate the list and count the library name patterns.
555 Dyp
->libpat
= my_malloc(maxpat
* sizeof (char *), NULL
);
557 Dyp
->libpat
[Dyp
->nlibpat
++] = pat
;
558 while ((pat
= strtok_r(NULL
, sepr
, &lasts
)) != NULL
) {
559 if (Dyp
->nlibpat
== maxpat
) {
561 Dyp
->libpat
= my_realloc(Dyp
->libpat
,
562 maxpat
* sizeof (char *), NULL
);
564 Dyp
->libpat
[Dyp
->nlibpat
++] = pat
;
569 * Function name patterns.
575 * We have already seen a ':'. Look for another.
576 * Double ':' means trace internal calls.
578 fpat
+= strspn(fpat
, white
);
583 pat
= strtok_r(fpat
, csepr
, &lasts
);
586 /* '!' introduces an exclusion list */
587 if (pat
!= NULL
&& *pat
== '!') {
590 pat
+= strspn(pat
, "!");
592 pat
= strtok_r(NULL
, sepr
, &lasts
);
596 /* empty function list means exclude all functions */
597 Dyp
->sympat
= my_malloc(sizeof (char *), NULL
);
598 Dyp
->sympat
[0] = star
;
602 * We are now at the function list.
603 * Generate the list and count the symbol name patterns.
606 Dyp
->sympat
= my_malloc(maxpat
* sizeof (char *), NULL
);
608 Dyp
->sympat
[Dyp
->nsympat
++] = pat
;
609 while ((pat
= strtok_r(NULL
, sepr
, &lasts
)) != NULL
) {
610 if (Dyp
->nsympat
== maxpat
) {
612 Dyp
->sympat
= my_realloc(Dyp
->sympat
,
613 maxpat
* sizeof (char *), NULL
);
615 Dyp
->sympat
[Dyp
->nsympat
++] = pat
;