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