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
read_safe(int fd,struct frame * fp,struct frame ** savefp,uintptr_t * savepc)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
walkcontext(const ucontext_t * uptr,int (* operate_func)(uintptr_t,int,void *),void * usrarg)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 = 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
async_filenoprintf(int filenum,const char * format,...)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
display_stack_info(uintptr_t pc,int signo,void * arg)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
printstack(int dofd)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
callback(uintptr_t pc,int signo,void * arg)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
backtrace(void ** buffer,int count)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
addrtosymstr(void * pc,char * buffer,int size)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 **
backtrace_symbols(void * const * array,int size)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
backtrace_symbols_fd(void * const * array,int size,int fd)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