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