Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:37:30

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