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
)) {
92 if (*name
== '!') { /* exclude remainder from set */
94 while (*++name
== '!')
100 sys
= strtol(name
, &next
, 0);
101 sysx
= sysxx
= sys64
= 0;
102 if (sys
< 0 || sys
> PRMAXSYS
|| *next
!= '\0')
105 const struct systable
*stp
= systable
;
106 for (; sys
== 0 && stp
->nargs
>= 0; stp
++)
107 if (stp
->name
&& strcmp(stp
->name
, name
) == 0)
111 const struct sysalias
*sap
= sysalias
;
112 for (; sys
== 0 && sap
->name
; sap
++)
113 if (strcmp(sap
->name
, name
) == 0)
116 if (sys
> 0 && sys
<= PRMAXSYS
) {
118 case SYS_fstatat
: /* set both if either */
121 sys64
= SYS_fstatat64
;
124 case SYS_stat
: /* set all if either */
129 sysxx
= SYS_fstatat64
;
132 case SYS_lstat
: /* set all if either */
137 sysxx
= SYS_fstatat64
;
140 case SYS_fstat
: /* set all if either */
145 sysxx
= SYS_fstatat64
;
148 case SYS_getdents
: /* set both if either */
151 sys64
= SYS_getdents64
;
154 case SYS_mmap
: /* set both if either */
160 case SYS_statvfs
: /* set both if either */
163 sys64
= SYS_statvfs64
;
166 case SYS_fstatvfs
: /* set both if either */
169 sys64
= SYS_fstatvfs64
;
172 case SYS_setrlimit
: /* set both if either */
173 case SYS_setrlimit64
:
175 sys64
= SYS_setrlimit64
;
178 case SYS_getrlimit
: /* set both if either */
179 case SYS_getrlimit64
:
181 sys64
= SYS_getrlimit64
;
184 case SYS_pread
: /* set both if either */
190 case SYS_pwrite
: /* set both if either */
193 sys64
= SYS_pwrite64
;
196 case SYS_openat
: /* set all if any */
201 sys64
= SYS_openat64
;
206 case SYS_forksys
: /* set both if either */
212 case SYS_sigprocmask
: /* set both if either */
213 case SYS_lwp_sigmask
:
214 sysx
= SYS_sigprocmask
;
215 sys
= SYS_lwp_sigmask
;
218 case SYS_lseek
: /* set both if either */
224 case SYS_rename
: /* set both */
228 case SYS_link
: /* set both */
232 case SYS_unlink
: /* set both */
233 case SYS_rmdir
: /* set both */
237 case SYS_symlink
: /* set both */
238 sysx
= SYS_symlinkat
;
241 case SYS_readlink
: /* set both */
242 sysx
= SYS_readlinkat
;
245 case SYS_chmod
: /* set both */
246 case SYS_fchmod
: /* set both */
250 case SYS_chown
: /* set both */
251 case SYS_lchown
: /* set both */
252 case SYS_fchown
: /* set both */
256 case SYS_mkdir
: /* set both */
260 case SYS_mknod
: /* set both */
264 case SYS_access
: /* set both */
265 sysx
= SYS_faccessat
;
273 prdelset(setp
, sysx
);
275 prdelset(setp
, sysxx
);
277 prdelset(setp
, sys64
);
281 praddset(setp
, sysx
);
283 praddset(setp
, sysxx
);
285 praddset(setp
, sys64
);
289 } else if (strcmp(name
, "all") == 0 ||
290 strcmp(name
, "ALL") == 0) {
297 (void) fprintf(stderr
,
298 "%s: unrecognized syscall: %s\n",
308 * List of signals to trace.
309 * Return 0 on success, != 0 on any failure.
312 siglist(private_t
*pri
,
313 char *str
, /* string of signal names */
314 sigset_t
*setp
, /* signal set */
315 int *fp
) /* first-time flag */
323 name
= strtok_r(str
, sepr
, &lasts
);
325 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
328 name
= strtok_r(NULL
, sepr
, &lasts
);
329 } else if (!*fp
) { /* first time, clear the set */
334 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
338 if (*name
== '!') { /* exclude remainder from set */
340 while (*++name
== '!')
346 sig
= strtol(name
, &next
, 0);
347 if (sig
<= 0 || sig
> PRMAXSIG
|| *next
!= '\0') {
348 for (sig
= 1; sig
<= PRMAXSIG
; sig
++) {
349 const char *sname
= rawsigname(pri
, sig
);
352 if (strcmp(sname
, name
) == 0 ||
353 strcmp(sname
+3, name
) == 0)
359 if (sig
> 0 && sig
<= PRMAXSIG
) {
365 } else if (strcmp(name
, "ALL") == 0) {
372 (void) fprintf(stderr
,
373 "%s: unrecognized signal name/number: %s\n",
383 * List of faults to trace.
384 * return 0 on success, != 0 on any failure.
387 fltlist(char *str
, /* string of fault names */
388 fltset_t
*setp
, /* fault set */
389 int *fp
) /* first-time flag */
397 name
= strtok_r(str
, sepr
, &lasts
);
399 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
402 name
= strtok_r(NULL
, sepr
, &lasts
);
403 } else if (!*fp
) { /* first time, clear the set */
408 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
412 if (*name
== '!') { /* exclude remainder from set */
414 while (*++name
== '!')
420 flt
= strtol(name
, &next
, 0);
421 if (flt
<= 0 || flt
> PRMAXFAULT
|| *next
!= '\0') {
422 for (flt
= 1; flt
<= PRMAXFAULT
; flt
++) {
425 if (proc_fltname(flt
, fname
,
426 sizeof (fname
)) == NULL
)
429 if (strcmp(fname
, name
) == 0 ||
430 strcmp(fname
+3, name
) == 0)
433 if (flt
> PRMAXFAULT
)
436 if (flt
> 0 && flt
<= PRMAXFAULT
) {
442 } else if (strcmp(name
, "ALL") == 0) {
449 (void) fprintf(stderr
,
450 "%s: unrecognized fault name/number: %s\n",
460 * Gather file descriptors to dump.
461 * Return 0 on success, != 0 on any failure.
464 fdlist(char *str
, /* string of filedescriptors */
465 fileset_t
*setp
) /* set of boolean flags */
473 name
= strtok_r(str
, sepr
, &lasts
);
475 if (name
!= NULL
&& *name
== '!') { /* exclude from set */
478 name
= strtok_r(NULL
, sepr
, &lasts
);
481 for (; name
; name
= strtok_r(NULL
, sepr
, &lasts
)) {
485 if (*name
== '!') { /* exclude remainder from set */
487 while (*++name
== '!')
493 fd
= strtol(name
, &next
, 0);
494 if (fd
>= 0 && fd
< NOFILES_MAX
&& *next
== '\0') {
501 } else if (strcmp(name
, "ALL") == 0) {
508 (void) fprintf(stderr
,
509 "%s: filedescriptor not in range[0..%d]: %s\n",
510 command
, NOFILES_MAX
-1, name
);
523 while ((c
= *str
) != '\0')
528 * 'arg' points to a string like:
529 * libc,libnsl,... : printf,read,write,...
531 * libc,libnsl,... :: printf,read,write,...
532 * with possible filename pattern-matching metacharacters.
534 * Assumption: No library or function name can contain ',' or ':'.
537 liblist(char *arg
, int hang
)
539 const char *star
= "*";
546 /* append a new dynpat structure to the end of the Dynpat list */
547 Dyp
= my_malloc(sizeof (struct dynpat
), NULL
);
550 Dynpat
= Lastpat
= Dyp
;
555 Dyp
->flag
= hang
? BPT_HANG
: 0;
556 Dyp
->exclude_lib
= 0;
562 * Find the beginning of the filename patterns
563 * and null-terminate the library name patterns.
565 if ((fpat
= strchr(arg
, ':')) != NULL
)
569 * Library name patterns.
571 pat
= strtok_r(arg
, sepr
, &lasts
);
573 /* '!' introduces an exclusion list */
574 if (pat
!= NULL
&& *pat
== '!') {
575 Dyp
->exclude_lib
= 1;
576 pat
+= strspn(pat
, "!");
578 pat
= strtok_r(NULL
, sepr
, &lasts
);
579 /* force exclusion of all functions as well */
586 /* empty list means all libraries */
587 Dyp
->libpat
= my_malloc(sizeof (char *), NULL
);
588 Dyp
->libpat
[0] = star
;
592 * We are now at the library list.
593 * Generate the list and count the library name patterns.
596 Dyp
->libpat
= my_malloc(maxpat
* sizeof (char *), NULL
);
598 Dyp
->libpat
[Dyp
->nlibpat
++] = pat
;
599 while ((pat
= strtok_r(NULL
, sepr
, &lasts
)) != NULL
) {
600 if (Dyp
->nlibpat
== maxpat
) {
602 Dyp
->libpat
= my_realloc(Dyp
->libpat
,
603 maxpat
* sizeof (char *), NULL
);
605 Dyp
->libpat
[Dyp
->nlibpat
++] = pat
;
610 * Function name patterns.
616 * We have already seen a ':'. Look for another.
617 * Double ':' means trace internal calls.
619 fpat
+= strspn(fpat
, white
);
624 pat
= strtok_r(fpat
, csepr
, &lasts
);
627 /* '!' introduces an exclusion list */
628 if (pat
!= NULL
&& *pat
== '!') {
631 pat
+= strspn(pat
, "!");
633 pat
= strtok_r(NULL
, sepr
, &lasts
);
637 /* empty function list means exclude all functions */
638 Dyp
->sympat
= my_malloc(sizeof (char *), NULL
);
639 Dyp
->sympat
[0] = star
;
643 * We are now at the function list.
644 * Generate the list and count the symbol name patterns.
647 Dyp
->sympat
= my_malloc(maxpat
* sizeof (char *), NULL
);
649 Dyp
->sympat
[Dyp
->nsympat
++] = pat
;
650 while ((pat
= strtok_r(NULL
, sepr
, &lasts
)) != NULL
) {
651 if (Dyp
->nsympat
== maxpat
) {
653 Dyp
->sympat
= my_realloc(Dyp
->sympat
,
654 maxpat
* sizeof (char *), NULL
);
656 Dyp
->sympat
[Dyp
->nsympat
++] = pat
;