xref: /illumos-gate/usr/src/lib/libc/port/gen/walkstack.c (revision a61ed2ce7a86a4d6428f2a83eb4739fae945447e)
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