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