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