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