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