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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 /* 28 * This file provides a general purpose mechanism 29 * for a user thread to walk its own call stack, 30 * calling a user-specified iterator function for each 31 * stack frame. Special handling is provided to indicate 32 * kernel-constructed signal handler frames. 33 * 34 * Adapted from usr/src/lib/libproc/common/Pstack.c: 35 * 36 * A signal handler frame is essentially a set of data pushed on to the user 37 * stack by the kernel prior to returning to the user program in one of the 38 * pre-defined signal handlers. The signal handler itself receives the signal 39 * number, an optional pointer to a siginfo_t, and a pointer to the interrupted 40 * ucontext as arguments. 41 * 42 * When performing a stack backtrace, we would like to 43 * detect these frames so that we can correctly return the interrupted program 44 * counter and frame pointer as a separate frame. 45 * 46 * The stack layout for a signal handler frame is as follows: 47 * 48 * SPARC v7/v9: Intel ia32: 49 * +--------------+ - high +--------------+ - 50 * | struct fq | ^ addrs | siginfo_t | optional 51 * +--------------+ | ^ +--------------+ - 52 * | gwindows_t | | | ucontext_t | ^ 53 * +--------------+ optional +--------------+ | 54 * | siginfo_t | | ucontext_t * | | 55 * +--------------+ | | +--------------+ 56 * | xregs data | v v | siginfo_t * | mandatory 57 * +--------------+ - low +--------------+ 58 * | ucontext_t | ^ addrs | int (signo) | | 59 * +--------------+ mandatory +--------------+ | 60 * | struct frame | v | struct frame | v 61 * +--------------+ - <- %sp on resume +--------------+ - <- %esp on resume 62 * 63 * amd64 (64-bit) 64 * +--------------+ - 65 * | siginfo_t | optional 66 * +--------------+ - 67 * | ucontext_t | ^ 68 * +--------------+ | 69 * | siginfo_t * | 70 * +--------------+ mandatory 71 * | int (signo) | 72 * +--------------+ | 73 * | struct frame | v 74 * +--------------+ - <- %rsp on resume 75 * 76 * The bottom-most struct frame is actually constructed by the kernel by 77 * copying the previous stack frame, allowing naive backtrace code to simply 78 * skip over the interrupted frame. The copied frame is never really used, 79 * since it is presumed the signal handler wrapper function 80 * will explicitly setcontext(2) to the interrupted context if the user 81 * program's handler returns. If we detect a signal handler frame, we simply 82 * read the interrupted context structure from the stack, use its embedded 83 * gregs to construct the register set for the interrupted frame, and then 84 * continue our backtrace. Detecting the frame itself is easy according to 85 * the diagram ("oldcontext" represents any element in the uc_link chain): 86 * 87 * On SPARC v7 or v9: 88 * %fp + sizeof (struct frame) == oldcontext 89 * 90 * On i386: 91 * %ebp + sizeof (struct frame) + (3 words) == oldcontext 92 * 93 * On amd64: 94 * %rbp + sizeof (struct frame) + (2 words) == oldcontext 95 * 96 * Since we want to provide the signal number that generated a signal stack 97 * frame and on sparc this information isn't written to the stack by the kernel 98 * the way it's done on i386, we're forced to read the signo from the stack as 99 * one of the arguments to the signal handler. We use the thr_sighndlrinfo 100 * interface to find the correct frame. 101 */ 102 103 #include "lint.h" 104 #include <assert.h> 105 #include <dlfcn.h> 106 #include <fcntl.h> 107 #include <link.h> 108 #include <procfs.h> 109 #include <strings.h> 110 #include <signal.h> 111 #include <sys/frame.h> 112 #include <sys/regset.h> 113 #include <sys/types.h> 114 #include <sys/uio.h> 115 #include <thread.h> 116 #include <ucontext.h> 117 #include <unistd.h> 118 #include <stdarg.h> 119 #include <sys/stack.h> 120 #include <errno.h> 121 #include <stdio.h> 122 #include <alloca.h> 123 #include <limits.h> 124 #include <stdlib.h> 125 126 #ifdef _LP64 127 #define _ELF64 128 #endif 129 130 #include <sys/machelf.h> 131 132 133 #if defined(__sparc) 134 #define FRAME_PTR_REGISTER REG_SP 135 #define PC_REGISTER REG_PC 136 #define CHECK_FOR_SIGFRAME(fp, oldctx) ((fp) + SA(sizeof (struct frame)) \ 137 == (oldctx)) 138 139 #elif defined(__amd64) 140 #define FRAME_PTR_REGISTER REG_RBP 141 #define PC_REGISTER REG_RIP 142 #define CHECK_FOR_SIGFRAME(fp, oldctx) ((((fp) + sizeof (struct frame)) + \ 143 2 * sizeof (long) == (oldctx)) && \ 144 (((struct frame *)fp)->fr_savpc == (greg_t)-1)) 145 146 #elif defined(__i386) 147 #define FRAME_PTR_REGISTER EBP 148 #define PC_REGISTER EIP 149 #define CHECK_FOR_SIGFRAME(fp, oldctx) ((((fp) + sizeof (struct frame)) + \ 150 3 * sizeof (int) == (oldctx)) && \ 151 (((struct frame *)fp)->fr_savpc == (greg_t)-1)) 152 #else 153 #error no arch defined 154 #endif 155 156 #define MAX_LINE 2048 /* arbitrary large value */ 157 158 /* 159 * use /proc/self/as to safely dereference pointers so we don't 160 * die in the case of a stack smash 161 */ 162 163 static int 164 read_safe(int fd, struct frame *fp, struct frame **savefp, uintptr_t *savepc) 165 { 166 167 uintptr_t newfp; 168 169 if ((uintptr_t)fp & (sizeof (void *) - 1)) 170 return (-1); /* misaligned */ 171 172 if ((pread(fd, (void *)&newfp, sizeof (fp->fr_savfp), 173 (off_t)&fp->fr_savfp) != sizeof (fp->fr_savfp)) || 174 pread(fd, (void *)savepc, sizeof (fp->fr_savpc), 175 (off_t)&fp->fr_savpc) != sizeof (fp->fr_savpc)) 176 return (-1); 177 178 /* 179 * handle stack bias on sparcv9 180 */ 181 182 if (newfp != 0) 183 newfp += STACK_BIAS; 184 185 *savefp = (struct frame *)newfp; 186 187 return (0); 188 } 189 190 int 191 walkcontext(const ucontext_t *uptr, int (*operate_func)(uintptr_t, int, void *), 192 void *usrarg) 193 { 194 ucontext_t *oldctx = uptr->uc_link; 195 196 int fd; 197 int sig; 198 #if defined(__sparc) 199 int signo = 0; 200 #endif 201 202 struct frame *savefp; 203 uintptr_t savepc; 204 205 /* 206 * snag frame point from ucontext... we'll see caller of 207 * getucontext since we'll start by working up the call 208 * stack by one 209 */ 210 211 struct frame *fp = (struct frame *) 212 ((uintptr_t)uptr->uc_mcontext.gregs[FRAME_PTR_REGISTER] + 213 STACK_BIAS); 214 215 /* 216 * Since we don't write signo to the stack on sparc, we need 217 * to extract signo from the stack frames. 218 * An awkward interface is provided for this purpose: 219 * thr_sighndlrinfo; this is documented in 220 * /shared/sac/PSARC/1999/024. When called, this function 221 * returns the PC of a special function (and its size) that 222 * will be present in the stack frame if a signal was 223 * delivered and will have the following signature 224 * __sighndlr(int sig, siginfo_t *si, ucontex_t *uc, 225 * void (*hndlr)()) 226 * Since this function is written in assembler and doesn't 227 * perturb its registers, we can then read sig out of arg0 228 * when the saved pc is inside this function. 229 */ 230 #if defined(__sparc) 231 232 uintptr_t special_pc = NULL; 233 int special_size = 0; 234 235 extern void thr_sighndlrinfo(void (**func)(), int *funcsize); 236 237 thr_sighndlrinfo((void (**)())&special_pc, &special_size); 238 #endif /* sparc */ 239 240 241 if ((fd = open("/proc/self/as", O_RDONLY)) < 0) 242 return (-1); 243 244 while (fp != NULL) { 245 246 sig = 0; 247 248 /* 249 * get value of saved fp and pc w/o crashing 250 */ 251 252 if (read_safe(fd, fp, &savefp, &savepc) != 0) { 253 (void) close(fd); 254 return (-1); 255 } 256 257 if (savefp == NULL) 258 break; 259 260 /* 261 * note that the following checks to see if we've got a 262 * special signal stack frame present; this allows us to 263 * detect signals and pass that info to the user stack walker 264 */ 265 266 if (oldctx != NULL && 267 CHECK_FOR_SIGFRAME((uintptr_t)savefp, (uintptr_t)oldctx)) { 268 269 #if defined(__i386) || defined(__amd64) 270 /* 271 * i386 and amd64 store signo on stack; 272 * simple to detect and use 273 */ 274 sig = *((int *)(savefp + 1)); 275 #endif 276 277 #if defined(__sparc) 278 /* 279 * In the case of threads, since there are multiple 280 * complex routines between kernel and user handler, 281 * we need to figure out where we can read signal from 282 * using thr_sighndlrinfo - which we've already done 283 * for this signal, since it appeared on the stack 284 * before the signal frame.... sigh. 285 */ 286 sig = signo; /* already read - see below */ 287 #endif 288 /* 289 * this is the special signal frame, so cons up 290 * the saved fp & pc to pass to user's function 291 */ 292 293 savefp = (struct frame *) 294 ((uintptr_t)oldctx-> 295 uc_mcontext.gregs[FRAME_PTR_REGISTER] + 296 STACK_BIAS); 297 savepc = oldctx->uc_mcontext.gregs[PC_REGISTER]; 298 299 oldctx = oldctx->uc_link; /* handle nested signals */ 300 } 301 #if defined(__sparc) 302 303 /* 304 * lookahead code to find right spot to read signo from... 305 */ 306 307 if (savepc >= special_pc && savepc < 308 (special_pc + special_size)) 309 signo = fp->fr_arg[0]; 310 #endif 311 312 /* 313 * call user-supplied function and quit if non-zero return. 314 */ 315 316 if (operate_func((uintptr_t)savepc, sig, usrarg) != 0) 317 break; 318 319 fp = savefp; /* up one in the call stack */ 320 } 321 322 (void) close(fd); 323 return (0); 324 } 325 326 /* 327 * async safe version of fprintf 328 */ 329 330 static void 331 async_filenoprintf(int filenum, const char *format, ...) 332 { 333 va_list ap; 334 char buffer[MAX_LINE]; 335 336 va_start(ap, format); 337 (void) vsnprintf(buffer, sizeof (buffer), format, ap); 338 va_end(ap); 339 340 (void) write(filenum, buffer, strlen(buffer)); 341 342 } 343 344 /* 345 * print out stack frame info 346 */ 347 348 static int 349 display_stack_info(uintptr_t pc, int signo, void *arg) 350 { 351 352 char buffer[MAX_LINE]; 353 char sigbuf[SIG2STR_MAX]; 354 355 356 int filenum = (intptr_t)arg; 357 358 (void) addrtosymstr((void *)pc, buffer, sizeof (buffer)); 359 360 if (signo) { 361 sigbuf[0] = '?'; 362 sigbuf[1] = 0; 363 364 (void) sig2str(signo, sigbuf); 365 366 async_filenoprintf(filenum, "%s [Signal %d (%s)]\n", 367 buffer, (ulong_t)signo, sigbuf); 368 } else 369 async_filenoprintf(filenum, "%s\n", buffer); 370 371 return (0); 372 } 373 374 /* 375 * walk current thread stack, writing symbolic stack trace to specified fd 376 */ 377 378 int 379 printstack(int dofd) 380 { 381 ucontext_t u; 382 383 if (getcontext(&u) < 0) 384 return (-1); 385 386 return (walkcontext(&u, display_stack_info, (void*)(intptr_t)dofd)); 387 } 388 389 /* 390 * Some routines for better opensource compatibility w/ glibc. 391 */ 392 393 typedef struct backtrace { 394 void **bt_buffer; 395 int bt_maxcount; 396 int bt_actcount; 397 } backtrace_t; 398 399 /* ARGSUSED */ 400 static int 401 callback(uintptr_t pc, int signo, void *arg) 402 { 403 backtrace_t *bt = (backtrace_t *)arg; 404 405 if (bt->bt_actcount >= bt->bt_maxcount) 406 return (-1); 407 408 bt->bt_buffer[bt->bt_actcount++] = (void *)pc; 409 410 return (0); 411 } 412 413 /* 414 * dump stack trace up to length count into buffer 415 */ 416 417 int 418 backtrace(void **buffer, int count) 419 { 420 backtrace_t bt; 421 ucontext_t u; 422 423 bt.bt_buffer = buffer; 424 bt.bt_maxcount = count; 425 bt.bt_actcount = 0; 426 427 if (getcontext(&u) < 0) 428 return (0); 429 430 (void) walkcontext(&u, callback, &bt); 431 432 return (bt.bt_actcount); 433 } 434 435 /* 436 * format backtrace string 437 */ 438 439 int 440 addrtosymstr(void *pc, char *buffer, int size) 441 { 442 Dl_info info; 443 Sym *sym; 444 445 if (dladdr1(pc, &info, (void **)&sym, 446 RTLD_DL_SYMENT) == 0) { 447 return (snprintf(buffer, size, "[0x%p]", pc)); 448 } 449 450 if ((info.dli_fname != NULL && info.dli_sname != NULL) && 451 ((uintptr_t)pc - (uintptr_t)info.dli_saddr < sym->st_size)) { 452 /* 453 * we have containing symbol info 454 */ 455 return (snprintf(buffer, size, "%s'%s+0x%x [0x%p]", 456 info.dli_fname, 457 info.dli_sname, 458 (unsigned long)pc - (unsigned long)info.dli_saddr, 459 pc)); 460 } else { 461 /* 462 * no local symbol info 463 */ 464 return (snprintf(buffer, size, "%s'0x%p [0x%p]", 465 info.dli_fname, 466 (unsigned long)pc - (unsigned long)info.dli_fbase, 467 pc)); 468 } 469 } 470 471 /* 472 * This function returns the symbolic representation of stack trace; calls 473 * malloc so it is NOT async safe! A rather mis-designed and certainly misused 474 * interface. 475 */ 476 477 char ** 478 backtrace_symbols(void *const *array, int size) 479 { 480 int bufferlen, len; 481 char **ret_buffer; 482 char **ret; 483 char linebuffer[MAX_LINE]; 484 int i; 485 486 bufferlen = size * sizeof (char *); 487 488 /* 489 * tmp buffer to hold strings while finding all symbol names 490 */ 491 492 ret_buffer = (char **)alloca(bufferlen); 493 494 for (i = 0; i < size; i++) { 495 (void) addrtosymstr(array[i], linebuffer, sizeof (linebuffer)); 496 ret_buffer[i] = strcpy(alloca(len = strlen(linebuffer) + 1), 497 linebuffer); 498 bufferlen += len; 499 } 500 501 /* 502 * allocate total amount of storage required and copy strings 503 */ 504 505 if ((ret = (char **)malloc(bufferlen)) == NULL) 506 return (NULL); 507 508 509 for (len = i = 0; i < size; i++) { 510 ret[i] = (char *)ret + size * sizeof (char *) + len; 511 strcpy(ret[i], ret_buffer[i]); 512 len += strlen(ret_buffer[i]) + 1; 513 } 514 515 return (ret); 516 } 517 518 /* 519 * Write out symbolic stack trace in an async-safe way. 520 */ 521 522 void 523 backtrace_symbols_fd(void *const *array, int size, int fd) 524 { 525 char linebuffer[MAX_LINE]; 526 int i; 527 int len; 528 529 for (i = 0; i < size; i++) { 530 len = addrtosymstr(array[i], linebuffer, 531 sizeof (linebuffer) - 1); 532 if (len >= sizeof (linebuffer)) 533 len = sizeof (linebuffer) - 1; 534 linebuffer[len] = '\n'; 535 (void) write(fd, linebuffer, len + 1); 536 } 537 } 538