itanium.hpp 14 KB

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