]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
7c673cae FG |
4 | #include <ostream> |
5 | #include <cxxabi.h> | |
7c673cae FG |
6 | #include <string.h> |
7 | ||
8 | #include "BackTrace.h" | |
7c673cae | 9 | #include "common/version.h" |
11fdf7f2 | 10 | #include "common/Formatter.h" |
7c673cae FG |
11 | |
12 | #define _STR(x) #x | |
13 | #define STRINGIFY(x) _STR(x) | |
14 | ||
15 | namespace ceph { | |
16 | ||
17 | void BackTrace::print(std::ostream& out) const | |
18 | { | |
19 | out << " " << pretty_version_to_str() << std::endl; | |
20 | for (size_t i = skip; i < size; i++) { | |
21 | // out << " " << (i-skip+1) << ": " << strings[i] << std::endl; | |
22 | ||
23 | size_t sz = 1024; // just a guess, template names will go much wider | |
24 | char *function = (char *)malloc(sz); | |
25 | if (!function) | |
26 | return; | |
27 | char *begin = 0, *end = 0; | |
28 | ||
29 | // find the parentheses and address offset surrounding the mangled name | |
30 | #ifdef __FreeBSD__ | |
31 | static constexpr char OPEN = '<'; | |
32 | #else | |
33 | static constexpr char OPEN = '('; | |
34 | #endif | |
35 | for (char *j = strings[i]; *j; ++j) { | |
36 | if (*j == OPEN) | |
37 | begin = j+1; | |
38 | else if (*j == '+') | |
39 | end = j; | |
40 | } | |
41 | if (begin && end) { | |
42 | int len = end - begin; | |
43 | char *foo = (char *)malloc(len+1); | |
44 | if (!foo) { | |
45 | free(function); | |
46 | return; | |
47 | } | |
48 | memcpy(foo, begin, len); | |
49 | foo[len] = 0; | |
50 | ||
51 | int status; | |
52 | char *ret = nullptr; | |
53 | // only demangle a C++ mangled name | |
54 | if (foo[0] == '_' && foo[1] == 'Z') | |
55 | ret = abi::__cxa_demangle(foo, function, &sz, &status); | |
56 | if (ret) { | |
57 | // return value may be a realloc() of the input | |
58 | function = ret; | |
59 | } | |
60 | else { | |
61 | // demangling failed, just pretend it's a C function with no args | |
62 | strncpy(function, foo, sz); | |
63 | strncat(function, "()", sz); | |
64 | function[sz-1] = 0; | |
65 | } | |
66 | out << " " << (i-skip+1) << ": " << OPEN << function << end << std::endl; | |
67 | //fprintf(out, " %s:%s\n", stack.strings[i], function); | |
68 | free(foo); | |
69 | } else { | |
70 | // didn't find the mangled name, just print the whole line | |
71 | out << " " << (i-skip+1) << ": " << strings[i] << std::endl; | |
72 | } | |
73 | free(function); | |
74 | } | |
75 | } | |
76 | ||
11fdf7f2 TL |
77 | void BackTrace::dump(Formatter *f) const |
78 | { | |
79 | f->open_array_section("backtrace"); | |
80 | for (size_t i = skip; i < size; i++) { | |
81 | // out << " " << (i-skip+1) << ": " << strings[i] << std::endl; | |
82 | ||
83 | size_t sz = 1024; // just a guess, template names will go much wider | |
84 | char *function = (char *)malloc(sz); | |
85 | if (!function) | |
86 | return; | |
87 | char *begin = 0, *end = 0; | |
88 | ||
89 | // find the parentheses and address offset surrounding the mangled name | |
90 | #ifdef __FreeBSD__ | |
91 | static constexpr char OPEN = '<'; | |
92 | #else | |
93 | static constexpr char OPEN = '('; | |
94 | #endif | |
95 | for (char *j = strings[i]; *j; ++j) { | |
96 | if (*j == OPEN) | |
97 | begin = j+1; | |
98 | else if (*j == '+') | |
99 | end = j; | |
100 | } | |
101 | if (begin && end) { | |
102 | int len = end - begin; | |
103 | char *foo = (char *)malloc(len+1); | |
104 | if (!foo) { | |
105 | free(function); | |
106 | return; | |
107 | } | |
108 | memcpy(foo, begin, len); | |
109 | foo[len] = 0; | |
110 | ||
111 | int status; | |
112 | char *ret = nullptr; | |
113 | // only demangle a C++ mangled name | |
114 | if (foo[0] == '_' && foo[1] == 'Z') | |
115 | ret = abi::__cxa_demangle(foo, function, &sz, &status); | |
116 | if (ret) { | |
117 | // return value may be a realloc() of the input | |
118 | function = ret; | |
119 | } | |
120 | else { | |
121 | // demangling failed, just pretend it's a C function with no args | |
122 | strncpy(function, foo, sz); | |
123 | strncat(function, "()", sz); | |
124 | function[sz-1] = 0; | |
125 | } | |
126 | f->dump_stream("frame") << OPEN << function << end; | |
127 | //fprintf(out, " %s:%s\n", stack.strings[i], function); | |
128 | free(foo); | |
129 | } else { | |
130 | // didn't find the mangled name, just print the whole line | |
131 | //out << " " << (i-skip+1) << ": " << strings[i] << std::endl; | |
132 | f->dump_string("frame", strings[i]); | |
133 | } | |
134 | free(function); | |
135 | } | |
136 | f->close_section(); | |
137 | } | |
138 | ||
7c673cae | 139 | } |