xref: /dpdk/lib/eal/unix/eal_debug.c (revision 0efcd352e257ae88a16667b8b6d5dcf0319a4192)
1*0efcd352SStephen Hemminger /* SPDX-License-Identifier: BSD-3-Clause
2*0efcd352SStephen Hemminger  * Copyright(c) 2010-2014 Intel Corporation
3*0efcd352SStephen Hemminger  */
4*0efcd352SStephen Hemminger 
5*0efcd352SStephen Hemminger #include <rte_debug.h>
6*0efcd352SStephen Hemminger 
7*0efcd352SStephen Hemminger #ifdef RTE_BACKTRACE
8*0efcd352SStephen Hemminger 
9*0efcd352SStephen Hemminger #include <dlfcn.h>
10*0efcd352SStephen Hemminger #include <execinfo.h>
11*0efcd352SStephen Hemminger #include <string.h>
12*0efcd352SStephen Hemminger #include <sys/uio.h>
13*0efcd352SStephen Hemminger #include <unistd.h>
14*0efcd352SStephen Hemminger 
15*0efcd352SStephen Hemminger #define BACKTRACE_SIZE 256
16*0efcd352SStephen Hemminger 
17*0efcd352SStephen Hemminger /*
18*0efcd352SStephen Hemminger  * Convert number to string and return start of string.
19*0efcd352SStephen Hemminger  * Note: string does not start at beginning of buffer.
20*0efcd352SStephen Hemminger  */
safe_itoa(long val,char * buf,size_t len,unsigned int radix)21*0efcd352SStephen Hemminger static char *safe_itoa(long val, char *buf, size_t len, unsigned int radix)
22*0efcd352SStephen Hemminger {
23*0efcd352SStephen Hemminger 	char *bp = buf + len;
24*0efcd352SStephen Hemminger 	static const char hexdigit[] = "0123456789abcdef";
25*0efcd352SStephen Hemminger 
26*0efcd352SStephen Hemminger 	*--bp = '\0'; /* Null terminate the string */
27*0efcd352SStephen Hemminger 	do {
28*0efcd352SStephen Hemminger 		/* if buffer is not big enough, then truncate */
29*0efcd352SStephen Hemminger 		if (bp == buf)
30*0efcd352SStephen Hemminger 			return bp;
31*0efcd352SStephen Hemminger 
32*0efcd352SStephen Hemminger 		*--bp = hexdigit[val % radix];
33*0efcd352SStephen Hemminger 		val /= radix;
34*0efcd352SStephen Hemminger 	} while (val != 0);
35*0efcd352SStephen Hemminger 
36*0efcd352SStephen Hemminger 	return bp;
37*0efcd352SStephen Hemminger }
38*0efcd352SStephen Hemminger 
39*0efcd352SStephen Hemminger /*
40*0efcd352SStephen Hemminger  * Dump the stack of the calling core
41*0efcd352SStephen Hemminger  *
42*0efcd352SStephen Hemminger  * To be safe in signal handler requires limiting what functions are
43*0efcd352SStephen Hemminger  * used in this code since may be called from inside libc or
44*0efcd352SStephen Hemminger  * when malloc poll is corrupt.
45*0efcd352SStephen Hemminger  *
46*0efcd352SStephen Hemminger  * Most of libc is therefore not safe, include RTE_LOG (calls syslog);
47*0efcd352SStephen Hemminger  * backtrace_symbols (calls malloc), etc.
48*0efcd352SStephen Hemminger  */
rte_dump_stack(void)49*0efcd352SStephen Hemminger void rte_dump_stack(void)
50*0efcd352SStephen Hemminger {
51*0efcd352SStephen Hemminger 	void *func[BACKTRACE_SIZE];
52*0efcd352SStephen Hemminger 	Dl_info info;
53*0efcd352SStephen Hemminger 	char buf1[8], buf2[32], buf3[32], buf4[32];
54*0efcd352SStephen Hemminger 	struct iovec iov[10];
55*0efcd352SStephen Hemminger 	int i, size;
56*0efcd352SStephen Hemminger 
57*0efcd352SStephen Hemminger 	size = backtrace(func, BACKTRACE_SIZE);
58*0efcd352SStephen Hemminger 
59*0efcd352SStephen Hemminger 	for (i = 0; i < size; i++) {
60*0efcd352SStephen Hemminger 		struct iovec *io = iov;
61*0efcd352SStephen Hemminger 		char *str;
62*0efcd352SStephen Hemminger 		uintptr_t base;
63*0efcd352SStephen Hemminger 		long offset;
64*0efcd352SStephen Hemminger 		void *pc = func[i];
65*0efcd352SStephen Hemminger 
66*0efcd352SStephen Hemminger /*
67*0efcd352SStephen Hemminger  * Macro to put string onto set of iovecs.
68*0efcd352SStephen Hemminger  * cast is to suppress warnings about lose of const qualifier.
69*0efcd352SStephen Hemminger  */
70*0efcd352SStephen Hemminger #define PUSH_IOV(io, str) {					\
71*0efcd352SStephen Hemminger 		(io)->iov_base = (char *)(uintptr_t)str;	\
72*0efcd352SStephen Hemminger 		(io)->iov_len = strlen(str);			\
73*0efcd352SStephen Hemminger 		++io; }
74*0efcd352SStephen Hemminger 
75*0efcd352SStephen Hemminger 		/* output stack frame number */
76*0efcd352SStephen Hemminger 		str = safe_itoa(i, buf1, sizeof(buf1), 10);
77*0efcd352SStephen Hemminger 		PUSH_IOV(io, str);	/* iov[0] */
78*0efcd352SStephen Hemminger 		PUSH_IOV(io, ": ");	/* iov[1] */
79*0efcd352SStephen Hemminger 
80*0efcd352SStephen Hemminger 		/* Lookup the symbol information */
81*0efcd352SStephen Hemminger 		if (dladdr(pc, &info) == 0) {
82*0efcd352SStephen Hemminger 			PUSH_IOV(io, "?? [");
83*0efcd352SStephen Hemminger 		} else {
84*0efcd352SStephen Hemminger 			const char *fname;
85*0efcd352SStephen Hemminger 
86*0efcd352SStephen Hemminger 			if (info.dli_fname && *info.dli_fname)
87*0efcd352SStephen Hemminger 				fname = info.dli_fname;
88*0efcd352SStephen Hemminger 			else
89*0efcd352SStephen Hemminger 				fname = "(vdso)";
90*0efcd352SStephen Hemminger 			PUSH_IOV(io, fname);	/* iov[2] */
91*0efcd352SStephen Hemminger 			PUSH_IOV(io, " (");	/* iov[3] */
92*0efcd352SStephen Hemminger 
93*0efcd352SStephen Hemminger 			if (info.dli_saddr != NULL) {
94*0efcd352SStephen Hemminger 				PUSH_IOV(io, info.dli_sname);	/* iov[4] */
95*0efcd352SStephen Hemminger 				base = (uintptr_t)info.dli_saddr;
96*0efcd352SStephen Hemminger 			} else {
97*0efcd352SStephen Hemminger 				str = safe_itoa((unsigned long)info.dli_fbase,
98*0efcd352SStephen Hemminger 					buf3, sizeof(buf3), 16);
99*0efcd352SStephen Hemminger 				PUSH_IOV(io, str);
100*0efcd352SStephen Hemminger 				base = (uintptr_t)info.dli_fbase;
101*0efcd352SStephen Hemminger 			}
102*0efcd352SStephen Hemminger 
103*0efcd352SStephen Hemminger 			PUSH_IOV(io, "+0x");	/* iov[5] */
104*0efcd352SStephen Hemminger 
105*0efcd352SStephen Hemminger 			offset = (uintptr_t)pc - base;
106*0efcd352SStephen Hemminger 			str = safe_itoa(offset, buf4, sizeof(buf4), 16);
107*0efcd352SStephen Hemminger 			PUSH_IOV(io, str);	/* iov[6] */
108*0efcd352SStephen Hemminger 
109*0efcd352SStephen Hemminger 			PUSH_IOV(io, ") [");	/* iov[7] */
110*0efcd352SStephen Hemminger 		}
111*0efcd352SStephen Hemminger 
112*0efcd352SStephen Hemminger 		str = safe_itoa((unsigned long)pc, buf2, sizeof(buf2), 16);
113*0efcd352SStephen Hemminger 		PUSH_IOV(io, str);	/* iov[8] */
114*0efcd352SStephen Hemminger 		PUSH_IOV(io, "]\n");	/* iov[9] */
115*0efcd352SStephen Hemminger 
116*0efcd352SStephen Hemminger 		if (writev(STDERR_FILENO, iov, io - iov) < 0)
117*0efcd352SStephen Hemminger 			break;
118*0efcd352SStephen Hemminger #undef PUSH_IOV
119*0efcd352SStephen Hemminger 	}
120*0efcd352SStephen Hemminger }
121*0efcd352SStephen Hemminger 
122*0efcd352SStephen Hemminger #else /* !RTE_BACKTRACE */
123*0efcd352SStephen Hemminger 
124*0efcd352SStephen Hemminger /* stub if not enabled */
rte_dump_stack(void)125*0efcd352SStephen Hemminger void rte_dump_stack(void) { }
126*0efcd352SStephen Hemminger 
127*0efcd352SStephen Hemminger #endif /* RTE_BACKTRACE */
128