Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:42

0001 //  Copyright 2016 Klemens Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
0008 #define BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
0009 
0010 #include <boost/dll/detail/demangling/mangled_storage_base.hpp>
0011 #include <iterator>
0012 #include <algorithm>
0013 #include <boost/type_traits/is_const.hpp>
0014 #include <boost/type_traits/is_volatile.hpp>
0015 #include <boost/type_traits/is_rvalue_reference.hpp>
0016 #include <boost/type_traits/is_lvalue_reference.hpp>
0017 #include <boost/type_traits/function_traits.hpp>
0018 
0019 
0020 namespace boost { namespace dll { namespace detail {
0021 
0022 
0023 
0024 class mangled_storage_impl : public mangled_storage_base
0025 {
0026     template<typename T>
0027     struct dummy {};
0028 
0029     template<typename Return, typename ...Args>
0030     std::vector<std::string> get_func_params(dummy<Return(Args...)>)  const
0031     {
0032         return {get_name<Args>()...};
0033     }
0034     template<typename Return, typename ...Args>
0035     std::string get_return_type(dummy<Return(Args...)>)  const
0036     {
0037         return get_name<Return>();
0038     }
0039 public:
0040     using mangled_storage_base::mangled_storage_base;
0041     struct ctor_sym
0042     {
0043         std::string C1;
0044         std::string C2;
0045         std::string C3;
0046 
0047         bool empty() const
0048         {
0049             return C1.empty() && C2.empty() && C3.empty();
0050         }
0051     };
0052 
0053     struct dtor_sym
0054     {
0055         std::string D0;
0056         std::string D1;
0057         std::string D2;
0058         bool empty() const
0059         {
0060             return D0.empty() && D1.empty() && D2.empty();
0061         }
0062     };
0063 
0064     template<typename T>
0065     std::string get_variable(const std::string &name) const;
0066 
0067     template<typename Func>
0068     std::string get_function(const std::string &name) const;
0069 
0070     template<typename Class, typename Func>
0071     std::string get_mem_fn(const std::string &name) const;
0072 
0073     template<typename Signature>
0074     ctor_sym get_constructor() const;
0075 
0076     template<typename Class>
0077     dtor_sym get_destructor() const;
0078 
0079     template<typename T>
0080     std::string get_type_info() const;
0081 
0082     template<typename T>
0083     std::vector<std::string> get_related() const;
0084 
0085 };
0086 
0087 
0088 
0089 namespace parser
0090 {
0091     //! declare
0092     template <typename... T>
0093     struct dummy;
0094 
0095     template <typename T>
0096     std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*);
0097 
0098     template <typename... T, template <typename...> class Tn>
0099     std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
0100 
0101     template <typename... T, template <typename...> class Tn>
0102     std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
0103 
0104     template <typename T>
0105     std::string parse_type(const mangled_storage_impl & ms, dummy<T>*);
0106 
0107     template <typename T1, typename T2, typename... T3>
0108     std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*);
0109 
0110     template <typename R, typename... Args>
0111     std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*);
0112 
0113     std::string parse_type(const mangled_storage_impl & ms, dummy<>*);
0114 
0115     template<typename T>
0116     std::string
0117     type_name(const mangled_storage_impl &);
0118 
0119 
0120     //The purpose of this class template is to separate the pure type from the rule name from the target type
0121     template<typename T>
0122     struct pure_type
0123     {
0124         typedef T type;
0125         inline static std::string type_rule() { return ""; }
0126     };
0127 
0128     template<typename T>
0129     struct pure_type<T*>
0130     {
0131         typedef typename pure_type<T>::type type;
0132         inline static std::string type_rule()
0133         {
0134             return pure_type<T>::type_rule() + "*";
0135         }
0136     };
0137 
0138     template<typename T>
0139     struct pure_type<T const>
0140     {
0141         typedef typename pure_type<T>::type type;
0142         inline static std::string type_rule()
0143         {
0144             return pure_type<T>::type_rule() + " const";
0145         }
0146     };
0147 
0148     template<typename T>
0149     struct pure_type<T volatile>
0150     {
0151         typedef typename pure_type<T>::type type;
0152         inline static std::string type_rule()
0153         {
0154             return pure_type<T>::type_rule() + " volatile";
0155         }
0156     };
0157 
0158     template<typename T>
0159     struct pure_type<T const volatile>
0160     {
0161         typedef typename pure_type<T>::type type;
0162         inline static std::string type_rule()
0163         {
0164             return pure_type<T>::type_rule() + " const volatile";
0165         }
0166     };
0167 
0168     template<typename T>
0169     struct pure_type<T&>
0170     {
0171         typedef typename pure_type<T>::type type;
0172         inline static std::string type_rule()
0173         {
0174             return pure_type<T>::type_rule() + "&";
0175         }
0176     };
0177 
0178     template<typename T>
0179     struct pure_type<T&&>
0180     {
0181         typedef typename pure_type<T>::type type;
0182         inline static std::string type_rule()
0183         {
0184             return pure_type<T>::type_rule() + "&&";
0185         }
0186     };
0187 
0188     inline std::string const_rule_impl(true_type )  {return " const";}
0189     inline std::string const_rule_impl(false_type)  {return "";}
0190     template<typename T>
0191     std::string const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
0192 
0193     inline std::string volatile_rule_impl(true_type )  {return " volatile";}
0194     inline std::string volatile_rule_impl(false_type)  {return "";}
0195     template<typename T>
0196     std::string volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
0197 
0198     inline std::string reference_rule_impl(false_type, false_type) {return "";}
0199     inline std::string reference_rule_impl(true_type,  false_type) {return "&" ;}
0200     inline std::string reference_rule_impl(false_type, true_type ) {return "&&";}
0201 
0202     template<typename T>
0203     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());}
0204 
0205     //it takes a string, because it may be overloaded.
0206     template<typename Return, typename Arg>
0207     std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
0208     {
0209         using namespace std;
0210         return type_name<Arg>(ms);
0211     }
0212 
0213     template<typename Return, typename First, typename Second, typename ...Args>
0214     std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
0215     {
0216         using next_type = Return (*)(Second, Args...);
0217         return type_name<First>(ms) + ", " + arg_list(ms, next_type());
0218     }
0219 
0220     template<typename Return>
0221     std::string arg_list(const mangled_storage_impl &, Return (*)())
0222     {
0223         return "";
0224     }
0225 
0226     //! implement
0227     template <typename T>
0228     inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*) {
0229         return  ms.get_name<T>();
0230     }
0231 
0232     template <typename... T, template <typename...> class Tn>
0233     inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
0234         using type = dummy<Tn<T...>>*;
0235         return parse_type(ms, type());
0236     }
0237 
0238     template <typename R, typename... Args>
0239     inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(*)(Args...)>*) {
0240         using args_type = dummy<Args...>*;
0241         using return_type = dummy<R>*;
0242         return parse_type(ms, return_type()) + " (*)(" + parse_type(ms, args_type()) + ")";
0243     }
0244 
0245     template <typename R, typename... Args>
0246     inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*) {
0247         using args_type = dummy<Args...>*;
0248         using return_type = dummy<R>*;
0249         return parse_type(ms, return_type()) + " (" + parse_type(ms, args_type()) + ")";
0250     }
0251 
0252     template <typename T>
0253     inline std::string parse_type(const mangled_storage_impl & ms, dummy<T>*) {
0254         using type = dummy<typename pure_type<T>::type>*;
0255         auto str = parse_type_helper(ms, type());
0256         return str + pure_type<T>::type_rule();
0257     }
0258 
0259     template <typename T1, typename T2, typename... T3>
0260     inline std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*) {
0261         using first_type = dummy<T1>*;
0262         using next_type = dummy<T2, T3...>*;
0263         return parse_type(ms, first_type()) + ", " + parse_type(ms, next_type());
0264     }
0265 
0266     template <typename... T, template <typename...> class Tn>
0267     inline std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
0268         using next_type = dummy<T...>*;
0269         std::string str = ms.get_name<Tn<T...>>();
0270         auto frist = str.find_first_of("<");
0271         std::string template_name = str.substr(0, frist);
0272         std::string args_name = parse_type(ms, next_type());
0273         char last_ch = args_name[args_name.size() - 1];
0274         return template_name + "<" + args_name + (last_ch == '>' ? " >" : ">");
0275     }
0276 
0277     inline std::string parse_type(const mangled_storage_impl &, dummy<>*) {
0278         return "";
0279     }
0280 
0281     template<typename T>
0282     inline  std::string
0283     type_name(const mangled_storage_impl &ms)
0284     {
0285         using namespace parser;
0286         using type = dummy<T>*;
0287         return  parse_type(ms, type());
0288     }
0289 }
0290 
0291 
0292 
0293 template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const
0294 {
0295     auto found = std::find_if(storage_.begin(), storage_.end(),
0296             [&](const entry& e) {return e.demangled == name;});
0297 
0298     if (found != storage_.end())
0299         return found->mangled;
0300     else
0301         return "";
0302 }
0303 
0304 template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const
0305 {
0306     using func_type = Func*;
0307 
0308     auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')';
0309 
0310     auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
0311     if (found != storage_.end())
0312         return found->mangled;
0313     else
0314         return "";
0315 
0316 }
0317 
0318 template<typename Class, typename Func>
0319 std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
0320 {
0321     using namespace parser;
0322 
0323     using func_type = Func*;
0324 
0325     std::string cname = get_name<Class>();
0326 
0327     const auto matcher = cname + "::" + name +
0328              '(' + parser::arg_list(*this, func_type()) + ')'
0329              + const_rule<Class>() + volatile_rule<Class>();
0330 
0331     // Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type.
0332     auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) {
0333         if (e.demangled == matcher) {
0334           return true;
0335         }
0336 
0337         const auto pos = e.demangled.rfind(matcher);
0338         if (pos == std::string::npos) {
0339           // Not found.
0340           return false;
0341         }
0342 
0343         if (pos + matcher.size() != e.demangled.size()) {
0344           // There are some characters after the `matcher` string.
0345           return false;
0346         }
0347 
0348         // Double checking that we matched a full function name
0349         return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0`
0350     });
0351 
0352     if (found != storage_.end())
0353         return found->mangled;
0354     else
0355         return "";
0356 
0357 }
0358 
0359 
0360 template<typename Signature>
0361 auto mangled_storage_impl::get_constructor() const -> ctor_sym
0362 {
0363     using namespace parser;
0364 
0365     using func_type = Signature*;
0366 
0367     std::string ctor_name; // = class_name + "::" + name;
0368     std::string unscoped_cname; //the unscoped class-name
0369     {
0370         auto class_name = get_return_type(dummy<Signature>());
0371         auto pos = class_name.rfind("::");
0372         if (pos == std::string::npos)
0373         {
0374             ctor_name = class_name+ "::" +class_name ;
0375             unscoped_cname = class_name;
0376         }
0377         else
0378         {
0379             unscoped_cname = class_name.substr(pos+2) ;
0380             ctor_name = class_name+ "::" + unscoped_cname;
0381         }
0382     }
0383 
0384     auto matcher =
0385                 ctor_name + '(' + parser::arg_list(*this, func_type()) + ')';
0386 
0387 
0388     std::vector<entry> findings;
0389     std::copy_if(storage_.begin(), storage_.end(),
0390             std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;});
0391 
0392     ctor_sym ct;
0393 
0394     for (auto & e : findings)
0395     {
0396 
0397         if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos)
0398             ct.C1 = e.mangled;
0399         else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos)
0400             ct.C2 = e.mangled;
0401         else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos)
0402             ct.C3 = e.mangled;
0403     }
0404     return ct;
0405 }
0406 
0407 template<typename Class>
0408 auto mangled_storage_impl::get_destructor() const -> dtor_sym
0409 {
0410     std::string dtor_name; // = class_name + "::" + name;
0411     std::string unscoped_cname; //the unscoped class-name
0412     {
0413         auto class_name = get_name<Class>();
0414         auto pos = class_name.rfind("::");
0415         if (pos == std::string::npos)
0416         {
0417             dtor_name = class_name+ "::~" + class_name  + "()";
0418             unscoped_cname = class_name;
0419         }
0420         else
0421         {
0422             unscoped_cname = class_name.substr(pos+2) ;
0423             dtor_name = class_name+ "::~" + unscoped_cname + "()";
0424         }
0425     }
0426 
0427     auto d0 = unscoped_cname + "D0Ev";
0428     auto d1 = unscoped_cname + "D1Ev";
0429     auto d2 = unscoped_cname + "D2Ev";
0430 
0431     dtor_sym dt;
0432     //this is so simple, i don#t need a predicate
0433     for (auto & s : storage_)
0434     {
0435         //alright, name fits
0436         if (s.demangled == dtor_name)
0437         {
0438             if (s.mangled.find(d0) != std::string::npos)
0439                 dt.D0 = s.mangled;
0440             else if (s.mangled.find(d1) != std::string::npos)
0441                 dt.D1 = s.mangled;
0442             else if (s.mangled.find(d2) != std::string::npos)
0443                 dt.D2 = s.mangled;
0444 
0445         }
0446     }
0447     return dt;
0448 
0449 }
0450 
0451 template<typename T>
0452 std::string mangled_storage_impl::get_type_info() const
0453 {
0454     std::string id = "typeinfo for " + get_name<T>();
0455 
0456 
0457     auto predicate = [&](const mangled_storage_base::entry & e)
0458                 {
0459                     return e.demangled == id;
0460                 };
0461 
0462     auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
0463 
0464 
0465     if (found != storage_.end())
0466         return found->mangled;
0467     else
0468         return "";
0469 }
0470 
0471 template<typename T>
0472 std::vector<std::string> mangled_storage_impl::get_related()  const
0473 {
0474     std::vector<std::string> ret;
0475     auto name = get_name<T>();
0476 
0477     for (auto & c : storage_)
0478     {
0479         if (c.demangled.find(name) != std::string::npos)
0480             ret.push_back(c.demangled);
0481     }
0482 
0483     return ret;
0484 }
0485 
0486 }}}
0487 
0488 
0489 #endif /* BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */