]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2016 Klemens Morgenstern |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #ifndef BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ | |
8 | #define BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ | |
9 | ||
10 | #include <boost/dll/detail/demangling/mangled_storage_base.hpp> | |
11 | #include <iterator> | |
12 | #include <algorithm> | |
13 | #include <boost/type_traits/is_const.hpp> | |
14 | #include <boost/type_traits/is_volatile.hpp> | |
15 | #include <boost/type_traits/is_rvalue_reference.hpp> | |
16 | #include <boost/type_traits/is_lvalue_reference.hpp> | |
17 | #include <boost/type_traits/function_traits.hpp> | |
18 | ||
19 | ||
20 | namespace boost { namespace dll { namespace detail { | |
21 | ||
22 | ||
23 | ||
24 | class mangled_storage_impl : public mangled_storage_base | |
25 | { | |
26 | template<typename T> | |
27 | struct dummy {}; | |
28 | ||
29 | template<typename Return, typename ...Args> | |
30 | std::vector<std::string> get_func_params(dummy<Return(Args...)>) const | |
31 | { | |
32 | return {get_name<Args>()...}; | |
33 | } | |
34 | template<typename Return, typename ...Args> | |
35 | std::string get_return_type(dummy<Return(Args...)>) const | |
36 | { | |
37 | return get_name<Return>(); | |
38 | } | |
39 | public: | |
40 | using mangled_storage_base::mangled_storage_base; | |
41 | struct ctor_sym | |
42 | { | |
43 | std::string C1; | |
44 | std::string C2; | |
45 | std::string C3; | |
46 | ||
47 | bool empty() const | |
48 | { | |
49 | return C1.empty() && C2.empty() && C3.empty(); | |
50 | } | |
51 | }; | |
52 | ||
53 | struct dtor_sym | |
54 | { | |
55 | std::string D0; | |
56 | std::string D1; | |
57 | std::string D2; | |
58 | bool empty() const | |
59 | { | |
60 | return D0.empty() && D1.empty() && D2.empty(); | |
61 | } | |
62 | }; | |
63 | ||
64 | template<typename T> | |
65 | std::string get_variable(const std::string &name) const; | |
66 | ||
67 | template<typename Func> | |
68 | std::string get_function(const std::string &name) const; | |
69 | ||
70 | template<typename Class, typename Func> | |
71 | std::string get_mem_fn(const std::string &name) const; | |
72 | ||
73 | template<typename Signature> | |
74 | ctor_sym get_constructor() const; | |
75 | ||
76 | template<typename Class> | |
77 | dtor_sym get_destructor() const; | |
78 | ||
79 | template<typename T> | |
80 | std::string get_type_info() const; | |
81 | ||
82 | template<typename T> | |
83 | std::vector<std::string> get_related() const; | |
84 | ||
85 | }; | |
86 | ||
87 | ||
88 | ||
89 | namespace parser | |
90 | { | |
20effc67 TL |
91 | //! declare |
92 | template <typename... T> | |
93 | struct dummy; | |
94 | ||
95 | template <typename T> | |
96 | std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*); | |
97 | ||
98 | template <typename... T, template <typename...> class Tn> | |
99 | std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*); | |
100 | ||
101 | template <typename... T, template <typename...> class Tn> | |
102 | std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*); | |
103 | ||
104 | template <typename T> | |
105 | std::string parse_type(const mangled_storage_impl & ms, dummy<T>*); | |
106 | ||
107 | template <typename T1, typename T2, typename... T3> | |
108 | std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*); | |
109 | ||
110 | template <typename R, typename... Args> | |
111 | std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*); | |
112 | ||
113 | std::string parse_type(const mangled_storage_impl & ms, dummy<>*); | |
114 | ||
115 | template<typename T> | |
116 | std::string | |
117 | type_name(const mangled_storage_impl &); | |
118 | ||
119 | ||
120 | //The purpose of this class template is to separate the pure type from the rule name from the target type | |
121 | template<typename T> | |
122 | struct pure_type | |
123 | { | |
124 | typedef T type; | |
125 | inline static std::string type_rule() { return ""; } | |
126 | }; | |
127 | ||
128 | template<typename T> | |
129 | struct pure_type<T*> | |
130 | { | |
131 | typedef typename pure_type<T>::type type; | |
132 | inline static std::string type_rule() | |
133 | { | |
134 | return pure_type<T>::type_rule() + "*"; | |
135 | } | |
136 | }; | |
137 | ||
138 | template<typename T> | |
139 | struct pure_type<T const> | |
140 | { | |
141 | typedef typename pure_type<T>::type type; | |
142 | inline static std::string type_rule() | |
143 | { | |
144 | return pure_type<T>::type_rule() + " const"; | |
145 | } | |
146 | }; | |
147 | ||
148 | template<typename T> | |
149 | struct pure_type<T volatile> | |
150 | { | |
151 | typedef typename pure_type<T>::type type; | |
152 | inline static std::string type_rule() | |
153 | { | |
154 | return pure_type<T>::type_rule() + " volatile"; | |
155 | } | |
156 | }; | |
157 | ||
158 | template<typename T> | |
159 | struct pure_type<T const volatile> | |
160 | { | |
161 | typedef typename pure_type<T>::type type; | |
162 | inline static std::string type_rule() | |
163 | { | |
164 | return pure_type<T>::type_rule() + " const volatile"; | |
165 | } | |
166 | }; | |
167 | ||
168 | template<typename T> | |
169 | struct pure_type<T&> | |
170 | { | |
171 | typedef typename pure_type<T>::type type; | |
172 | inline static std::string type_rule() | |
173 | { | |
174 | return pure_type<T>::type_rule() + "&"; | |
175 | } | |
176 | }; | |
177 | ||
178 | template<typename T> | |
179 | struct pure_type<T&&> | |
180 | { | |
181 | typedef typename pure_type<T>::type type; | |
182 | inline static std::string type_rule() | |
183 | { | |
184 | return pure_type<T>::type_rule() + "&&"; | |
185 | } | |
186 | }; | |
7c673cae FG |
187 | |
188 | inline std::string const_rule_impl(true_type ) {return " const";} | |
189 | inline std::string const_rule_impl(false_type) {return "";} | |
190 | template<typename T> | |
191 | std::string const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());} | |
192 | ||
193 | inline std::string volatile_rule_impl(true_type ) {return " volatile";} | |
194 | inline std::string volatile_rule_impl(false_type) {return "";} | |
195 | template<typename T> | |
196 | std::string volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());} | |
197 | ||
198 | inline std::string reference_rule_impl(false_type, false_type) {return "";} | |
199 | inline std::string reference_rule_impl(true_type, false_type) {return "&" ;} | |
200 | inline std::string reference_rule_impl(false_type, true_type ) {return "&&";} | |
201 | ||
7c673cae FG |
202 | template<typename T> |
203 | std::string reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());} | |
204 | ||
205 | //it takes a string, because it may be overloaded. | |
7c673cae FG |
206 | template<typename Return, typename Arg> |
207 | std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) | |
208 | { | |
209 | using namespace std; | |
20effc67 | 210 | return type_name<Arg>(ms); |
7c673cae FG |
211 | } |
212 | ||
213 | template<typename Return, typename First, typename Second, typename ...Args> | |
214 | std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...)) | |
215 | { | |
7c673cae | 216 | using next_type = Return (*)(Second, Args...); |
20effc67 | 217 | return type_name<First>(ms) + ", " + arg_list(ms, next_type()); |
7c673cae FG |
218 | } |
219 | ||
220 | template<typename Return> | |
221 | std::string arg_list(const mangled_storage_impl &, Return (*)()) | |
222 | { | |
223 | return ""; | |
224 | } | |
20effc67 TL |
225 | |
226 | //! implement | |
227 | template <typename T> | |
228 | inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*) { | |
229 | return ms.get_name<T>(); | |
230 | } | |
231 | ||
232 | template <typename... T, template <typename...> class Tn> | |
233 | inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*) { | |
234 | using type = dummy<Tn<T...>>*; | |
235 | return parse_type(ms, type()); | |
236 | } | |
237 | ||
238 | template <typename R, typename... Args> | |
239 | inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(*)(Args...)>*) { | |
240 | using args_type = dummy<Args...>*; | |
241 | using return_type = dummy<R>*; | |
242 | return parse_type(ms, return_type()) + " (*)(" + parse_type(ms, args_type()) + ")"; | |
243 | } | |
244 | ||
245 | template <typename R, typename... Args> | |
246 | inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*) { | |
247 | using args_type = dummy<Args...>*; | |
248 | using return_type = dummy<R>*; | |
249 | return parse_type(ms, return_type()) + " (" + parse_type(ms, args_type()) + ")"; | |
250 | } | |
251 | ||
252 | template <typename T> | |
253 | inline std::string parse_type(const mangled_storage_impl & ms, dummy<T>*) { | |
254 | using type = dummy<typename pure_type<T>::type>*; | |
255 | auto str = parse_type_helper(ms, type()); | |
256 | return str + pure_type<T>::type_rule(); | |
257 | } | |
258 | ||
259 | template <typename T1, typename T2, typename... T3> | |
260 | inline std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*) { | |
261 | using first_type = dummy<T1>*; | |
262 | using next_type = dummy<T2, T3...>*; | |
263 | return parse_type(ms, first_type()) + ", " + parse_type(ms, next_type()); | |
264 | } | |
265 | ||
266 | template <typename... T, template <typename...> class Tn> | |
267 | inline std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*) { | |
268 | using next_type = dummy<T...>*; | |
269 | std::string str = ms.get_name<Tn<T...>>(); | |
270 | auto frist = str.find_first_of("<"); | |
271 | std::string template_name = str.substr(0, frist); | |
272 | std::string args_name = parse_type(ms, next_type()); | |
273 | char last_ch = args_name[args_name.size() - 1]; | |
274 | return template_name + "<" + args_name + (last_ch == '>' ? " >" : ">"); | |
275 | } | |
276 | ||
277 | inline std::string parse_type(const mangled_storage_impl &, dummy<>*) { | |
278 | return ""; | |
279 | } | |
280 | ||
281 | template<typename T> | |
282 | inline std::string | |
283 | type_name(const mangled_storage_impl &ms) | |
284 | { | |
285 | using namespace parser; | |
286 | using type = dummy<T>*; | |
287 | return parse_type(ms, type()); | |
288 | } | |
7c673cae FG |
289 | } |
290 | ||
291 | ||
292 | ||
293 | template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const | |
294 | { | |
295 | auto found = std::find_if(storage_.begin(), storage_.end(), | |
296 | [&](const entry& e) {return e.demangled == name;}); | |
297 | ||
298 | if (found != storage_.end()) | |
299 | return found->mangled; | |
300 | else | |
301 | return ""; | |
302 | } | |
303 | ||
304 | template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const | |
305 | { | |
306 | using func_type = Func*; | |
307 | ||
308 | auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')'; | |
309 | ||
310 | auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;}); | |
311 | if (found != storage_.end()) | |
312 | return found->mangled; | |
313 | else | |
314 | return ""; | |
315 | ||
316 | } | |
317 | ||
318 | template<typename Class, typename Func> | |
319 | std::string mangled_storage_impl::get_mem_fn(const std::string &name) const | |
320 | { | |
321 | using namespace parser; | |
322 | ||
323 | using func_type = Func*; | |
324 | ||
325 | std::string cname = get_name<Class>(); | |
326 | ||
f67539c2 | 327 | const auto matcher = cname + "::" + name + |
7c673cae FG |
328 | '(' + parser::arg_list(*this, func_type()) + ')' |
329 | + const_rule<Class>() + volatile_rule<Class>(); | |
330 | ||
f67539c2 TL |
331 | // Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type. |
332 | auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) { | |
333 | if (e.demangled == matcher) { | |
334 | return true; | |
335 | } | |
336 | ||
337 | const auto pos = e.demangled.rfind(matcher); | |
338 | if (pos == std::string::npos) { | |
339 | // Not found. | |
340 | return false; | |
341 | } | |
342 | ||
343 | if (pos + matcher.size() != e.demangled.size()) { | |
344 | // There are some characters after the `matcher` string. | |
345 | return false; | |
346 | } | |
347 | ||
348 | // Double checking that we matched a full function name | |
349 | return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0` | |
350 | }); | |
7c673cae FG |
351 | |
352 | if (found != storage_.end()) | |
353 | return found->mangled; | |
354 | else | |
355 | return ""; | |
356 | ||
357 | } | |
358 | ||
359 | ||
360 | template<typename Signature> | |
361 | auto mangled_storage_impl::get_constructor() const -> ctor_sym | |
362 | { | |
363 | using namespace parser; | |
364 | ||
365 | using func_type = Signature*; | |
366 | ||
367 | std::string ctor_name; // = class_name + "::" + name; | |
368 | std::string unscoped_cname; //the unscoped class-name | |
369 | { | |
370 | auto class_name = get_return_type(dummy<Signature>()); | |
371 | auto pos = class_name.rfind("::"); | |
372 | if (pos == std::string::npos) | |
373 | { | |
374 | ctor_name = class_name+ "::" +class_name ; | |
375 | unscoped_cname = class_name; | |
376 | } | |
377 | else | |
378 | { | |
379 | unscoped_cname = class_name.substr(pos+2) ; | |
380 | ctor_name = class_name+ "::" + unscoped_cname; | |
381 | } | |
382 | } | |
383 | ||
384 | auto matcher = | |
385 | ctor_name + '(' + parser::arg_list(*this, func_type()) + ')'; | |
386 | ||
387 | ||
388 | std::vector<entry> findings; | |
389 | std::copy_if(storage_.begin(), storage_.end(), | |
390 | std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;}); | |
391 | ||
392 | ctor_sym ct; | |
393 | ||
394 | for (auto & e : findings) | |
395 | { | |
396 | ||
397 | if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos) | |
398 | ct.C1 = e.mangled; | |
399 | else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos) | |
400 | ct.C2 = e.mangled; | |
401 | else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos) | |
402 | ct.C3 = e.mangled; | |
403 | } | |
404 | return ct; | |
405 | } | |
406 | ||
407 | template<typename Class> | |
408 | auto mangled_storage_impl::get_destructor() const -> dtor_sym | |
409 | { | |
410 | std::string dtor_name; // = class_name + "::" + name; | |
411 | std::string unscoped_cname; //the unscoped class-name | |
412 | { | |
413 | auto class_name = get_name<Class>(); | |
414 | auto pos = class_name.rfind("::"); | |
415 | if (pos == std::string::npos) | |
416 | { | |
417 | dtor_name = class_name+ "::~" + class_name + "()"; | |
418 | unscoped_cname = class_name; | |
419 | } | |
420 | else | |
421 | { | |
422 | unscoped_cname = class_name.substr(pos+2) ; | |
423 | dtor_name = class_name+ "::~" + unscoped_cname + "()"; | |
424 | } | |
425 | } | |
426 | ||
427 | auto d0 = unscoped_cname + "D0Ev"; | |
428 | auto d1 = unscoped_cname + "D1Ev"; | |
429 | auto d2 = unscoped_cname + "D2Ev"; | |
430 | ||
431 | dtor_sym dt; | |
432 | //this is so simple, i don#t need a predicate | |
433 | for (auto & s : storage_) | |
434 | { | |
435 | //alright, name fits | |
436 | if (s.demangled == dtor_name) | |
437 | { | |
438 | if (s.mangled.find(d0) != std::string::npos) | |
439 | dt.D0 = s.mangled; | |
440 | else if (s.mangled.find(d1) != std::string::npos) | |
441 | dt.D1 = s.mangled; | |
442 | else if (s.mangled.find(d2) != std::string::npos) | |
443 | dt.D2 = s.mangled; | |
444 | ||
445 | } | |
446 | } | |
447 | return dt; | |
448 | ||
449 | } | |
450 | ||
451 | template<typename T> | |
452 | std::string mangled_storage_impl::get_type_info() const | |
453 | { | |
454 | std::string id = "typeinfo for " + get_name<T>(); | |
455 | ||
456 | ||
457 | auto predicate = [&](const mangled_storage_base::entry & e) | |
458 | { | |
459 | return e.demangled == id; | |
460 | }; | |
461 | ||
462 | auto found = std::find_if(storage_.begin(), storage_.end(), predicate); | |
463 | ||
464 | ||
465 | if (found != storage_.end()) | |
466 | return found->mangled; | |
467 | else | |
468 | return ""; | |
469 | } | |
470 | ||
471 | template<typename T> | |
472 | std::vector<std::string> mangled_storage_impl::get_related() const | |
473 | { | |
474 | std::vector<std::string> ret; | |
475 | auto name = get_name<T>(); | |
476 | ||
477 | for (auto & c : storage_) | |
478 | { | |
479 | if (c.demangled.find(name) != std::string::npos) | |
480 | ret.push_back(c.demangled); | |
481 | } | |
482 | ||
483 | return ret; | |
484 | } | |
485 | ||
486 | }}} | |
487 | ||
488 | ||
489 | #endif /* BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */ |