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