Line data Source code
1 : // Copyright (c) 2019-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/
4 : // contact@m2osw.com
5 : //
6 : // Permission is hereby granted, free of charge, to any person obtaining a
7 : // copy of this software and associated documentation files (the
8 : // "Software"), to deal in the Software without restriction, including
9 : // without limitation the rights to use, copy, modify, merge, publish,
10 : // distribute, sublicense, and/or sell copies of the Software, and to
11 : // permit persons to whom the Software is furnished to do so, subject to
12 : // the following conditions:
13 : //
14 : // The above copyright notice and this permission notice shall be included
15 : // in all copies or substantial portions of the Software.
16 : //
17 : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 : // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 : // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 : // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 : // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 : // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 :
25 : #include "./demangle.h"
26 :
27 : // C++ includes
28 : //
29 : #include <cxxabi.h>
30 : #include <memory>
31 :
32 :
33 : /** \file
34 : * \brief Implementation of the demandler functions.
35 : *
36 : * This file includes functions we can use to demangle C++ names.
37 : */
38 :
39 :
40 :
41 : namespace libexcept
42 : {
43 :
44 :
45 :
46 : /** \brief Demangle the specified type string.
47 : *
48 : * C++ offers a `typeid(\<type>).name()` function, only that does not
49 : * return a readable name in many cases. This function transforms that
50 : * name back to the original. This is particularly useful for C++ base
51 : * types. For example "unsigned short" becomes "t". To verify a type,
52 : * it is quite practical.
53 : *
54 : * This function demangles all names, including those we get when
55 : * building a stack trace.
56 : *
57 : * \note
58 : * This is similar to using the c++filt command line tool. If the
59 : * conversion fails, then the function returns the input string as is.
60 : *
61 : * \note
62 : * I found a piece of code snippet on Catch2 which is used to demangle a C++
63 : * name. It is one simple ABI call!
64 : *
65 : * \code
66 : * #include "catch.hpp"
67 : *
68 : * #include <cxxabi.h>
69 : * #include <typeinfo>
70 : *
71 : * CATCH_TRANSLATE_EXCEPTION(std::exception& e) {
72 : * std::string s;
73 : * int status;
74 : *
75 : * const char* name = typeid(e).name();
76 : * char* realname = abi::__cxa_demangle(name, 0, 0, &status);
77 : * if(realname) {
78 : * s.append(realname);
79 : * } else {
80 : * s.append(name);
81 : * }
82 : * s.append(": ");
83 : * s.append(e.what());
84 : * free(realname);
85 : * return s;
86 : * }
87 : * \endcode
88 : *
89 : * Source: https://github.com/catchorg/Catch2/issues/539
90 : *
91 : * \param[in] type_id_name The mangled C++ name.
92 : *
93 : * \return The converted name.
94 : *
95 : * \sa https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
96 : */
97 29 : std::string demangle_cpp_name(char const * type_id_name)
98 : {
99 : #if 1
100 29 : int status(0);
101 :
102 29 : std::unique_ptr<char, void(*)(void*)> res {
103 : abi::__cxa_demangle(type_id_name, nullptr, nullptr, &status),
104 : std::free
105 58 : };
106 :
107 29 : return status == 0
108 : ? res.get()
109 87 : : type_id_name;
110 : #else
111 : // keeping the fallback in case the ABI stops working over time
112 : // this is "very" slow since it runs an external tool (c++filt)
113 : //
114 : std::string cppfilt("c++filt "
115 : + raw_function_name);
116 : std::unique_ptr<FILE, decltype(&::pclose)> p(popen(cppfilt.c_str(), "r"), &::pclose);
117 : for(;;)
118 : {
119 : int const c(fgetc(p.get()));
120 : if(c == EOF)
121 : {
122 : break;
123 : }
124 : if(c != '\n')
125 : {
126 : result += c;
127 : }
128 : }
129 : #endif
130 : }
131 :
132 :
133 :
134 : }
135 : // namespace libexcept
136 : // vim: ts=4 sw=4 et
|