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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/isa_defs.h> 29 30 #include <stdio.h> 31 #include <stdio_ext.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 (void) enable_extended_FILE_stdio(-1, -1); 185 } 186 187 (void) proc_initstdio(); 188 189 while (--argc >= 0) { 190 int gcode; 191 psinfo_t psinfo; 192 const psinfo_t *tpsinfo; 193 struct ps_prochandle *Pr = NULL; 194 td_thragent_t *Tap; 195 int threaded; 196 pstack_handle_t handle; 197 const char *lwps, *arg; 198 199 (void) proc_flushstdio(); 200 201 arg = *argv++; 202 203 if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_ANY, 204 Fflag, &gcode, &lwps)) == NULL) { 205 (void) fprintf(stderr, "%s: cannot examine %s: %s\n", 206 command, arg, Pgrab_error(gcode)); 207 retc++; 208 continue; 209 } 210 211 if ((tpsinfo = Ppsinfo(Pr)) == NULL) { 212 (void) fprintf(stderr, "%s: cannot examine %s: " 213 "lost control of process\n", command, arg); 214 Prelease(Pr, 0); 215 retc++; 216 continue; 217 } 218 (void) memcpy(&psinfo, tpsinfo, sizeof (psinfo_t)); 219 proc_unctrl_psinfo(&psinfo); 220 221 if (Pstate(Pr) == PS_DEAD) { 222 if ((Pcontent(Pr) & content) != content) { 223 (void) fprintf(stderr, "%s: core '%s' has " 224 "insufficient content\n", command, arg); 225 retc++; 226 continue; 227 } 228 (void) printf("core '%s' of %d:\t%.70s\n", 229 arg, (int)psinfo.pr_pid, psinfo.pr_psargs); 230 } else { 231 (void) printf("%d:\t%.70s\n", 232 (int)psinfo.pr_pid, psinfo.pr_psargs); 233 } 234 235 is64 = (psinfo.pr_dmodel == PR_MODEL_LP64); 236 237 if (Pgetauxval(Pr, AT_BASE) != -1L && Prd_agent(Pr) == NULL) { 238 (void) fprintf(stderr, "%s: warning: librtld_db failed " 239 "to initialize; symbols from shared libraries will " 240 "not be available\n", command); 241 } 242 243 /* 244 * First we need to get a thread agent handle. 245 */ 246 if (td_init() != TD_OK || 247 td_ta_new(Pr, &Tap) != TD_OK) /* no libc */ 248 threaded = FALSE; 249 else { 250 /* 251 * Iterate over all threads, calling: 252 * thr_stack(td_thrhandle_t *Thp, NULL); 253 * for each one to generate the list of threads. 254 */ 255 nthreads = 0; 256 (void) td_ta_thr_iter(Tap, thr_stack, NULL, 257 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 258 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 259 260 (void) td_ta_delete(Tap); 261 threaded = TRUE; 262 } 263 264 handle.proc = Pr; 265 handle.jvm = load_libjvm(Pr); 266 handle.lwps = lwps; 267 handle.count = 0; 268 269 if (all_call_stacks(&handle, threaded) != 0) 270 retc++; 271 if (threaded) 272 free_threadinfo(); 273 274 reset_libjvm(handle.jvm); 275 Prelease(Pr, 0); 276 277 if (handle.count == 0) 278 (void) fprintf(stderr, "%s: no matching LWPs found\n", 279 command); 280 } 281 282 (void) proc_finistdio(); 283 284 return (retc); 285 } 286 287 /* 288 * Thread iteration call-back function. 289 * Called once for each user-level thread. 290 * Used to build the list of all threads. 291 */ 292 /* ARGSUSED1 */ 293 static int 294 thr_stack(const td_thrhandle_t *Thp, void *cd) 295 { 296 td_thrinfo_t thrinfo; 297 struct threadinfo *tip; 298 td_err_e error; 299 300 if (td_thr_get_info(Thp, &thrinfo) != TD_OK) 301 return (0); 302 303 tip = malloc(sizeof (struct threadinfo)); 304 tip->next = NULL; 305 tip->threadid = thrinfo.ti_tid; 306 tip->lwpid = thrinfo.ti_lid; 307 tip->state = thrinfo.ti_state; 308 tip->startfunc = thrinfo.ti_startfunc; 309 tip->exitval = (uintptr_t)thrinfo.ti_exitval; 310 nthreads++; 311 312 if (thrinfo.ti_state == TD_THR_ZOMBIE || 313 ((error = td_thr_getgregs(Thp, tip->regs)) != TD_OK && 314 error != TD_PARTIALREG)) 315 (void) memset(tip->regs, 0, sizeof (prgregset_t)); 316 317 if (thr_tail) 318 thr_tail->next = tip; 319 else 320 thr_head = tip; 321 thr_tail = tip; 322 323 return (0); 324 } 325 326 static void 327 free_threadinfo() 328 { 329 struct threadinfo *tip = thr_head; 330 struct threadinfo *next; 331 332 while (tip) { 333 next = tip->next; 334 free(tip); 335 tip = next; 336 } 337 338 thr_head = thr_tail = NULL; 339 } 340 341 /* 342 * Find and eliminate the thread corresponding to the given lwpid. 343 */ 344 static struct threadinfo * 345 find_thread(id_t lwpid) 346 { 347 struct threadinfo *tip; 348 349 for (tip = thr_head; tip; tip = tip->next) { 350 if (lwpid == tip->lwpid) { 351 tip->lwpid = 0; 352 return (tip); 353 } 354 } 355 return (NULL); 356 } 357 358 static int 359 thread_call_stack(void *data, const lwpstatus_t *psp, 360 const lwpsinfo_t *pip) 361 { 362 pstack_handle_t *h = data; 363 lwpstatus_t lwpstatus; 364 struct threadinfo *tip; 365 366 if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid)) 367 return (0); 368 h->count++; 369 370 if ((tip = find_thread(pip->pr_lwpid)) == NULL) 371 return (0); 372 373 tlhead(tip->threadid, pip->pr_lwpid); 374 tip->threadid = 0; /* finish eliminating tid */ 375 if (psp) 376 call_stack(h, psp); 377 else { 378 if (tip->state == TD_THR_ZOMBIE) 379 print_zombie(h->proc, tip); 380 else { 381 (void) memset(&lwpstatus, 0, sizeof (lwpstatus)); 382 (void) memcpy(lwpstatus.pr_reg, tip->regs, 383 sizeof (prgregset_t)); 384 call_stack(h, &lwpstatus); 385 } 386 } 387 return (0); 388 } 389 390 static int 391 lwp_call_stack(void *data, 392 const lwpstatus_t *psp, const lwpsinfo_t *pip) 393 { 394 pstack_handle_t *h = data; 395 396 if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid)) 397 return (0); 398 h->count++; 399 400 tlhead(0, pip->pr_lwpid); 401 if (psp) 402 call_stack(h, psp); 403 else 404 (void) printf("\t** zombie " 405 "(exited, not detached, not yet joined) **\n"); 406 return (0); 407 } 408 409 static int 410 all_call_stacks(pstack_handle_t *h, int dothreads) 411 { 412 struct ps_prochandle *Pr = h->proc; 413 pstatus_t status = *Pstatus(Pr); 414 415 (void) memset(&sigh, 0, sizeof (GElf_Sym)); 416 (void) Plookup_by_name(Pr, "libc.so", "sigacthandler", &sigh); 417 418 if ((status.pr_nlwp + status.pr_nzomb) <= 1 && 419 !(dothreads && nthreads > 1)) { 420 if (proc_lwp_in_set(h->lwps, status.pr_lwp.pr_lwpid)) { 421 call_stack(h, &status.pr_lwp); 422 h->count++; 423 } 424 } else { 425 lwpstatus_t lwpstatus; 426 struct threadinfo *tip; 427 id_t tid; 428 429 if (dothreads) 430 (void) Plwp_iter_all(Pr, thread_call_stack, h); 431 else 432 (void) Plwp_iter_all(Pr, lwp_call_stack, h); 433 434 /* for each remaining thread w/o an lwp */ 435 (void) memset(&lwpstatus, 0, sizeof (lwpstatus)); 436 for (tip = thr_head; tip; tip = tip->next) { 437 438 if (!proc_lwp_in_set(h->lwps, tip->lwpid)) 439 tip->threadid = 0; 440 441 if ((tid = tip->threadid) != 0) { 442 (void) memcpy(lwpstatus.pr_reg, tip->regs, 443 sizeof (prgregset_t)); 444 tlhead(tid, tip->lwpid); 445 if (tip->state == TD_THR_ZOMBIE) 446 print_zombie(Pr, tip); 447 else 448 call_stack(h, &lwpstatus); 449 } 450 tip->threadid = 0; 451 tip->lwpid = 0; 452 } 453 } 454 return (0); 455 } 456 457 static void 458 tlhead(id_t threadid, id_t lwpid) 459 { 460 if (threadid == 0 && lwpid == 0) 461 return; 462 463 (void) printf("-----------------"); 464 465 if (threadid && lwpid) 466 (void) printf(" lwp# %d / thread# %d ", 467 (int)lwpid, (int)threadid); 468 else if (threadid) 469 (void) printf("--------- thread# %d ", (int)threadid); 470 else if (lwpid) 471 (void) printf(" lwp# %d ------------", (int)lwpid); 472 473 (void) printf("--------------------\n"); 474 } 475 476 /*ARGSUSED*/ 477 static int 478 print_java_frame(void *cld, prgregset_t gregs, const char *name, int bci, 479 int line, void *handle) 480 { 481 int length = (is64 ? 16 : 8); 482 483 (void) printf(" %.*lx * %s", length, (long)gregs[R_PC], name); 484 485 if (bci != -1) { 486 (void) printf("+%d", bci); 487 if (line) 488 (void) printf(" (line %d)", line); 489 } 490 (void) printf("\n"); 491 492 return (0); 493 } 494 495 static sigjmp_buf jumpbuf; 496 497 /*ARGSUSED*/ 498 static void 499 fatal_signal(int signo) 500 { 501 siglongjmp(jumpbuf, 1); 502 } 503 504 static int 505 print_frame(void *cd, prgregset_t gregs, uint_t argc, const long *argv) 506 { 507 pstack_handle_t *h = cd; 508 struct ps_prochandle *Pr = h->proc; 509 uintptr_t pc = gregs[R_PC]; 510 char buff[255]; 511 GElf_Sym sym; 512 uintptr_t start; 513 int length = (is64? 16 : 8); 514 int i; 515 516 /* 517 * If we are in a system call, we display the entry frame in a more 518 * readable manner, using the name of the system call. In this case, we 519 * want to ignore this first frame, since we already displayed it 520 * separately. 521 */ 522 if (h->ignore_frame) { 523 h->ignore_frame = 0; 524 return (0); 525 } 526 527 (void) sprintf(buff, "%.*lx", length, (long)pc); 528 (void) strcpy(buff + length, " ????????"); 529 if (Plookup_by_addr(Pr, pc, 530 buff + 1 + length, sizeof (buff) - 1 - length, &sym) == 0) { 531 start = sym.st_value; 532 } else if (h->jvm != NULL) { 533 int ret; 534 void (*segv)(int), (*bus)(int), (*ill)(int); 535 536 segv = signal(SIGSEGV, fatal_signal); 537 bus = signal(SIGBUS, fatal_signal); 538 ill = signal(SIGILL, fatal_signal); 539 540 /* Insure against a bad libjvm_db */ 541 if (sigsetjmp(jumpbuf, 0) == 0) 542 ret = j_frame_iter(h->jvm, gregs, print_java_frame, 543 NULL); 544 else 545 ret = -1; 546 547 (void) signal(SIGSEGV, segv); 548 (void) signal(SIGBUS, bus); 549 (void) signal(SIGILL, ill); 550 551 if (ret == 0) 552 return (ret); 553 } else { 554 start = pc; 555 } 556 557 (void) printf(" %-17s (", buff); 558 for (i = 0; i < argc && i < MAX_ARGS; i++) 559 (void) printf((i+1 == argc)? "%lx" : "%lx, ", 560 argv[i]); 561 if (i != argc) 562 (void) printf("..."); 563 (void) printf((start != pc)? 564 ") + %lx\n" : ")\n", (long)(pc - start)); 565 566 /* 567 * If the frame's pc is in the "sigh" (a.k.a. signal handler, signal 568 * hack, or *sigh* ...) range, then we're about to cross a signal 569 * frame. The signal number is the first argument to this function. 570 */ 571 if (pc - sigh.st_value < sigh.st_size) { 572 if (sig2str((int)argv[0], buff) == -1) 573 (void) strcpy(buff, " Unknown"); 574 (void) printf(" --- called from signal handler with " 575 "signal %d (SIG%s) ---\n", (int)argv[0], buff); 576 } 577 578 return (0); 579 } 580 581 static void 582 print_zombie(struct ps_prochandle *Pr, struct threadinfo *tip) 583 { 584 char buff[255]; 585 GElf_Sym sym; 586 uintptr_t start; 587 int length = (is64? 16 : 8); 588 589 (void) sprintf(buff, "%.*lx", length, (long)tip->startfunc); 590 (void) strcpy(buff + length, " ????????"); 591 if (Plookup_by_addr(Pr, tip->startfunc, 592 buff + 1 + length, sizeof (buff) - 1 - length, &sym) == 0) 593 start = sym.st_value; 594 else 595 start = tip->startfunc; 596 (void) printf(" %s()", buff); 597 if (start != tip->startfunc) /* doesn't happen? */ 598 (void) printf("+%lx", (long)(tip->startfunc - start)); 599 (void) printf(", exit value = 0x%.*lx\n", length, (long)tip->exitval); 600 (void) printf("\t** zombie " 601 "(exited, not detached, not yet joined) **\n"); 602 } 603 604 static void 605 print_syscall(const lwpstatus_t *psp, prgregset_t reg) 606 { 607 char sname[32]; 608 int length = (is64? 16 : 8); 609 uint_t i; 610 611 (void) proc_sysname(psp->pr_syscall, sname, sizeof (sname)); 612 (void) printf(" %.*lx %-8s (", length, (long)reg[R_PC], sname); 613 for (i = 0; i < psp->pr_nsysarg; i++) 614 (void) printf((i+1 == psp->pr_nsysarg)? "%lx" : "%lx, ", 615 (long)psp->pr_sysarg[i]); 616 (void) printf(")\n"); 617 } 618 619 static void 620 call_stack(pstack_handle_t *h, const lwpstatus_t *psp) 621 { 622 prgregset_t reg; 623 624 (void) memcpy(reg, psp->pr_reg, sizeof (reg)); 625 626 if ((psp->pr_flags & (PR_ASLEEP|PR_VFORKP)) || 627 ((psp->pr_flags & PR_ISTOP) && 628 (psp->pr_why == PR_SYSENTRY || 629 psp->pr_why == PR_SYSEXIT))) { 630 print_syscall(psp, reg); 631 h->ignore_frame = 1; 632 } else { 633 h->ignore_frame = 0; 634 } 635 636 (void) Pstack_iter(h->proc, reg, print_frame, h); 637 } 638 639 /*ARGSUSED*/ 640 static int 641 jvm_object_iter(void *cd, const prmap_t *pmp, const char *obj) 642 { 643 char path[PATH_MAX]; 644 char *name; 645 char *s1, *s2; 646 struct ps_prochandle *Pr = cd; 647 648 if ((name = strstr(obj, "/libjvm.so")) == NULL) 649 name = strstr(obj, "/libjvm_g.so"); 650 651 if (name) { 652 (void) strcpy(path, obj); 653 if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) { 654 s1 = name; 655 s2 = path + (s1 - obj); 656 (void) strcpy(s2, "/64"); 657 s2 += 3; 658 (void) strcpy(s2, s1); 659 } 660 661 s1 = strstr(obj, ".so"); 662 s2 = strstr(path, ".so"); 663 (void) strcpy(s2, "_db"); 664 s2 += 3; 665 (void) strcpy(s2, s1); 666 667 if ((libjvm = dlopen(path, RTLD_LAZY|RTLD_GLOBAL)) != NULL) 668 return (1); 669 } 670 671 return (0); 672 } 673 674 static jvm_agent_t * 675 load_libjvm(struct ps_prochandle *Pr) 676 { 677 jvm_agent_t *ret; 678 679 (void) Pobject_iter(Pr, jvm_object_iter, Pr); 680 681 if (libjvm) { 682 j_agent_create = (j_agent_create_f) 683 dlsym(libjvm, "Jagent_create"); 684 j_agent_destroy = (j_agent_destroy_f) 685 dlsym(libjvm, "Jagent_destroy"); 686 j_frame_iter = (j_frame_iter_f) 687 dlsym(libjvm, "Jframe_iter"); 688 689 if (j_agent_create == NULL || j_agent_destroy == NULL || 690 j_frame_iter == NULL || 691 (ret = j_agent_create(Pr, JVM_DB_VERSION)) == NULL) { 692 reset_libjvm(NULL); 693 return (NULL); 694 } 695 696 return (ret); 697 } 698 699 return (NULL); 700 } 701 702 static void 703 reset_libjvm(jvm_agent_t *agent) 704 { 705 if (libjvm) { 706 if (agent) 707 j_agent_destroy(agent); 708 709 (void) dlclose(libjvm); 710 } 711 712 j_agent_create = NULL; 713 j_agent_destroy = NULL; 714 j_frame_iter = NULL; 715 libjvm = NULL; 716 } 717