itanium.hpp 14 KB

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