Line data Source code
1 : // Copyright (c) 2019-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/libexcept
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : #include "./demangle.h"
21 :
22 : // C++ includes
23 : //
24 : #include <cxxabi.h>
25 : #include <memory>
26 :
27 :
28 : /** \file
29 : * \brief Implementation of the demandler functions.
30 : *
31 : * This file includes functions we can use to demangle C++ names.
32 : */
33 :
34 :
35 :
36 : namespace libexcept
37 : {
38 :
39 :
40 :
41 : /** \brief Demangle the specified type string.
42 : *
43 : * C++ offers a `typeid(\<type>).name()` function, only that does not
44 : * return a readable name in many cases. This function transforms that
45 : * name back to the original. This is particularly useful for C++ base
46 : * types. For example "unsigned short" becomes "t". To verify a type,
47 : * it is quite practical.
48 : *
49 : * This function demangles all names, including those we get when
50 : * building a stack trace.
51 : *
52 : * \note
53 : * This is similar to using the c++filt command line tool. If the
54 : * conversion fails, then the function returns the input string as is.
55 : *
56 : * \note
57 : * I found a piece of code snippet on Catch2 which is used to demangle a C++
58 : * name. It is one simple ABI call!
59 : *
60 : * \code
61 : * #include "catch.hpp"
62 : *
63 : * #include <cxxabi.h>
64 : * #include <typeinfo>
65 : *
66 : * CATCH_TRANSLATE_EXCEPTION(std::exception& e) {
67 : * std::string s;
68 : * int status;
69 : *
70 : * const char* name = typeid(e).name();
71 : * char* realname = abi::__cxa_demangle(name, 0, 0, &status);
72 : * if(realname) {
73 : * s.append(realname);
74 : * } else {
75 : * s.append(name);
76 : * }
77 : * s.append(": ");
78 : * s.append(e.what());
79 : * free(realname);
80 : * return s;
81 : * }
82 : * \endcode
83 : *
84 : * Source: https://github.com/catchorg/Catch2/issues/539
85 : *
86 : * \param[in] type_id_name The mangled C++ name.
87 : *
88 : * \return The converted name.
89 : *
90 : * \sa https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
91 : */
92 29 : std::string demangle_cpp_name(char const * type_id_name)
93 : {
94 : #if 1
95 29 : int status(0);
96 :
97 29 : std::unique_ptr<char, void(*)(void*)> res {
98 : abi::__cxa_demangle(type_id_name, nullptr, nullptr, &status),
99 : std::free
100 58 : };
101 :
102 29 : return status == 0
103 : ? res.get()
104 87 : : type_id_name;
105 : #else
106 : // keeping the fallback in case the ABI stops working over time
107 : // this is "very" slow since it runs an external tool (c++filt)
108 : //
109 : std::string cppfilt("c++filt "
110 : + raw_function_name);
111 : std::unique_ptr<FILE, decltype(&::pclose)> p(popen(cppfilt.c_str(), "r"), &::pclose);
112 : for(;;)
113 : {
114 : int const c(fgetc(p.get()));
115 : if(c == EOF)
116 : {
117 : break;
118 : }
119 : if(c != '\n')
120 : {
121 : result += c;
122 : }
123 : }
124 : #endif
125 : }
126 :
127 :
128 :
129 : }
130 : // namespace libexcept
131 : // vim: ts=4 sw=4 et
|