xref: /illumos-gate/usr/src/cmd/ptools/pstack/pstack.c (revision e00bdde3c6d406f40f53f3025defadc22f7ec31a)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * Copyright 2018 Joyent, Inc.
26  * Copyright 2024 Bill Sommerfeld <sommerfeld@hamachi.org>
27  */
28 
29 #include <sys/isa_defs.h>
30 
31 #include <stdio.h>
32 #include <stdio_ext.h>
33 #include <fcntl.h>
34 #include <ctype.h>
35 #include <string.h>
36 #include <signal.h>
37 #include <dirent.h>
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/stack.h>
45 #include <link.h>
46 #include <limits.h>
47 #include <libelf.h>
48 #include <thread_db.h>
49 #include <libproc.h>
50 #include <setjmp.h>
51 
52 static	char	*command;
53 static	int	Fflag;
54 static	int	is64;
55 static	GElf_Sym sigh;
56 
57 /*
58  * To keep the list of user-level threads for a multithreaded process.
59  */
60 struct threadinfo {
61 	struct threadinfo *next;
62 	id_t	threadid;
63 	id_t	lwpid;
64 	td_thr_state_e state;
65 	uintptr_t startfunc;
66 	uintptr_t exitval;
67 	prgregset_t regs;
68 };
69 
70 static struct threadinfo *thr_head, *thr_tail;
71 
72 #define	TRUE	1
73 #define	FALSE	0
74 
75 #define	MAX_ARGS	8
76 
77 /*
78  * To support debugging java programs, we display java frames within a stack.
79  * The logic to walk the java frames is contained in libjvm_db.so, which is
80  * found in the same directory as libjvm.so, linked with the program.  If we are
81  * debugging a 32-bit app with a 64-binary, then the debugging library is found
82  * in the '64' subdirectory.  If we find libjvm_db.so, then we fill in these
83  * stub routines.
84  */
85 typedef struct jvm_agent jvm_agent_t;
86 typedef int java_stack_f(void *, prgregset_t, const char *, int, int, void *);
87 
88 /*
89  * The j_agent_create function takes a version parameter.  This ensures that the
90  * interface can evolve appropriately.
91  */
92 #define	JVM_DB_VERSION	1
93 static void *libjvm;
94 typedef jvm_agent_t *(*j_agent_create_f)(struct ps_prochandle *, int);
95 typedef void (*j_agent_destroy_f)(jvm_agent_t *);
96 typedef int (*j_frame_iter_f)(jvm_agent_t *, prgregset_t, java_stack_f *,
97     void *);
98 
99 static j_agent_create_f j_agent_create;
100 static j_agent_destroy_f j_agent_destroy;
101 static j_frame_iter_f j_frame_iter;
102 
103 static jvm_agent_t *load_libjvm(struct ps_prochandle *P);
104 static void reset_libjvm(jvm_agent_t *);
105 
106 /*
107  * Similar to what's done for debugging java programs, here are prototypes for
108  * the library that allows us to debug Python programs.
109  */
110 #define	PYDB_VERSION	1
111 static void *libpython;
112 
113 typedef struct pydb_agent pydb_agent_t;
114 
115 typedef pydb_agent_t *(*pydb_agent_create_f)(struct ps_prochandle *P, int vers);
116 typedef void (*pydb_agent_destroy_f)(pydb_agent_t *py);
117 typedef int (*pydb_pc_frameinfo_f)(pydb_agent_t *py, uintptr_t pc,
118     uintptr_t frame_addr, char *fbuf, size_t bufsz);
119 typedef int (*pydb_pc_frameinfo_argv_f)(pydb_agent_t *py, uintptr_t pc,
120     const long *argv, char *fbuf, size_t bufsz);
121 
122 static pydb_agent_create_f pydb_agent_create;
123 static pydb_agent_destroy_f pydb_agent_destroy;
124 static pydb_pc_frameinfo_f pydb_pc_frameinfo;
125 static pydb_pc_frameinfo_argv_f pydb_pc_frameinfo_argv;
126 
127 static pydb_agent_t *load_libpython(struct ps_prochandle *P);
128 static void reset_libpython(pydb_agent_t *);
129 /*
130  * Since we must maintain both a proc handle and a jvm handle, this structure
131  * is the basic type that gets passed around.
132  */
133 typedef struct pstack_handle {
134 	struct ps_prochandle *proc;
135 	jvm_agent_t *jvm;
136 	int ignore_frame;
137 	const char *lwps;
138 	int count;
139 	pydb_agent_t *pydb;
140 } pstack_handle_t;
141 
142 static	int	thr_stack(const td_thrhandle_t *, void *);
143 static	void	free_threadinfo(void);
144 static	struct threadinfo *find_thread(id_t);
145 static	int	all_call_stacks(pstack_handle_t *, int);
146 static	void	tlhead(id_t, id_t, const char *);
147 static	int	print_frame(void *, prgregset_t, uint_t, const long *);
148 static	void	print_zombie(struct ps_prochandle *, struct threadinfo *);
149 static	void	print_syscall(const lwpstatus_t *, prgregset_t);
150 static	void	call_stack(pstack_handle_t *, const lwpstatus_t *);
151 
152 /*
153  * The number of active and zombie threads.
154  */
155 static	int	nthreads;
156 
157 int
158 main(int argc, char **argv)
159 {
160 	int retc = 0;
161 	int opt;
162 	int errflg = FALSE;
163 	core_content_t content = CC_CONTENT_DATA | CC_CONTENT_ANON |
164 	    CC_CONTENT_STACK;
165 	struct rlimit rlim;
166 
167 	if ((command = strrchr(argv[0], '/')) != NULL)
168 		command++;
169 	else
170 		command = argv[0];
171 
172 	/* options */
173 	while ((opt = getopt(argc, argv, "F")) != EOF) {
174 		switch (opt) {
175 		case 'F':
176 			/*
177 			 * If the user specifies the force option, we'll
178 			 * consent to printing out other threads' stacks
179 			 * even if the main stack is absent.
180 			 */
181 			content &= ~CC_CONTENT_STACK;
182 			Fflag = PGRAB_FORCE;
183 			break;
184 		default:
185 			errflg = TRUE;
186 			break;
187 		}
188 	}
189 
190 	argc -= optind;
191 	argv += optind;
192 
193 	if (errflg || argc <= 0) {
194 		(void) fprintf(stderr,
195 		    "usage:\t%s [-F] { pid | core }[/lwps] ...\n", command);
196 		(void) fprintf(stderr, "  (show process call stack)\n");
197 		(void) fprintf(stderr,
198 		    "  -F: force grabbing of the target process\n");
199 		exit(2);
200 	}
201 
202 	/*
203 	 * Make sure we'll have enough file descriptors to handle a target
204 	 * that has many many mappings.
205 	 */
206 	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
207 		rlim.rlim_cur = rlim.rlim_max;
208 		(void) setrlimit(RLIMIT_NOFILE, &rlim);
209 		(void) enable_extended_FILE_stdio(-1, -1);
210 	}
211 
212 	(void) proc_initstdio();
213 
214 	while (--argc >= 0) {
215 		int gcode;
216 		psinfo_t psinfo;
217 		const psinfo_t *tpsinfo;
218 		struct ps_prochandle *Pr = NULL;
219 		td_thragent_t *Tap;
220 		int threaded;
221 		pstack_handle_t handle;
222 		const char *lwps, *arg;
223 
224 		(void) proc_flushstdio();
225 
226 		arg = *argv++;
227 
228 		if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_ANY,
229 		    Fflag, &gcode, &lwps)) == NULL) {
230 			(void) fprintf(stderr, "%s: cannot examine %s: %s\n",
231 			    command, arg, Pgrab_error(gcode));
232 			retc++;
233 			continue;
234 		}
235 
236 		if ((tpsinfo = Ppsinfo(Pr)) == NULL) {
237 			(void) fprintf(stderr, "%s: cannot examine %s: "
238 			    "lost control of process\n", command, arg);
239 			Prelease(Pr, 0);
240 			retc++;
241 			continue;
242 		}
243 		(void) memcpy(&psinfo, tpsinfo, sizeof (psinfo_t));
244 		proc_unctrl_psinfo(&psinfo);
245 
246 		if (Pstate(Pr) == PS_DEAD) {
247 			if ((Pcontent(Pr) & content) != content) {
248 				(void) fprintf(stderr, "%s: core '%s' has "
249 				    "insufficient content\n", command, arg);
250 				retc++;
251 				continue;
252 			}
253 			(void) printf("core '%s' of %d:\t%.70s\n",
254 			    arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
255 		} else {
256 			(void) printf("%d:\t%.70s\n",
257 			    (int)psinfo.pr_pid, psinfo.pr_psargs);
258 		}
259 
260 		is64 = (psinfo.pr_dmodel == PR_MODEL_LP64);
261 
262 		if (Pgetauxval(Pr, AT_BASE) != -1L && Prd_agent(Pr) == NULL) {
263 			(void) fprintf(stderr, "%s: warning: librtld_db failed "
264 			    "to initialize; symbols from shared libraries will "
265 			    "not be available\n", command);
266 		}
267 
268 		/*
269 		 * First we need to get a thread agent handle.
270 		 */
271 		if (td_init() != TD_OK ||
272 		    td_ta_new(Pr, &Tap) != TD_OK)	/* no libc */
273 			threaded = FALSE;
274 		else {
275 			/*
276 			 * Iterate over all threads, calling:
277 			 *   thr_stack(td_thrhandle_t *Thp, NULL);
278 			 * for each one to generate the list of threads.
279 			 */
280 			nthreads = 0;
281 			(void) td_ta_thr_iter(Tap, thr_stack, NULL,
282 			    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
283 			    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
284 
285 			(void) td_ta_delete(Tap);
286 			threaded = TRUE;
287 		}
288 
289 		handle.proc = Pr;
290 		handle.jvm = load_libjvm(Pr);
291 		handle.pydb = load_libpython(Pr);
292 		handle.lwps = lwps;
293 		handle.count = 0;
294 
295 		if (all_call_stacks(&handle, threaded) != 0)
296 			retc++;
297 		if (threaded)
298 			free_threadinfo();
299 
300 		reset_libjvm(handle.jvm);
301 		reset_libpython(handle.pydb);
302 		Prelease(Pr, 0);
303 
304 		if (handle.count == 0)
305 			(void) fprintf(stderr, "%s: no matching LWPs found\n",
306 			    command);
307 	}
308 
309 	(void) proc_finistdio();
310 
311 	return (retc);
312 }
313 
314 /*
315  * Thread iteration call-back function.
316  * Called once for each user-level thread.
317  * Used to build the list of all threads.
318  */
319 /* ARGSUSED1 */
320 static int
321 thr_stack(const td_thrhandle_t *Thp, void *cd)
322 {
323 	td_thrinfo_t thrinfo;
324 	struct threadinfo *tip;
325 	td_err_e error;
326 
327 	if (td_thr_get_info(Thp, &thrinfo) != TD_OK)
328 		return (0);
329 
330 	tip = malloc(sizeof (struct threadinfo));
331 	tip->next = NULL;
332 	tip->threadid = thrinfo.ti_tid;
333 	tip->lwpid = thrinfo.ti_lid;
334 	tip->state = thrinfo.ti_state;
335 	tip->startfunc = thrinfo.ti_startfunc;
336 	tip->exitval = (uintptr_t)thrinfo.ti_exitval;
337 	nthreads++;
338 
339 	if (thrinfo.ti_state == TD_THR_ZOMBIE ||
340 	    ((error = td_thr_getgregs(Thp, tip->regs)) != TD_OK &&
341 	    error != TD_PARTIALREG))
342 		(void) memset(tip->regs, 0, sizeof (prgregset_t));
343 
344 	if (thr_tail)
345 		thr_tail->next = tip;
346 	else
347 		thr_head = tip;
348 	thr_tail = tip;
349 
350 	return (0);
351 }
352 
353 static void
354 free_threadinfo()
355 {
356 	struct threadinfo *tip = thr_head;
357 	struct threadinfo *next;
358 
359 	while (tip) {
360 		next = tip->next;
361 		free(tip);
362 		tip = next;
363 	}
364 
365 	thr_head = thr_tail = NULL;
366 }
367 
368 /*
369  * Find and eliminate the thread corresponding to the given lwpid.
370  */
371 static struct threadinfo *
372 find_thread(id_t lwpid)
373 {
374 	struct threadinfo *tip;
375 
376 	for (tip = thr_head; tip; tip = tip->next) {
377 		if (lwpid == tip->lwpid) {
378 			tip->lwpid = 0;
379 			return (tip);
380 		}
381 	}
382 	return (NULL);
383 }
384 
385 static int
386 thread_call_stack(void *data, const lwpstatus_t *psp,
387     const lwpsinfo_t *pip)
388 {
389 	char lwpname[THREAD_NAME_MAX] = "";
390 	pstack_handle_t *h = data;
391 	lwpstatus_t lwpstatus;
392 	struct threadinfo *tip;
393 
394 	if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid))
395 		return (0);
396 	h->count++;
397 
398 	if ((tip = find_thread(pip->pr_lwpid)) == NULL)
399 		return (0);
400 
401 	(void) Plwp_getname(h->proc, pip->pr_lwpid,
402 	    lwpname, sizeof (lwpname));
403 
404 	tlhead(tip->threadid, pip->pr_lwpid, lwpname);
405 	tip->threadid = 0;	/* finish eliminating tid */
406 	if (psp)
407 		call_stack(h, psp);
408 	else {
409 		if (tip->state == TD_THR_ZOMBIE)
410 			print_zombie(h->proc, tip);
411 		else {
412 			(void) memset(&lwpstatus, 0, sizeof (lwpstatus));
413 			(void) memcpy(lwpstatus.pr_reg, tip->regs,
414 			    sizeof (prgregset_t));
415 			call_stack(h, &lwpstatus);
416 		}
417 	}
418 	return (0);
419 }
420 
421 static int
422 lwp_call_stack(void *data,
423     const lwpstatus_t *psp, const lwpsinfo_t *pip)
424 {
425 	char lwpname[THREAD_NAME_MAX] = "";
426 	pstack_handle_t *h = data;
427 
428 	if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid))
429 		return (0);
430 	h->count++;
431 
432 	(void) Plwp_getname(h->proc, pip->pr_lwpid,
433 	    lwpname, sizeof (lwpname));
434 
435 	tlhead(0, pip->pr_lwpid, lwpname);
436 	if (psp)
437 		call_stack(h, psp);
438 	else
439 		(void) printf("\t** zombie "
440 		    "(exited, not detached, not yet joined) **\n");
441 	return (0);
442 }
443 
444 static int
445 all_call_stacks(pstack_handle_t *h, int dothreads)
446 {
447 	struct ps_prochandle *Pr = h->proc;
448 	pstatus_t status = *Pstatus(Pr);
449 
450 	(void) memset(&sigh, 0, sizeof (GElf_Sym));
451 	(void) Plookup_by_name(Pr, "libc.so", "sigacthandler", &sigh);
452 
453 	if ((status.pr_nlwp + status.pr_nzomb) <= 1 &&
454 	    !(dothreads && nthreads > 1)) {
455 		if (proc_lwp_in_set(h->lwps, status.pr_lwp.pr_lwpid)) {
456 			call_stack(h, &status.pr_lwp);
457 			h->count++;
458 		}
459 	} else {
460 		lwpstatus_t lwpstatus;
461 		struct threadinfo *tip;
462 		id_t tid;
463 
464 		if (dothreads)
465 			(void) Plwp_iter_all(Pr, thread_call_stack, h);
466 		else
467 			(void) Plwp_iter_all(Pr, lwp_call_stack, h);
468 
469 		/* for each remaining thread w/o an lwp */
470 		(void) memset(&lwpstatus, 0, sizeof (lwpstatus));
471 		for (tip = thr_head; tip; tip = tip->next) {
472 
473 			if (!proc_lwp_in_set(h->lwps, tip->lwpid))
474 				tip->threadid = 0;
475 
476 			if ((tid = tip->threadid) != 0) {
477 				(void) memcpy(lwpstatus.pr_reg, tip->regs,
478 				    sizeof (prgregset_t));
479 				tlhead(tid, tip->lwpid, NULL);
480 				if (tip->state == TD_THR_ZOMBIE)
481 					print_zombie(Pr, tip);
482 				else
483 					call_stack(h, &lwpstatus);
484 			}
485 			tip->threadid = 0;
486 			tip->lwpid = 0;
487 		}
488 	}
489 	return (0);
490 }
491 
492 /* The width of the header */
493 #define	HEAD_WIDTH	(62)
494 static void
495 tlhead(id_t threadid, id_t lwpid, const char *name)
496 {
497 	char buf[128] = { 0 };
498 	char num[16];
499 	ssize_t amt = 0;
500 	int i;
501 
502 	if (threadid == 0 && lwpid == 0)
503 		return;
504 
505 	if (lwpid > 0) {
506 		(void) snprintf(num, sizeof (num), "%d", (int)lwpid);
507 		(void) strlcat(buf, "thread# ", sizeof (buf));
508 		(void) strlcat(buf, num, sizeof (buf));
509 	}
510 
511 	if (threadid > 0) {
512 		(void) snprintf(num, sizeof (num), "%d", (int)threadid);
513 		if (lwpid > 0)
514 			(void) strlcat(buf, " / ", sizeof (buf));
515 		(void) strlcat(buf, "lwp# ", sizeof (buf));
516 		(void) strlcat(buf, num, sizeof (buf));
517 	}
518 
519 	if (name != NULL && strlen(name) > 0) {
520 		(void) strlcat(buf, " [", sizeof (buf));
521 		(void) strlcat(buf, name, sizeof (buf));
522 		(void) strlcat(buf, "]", sizeof (buf));
523 	}
524 
525 	amt = (HEAD_WIDTH - strlen(buf) - 2);
526 	if (amt < 4)
527 		amt = 4;
528 
529 	for (i = 0; i < amt / 2; i++)
530 		(void) putc('-', stdout);
531 	(void) printf(" %s ", buf);
532 	for (i = 0; i < (amt / 2) + (amt % 2); i++)
533 		(void) putc('-', stdout);
534 	(void) putc('\n', stdout);
535 }
536 
537 /*ARGSUSED*/
538 static int
539 print_java_frame(void *cld, prgregset_t gregs, const char *name, int bci,
540     int line, void *handle)
541 {
542 	int length = (is64 ? 16 : 8);
543 
544 	(void) printf(" %.*lx * %s", length, (long)gregs[R_PC], name);
545 
546 	if (bci != -1) {
547 		(void) printf("+%d", bci);
548 		if (line)
549 			(void) printf(" (line %d)", line);
550 	}
551 	(void) printf("\n");
552 
553 	return (0);
554 }
555 
556 static sigjmp_buf jumpbuf;
557 
558 /*ARGSUSED*/
559 static void
560 fatal_signal(int signo)
561 {
562 	siglongjmp(jumpbuf, 1);
563 }
564 
565 static int
566 print_frame(void *cd, prgregset_t gregs, uint_t argc, const long *argv)
567 {
568 	pstack_handle_t *h = cd;
569 	struct ps_prochandle *Pr = h->proc;
570 	uintptr_t pc = gregs[R_PC];
571 	char buff[255];
572 	GElf_Sym sym;
573 	uintptr_t start;
574 	int length = (is64? 16 : 8);
575 	int i;
576 
577 	/*
578 	 * If we are in a system call, we display the entry frame in a more
579 	 * readable manner, using the name of the system call.  In this case, we
580 	 * want to ignore this first frame, since we already displayed it
581 	 * separately.
582 	 */
583 	if (h->ignore_frame) {
584 		h->ignore_frame = 0;
585 		return (0);
586 	}
587 
588 	(void) sprintf(buff, "%.*lx", length, (long)pc);
589 	(void) strcpy(buff + length, " ????????");
590 	if (Plookup_by_addr(Pr, pc,
591 	    buff + 1 + length, sizeof (buff) - 1 - length, &sym) == 0) {
592 		start = sym.st_value;
593 	} else if (h->jvm != NULL) {
594 		int ret;
595 		void (*segv)(int), (*bus)(int), (*ill)(int);
596 
597 		segv = signal(SIGSEGV, fatal_signal);
598 		bus = signal(SIGBUS, fatal_signal);
599 		ill = signal(SIGILL, fatal_signal);
600 
601 		/* Insure against a bad libjvm_db */
602 		if (sigsetjmp(jumpbuf, 0) == 0)
603 			ret = j_frame_iter(h->jvm, gregs, print_java_frame,
604 			    NULL);
605 		else
606 			ret = -1;
607 
608 		(void) signal(SIGSEGV, segv);
609 		(void) signal(SIGBUS, bus);
610 		(void) signal(SIGILL, ill);
611 
612 		if (ret == 0)
613 			return (ret);
614 	} else {
615 		start = pc;
616 	}
617 
618 	(void) printf(" %-17s (", buff);
619 	for (i = 0; i < argc && i < MAX_ARGS; i++)
620 		(void) printf((i+1 == argc) ? "%lx" : "%lx, ", argv[i]);
621 	if (i != argc)
622 		(void) printf("...");
623 	(void) printf((start != pc) ? ") + %lx\n" : ")\n", (long)(pc - start));
624 
625 	if (h->pydb != NULL && argc > 0) {
626 		char buf_py[1024];
627 		int rc;
628 		if (pydb_pc_frameinfo_argv != NULL) {
629 			rc = pydb_pc_frameinfo_argv(h->pydb, pc, argv, buf_py,
630 			    sizeof (buf_py));
631 		} else {
632 			rc = pydb_pc_frameinfo(h->pydb, pc, argv[0], buf_py,
633 			    sizeof (buf_py));
634 		}
635 		if (rc == 0) {
636 			(void) printf("   %s", buf_py);
637 		}
638 	}
639 
640 	/*
641 	 * If the frame's pc is in the "sigh" (a.k.a. signal handler, signal
642 	 * hack, or *sigh* ...) range, then we're about to cross a signal
643 	 * frame.  The signal number is the first argument to this function.
644 	 */
645 	if (pc - sigh.st_value < sigh.st_size) {
646 		if (sig2str((int)argv[0], buff) == -1)
647 			(void) strcpy(buff, " Unknown");
648 		(void) printf(" --- called from signal handler with "
649 		    "signal %d (SIG%s) ---\n", (int)argv[0], buff);
650 	}
651 
652 	return (0);
653 }
654 
655 static void
656 print_zombie(struct ps_prochandle *Pr, struct threadinfo *tip)
657 {
658 	char buff[255];
659 	GElf_Sym sym;
660 	uintptr_t start;
661 	int length = (is64? 16 : 8);
662 
663 	(void) sprintf(buff, "%.*lx", length, (long)tip->startfunc);
664 	(void) strcpy(buff + length, " ????????");
665 	if (Plookup_by_addr(Pr, tip->startfunc,
666 	    buff + 1 + length, sizeof (buff) - 1 - length, &sym) == 0)
667 		start = sym.st_value;
668 	else
669 		start = tip->startfunc;
670 	(void) printf(" %s()", buff);
671 	if (start != tip->startfunc)	/* doesn't happen? */
672 		(void) printf("+%lx", (long)(tip->startfunc - start));
673 	(void) printf(", exit value = 0x%.*lx\n", length, (long)tip->exitval);
674 	(void) printf("\t** zombie "
675 	    "(exited, not detached, not yet joined) **\n");
676 }
677 
678 static void
679 print_syscall(const lwpstatus_t *psp, prgregset_t reg)
680 {
681 	char sname[32];
682 	int length = (is64? 16 : 8);
683 	uint_t i;
684 
685 	(void) proc_sysname(psp->pr_syscall, sname, sizeof (sname));
686 	(void) printf(" %.*lx %-8s (", length, (long)reg[R_PC], sname);
687 	for (i = 0; i < psp->pr_nsysarg; i++)
688 		(void) printf((i+1 == psp->pr_nsysarg)? "%lx" : "%lx, ",
689 		    (long)psp->pr_sysarg[i]);
690 	(void) printf(")\n");
691 }
692 
693 static void
694 call_stack(pstack_handle_t *h, const lwpstatus_t *psp)
695 {
696 	prgregset_t reg;
697 
698 	(void) memcpy(reg, psp->pr_reg, sizeof (reg));
699 
700 	if ((psp->pr_flags & (PR_ASLEEP|PR_VFORKP)) ||
701 	    ((psp->pr_flags & PR_ISTOP) &&
702 	    (psp->pr_why == PR_SYSENTRY ||
703 	    psp->pr_why == PR_SYSEXIT))) {
704 		print_syscall(psp, reg);
705 		h->ignore_frame = 1;
706 	} else {
707 		h->ignore_frame = 0;
708 	}
709 
710 	(void) Pstack_iter(h->proc, reg, print_frame, h);
711 }
712 
713 /*ARGSUSED*/
714 static int
715 jvm_object_iter(void *cd, const prmap_t *pmp, const char *obj)
716 {
717 	char path[PATH_MAX];
718 	char *name;
719 	char *s1, *s2;
720 	struct ps_prochandle *Pr = cd;
721 
722 	if ((name = strstr(obj, "/libjvm.so")) == NULL)
723 		name = strstr(obj, "/libjvm_g.so");
724 
725 	if (name) {
726 		(void) strcpy(path, obj);
727 		if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
728 			s1 = name;
729 			s2 = path + (s1 - obj);
730 			(void) strcpy(s2, "/64");
731 			s2 += 3;
732 			(void) strcpy(s2, s1);
733 		}
734 
735 		s1 = strstr(obj, ".so");
736 		s2 = strstr(path, ".so");
737 		(void) strcpy(s2, "_db");
738 		s2 += 3;
739 		(void) strcpy(s2, s1);
740 
741 		if ((libjvm = dlopen(path, RTLD_LAZY|RTLD_GLOBAL)) != NULL)
742 			return (1);
743 	}
744 
745 	return (0);
746 }
747 
748 static jvm_agent_t *
749 load_libjvm(struct ps_prochandle *Pr)
750 {
751 	jvm_agent_t *ret;
752 
753 	/*
754 	 * Iterate through all the loaded objects in the target, looking
755 	 * for libjvm.so.  If we find libjvm.so we'll try to load the
756 	 * corresponding libjvm_db.so that lives in the same directory.
757 	 *
758 	 * At first glance it seems like we'd want to use
759 	 * Pobject_iter_resolved() here since we'd want to make sure that
760 	 * we have the full path to the libjvm.so.  But really, we don't
761 	 * want that since we're going to be dlopen()ing a library and
762 	 * executing code from that path, and therefore we don't want to
763 	 * load any library code that could be from a zone since it could
764 	 * have been replaced with a trojan.  Hence, we use Pobject_iter().
765 	 * So if we're debugging java processes in a zone from the global
766 	 * zone, and we want to get proper java stack stack frames, then
767 	 * the same jvm that is running within the zone needs to be
768 	 * installed in the global zone.
769 	 */
770 	(void) Pobject_iter(Pr, jvm_object_iter, Pr);
771 
772 	if (libjvm) {
773 		j_agent_create = (j_agent_create_f)
774 		    dlsym(libjvm, "Jagent_create");
775 		j_agent_destroy = (j_agent_destroy_f)
776 		    dlsym(libjvm, "Jagent_destroy");
777 		j_frame_iter = (j_frame_iter_f)
778 		    dlsym(libjvm, "Jframe_iter");
779 
780 		if (j_agent_create == NULL || j_agent_destroy == NULL ||
781 		    j_frame_iter == NULL ||
782 		    (ret = j_agent_create(Pr, JVM_DB_VERSION)) == NULL) {
783 			reset_libjvm(NULL);
784 			return (NULL);
785 		}
786 
787 		return (ret);
788 	}
789 
790 	return (NULL);
791 }
792 
793 static void
794 reset_libjvm(jvm_agent_t *agent)
795 {
796 	if (libjvm) {
797 		if (agent)
798 			j_agent_destroy(agent);
799 
800 		(void) dlclose(libjvm);
801 	}
802 
803 	j_agent_create = NULL;
804 	j_agent_destroy = NULL;
805 	j_frame_iter = NULL;
806 	libjvm = NULL;
807 }
808 
809 /*ARGSUSED*/
810 static int
811 python_object_iter(void *cd, const prmap_t *pmp, const char *obj)
812 {
813 	char path[PATH_MAX];
814 	char *name;
815 	char *s1, *s2;
816 	struct ps_prochandle *Pr = cd;
817 
818 	name = strstr(obj, "/libpython");
819 
820 	if (name) {
821 		(void) strcpy(path, obj);
822 		if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
823 			s1 = name;
824 			s2 = path + (s1 - obj);
825 			(void) strcpy(s2, "/64");
826 			s2 += 3;
827 			(void) strcpy(s2, s1);
828 		}
829 
830 		s1 = strstr(obj, ".so");
831 		s2 = strstr(path, ".so");
832 		(void) strcpy(s2, "_db");
833 		s2 += 3;
834 		(void) strcpy(s2, s1);
835 
836 		if ((libpython = dlopen(path, RTLD_LAZY|RTLD_GLOBAL)) != NULL)
837 			return (1);
838 	}
839 
840 	return (0);
841 }
842 
843 static pydb_agent_t *
844 load_libpython(struct ps_prochandle *Pr)
845 {
846 	pydb_agent_t *pdb;
847 
848 	(void) Pobject_iter(Pr, python_object_iter, Pr);
849 
850 	if (libpython) {
851 		pydb_agent_create = (pydb_agent_create_f)
852 		    dlsym(libpython, "pydb_agent_create");
853 		pydb_agent_destroy = (pydb_agent_destroy_f)
854 		    dlsym(libpython, "pydb_agent_destroy");
855 		pydb_pc_frameinfo = (pydb_pc_frameinfo_f)
856 		    dlsym(libpython, "pydb_pc_frameinfo");
857 		pydb_pc_frameinfo_argv = (pydb_pc_frameinfo_argv_f)
858 		    dlsym(libpython, "pydb_pc_frameinfo_argv");
859 
860 		if (pydb_agent_create == NULL || pydb_agent_destroy == NULL ||
861 		    (pydb_pc_frameinfo == NULL &&
862 		    pydb_pc_frameinfo_argv == NULL)) {
863 			(void) dlclose(libpython);
864 			libpython = NULL;
865 			return (NULL);
866 		}
867 
868 		pdb = pydb_agent_create(Pr, PYDB_VERSION);
869 		if (pdb == NULL) {
870 			(void) dlclose(libpython);
871 			libpython = NULL;
872 			return (NULL);
873 		}
874 		return (pdb);
875 	}
876 
877 	return (NULL);
878 }
879 
880 static void
881 reset_libpython(pydb_agent_t *pdb)
882 {
883 	if (libpython != NULL) {
884 		if (pdb != NULL) {
885 			pydb_agent_destroy(pdb);
886 		}
887 		(void) dlclose(libpython);
888 	}
889 
890 	libpython = NULL;
891 	pydb_agent_create = NULL;
892 	pydb_agent_destroy = NULL;
893 	pydb_pc_frameinfo = NULL;
894 }
895