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