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 uintptr_t newfp;
165
166 if ((uintptr_t)fp & (sizeof (void *) - 1))
167 return (-1); /* misaligned */
168
169 if ((pread(fd, (void *)&newfp, sizeof (fp->fr_savfp),
170 (off_t)&fp->fr_savfp) != sizeof (fp->fr_savfp)) ||
171 pread(fd, (void *)savepc, sizeof (fp->fr_savpc),
172 (off_t)&fp->fr_savpc) != sizeof (fp->fr_savpc))
173 return (-1);
174
175 /*
176 * handle stack bias on sparcv9
177 */
178
179 if (newfp != 0)
180 newfp += STACK_BIAS;
181
182 *savefp = (struct frame *)newfp;
183
184 return (0);
185 }
186
187 int
walkcontext(const ucontext_t * uptr,int (* operate_func)(uintptr_t,int,void *),void * usrarg)188 walkcontext(const ucontext_t *uptr, int (*operate_func)(uintptr_t, int, void *),
189 void *usrarg)
190 {
191 ucontext_t *oldctx = uptr->uc_link;
192
193 int fd;
194 int sig;
195 #if defined(__sparc)
196 int signo = 0;
197 #endif
198
199 struct frame *savefp;
200 uintptr_t savepc;
201
202 /*
203 * snag frame point from ucontext... we'll see caller of
204 * getucontext since we'll start by working up the call
205 * stack by one
206 */
207
208 struct frame *fp = (struct frame *)
209 ((uintptr_t)uptr->uc_mcontext.gregs[FRAME_PTR_REGISTER] +
210 STACK_BIAS);
211
212 /*
213 * Since we don't write signo to the stack on sparc, we need
214 * to extract signo from the stack frames.
215 * An awkward interface is provided for this purpose:
216 * thr_sighndlrinfo; this is documented in
217 * /shared/sac/PSARC/1999/024. When called, this function
218 * returns the PC of a special function (and its size) that
219 * will be present in the stack frame if a signal was
220 * delivered and will have the following signature
221 * __sighndlr(int sig, siginfo_t *si, ucontex_t *uc,
222 * void (*hndlr)())
223 * Since this function is written in assembler and doesn't
224 * perturb its registers, we can then read sig out of arg0
225 * when the saved pc is inside this function.
226 */
227 #if defined(__sparc)
228
229 uintptr_t special_pc = (uintptr_t)NULL;
230 int special_size = 0;
231
232 extern void thr_sighndlrinfo(void (**func)(), int *funcsize);
233
234 thr_sighndlrinfo((void (**)())&special_pc, &special_size);
235 #endif /* sparc */
236
237
238 if ((fd = open("/proc/self/as", O_RDONLY)) < 0)
239 return (-1);
240
241 while (fp != NULL) {
242
243 sig = 0;
244
245 /*
246 * get value of saved fp and pc w/o crashing
247 */
248
249 if (read_safe(fd, fp, &savefp, &savepc) != 0) {
250 (void) close(fd);
251 return (-1);
252 }
253
254 if (savefp == NULL)
255 break;
256
257 /*
258 * note that the following checks to see if we've got a
259 * special signal stack frame present; this allows us to
260 * detect signals and pass that info to the user stack walker
261 */
262
263 if (oldctx != NULL &&
264 CHECK_FOR_SIGFRAME((uintptr_t)savefp, (uintptr_t)oldctx)) {
265
266 #if defined(__i386) || defined(__amd64)
267 /*
268 * i386 and amd64 store signo on stack;
269 * simple to detect and use
270 */
271 sig = *((int *)(savefp + 1));
272 #endif
273
274 #if defined(__sparc)
275 /*
276 * In the case of threads, since there are multiple
277 * complex routines between kernel and user handler,
278 * we need to figure out where we can read signal from
279 * using thr_sighndlrinfo - which we've already done
280 * for this signal, since it appeared on the stack
281 * before the signal frame.... sigh.
282 */
283 sig = signo; /* already read - see below */
284 #endif
285 /*
286 * this is the special signal frame, so cons up
287 * the saved fp & pc to pass to user's function
288 */
289
290 savefp = (struct frame *)
291 ((uintptr_t)oldctx->
292 uc_mcontext.gregs[FRAME_PTR_REGISTER] +
293 STACK_BIAS);
294 savepc = oldctx->uc_mcontext.gregs[PC_REGISTER];
295
296 oldctx = oldctx->uc_link; /* handle nested signals */
297 }
298 #if defined(__sparc)
299
300 /*
301 * lookahead code to find right spot to read signo from...
302 */
303
304 if (savepc >= special_pc && savepc <
305 (special_pc + special_size))
306 signo = fp->fr_arg[0];
307 #endif
308
309 /*
310 * call user-supplied function and quit if non-zero return.
311 */
312
313 if (operate_func((uintptr_t)savepc, sig, usrarg) != 0)
314 break;
315
316 fp = savefp; /* up one in the call stack */
317 }
318
319 (void) close(fd);
320 return (0);
321 }
322
323 /*
324 * async safe version of fprintf
325 */
326
327 static void
async_filenoprintf(int filenum,const char * format,...)328 async_filenoprintf(int filenum, const char *format, ...)
329 {
330 va_list ap;
331 char buffer[MAX_LINE];
332
333 va_start(ap, format);
334 (void) vsnprintf(buffer, sizeof (buffer), format, ap);
335 va_end(ap);
336
337 (void) write(filenum, buffer, strlen(buffer));
338
339 }
340
341 /*
342 * print out stack frame info
343 */
344
345 static int
display_stack_info(uintptr_t pc,int signo,void * arg)346 display_stack_info(uintptr_t pc, int signo, void *arg)
347 {
348 char buffer[MAX_LINE];
349 char sigbuf[SIG2STR_MAX];
350
351
352 int filenum = (intptr_t)arg;
353
354 (void) addrtosymstr((void *)pc, buffer, sizeof (buffer));
355
356 if (signo) {
357 sigbuf[0] = '?';
358 sigbuf[1] = 0;
359
360 (void) sig2str(signo, sigbuf);
361
362 async_filenoprintf(filenum, "%s [Signal %d (%s)]\n",
363 buffer, (ulong_t)signo, sigbuf);
364 } else
365 async_filenoprintf(filenum, "%s\n", buffer);
366
367 return (0);
368 }
369
370 /*
371 * walk current thread stack, writing symbolic stack trace to specified fd
372 */
373
374 int
printstack(int dofd)375 printstack(int dofd)
376 {
377 ucontext_t u;
378
379 if (getcontext(&u) < 0)
380 return (-1);
381
382 return (walkcontext(&u, display_stack_info, (void*)(intptr_t)dofd));
383 }
384
385 /*
386 * Some routines for better opensource compatibility w/ glibc.
387 */
388
389 typedef struct backtrace {
390 void **bt_buffer;
391 int bt_maxcount;
392 int bt_actcount;
393 } backtrace_t;
394
395 static int
callback(uintptr_t pc,int signo __unused,void * arg)396 callback(uintptr_t pc, int signo __unused, void *arg)
397 {
398 backtrace_t *bt = (backtrace_t *)arg;
399
400 if (bt->bt_actcount >= bt->bt_maxcount)
401 return (-1);
402
403 bt->bt_buffer[bt->bt_actcount++] = (void *)pc;
404
405 return (0);
406 }
407
408 /*
409 * dump stack trace up to length count into buffer
410 */
411
412 int
backtrace(void ** buffer,int count)413 backtrace(void **buffer, int count)
414 {
415 backtrace_t bt;
416 ucontext_t u;
417
418 bt.bt_buffer = buffer;
419 bt.bt_maxcount = count;
420 bt.bt_actcount = 0;
421
422 if (getcontext(&u) < 0)
423 return (0);
424
425 (void) walkcontext(&u, callback, &bt);
426
427 return (bt.bt_actcount);
428 }
429
430 /*
431 * format backtrace string
432 */
433
434 int
addrtosymstr(void * pc,char * buffer,int size)435 addrtosymstr(void *pc, char *buffer, int size)
436 {
437 Dl_info info;
438 Sym *sym;
439
440 if (dladdr1(pc, &info, (void **)&sym,
441 RTLD_DL_SYMENT) == 0) {
442 return (snprintf(buffer, size, "[0x%p]", pc));
443 }
444
445 if ((info.dli_fname != NULL && info.dli_sname != NULL) &&
446 ((uintptr_t)pc - (uintptr_t)info.dli_saddr < sym->st_size)) {
447 /*
448 * we have containing symbol info
449 */
450 return (snprintf(buffer, size, "%s'%s+0x%x [0x%p]",
451 info.dli_fname,
452 info.dli_sname,
453 (unsigned long)pc - (unsigned long)info.dli_saddr,
454 pc));
455 } else {
456 /*
457 * no local symbol info
458 */
459 return (snprintf(buffer, size, "%s'0x%p [0x%p]",
460 info.dli_fname,
461 (unsigned long)pc - (unsigned long)info.dli_fbase,
462 pc));
463 }
464 }
465
466 /*
467 * This function returns the symbolic representation of stack trace; calls
468 * malloc so it is NOT async safe! A rather mis-designed and certainly misused
469 * interface.
470 */
471
472 char **
backtrace_symbols(void * const * array,int size)473 backtrace_symbols(void *const *array, int size)
474 {
475 int bufferlen, len;
476 char **ret_buffer;
477 char **ret;
478 char linebuffer[MAX_LINE];
479 int i;
480
481 bufferlen = size * sizeof (char *);
482
483 /*
484 * tmp buffer to hold strings while finding all symbol names
485 */
486
487 ret_buffer = (char **)alloca(bufferlen);
488
489 for (i = 0; i < size; i++) {
490 (void) addrtosymstr(array[i], linebuffer, sizeof (linebuffer));
491 ret_buffer[i] = strcpy(alloca(len = strlen(linebuffer) + 1),
492 linebuffer);
493 bufferlen += len;
494 }
495
496 /*
497 * allocate total amount of storage required and copy strings
498 */
499
500 if ((ret = (char **)malloc(bufferlen)) == NULL)
501 return (NULL);
502
503
504 for (len = i = 0; i < size; i++) {
505 ret[i] = (char *)ret + size * sizeof (char *) + len;
506 (void) strcpy(ret[i], ret_buffer[i]);
507 len += strlen(ret_buffer[i]) + 1;
508 }
509
510 return (ret);
511 }
512
513 /*
514 * Write out symbolic stack trace in an async-safe way.
515 */
516
517 void
backtrace_symbols_fd(void * const * array,int size,int fd)518 backtrace_symbols_fd(void *const *array, int size, int fd)
519 {
520 char linebuffer[MAX_LINE];
521 int i;
522 int len;
523
524 for (i = 0; i < size; i++) {
525 len = addrtosymstr(array[i], linebuffer,
526 sizeof (linebuffer) - 1);
527 if (len >= sizeof (linebuffer))
528 len = sizeof (linebuffer) - 1;
529 linebuffer[len] = '\n';
530 (void) write(fd, linebuffer, len + 1);
531 }
532 }
533