123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- // Copyright 2016 Klemens Morgenstern
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt
- // or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
- #define BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
- #include <boost/dll/detail/demangling/mangled_storage_base.hpp>
- #include <iterator>
- #include <algorithm>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/is_volatile.hpp>
- #include <boost/type_traits/is_rvalue_reference.hpp>
- #include <boost/type_traits/is_lvalue_reference.hpp>
- #include <boost/type_traits/function_traits.hpp>
- namespace boost { namespace dll { namespace detail {
- class mangled_storage_impl : public mangled_storage_base
- {
- template<typename T>
- struct dummy {};
- template<typename Return, typename ...Args>
- std::vector<std::string> get_func_params(dummy<Return(Args...)>) const
- {
- return {get_name<Args>()...};
- }
- template<typename Return, typename ...Args>
- std::string get_return_type(dummy<Return(Args...)>) const
- {
- return get_name<Return>();
- }
- public:
- using mangled_storage_base::mangled_storage_base;
- struct ctor_sym
- {
- std::string C1;
- std::string C2;
- std::string C3;
- bool empty() const
- {
- return C1.empty() && C2.empty() && C3.empty();
- }
- };
- struct dtor_sym
- {
- std::string D0;
- std::string D1;
- std::string D2;
- bool empty() const
- {
- return D0.empty() && D1.empty() && D2.empty();
- }
- };
- template<typename T>
- std::string get_variable(const std::string &name) const;
- template<typename Func>
- std::string get_function(const std::string &name) const;
- template<typename Class, typename Func>
- std::string get_mem_fn(const std::string &name) const;
- template<typename Signature>
- ctor_sym get_constructor() const;
- template<typename Class>
- dtor_sym get_destructor() const;
- template<typename T>
- std::string get_type_info() const;
- template<typename T>
- std::vector<std::string> get_related() const;
- };
- namespace parser
- {
- //! declare
- template <typename... T>
- struct dummy;
- template <typename T>
- std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*);
- template <typename... T, template <typename...> class Tn>
- std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
- template <typename... T, template <typename...> class Tn>
- std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*);
- template <typename T>
- std::string parse_type(const mangled_storage_impl & ms, dummy<T>*);
- template <typename T1, typename T2, typename... T3>
- std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*);
- template <typename R, typename... Args>
- std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*);
- std::string parse_type(const mangled_storage_impl & ms, dummy<>*);
- template<typename T>
- std::string
- type_name(const mangled_storage_impl &);
- //The purpose of this class template is to separate the pure type from the rule name from the target type
- template<typename T>
- struct pure_type
- {
- typedef T type;
- inline static std::string type_rule() { return ""; }
- };
- template<typename T>
- struct pure_type<T*>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + "*";
- }
- };
- template<typename T>
- struct pure_type<T const>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + " const";
- }
- };
- template<typename T>
- struct pure_type<T volatile>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + " volatile";
- }
- };
- template<typename T>
- struct pure_type<T const volatile>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + " const volatile";
- }
- };
- template<typename T>
- struct pure_type<T&>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + "&";
- }
- };
- template<typename T>
- struct pure_type<T&&>
- {
- typedef typename pure_type<T>::type type;
- inline static std::string type_rule()
- {
- return pure_type<T>::type_rule() + "&&";
- }
- };
- inline std::string const_rule_impl(true_type ) {return " const";}
- inline std::string const_rule_impl(false_type) {return "";}
- template<typename T>
- std::string const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
- inline std::string volatile_rule_impl(true_type ) {return " volatile";}
- inline std::string volatile_rule_impl(false_type) {return "";}
- template<typename T>
- std::string volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
- inline std::string reference_rule_impl(false_type, false_type) {return "";}
- inline std::string reference_rule_impl(true_type, false_type) {return "&" ;}
- inline std::string reference_rule_impl(false_type, true_type ) {return "&&";}
- template<typename T>
- 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());}
- //it takes a string, because it may be overloaded.
- template<typename Return, typename Arg>
- std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
- {
- using namespace std;
- return type_name<Arg>(ms);
- }
- template<typename Return, typename First, typename Second, typename ...Args>
- std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
- {
- using next_type = Return (*)(Second, Args...);
- return type_name<First>(ms) + ", " + arg_list(ms, next_type());
- }
- template<typename Return>
- std::string arg_list(const mangled_storage_impl &, Return (*)())
- {
- return "";
- }
- //! implement
- template <typename T>
- inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<T>*) {
- return ms.get_name<T>();
- }
- template <typename... T, template <typename...> class Tn>
- inline std::string parse_type_helper(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
- using type = dummy<Tn<T...>>*;
- return parse_type(ms, type());
- }
- template <typename R, typename... Args>
- inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(*)(Args...)>*) {
- using args_type = dummy<Args...>*;
- using return_type = dummy<R>*;
- return parse_type(ms, return_type()) + " (*)(" + parse_type(ms, args_type()) + ")";
- }
- template <typename R, typename... Args>
- inline std::string parse_type(const mangled_storage_impl & ms, dummy<R(Args...)>*) {
- using args_type = dummy<Args...>*;
- using return_type = dummy<R>*;
- return parse_type(ms, return_type()) + " (" + parse_type(ms, args_type()) + ")";
- }
- template <typename T>
- inline std::string parse_type(const mangled_storage_impl & ms, dummy<T>*) {
- using type = dummy<typename pure_type<T>::type>*;
- auto str = parse_type_helper(ms, type());
- return str + pure_type<T>::type_rule();
- }
- template <typename T1, typename T2, typename... T3>
- inline std::string parse_type(const mangled_storage_impl & ms, dummy<T1, T2, T3...>*) {
- using first_type = dummy<T1>*;
- using next_type = dummy<T2, T3...>*;
- return parse_type(ms, first_type()) + ", " + parse_type(ms, next_type());
- }
- template <typename... T, template <typename...> class Tn>
- inline std::string parse_type(const mangled_storage_impl & ms, dummy<Tn<T...>>*) {
- using next_type = dummy<T...>*;
- std::string str = ms.get_name<Tn<T...>>();
- auto frist = str.find_first_of("<");
- std::string template_name = str.substr(0, frist);
- std::string args_name = parse_type(ms, next_type());
- char last_ch = args_name[args_name.size() - 1];
- return template_name + "<" + args_name + (last_ch == '>' ? " >" : ">");
- }
- inline std::string parse_type(const mangled_storage_impl &, dummy<>*) {
- return "";
- }
- template<typename T>
- inline std::string
- type_name(const mangled_storage_impl &ms)
- {
- using namespace parser;
- using type = dummy<T>*;
- return parse_type(ms, type());
- }
- }
- template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const
- {
- auto found = std::find_if(storage_.begin(), storage_.end(),
- [&](const entry& e) {return e.demangled == name;});
- if (found != storage_.end())
- return found->mangled;
- else
- return "";
- }
- template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const
- {
- using func_type = Func*;
- auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')';
- auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
- if (found != storage_.end())
- return found->mangled;
- else
- return "";
- }
- template<typename Class, typename Func>
- std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
- {
- using namespace parser;
- using func_type = Func*;
- std::string cname = get_name<Class>();
- const auto matcher = cname + "::" + name +
- '(' + parser::arg_list(*this, func_type()) + ')'
- + const_rule<Class>() + volatile_rule<Class>();
- // Linux export table contains int MyClass::Func<float>(), but expected in import_mangled MyClass::Func<float>() without returned type.
- auto found = std::find_if(storage_.begin(), storage_.end(), [&matcher](const entry& e) {
- if (e.demangled == matcher) {
- return true;
- }
- const auto pos = e.demangled.rfind(matcher);
- if (pos == std::string::npos) {
- // Not found.
- return false;
- }
- if (pos + matcher.size() != e.demangled.size()) {
- // There are some characters after the `matcher` string.
- return false;
- }
- // Double checking that we matched a full function name
- return e.demangled[pos - 1] == ' '; // `if (e.demangled == matcher)` makes sure that `pos > 0`
- });
- if (found != storage_.end())
- return found->mangled;
- else
- return "";
- }
- template<typename Signature>
- auto mangled_storage_impl::get_constructor() const -> ctor_sym
- {
- using namespace parser;
- using func_type = Signature*;
- std::string ctor_name; // = class_name + "::" + name;
- std::string unscoped_cname; //the unscoped class-name
- {
- auto class_name = get_return_type(dummy<Signature>());
- auto pos = class_name.rfind("::");
- if (pos == std::string::npos)
- {
- ctor_name = class_name+ "::" +class_name ;
- unscoped_cname = class_name;
- }
- else
- {
- unscoped_cname = class_name.substr(pos+2) ;
- ctor_name = class_name+ "::" + unscoped_cname;
- }
- }
- auto matcher =
- ctor_name + '(' + parser::arg_list(*this, func_type()) + ')';
- std::vector<entry> findings;
- std::copy_if(storage_.begin(), storage_.end(),
- std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;});
- ctor_sym ct;
- for (auto & e : findings)
- {
- if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos)
- ct.C1 = e.mangled;
- else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos)
- ct.C2 = e.mangled;
- else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos)
- ct.C3 = e.mangled;
- }
- return ct;
- }
- template<typename Class>
- auto mangled_storage_impl::get_destructor() const -> dtor_sym
- {
- std::string dtor_name; // = class_name + "::" + name;
- std::string unscoped_cname; //the unscoped class-name
- {
- auto class_name = get_name<Class>();
- auto pos = class_name.rfind("::");
- if (pos == std::string::npos)
- {
- dtor_name = class_name+ "::~" + class_name + "()";
- unscoped_cname = class_name;
- }
- else
- {
- unscoped_cname = class_name.substr(pos+2) ;
- dtor_name = class_name+ "::~" + unscoped_cname + "()";
- }
- }
- auto d0 = unscoped_cname + "D0Ev";
- auto d1 = unscoped_cname + "D1Ev";
- auto d2 = unscoped_cname + "D2Ev";
- dtor_sym dt;
- //this is so simple, i don#t need a predicate
- for (auto & s : storage_)
- {
- //alright, name fits
- if (s.demangled == dtor_name)
- {
- if (s.mangled.find(d0) != std::string::npos)
- dt.D0 = s.mangled;
- else if (s.mangled.find(d1) != std::string::npos)
- dt.D1 = s.mangled;
- else if (s.mangled.find(d2) != std::string::npos)
- dt.D2 = s.mangled;
- }
- }
- return dt;
- }
- template<typename T>
- std::string mangled_storage_impl::get_type_info() const
- {
- std::string id = "typeinfo for " + get_name<T>();
- auto predicate = [&](const mangled_storage_base::entry & e)
- {
- return e.demangled == id;
- };
- auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
- if (found != storage_.end())
- return found->mangled;
- else
- return "";
- }
- template<typename T>
- std::vector<std::string> mangled_storage_impl::get_related() const
- {
- std::vector<std::string> ret;
- auto name = get_name<T>();
- for (auto & c : storage_)
- {
- if (c.demangled.find(name) != std::string::npos)
- ret.push_back(c.demangled);
- }
- return ret;
- }
- }}}
- #endif /* BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */
|