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