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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <stdio_ext.h>
35 #include <sys/types.h>
39 /* evil knowledge of libc internals */
40 #include "../../../lib/libc/inc/thr_uberdata.h"
42 #define MAX_SYMNAMLEN 1024 /* Recommended max symbol name length */
44 static char *sigflags(int, int);
45 static int look(char *);
46 static void perr(char *);
47 static int usage(void);
48 static uintptr_t deinterpose(int, void *, psinfo_t
*, struct sigaction
*);
51 static char *procname
;
52 static int all_flag
= 0;
53 static int lookuphandlers_flag
= 1;
56 main(int argc
, char **argv
)
62 if ((command
= strrchr(argv
[0], '/')) != NULL
)
67 while ((c
= getopt(argc
, argv
, "an")) != EOF
) {
73 lookuphandlers_flag
= 0;
80 if (argc
- optind
< 1) {
85 * Make sure we'll have enough file descriptors to handle a target
86 * that has many many mappings.
88 if (getrlimit(RLIMIT_NOFILE
, &rlim
) == 0) {
89 rlim
.rlim_cur
= rlim
.rlim_max
;
90 (void) setrlimit(RLIMIT_NOFILE
, &rlim
);
91 (void) enable_extended_FILE_stdio(-1, -1);
94 for (; optind
!= argc
; optind
++) {
95 rc
+= look(argv
[optind
]);
104 (void) fprintf(stderr
, "usage:\t%s [-n] pid ...\n", command
);
105 (void) fprintf(stderr
, " (report process signal actions)\n");
111 uberdata_addr(struct ps_prochandle
*Pr
, char dmodel
)
115 if (Plookup_by_name(Pr
, "libc.so", "_tdb_bootstrap", &sym
) < 0)
116 return ((uintptr_t)NULL
);
118 if (dmodel
!= PR_MODEL_NATIVE
) {
122 if (Pread(Pr
, &addr
, sizeof (addr
), sym
.st_value
)
125 Pread(Pr
, &uaddr
, sizeof (uaddr
), (uintptr_t)addr
)
128 return ((uintptr_t)uaddr
);
131 if (dmodel
== PR_MODEL_NATIVE
) {
135 if (Pread(Pr
, &addr
, sizeof (addr
), sym
.st_value
)
138 Pread(Pr
, &uaddr
, sizeof (uaddr
), addr
)
143 if (Plookup_by_name(Pr
, "libc.so", "_uberdata", &sym
) < 0)
145 return (sym
.st_value
);
149 * Iterator function used to generate the process sigmask
150 * from the individual lwp sigmasks.
153 lwp_iter(void *cd
, const lwpstatus_t
*lwpstatus
)
157 ssp
->__sigbits
[0] &= lwpstatus
->pr_lwphold
.__sigbits
[0];
158 ssp
->__sigbits
[1] &= lwpstatus
->pr_lwphold
.__sigbits
[1];
159 ssp
->__sigbits
[2] &= lwpstatus
->pr_lwphold
.__sigbits
[2];
160 ssp
->__sigbits
[3] &= lwpstatus
->pr_lwphold
.__sigbits
[3];
163 * Return non-zero to terminate the iteration
164 * if the sigmask has become all zeros.
166 return ((ssp
->__sigbits
[0] | ssp
->__sigbits
[1] |
167 ssp
->__sigbits
[2] | ssp
->__sigbits
[3]) == 0);
179 struct sigaction
*action
= NULL
;
181 const psinfo_t
*psinfop
;
182 struct ps_prochandle
*Pr
= NULL
;
190 procname
= arg
; /* for perr() */
191 if ((Pr
= proc_arg_grab(arg
, PR_ARG_PIDS
, PGRAB_RDONLY
|PGRAB_FORCE
,
192 &gcode
)) == NULL
|| (psinfop
= Ppsinfo(Pr
)) == NULL
) {
193 (void) fprintf(stderr
, "%s: cannot examine %s: %s\n",
194 command
, arg
, Pgrab_error(gcode
));
197 (void) memcpy(&psinfo
, psinfop
, sizeof (psinfo_t
));
198 proc_unctrl_psinfo(&psinfo
);
200 (void) sprintf(pathname
, "/proc/%d/sigact", (int)psinfo
.pr_pid
);
201 if ((fd
= open(pathname
, O_RDONLY
)) < 0) {
206 if (fstat(fd
, &statb
) != 0) {
207 perr("fstat sigact");
210 maxsig
= statb
.st_size
/ sizeof (struct sigaction
);
211 action
= malloc(maxsig
* sizeof (struct sigaction
));
212 if (action
== NULL
) {
213 (void) fprintf(stderr
,
214 "%s: cannot malloc() space for %d sigaction structures\n",
218 if (read(fd
, (char *)action
, maxsig
* sizeof (struct sigaction
)) !=
219 maxsig
* sizeof (struct sigaction
)) {
226 (void) printf("%d:\t%.70s\n", (int)psinfo
.pr_pid
, psinfo
.pr_psargs
);
228 (void) sigfillset(&holdmask
);
229 (void) Plwp_iter(Pr
, lwp_iter
, &holdmask
);
231 if ((uberaddr
= uberdata_addr(Pr
, psinfo
.pr_dmodel
)) == 0) {
237 if (psinfo
.pr_dmodel
!= PR_MODEL_NATIVE
) {
239 aharraddr
= uberaddr
+
240 offsetof(uberdata32_t
, siguaction
);
241 aharrlen
= sizeof (siguaction32_t
) * NSIG
;
242 (void) Pread(Pr
, &addr
, sizeof (addr
),
243 uberaddr
+ offsetof(uberdata32_t
, sigacthandler
));
244 intfnaddr
= (uintptr_t)addr
;
248 aharraddr
= uberaddr
+
249 offsetof(uberdata_t
, siguaction
);
250 aharrlen
= sizeof (siguaction_t
) * NSIG
;
251 (void) Pread(Pr
, &intfnaddr
, sizeof (intfnaddr
),
252 uberaddr
+ offsetof(uberdata_t
, sigacthandler
));
257 aharr
= malloc(aharrlen
);
259 (void) fprintf(stderr
,
260 "%s: cannot malloc() space for actual handler array\n",
265 if (Pread(Pr
, aharr
, aharrlen
, aharraddr
) != aharrlen
) {
266 (void) fprintf(stderr
,
267 "%s: signal handler data at %p cannot be read.\n",
268 command
, (void *)aharraddr
);
274 for (sig
= 1; sig
<= maxsig
; sig
++) {
275 struct sigaction
*sp
= &action
[sig
- 1];
277 char buf
[SIG2STR_MAX
];
280 /* proc_signame() returns "SIG..."; skip the "SIG" part */
281 (void) printf("%s\t", proc_signame(sig
, buf
, sizeof (buf
)) + 3);
283 if (prismember(&holdmask
, sig
))
284 (void) printf("blocked,");
286 if (sp
->sa_handler
== SIG_DFL
)
287 (void) printf("default");
288 else if (sp
->sa_handler
== SIG_IGN
)
289 (void) printf("ignored");
293 if (caught
|| all_flag
) {
296 char hname
[MAX_SYMNAMLEN
];
297 char buf
[PRSIGBUFSZ
];
299 haddr
= (uintptr_t)sp
->sa_handler
;
301 if (aharr
&& intfnaddr
&& haddr
== intfnaddr
)
302 haddr
= deinterpose(sig
, aharr
, &psinfo
, sp
);
304 if (haddr
== (uintptr_t)SIG_DFL
) {
306 (void) printf("default");
308 } else if (haddr
== (uintptr_t)SIG_IGN
) {
310 (void) printf("ignored");
314 (void) printf("caught");
317 if (caught
|| all_flag
) {
318 if (lookuphandlers_flag
&& haddr
> 1 &&
319 Plookup_by_addr(Pr
, haddr
, hname
,
320 sizeof (hname
), &hsym
) == 0)
321 (void) printf("\t%-8s", hname
);
323 (void) printf("\t0x%-8lx",
326 s
= sigflags(sig
, sp
->sa_flags
);
327 (void) printf("%s", (*s
!= '\0')? s
: "\t0");
328 (void) proc_sigset2str(&sp
->sa_mask
, ",", 1,
331 (void) printf("\t%s", buf
);
333 } else if (sig
== SIGCLD
) {
335 sp
->sa_flags
& (SA_NOCLDWAIT
|SA_NOCLDSTOP
));
337 (void) printf("\t\t%s", s
);
358 (void) fprintf(stderr
, "%s: ", procname
);
365 sigflags(int sig
, int flags
)
367 static char code_buf
[100];
368 char *str
= code_buf
;
370 (SA_ONSTACK
|SA_RESETHAND
|SA_RESTART
|SA_SIGINFO
|SA_NODEFER
);
373 flagmask
|= (SA_NOCLDSTOP
|SA_NOCLDWAIT
);
376 if (flags
& ~flagmask
)
377 (void) sprintf(str
, ",0x%x,", flags
& ~flagmask
);
381 if (flags
& SA_RESTART
)
382 (void) strcat(str
, ",RESTART");
383 if (flags
& SA_RESETHAND
)
384 (void) strcat(str
, ",RESETHAND");
385 if (flags
& SA_ONSTACK
)
386 (void) strcat(str
, ",ONSTACK");
387 if (flags
& SA_SIGINFO
)
388 (void) strcat(str
, ",SIGINFO");
389 if (flags
& SA_NODEFER
)
390 (void) strcat(str
, ",NODEFER");
393 if (flags
& SA_NOCLDWAIT
)
394 (void) strcat(str
, ",NOCLDWAIT");
395 if (flags
& SA_NOCLDSTOP
)
396 (void) strcat(str
, ",NOCLDSTOP");
406 deinterpose(int sig
, void *aharr
, psinfo_t
*psinfo
, struct sigaction
*sp
)
408 if (sp
->sa_handler
== SIG_DFL
|| sp
->sa_handler
== SIG_IGN
)
409 return ((uintptr_t)sp
->sa_handler
);
411 if (psinfo
->pr_dmodel
!= PR_MODEL_NATIVE
) {
412 struct sigaction32
*sa32
= (struct sigaction32
*)
413 ((uintptr_t)aharr
+ sig
* sizeof (siguaction32_t
) +
414 offsetof(siguaction32_t
, sig_uaction
));
416 sp
->sa_flags
= sa32
->sa_flags
;
417 sp
->sa_handler
= (void (*)())(uintptr_t)sa32
->sa_handler
;
418 (void) memcpy(&sp
->sa_mask
, &sa32
->sa_mask
,
419 sizeof (sp
->sa_mask
));
423 struct sigaction
*sa
= (struct sigaction
*)
424 ((uintptr_t)aharr
+ sig
* sizeof (siguaction_t
) +
425 offsetof(siguaction_t
, sig_uaction
));
427 sp
->sa_flags
= sa
->sa_flags
;
428 sp
->sa_handler
= sa
->sa_handler
;
429 sp
->sa_mask
= sa
->sa_mask
;
431 return ((uintptr_t)sp
->sa_handler
);