itanium.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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. inline std::string const_rule_impl(true_type ) {return " const";}
  71. inline std::string const_rule_impl(false_type) {return "";}
  72. template<typename T>
  73. std::string const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
  74. inline std::string volatile_rule_impl(true_type ) {return " volatile";}
  75. inline std::string volatile_rule_impl(false_type) {return "";}
  76. template<typename T>
  77. std::string volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
  78. inline std::string reference_rule_impl(false_type, false_type) {return "";}
  79. inline std::string reference_rule_impl(true_type, false_type) {return "&" ;}
  80. inline std::string reference_rule_impl(false_type, true_type ) {return "&&";}
  81. template<typename T>
  82. 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());}
  83. //it takes a string, because it may be overloaded.
  84. template<typename T>
  85. std::string type_rule(const std::string & type_name)
  86. {
  87. using namespace std;
  88. return type_name +
  89. const_rule<T>() +
  90. volatile_rule<T>() +
  91. reference_rule<T>();
  92. }
  93. template<typename Return, typename Arg>
  94. std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
  95. {
  96. using namespace std;
  97. auto str = ms.get_name<Arg>();
  98. return type_rule<Arg>(str);
  99. }
  100. template<typename Return, typename First, typename Second, typename ...Args>
  101. std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
  102. {
  103. auto st = ms.get_name<First>();
  104. using next_type = Return (*)(Second, Args...);
  105. return type_rule<First>(st) + ", " + arg_list(ms, next_type());
  106. }
  107. template<typename Return>
  108. std::string arg_list(const mangled_storage_impl &, Return (*)())
  109. {
  110. return "";
  111. }
  112. }
  113. template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const
  114. {
  115. auto found = std::find_if(storage_.begin(), storage_.end(),
  116. [&](const entry& e) {return e.demangled == name;});
  117. if (found != storage_.end())
  118. return found->mangled;
  119. else
  120. return "";
  121. }
  122. template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const
  123. {
  124. using func_type = Func*;
  125. auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')';
  126. auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
  127. if (found != storage_.end())
  128. return found->mangled;
  129. else
  130. return "";
  131. }
  132. template<typename Class, typename Func>
  133. std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
  134. {
  135. using namespace parser;
  136. using func_type = Func*;
  137. std::string cname = get_name<Class>();
  138. const auto matcher = cname + "::" + name +
  139. '(' + parser::arg_list(*this, func_type()) + ')'
  140. + const_rule<Class>() + volatile_rule<Class>();
  141. // Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type.
  142. auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) {
  143. if (e.demangled == matcher) {
  144. return true;
  145. }
  146. const auto pos = e.demangled.rfind(matcher);
  147. if (pos == std::string::npos) {
  148. // Not found.
  149. return false;
  150. }
  151. if (pos + matcher.size() != e.demangled.size()) {
  152. // There are some characters after the `matcher` string.
  153. return false;
  154. }
  155. // Double checking that we matched a full function name
  156. return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0`
  157. });
  158. if (found != storage_.end())
  159. return found->mangled;
  160. else
  161. return "";
  162. }
  163. template<typename Signature>
  164. auto mangled_storage_impl::get_constructor() const -> ctor_sym
  165. {
  166. using namespace parser;
  167. using func_type = Signature*;
  168. std::string ctor_name; // = class_name + "::" + name;
  169. std::string unscoped_cname; //the unscoped class-name
  170. {
  171. auto class_name = get_return_type(dummy<Signature>());
  172. auto pos = class_name.rfind("::");
  173. if (pos == std::string::npos)
  174. {
  175. ctor_name = class_name+ "::" +class_name ;
  176. unscoped_cname = class_name;
  177. }
  178. else
  179. {
  180. unscoped_cname = class_name.substr(pos+2) ;
  181. ctor_name = class_name+ "::" + unscoped_cname;
  182. }
  183. }
  184. auto matcher =
  185. ctor_name + '(' + parser::arg_list(*this, func_type()) + ')';
  186. std::vector<entry> findings;
  187. std::copy_if(storage_.begin(), storage_.end(),
  188. std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;});
  189. ctor_sym ct;
  190. for (auto & e : findings)
  191. {
  192. if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos)
  193. ct.C1 = e.mangled;
  194. else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos)
  195. ct.C2 = e.mangled;
  196. else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos)
  197. ct.C3 = e.mangled;
  198. }
  199. return ct;
  200. }
  201. template<typename Class>
  202. auto mangled_storage_impl::get_destructor() const -> dtor_sym
  203. {
  204. std::string dtor_name; // = class_name + "::" + name;
  205. std::string unscoped_cname; //the unscoped class-name
  206. {
  207. auto class_name = get_name<Class>();
  208. auto pos = class_name.rfind("::");
  209. if (pos == std::string::npos)
  210. {
  211. dtor_name = class_name+ "::~" + class_name + "()";
  212. unscoped_cname = class_name;
  213. }
  214. else
  215. {
  216. unscoped_cname = class_name.substr(pos+2) ;
  217. dtor_name = class_name+ "::~" + unscoped_cname + "()";
  218. }
  219. }
  220. auto d0 = unscoped_cname + "D0Ev";
  221. auto d1 = unscoped_cname + "D1Ev";
  222. auto d2 = unscoped_cname + "D2Ev";
  223. dtor_sym dt;
  224. //this is so simple, i don#t need a predicate
  225. for (auto & s : storage_)
  226. {
  227. //alright, name fits
  228. if (s.demangled == dtor_name)
  229. {
  230. if (s.mangled.find(d0) != std::string::npos)
  231. dt.D0 = s.mangled;
  232. else if (s.mangled.find(d1) != std::string::npos)
  233. dt.D1 = s.mangled;
  234. else if (s.mangled.find(d2) != std::string::npos)
  235. dt.D2 = s.mangled;
  236. }
  237. }
  238. return dt;
  239. }
  240. template<typename T>
  241. std::string mangled_storage_impl::get_type_info() const
  242. {
  243. std::string id = "typeinfo for " + get_name<T>();
  244. auto predicate = [&](const mangled_storage_base::entry & e)
  245. {
  246. return e.demangled == id;
  247. };
  248. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  249. if (found != storage_.end())
  250. return found->mangled;
  251. else
  252. return "";
  253. }
  254. template<typename T>
  255. std::vector<std::string> mangled_storage_impl::get_related() const
  256. {
  257. std::vector<std::string> ret;
  258. auto name = get_name<T>();
  259. for (auto & c : storage_)
  260. {
  261. if (c.demangled.find(name) != std::string::npos)
  262. ret.push_back(c.demangled);
  263. }
  264. return ret;
  265. }
  266. }}}
  267. #endif /* BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */