summaryrefslogtreecommitdiff
path: root/boost/dll/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/dll/detail')
-rw-r--r--boost/dll/detail/aggressive_ptr_cast.hpp130
-rw-r--r--boost/dll/detail/ctor_dtor.hpp176
-rw-r--r--boost/dll/detail/demangling/demangle_symbol.hpp83
-rw-r--r--boost/dll/detail/demangling/itanium.hpp285
-rw-r--r--boost/dll/detail/demangling/mangled_storage_base.hpp118
-rw-r--r--boost/dll/detail/demangling/msvc.hpp400
-rw-r--r--boost/dll/detail/elf_info.hpp285
-rw-r--r--boost/dll/detail/get_mem_fn_type.hpp40
-rw-r--r--boost/dll/detail/macho_info.hpp321
-rw-r--r--boost/dll/detail/pe_info.hpp427
-rw-r--r--boost/dll/detail/posix/path_from_handle.hpp169
-rw-r--r--boost/dll/detail/posix/program_location_impl.hpp140
-rw-r--r--boost/dll/detail/posix/shared_library_impl.hpp215
-rw-r--r--boost/dll/detail/system_error.hpp56
-rw-r--r--boost/dll/detail/windows/path_from_handle.hpp62
-rw-r--r--boost/dll/detail/windows/shared_library_impl.hpp177
-rw-r--r--boost/dll/detail/x_info_interface.hpp32
17 files changed, 3116 insertions, 0 deletions
diff --git a/boost/dll/detail/aggressive_ptr_cast.hpp b/boost/dll/detail/aggressive_ptr_cast.hpp
new file mode 100644
index 0000000000..a8887f4382
--- /dev/null
+++ b/boost/dll/detail/aggressive_ptr_cast.hpp
@@ -0,0 +1,130 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 Antony Polukhin.
+//
+// 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_AGGRESSIVE_PTR_CAST_HPP
+#define BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/cstdint.hpp> // boost::uintptr_t
+#include <cstring> // std::memcpy
+
+namespace boost { namespace dll { namespace detail {
+
+// GCC warns when reinterpret_cast between function pointer and object pointer occur.
+// This method suppress the warnings and ensures that such casts are safe.
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<To>::value && boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<To>::type >::value
+ || boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(v) == sizeof(To),
+ "Pointer to function and pointer to object differ in size on your platform."
+ );
+
+ return reinterpret_cast<To>(
+ reinterpret_cast<boost::uintptr_t>(v)
+ );
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(v) == sizeof(typename boost::remove_reference<To>::type*),
+ "Pointer to function and pointer to object differ in size on your platform."
+ );
+
+ return static_cast<To>(
+ *reinterpret_cast<typename boost::remove_reference<To>::type*>(
+ *reinterpret_cast<boost::uintptr_t*>(
+ reinterpret_cast<unsigned char*>(
+ v
+ )
+ )
+ )
+ );
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ To res = 0;
+ std::memcpy(&res, &v, sizeof(To));
+ return res;
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || !boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<To>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<To>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ !sizeof(From),
+ "Casting from member pointers to void pointer is not implemnted in `agressive_ptr_cast`."
+ );
+
+ return 0;
+}
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
+
diff --git a/boost/dll/detail/ctor_dtor.hpp b/boost/dll/detail/ctor_dtor.hpp
new file mode 100644
index 0000000000..5950d9e60a
--- /dev/null
+++ b/boost/dll/detail/ctor_dtor.hpp
@@ -0,0 +1,176 @@
+// Copyright 2016 Klemens Morgenstern, Antony Polukhin
+//
+// 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)
+
+// For more information, see http://www.boost.org
+
+#ifndef INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
+#define INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+#include <boost/dll/detail/get_mem_fn_type.hpp>
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
+# include <boost/dll/detail/demangling/msvc.hpp>
+#else
+# include <boost/dll/detail/demangling/itanium.hpp>
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+/*!
+ * This class stores a constructor.
+ *
+ * In some compilers there are several constructors in code, which may include an allocating one.
+ * This can be used if the imported class shall be put on the heap, which is why the class provied both types.
+ */
+template<typename Signature>
+struct constructor;
+
+template<typename Class, typename ...Args>
+struct constructor<Class(Args...)> {
+ typedef typename detail::get_mem_fn_type<Class, void(Args...)>::mem_fn standard_t;
+ typedef Class*(*allocating_t)(Args...);
+
+
+ //! The standard, i.e. not allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_standard instead.
+ standard_t standard;
+ //! The allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_allocating instead.
+ allocating_t allocating;
+
+ //! Call the standard contructor
+ void call_standard (Class * const ptr, Args...args){ (ptr->*standard)(static_cast<Args>(args)...); }
+
+ //! Call the deleting destructor
+ Class * call_allocating(Args...args){ return allocating(static_cast<Args>(args)...); }
+
+
+ //! True if a allocating constructor could be loaded.
+ bool has_allocating() const { return allocating != nullptr; }
+
+ //! False if neither the allocating nor the standard constructor is available.
+ bool is_empty() const { return !((allocating == nullptr) && (standard != nullptr)) ; }
+
+ constructor() = delete;
+ constructor(const constructor &) = default;
+
+ explicit constructor(standard_t standard, allocating_t allocating = nullptr)
+ : standard(standard)
+ , allocating(allocating)
+ {}
+};
+
+
+
+template <typename Class>
+struct destructor {
+#if !defined(BOOST_MSVC) && !defined(BOOST_MSVC_VER)
+ typedef void( *type)(Class* const);
+#elif !defined(_WIN64)
+ typedef void(__thiscall * type)(Class* const);
+#else
+ typedef void(__cdecl * type)(Class* const);
+#endif
+
+ typedef type standard_t;
+ typedef type deleting_t;
+
+ //! The standard, i.e. not deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_standard instead.
+ standard_t standard;
+ //! The deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_deallocating instead.
+ deleting_t deleting;
+
+ //! Call the standard contructor
+ void call_standard(Class * const ptr){ standard(ptr); }
+
+ //! Call the deleting destructor
+ void call_deleting(Class * const ptr){ deleting(ptr); }
+
+ //! True if a deleting destructor could be loaded.
+ bool has_deleting() const { return deleting != nullptr; }
+
+ //! False if neither the deleting nor the standard destructor is available.
+ bool is_empty() const { return !((deleting == nullptr) && (standard != nullptr)) ; }
+ destructor() = delete;
+
+ //! Copy destructor.
+ destructor(const destructor &) = default;
+
+ //! Construct it from both the standard destructor and the allocating destructor
+ explicit destructor(const standard_t &standard, const deleting_t &deleting = nullptr)
+ : standard(standard)
+ , deleting(deleting)
+ {}
+};
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
+template<typename Signature, typename Lib>
+constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
+ typedef typename constructor<Signature>::standard_t standard_t;
+ standard_t ctor = lib.template get<standard_t>(ct);
+ return constructor<Signature>(ctor);
+}
+
+template<typename Class, typename Lib>
+destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
+ typedef typename destructor<Class>::standard_t standard_t;
+ standard_t dtor = &lib.template get< typename boost::remove_pointer<standard_t>::type >(dt);
+ return destructor<Class>(dtor);
+}
+
+#else
+
+template<typename Signature, typename Lib>
+constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
+ typedef typename constructor<Signature>::standard_t stand;
+ typedef typename constructor<Signature>::allocating_t alloc;
+
+ stand s = nullptr;
+ alloc a = nullptr;
+
+ //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
+
+ if (!ct.C1.empty()) {
+ s = lib.template get<stand>(ct.C1);
+ }
+
+ if (!ct.C3.empty()) {
+ a = lib.template get<alloc>(ct.C3);
+ }
+
+ return constructor<Signature>(s,a);
+}
+
+template<typename Class, typename Lib>
+destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
+ typedef typename destructor<Class>::standard_t stand;
+ typedef typename destructor<Class>::deleting_t delet;
+
+ stand s = nullptr;
+ delet d = nullptr;
+
+ //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
+ if (!dt.D1.empty()) {
+ s = &lib.template get< typename boost::remove_pointer<stand>::type >(dt.D1);
+ }
+
+ if (!dt.D0.empty()) {
+ d = &lib.template get< typename boost::remove_pointer<delet>::type >(dt.D0);
+ }
+
+ return destructor<Class>(s,d);
+
+}
+
+#endif
+
+}}} // namespace boost::dll::detail
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ */
diff --git a/boost/dll/detail/demangling/demangle_symbol.hpp b/boost/dll/detail/demangling/demangle_symbol.hpp
new file mode 100644
index 0000000000..e0590b38fa
--- /dev/null
+++ b/boost/dll/detail/demangling/demangle_symbol.hpp
@@ -0,0 +1,83 @@
+// Copyright 2015 Klemens Morgenstern
+//
+// This file provides a demangling for function names, i.e. entry points of a dll.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DLL_DEMANGLE_SYMBOL_HPP_
+#define BOOST_DLL_DEMANGLE_SYMBOL_HPP_
+
+#include <boost/config.hpp>
+#include <string>
+#include <algorithm>
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_FULL_VER)
+#include <boost/detail/winapi/dbghelp.hpp>
+
+namespace boost
+{
+namespace dll
+{
+namespace detail
+{
+
+
+inline std::string demangle_symbol(const char *mangled_name)
+{
+ char unmangled_name[2048];
+
+ ::boost::detail::winapi::
+ UnDecorateSymbolName(mangled_name, unmangled_name, 2048, 0);
+
+ return std::string(unmangled_name);
+}
+inline std::string demangle_symbol(const std::string& mangled_name)
+{
+ return demangle_symbol(mangled_name.c_str());
+}
+
+
+}}}
+#else
+
+#include <boost/core/demangle.hpp>
+
+namespace boost
+{
+namespace dll
+{
+namespace detail
+{
+
+inline std::string demangle_symbol(const char *mangled_name)
+{
+
+ if (*mangled_name == '_')
+ {
+ //because it start's with an underline _
+ auto dm = boost::core::demangle(mangled_name);
+ if (!dm.empty())
+ return dm;
+ else
+ return (mangled_name);
+ }
+
+ //could not demangled
+ return "";
+
+
+}
+
+//for my personal convinience
+inline std::string demangle_symbol(const std::string& mangled_name)
+{
+ return demangle_symbol(mangled_name.c_str());
+}
+
+
+}}}
+
+#endif
+
+#endif /* INCLUDE_BOOST_DEMANGLE_HPP_ */
diff --git a/boost/dll/detail/demangling/itanium.hpp b/boost/dll/detail/demangling/itanium.hpp
new file mode 100644
index 0000000000..356a5eca82
--- /dev/null
+++ b/boost/dll/detail/demangling/itanium.hpp
@@ -0,0 +1,285 @@
+// 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...)>)
+ {
+ return {get_name<Args>()...};
+ }
+ template<typename Return, typename ...Args>
+ std::string get_return_type(dummy<Return(Args...)>)
+ {
+ 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);
+
+ template<typename Func>
+ std::string get_function(const std::string &name);
+
+ template<typename Class, typename Func>
+ std::string get_mem_fn(const std::string &name);
+
+ template<typename Signature>
+ ctor_sym get_constructor();
+
+ template<typename Class>
+ dtor_sym get_destructor();
+
+};
+
+
+
+namespace parser
+{
+
+ inline std::string const_rule_impl(true_type ) {return " const";}
+ inline std::string const_rule_impl(false_type) {return "";}
+ template<typename T>
+ auto 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>
+ auto 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>
+ auto 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 T>
+ auto type_rule(const std::string & type_name)
+ {
+ using namespace std;
+
+ return type_name +
+ const_rule<T>() +
+ volatile_rule<T>() +
+ reference_rule<T>();
+ }
+
+
+ template<typename Return, typename Arg>
+ std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
+ {
+ using namespace std;
+ auto str = ms.get_name<Arg>();
+ return type_rule<Arg>(str);
+ }
+
+ template<typename Return, typename First, typename Second, typename ...Args>
+ std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
+ {
+ auto st = ms.get_name<First>();
+
+ using next_type = Return (*)(Second, Args...);
+ return type_rule<First>(st) + ", " + arg_list(ms, next_type());
+ }
+
+ template<typename Return>
+ std::string arg_list(const mangled_storage_impl &, Return (*)())
+ {
+ return "";
+ }
+}
+
+
+
+template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name)
+{
+ 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)
+{
+ 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)
+{
+ using namespace parser;
+
+ using func_type = Func*;
+
+ std::string cname = get_name<Class>();
+
+ auto matcher = cname + "::" + name +
+ '(' + parser::arg_list(*this, func_type()) + ')'
+ + const_rule<Class>() + volatile_rule<Class>();
+
+ 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 Signature>
+auto mangled_storage_impl::get_constructor() -> 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() -> 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;
+
+}
+
+}}}
+
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */
diff --git a/boost/dll/detail/demangling/mangled_storage_base.hpp b/boost/dll/detail/demangling/mangled_storage_base.hpp
new file mode 100644
index 0000000000..e4bf3753f9
--- /dev/null
+++ b/boost/dll/detail/demangling/mangled_storage_base.hpp
@@ -0,0 +1,118 @@
+// 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_MANGLE_STORAGE_BASE_HPP_
+#define BOOST_DLL_DETAIL_MANGLE_STORAGE_BASE_HPP_
+
+#include <vector>
+#include <string>
+#include <map>
+#include <boost/dll/detail/demangling/demangle_symbol.hpp>
+#include <boost/dll/library_info.hpp>
+#include <boost/type_index/stl_type_index.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+///stores the mangled names with the demangled name.
+struct mangled_storage_base
+{
+ struct entry
+ {
+ std::string mangled;
+ std::string demangled;
+ entry() = default;
+ entry(const std::string & m, const std::string &d) : mangled(m), demangled(d) {}
+ entry(const entry&) = default;
+ entry(entry&&) = default;
+ entry &operator= (const entry&) = default;
+ entry &operator= (entry&&) = default;
+ };
+protected:
+ std::vector<entry> storage_;
+ ///if a unknown class is imported it can be overloaded by this type
+ std::map<boost::typeindex::stl_type_index, std::string> aliases_;
+public:
+ void assign(const mangled_storage_base & storage)
+ {
+ aliases_ = storage.aliases_;
+ storage_ = storage.storage_;
+ }
+ void swap( mangled_storage_base & storage)
+ {
+ aliases_.swap(storage.aliases_);
+ storage_.swap(storage.storage_);
+ }
+ void clear()
+ {
+ storage_.clear();
+ aliases_.clear();
+ }
+ const std::vector<entry> & get_storage() const {return storage_;};
+ template<typename T>
+ std::string get_name() const
+ {
+ auto tx = boost::typeindex::stl_type_index::type_id<T>();
+ auto val = (aliases_.count(tx) > 0) ? aliases_.at(tx) : tx.pretty_name();
+ return val;
+ }
+
+ mangled_storage_base() = default;
+ mangled_storage_base(mangled_storage_base&&) = default;
+ mangled_storage_base(const mangled_storage_base&) = default;
+
+ mangled_storage_base(const std::vector<std::string> & symbols) { add_symbols(symbols);}
+
+ explicit mangled_storage_base(library_info & li) : mangled_storage_base(li.symbols()) {}
+
+ explicit mangled_storage_base(
+ const boost::filesystem::path& library_path,
+ bool throw_if_not_native_format = true)
+ : mangled_storage_base(library_info(library_path, throw_if_not_native_format).symbols())
+ {
+
+ }
+
+ void load(library_info & li) { storage_.clear(); add_symbols(li.symbols()); };
+ void load(const boost::filesystem::path& library_path,
+ bool throw_if_not_native_format = true)
+ {
+ storage_.clear();
+ add_symbols(library_info(library_path, throw_if_not_native_format).symbols());
+ };
+
+ /*! Allows do add a class as alias, if the class imported is not known
+ * in this binary.
+ * @tparam Alias The Alias type
+ * @param The name to create the alias for.
+ *
+ * @note There can be multiple aliases, this is on purpose.
+ */
+ template<typename Alias> void add_alias(const std::string& name)
+ {
+ aliases_.emplace(
+ boost::typeindex::stl_type_index::type_id<Alias>(),
+ name
+ );
+ }
+ void add_symbols(const std::vector<std::string> & symbols)
+ {
+ for (auto & sym : symbols)
+ {
+ auto dm = demangle_symbol(sym);
+ if (!dm.empty())
+ storage_.emplace_back(sym, dm);
+ else
+ storage_.emplace_back(sym, sym);
+ }
+ }
+
+
+};
+
+
+}}}
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_MANGLE_STORAGE_HPP_ */
diff --git a/boost/dll/detail/demangling/msvc.hpp b/boost/dll/detail/demangling/msvc.hpp
new file mode 100644
index 0000000000..4cab143266
--- /dev/null
+++ b/boost/dll/detail/demangling/msvc.hpp
@@ -0,0 +1,400 @@
+// 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_MSVC_HPP_
+#define BOOST_DLL_DETAIL_DEMANGLING_MSVC_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_lvalue_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/spirit/home/x3.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...)>)
+ {
+ return {get_name<Args>()...};
+ }
+ template<typename Return, typename ...Args>
+ std::string get_return_type(dummy<Return(Args...)>)
+ {
+ return get_name<Return>();
+ }
+ //function to remove preceeding 'class ' or 'struct ' if the are given in this format.
+
+ inline static void trim_typename(std::string & val);
+public:
+ using ctor_sym = std::string;
+ using dtor_sym = std::string;
+
+ using mangled_storage_base::mangled_storage_base;
+
+ template<typename T>
+ std::string get_variable(const std::string &name);
+
+ template<typename Func>
+ std::string get_function(const std::string &name);
+
+ template<typename Class, typename Func>
+ std::string get_mem_fn(const std::string &name);
+
+ template<typename Signature>
+ ctor_sym get_constructor();
+
+ template<typename Class>
+ dtor_sym get_destructor();
+
+ template<typename T> //overload, does not need to virtual.
+ std::string get_name() const
+ {
+ auto nm = mangled_storage_base::get_name<T>();
+ trim_typename(nm);
+ return nm;
+ }
+};
+
+void mangled_storage_impl::trim_typename(std::string & val)
+{
+ //remove preceeding class or struct, because you might want to use a struct as class, et vice versa
+ if (val.size() >= 6)
+ {
+ using namespace std;
+ static constexpr char class_ [7] = "class ";
+ static constexpr char struct_[8] = "struct ";
+
+ if (equal(begin(class_), end(class_)-1, val.begin())) //aklright, starts with 'class '
+ val.erase(0, 6);
+ else if (val.size() >= 7)
+ if (equal(begin(struct_), end(struct_)-1, val.begin()))
+ val.erase(0, 7);
+ }
+}
+
+
+namespace parser
+{
+ namespace x3 = spirit::x3;
+
+ auto ptr_rule_impl(std::integral_constant<std::size_t, 32>)
+ {
+ return -((-x3::space) >> "__ptr32");
+ }
+ auto ptr_rule_impl(std::integral_constant<std::size_t, 64>)
+ {
+ return -((-x3::space) >> "__ptr64");
+ }
+
+ auto ptr_rule() { return ptr_rule_impl(std::integral_constant<std::size_t, sizeof(std::size_t)*8>());}
+
+ auto const visibility = ("public:" | x3::lit("protected:") | "private:");
+ auto const virtual_ = x3::space >> "virtual";
+ auto const static_ = x3::space >> x3::lit("static") ;
+
+ auto const_rule_impl(true_type ) {return x3::space >> "const";};
+ auto const_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
+
+ auto volatile_rule_impl(true_type ) {return x3::space >> "volatile";};
+ auto volatile_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
+
+
+ auto inv_const_rule_impl(true_type ) {return "const" >> x3::space ;};
+ auto inv_const_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto inv_const_rule() {using t = is_const<typename remove_reference<T>::type>; return inv_const_rule_impl(t());}
+
+ auto inv_volatile_rule_impl(true_type ) {return "volatile" >> x3::space;};
+ auto inv_volatile_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto inv_volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return inv_volatile_rule_impl(t());}
+
+
+ auto reference_rule_impl(false_type, false_type) {return x3::eps;}
+ auto reference_rule_impl(true_type, false_type) {return x3::space >>"&" ;}
+ auto reference_rule_impl(false_type, true_type ) {return x3::space >>"&&" ;}
+
+
+ template<typename T>
+ auto reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());}
+
+ auto const class_ = ("class" | x3::lit("struct"));
+
+ //it takes a string, because it may be overloaded.
+ template<typename T>
+ auto type_rule(const std::string & type_name)
+ {
+ using namespace std;
+
+ return -(class_ >> x3::space)>> x3::string(type_name) >>
+ const_rule<T>() >>
+ volatile_rule<T>() >>
+ reference_rule<T>() >>
+ ptr_rule();
+ }
+ template<>
+ auto type_rule<void>(const std::string &) { return x3::string("void"); };
+
+ auto const cdecl_ = "__cdecl" >> x3::space;
+ auto const stdcall = "__stdcall" >> x3::space;
+#if defined(_WIN64)//seems to be necessary by msvc 14-x64
+ auto const thiscall = "__cdecl" >> x3::space;
+#else
+ auto const thiscall = "__thiscall" >> x3::space;
+#endif
+
+ template<typename Return, typename Arg>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
+ {
+ using namespace std;
+
+ return type_rule<Arg>(ms.get_name<Arg>());
+ }
+
+ template<typename Return, typename First, typename Second, typename ...Args>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
+ {
+
+ using next_type = Return (*)(Second, Args...);
+ return type_rule<First>(ms.get_name<First>()) >> x3::char_(',') >> arg_list(ms, next_type());
+ }
+
+ template<typename Return>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)())
+ {
+ return x3::string("void");
+ }
+}
+
+
+template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name)
+{
+ using namespace std;
+ using namespace boost;
+
+ namespace x3 = spirit::x3;
+ using namespace parser;
+
+ auto type_name = get_name<T>();
+
+ auto matcher =
+ -(visibility >> static_ >> x3::space) >> //it may be a static class-member
+ parser::type_rule<T>(type_name) >> x3::space >>
+ name;
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ if (e.demangled == name)//maybe not mangled,
+ return true;
+
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name)
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ using func_type = Func*;
+ using return_type = typename function_traits<Func>::result_type;
+ std::string return_type_name = get_name<return_type>();
+
+
+ auto matcher =
+ -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute.
+ parser::type_rule<return_type>(return_type_name) >> x3::space >>
+ cdecl_ >> //cdecl declaration for methods. stdcall cannot be
+ name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ if (e.demangled == name)//maybe not mangled,
+ return true;
+
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ 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)
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ using func_type = Func*;
+ using return_type = typename function_traits<Func>::result_type;
+ auto return_type_name = get_name<return_type>();
+
+
+ auto cname = get_name<Class>();
+
+ auto matcher =
+ visibility >> -virtual_ >> x3::space >>
+ parser::type_rule<return_type>(return_type_name) >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ cname >> "::" >> name >>
+ x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >>
+ inv_const_rule<Class>() >> inv_volatile_rule<Class>() >> parser::ptr_rule();
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+
+template<typename Signature>
+auto mangled_storage_impl::get_constructor() -> ctor_sym
+{
+ namespace x3 = spirit::x3;
+ 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 =
+ visibility >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ ctor_name >>
+ x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto f = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (f != storage_.end())
+ return f->mangled;
+ else
+ return "";
+}
+
+template<typename Class>
+auto mangled_storage_impl::get_destructor() -> dtor_sym
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ 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 + "(void)";
+ unscoped_cname = class_name;
+ }
+ else
+ {
+ unscoped_cname = class_name.substr(pos+2) ;
+ dtor_name = class_name+ "::~" + unscoped_cname + "(void)";
+ }
+ }
+
+ auto matcher =
+ visibility >> -virtual_ >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ dtor_name >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+
+
+
+}}}
+
+
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */
diff --git a/boost/dll/detail/elf_info.hpp b/boost/dll/detail/elf_info.hpp
new file mode 100644
index 0000000000..325df9cb10
--- /dev/null
+++ b/boost/dll/detail/elf_info.hpp
@@ -0,0 +1,285 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_POSIX_ELF_INFO_HPP
+#define BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <cstring>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+template <class AddressOffsetT>
+struct Elf_Ehdr_template {
+ unsigned char e_ident[16]; /* Magic number and other info */
+ boost::uint16_t e_type; /* Object file type */
+ boost::uint16_t e_machine; /* Architecture */
+ boost::uint32_t e_version; /* Object file version */
+ AddressOffsetT e_entry; /* Entry point virtual address */
+ AddressOffsetT e_phoff; /* Program header table file offset */
+ AddressOffsetT e_shoff; /* Section header table file offset */
+ boost::uint32_t e_flags; /* Processor-specific flags */
+ boost::uint16_t e_ehsize; /* ELF header size in bytes */
+ boost::uint16_t e_phentsize; /* Program header table entry size */
+ boost::uint16_t e_phnum; /* Program header table entry count */
+ boost::uint16_t e_shentsize; /* Section header table entry size */
+ boost::uint16_t e_shnum; /* Section header table entry count */
+ boost::uint16_t e_shstrndx; /* Section header string table index */
+};
+
+typedef Elf_Ehdr_template<boost::uint32_t> Elf32_Ehdr_;
+typedef Elf_Ehdr_template<boost::uint64_t> Elf64_Ehdr_;
+
+template <class AddressOffsetT>
+struct Elf_Shdr_template {
+ boost::uint32_t sh_name; /* Section name (string tbl index) */
+ boost::uint32_t sh_type; /* Section type */
+ AddressOffsetT sh_flags; /* Section flags */
+ AddressOffsetT sh_addr; /* Section virtual addr at execution */
+ AddressOffsetT sh_offset; /* Section file offset */
+ AddressOffsetT sh_size; /* Section size in bytes */
+ boost::uint32_t sh_link; /* Link to another section */
+ boost::uint32_t sh_info; /* Additional section information */
+ AddressOffsetT sh_addralign; /* Section alignment */
+ AddressOffsetT sh_entsize; /* Entry size if section holds table */
+};
+
+typedef Elf_Shdr_template<boost::uint32_t> Elf32_Shdr_;
+typedef Elf_Shdr_template<boost::uint64_t> Elf64_Shdr_;
+
+template <class AddressOffsetT>
+struct Elf_Sym_template;
+
+template <>
+struct Elf_Sym_template<boost::uint32_t> {
+ typedef boost::uint32_t AddressOffsetT;
+
+ boost::uint32_t st_name; /* Symbol name (string tbl index) */
+ AddressOffsetT st_value; /* Symbol value */
+ AddressOffsetT st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ boost::uint16_t st_shndx; /* Section index */
+};
+
+template <>
+struct Elf_Sym_template<boost::uint64_t> {
+ typedef boost::uint64_t AddressOffsetT;
+
+ boost::uint32_t st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ boost::uint16_t st_shndx; /* Section index */
+ AddressOffsetT st_value; /* Symbol value */
+ AddressOffsetT st_size; /* Symbol size */
+};
+
+
+typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_;
+typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_;
+
+template <class AddressOffsetT>
+class elf_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT> header_t;
+ typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT> section_t;
+ typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT> symbol_t;
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2);
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3);
+
+ BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0); /* Local symbol */
+ BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1); /* Global symbol */
+ BOOST_STATIC_CONSTANT(unsigned char, STB_WEAK_ = 2); /* Weak symbol */
+
+ /* Symbol visibility specification encoded in the st_other field. */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_DEFAULT_ = 0); /* Default symbol visibility rules */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_INTERNAL_ = 1); /* Processor specific hidden class */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_HIDDEN_ = 2); /* Sym unavailable in other modules */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3); /* Not preemptible, not exported */
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ const unsigned char magic_bytes[5] = {
+ 0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2
+ };
+
+ unsigned char ch;
+ f.seekg(0);
+ for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) {
+ f >> ch;
+ if (ch != magic_bytes[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ explicit elf_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+ std::vector<char> names;
+ sections_names_raw(names);
+
+ const char* name_begin = &names[0];
+ const char* const name_end = name_begin + names.size();
+ ret.reserve(header().e_shnum);
+ do {
+ ret.push_back(name_begin);
+ name_begin += ret.back().size() + 1;
+ } while (name_begin != name_end);
+
+ return ret;
+ }
+
+private:
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+ inline header_t header() {
+ header_t elf;
+
+ f_.seekg(0);
+ read_raw(elf);
+
+ return elf;
+ }
+
+ void sections_names_raw(std::vector<char>& sections) {
+ const header_t elf = header();
+
+ section_t section_names_section;
+ f_.seekg(elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
+ read_raw(section_names_section);
+
+ sections.resize(static_cast<std::size_t>(section_names_section.sh_size));
+ f_.seekg(section_names_section.sh_offset);
+ read_raw(sections[0], static_cast<std::size_t>(section_names_section.sh_size));
+ }
+
+ void symbols_text(std::vector<symbol_t>& symbols, std::vector<char>& text) {
+ const header_t elf = header();
+ f_.seekg(elf.e_shoff);
+
+ for (std::size_t i = 0; i < elf.e_shnum; ++i) {
+ section_t section;
+ read_raw(section);
+
+ if (section.sh_type == SHT_SYMTAB_) {
+ symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t)));
+
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ f_.seekg(section.sh_offset);
+ read_raw(symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) );
+ f_.seekg(pos);
+ } else if (section.sh_type == SHT_STRTAB_) {
+ text.resize(static_cast<std::size_t>(section.sh_size));
+
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ f_.seekg(section.sh_offset);
+ read_raw(text[0], static_cast<std::size_t>(section.sh_size));
+ f_.seekg(pos);
+ }
+ }
+ }
+
+ static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT {
+ // `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the
+ // GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621
+ return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
+ }
+
+public:
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+
+ std::vector<symbol_t> symbols;
+ std::vector<char> text;
+ symbols_text(symbols, text);
+
+ ret.reserve(symbols.size());
+ for (std::size_t i = 0; i < symbols.size(); ++i) {
+ if (is_visible(symbols[i])) {
+ ret.push_back(&text[0] + symbols[i].st_name);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ std::vector<std::string> ret;
+
+ std::size_t index = 0;
+ std::size_t ptrs_in_section_count = 0;
+ {
+ std::vector<char> names;
+ sections_names_raw(names);
+
+ const header_t elf = header();
+
+ for (; index < elf.e_shnum; ++index) {
+ section_t section;
+ f_.seekg(elf.e_shoff + index * sizeof(section_t));
+ read_raw(section);
+
+ if (!std::strcmp(&names[0] + section.sh_name, section_name)) {
+ if (!section.sh_entsize) {
+ section.sh_entsize = 1;
+ }
+ ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
+ break;
+ }
+ }
+ }
+
+ std::vector<symbol_t> symbols;
+ std::vector<char> text;
+ symbols_text(symbols, text);
+
+ if (ptrs_in_section_count < symbols.size()) {
+ ret.reserve(ptrs_in_section_count);
+ } else {
+ ret.reserve(symbols.size());
+ }
+
+ for (std::size_t i = 0; i < symbols.size(); ++i) {
+ if (symbols[i].st_shndx == index && is_visible(symbols[i])) {
+ ret.push_back(&text[0] + symbols[i].st_name);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+
+ return ret;
+ }
+};
+
+typedef elf_info<boost::uint32_t> elf_info32;
+typedef elf_info<boost::uint64_t> elf_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
diff --git a/boost/dll/detail/get_mem_fn_type.hpp b/boost/dll/detail/get_mem_fn_type.hpp
new file mode 100644
index 0000000000..65cead20bc
--- /dev/null
+++ b/boost/dll/detail/get_mem_fn_type.hpp
@@ -0,0 +1,40 @@
+// 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)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_DLL_SMART_LIBRARY_HPP_
+#define BOOST_DLL_SMART_LIBRARY_HPP_
+
+namespace boost { namespace dll { namespace detail {
+
+template<typename Class, typename Func>
+struct get_mem_fn_type;
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...);
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<const Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) const ;
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<volatile Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) volatile;
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<const volatile Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) const volatile ;
+};
+
+}}} // namespace boost::dll::detail
+
+
+#endif /* INCLUDE_BOOST_DLL_SMART_LIBRARY_HPP_ */
diff --git a/boost/dll/detail/macho_info.hpp b/boost/dll/detail/macho_info.hpp
new file mode 100644
index 0000000000..6911908238
--- /dev/null
+++ b/boost/dll/detail/macho_info.hpp
@@ -0,0 +1,321 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_MACHO_INFO_HPP
+#define BOOST_DLL_DETAIL_MACHO_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+typedef int integer_t;
+typedef int vm_prot_t;
+typedef integer_t cpu_type_t;
+typedef integer_t cpu_subtype_t;
+
+template <class AddressOffsetT>
+struct mach_header_template {
+ boost::uint32_t magic;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ boost::uint32_t filetype;
+ boost::uint32_t ncmds;
+ boost::uint32_t sizeofcmds;
+ boost::uint32_t flags[sizeof(AddressOffsetT) / sizeof(uint32_t)]; // Flags and reserved
+};
+
+typedef mach_header_template<boost::uint32_t> mach_header_32_;
+typedef mach_header_template<boost::uint64_t> mach_header_64_;
+
+struct load_command_ {
+ boost::uint32_t cmd; /* type of command */
+ boost::uint32_t cmdsize;
+};
+
+struct load_command_types {
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_ = 0x1); /* segment of this file to be mapped */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMTAB_ = 0x2); /* link-edit stab symbol table info */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMSEG_ = 0x3); /* link-edit gdb symbol table info (obsolete) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_THREAD_ = 0x4); /* thread */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UNIXTHREAD_ = 0x5); /* unix thread (includes a stack) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOADFVMLIB_ = 0x6); /* load a specified fixed VM shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDFVMLIB_ = 0x7); /* fixed VM shared library identification */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDENT_ = 0x8); /* object identification info (obsolete) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_FVMFILE_ = 0x9); /* fixed VM file inclusion (internal use) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREPAGE_ = 0xa); /* prepage command (internal use) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYSYMTAB_ = 0xb); /* dynamic link-edit symbol table info */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLIB_ = 0xc); /* load a dynamically linked shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLIB_ = 0xd); /* dynamically linked shared lib ident */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLINKER_ = 0xe); /* load a dynamic linker */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLINKER_ = 0xf); /* dynamic linker identification */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBOUND_DYLIB_ = 0x10); /* modules prebound for a dynamically linked shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_ = 0x11); /* image routines */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_FRAMEWORK_ = 0x12); /* sub framework */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_UMBRELLA_ = 0x13); /* sub umbrella */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_CLIENT_ = 0x14); /* sub client */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_LIBRARY_ = 0x15); /* sub library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_TWOLEVEL_HINTS_ = 0x16); /* two-level namespace lookup hints */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBIND_CKSUM_ = 0x17); /* prebind checksum */
+/*
+ * After MacOS X 10.1 when a new load command is added that is required to be
+ * understood by the dynamic linker for the image to execute properly the
+ * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
+ * linker sees such a load command it it does not understand will issue a
+ * "unknown load command required for execution" error and refuse to use the
+ * image. Other load commands without this bit that are not understood will
+ * simply be ignored.
+ */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REQ_DYLD_ = 0x80000000);
+
+/*
+ * load a dynamically linked shared library that is allowed to be missing
+ * (all symbols are weak imported).
+ */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_WEAK_DYLIB_ = (0x18 | LC_REQ_DYLD_));
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_64_ = 0x19); /* 64-bit segment of this file to be mapped */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_64_ = 0x1a); /* 64-bit image routines */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UUID_ = 0x1b); /* the uuid */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_RPATH_ = (0x1c | LC_REQ_DYLD_)); /* runpath additions */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_CODE_SIGNATURE_ = 0x1d); /* local of code signature */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_SPLIT_INFO_= 0x1e); /* local of info to split segments */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REEXPORT_DYLIB_ = (0x1f | LC_REQ_DYLD_)); /* load and re-export dylib */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LAZY_LOAD_DYLIB_ = 0x20); /* delay load of dylib until first use */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ENCRYPTION_INFO_ = 0x21); /* encrypted segment information */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ = 0x22); /* compressed dyld information */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ONLY_ = (0x22|LC_REQ_DYLD_)); /* compressed dyld information only */
+};
+
+template <class AddressOffsetT>
+struct segment_command_template {
+ boost::uint32_t cmd; /* LC_SEGMENT_ */
+ boost::uint32_t cmdsize; /* includes sizeof section structs */
+ char segname[16]; /* segment name */
+ AddressOffsetT vmaddr; /* memory address of this segment */
+ AddressOffsetT vmsize; /* memory size of this segment */
+ AddressOffsetT fileoff; /* file offset of this segment */
+ AddressOffsetT filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ boost::uint32_t nsects; /* number of sections in segment */
+ boost::uint32_t flags; /* flags */
+};
+
+typedef segment_command_template<boost::uint32_t> segment_command_32_;
+typedef segment_command_template<boost::uint64_t> segment_command_64_;
+
+template <class AddressOffsetT>
+struct section_template {
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ AddressOffsetT addr; /* memory address of this section */
+ AddressOffsetT size; /* size in bytes of this section */
+ boost::uint32_t offset; /* file offset of this section */
+ boost::uint32_t align; /* section alignment (power of 2) */
+ boost::uint32_t reloff; /* file offset of relocation entries */
+ boost::uint32_t nreloc; /* number of relocation entries */
+ boost::uint32_t flags; /* flags (section type and attributes)*/
+ boost::uint32_t reserved[1 + sizeof(AddressOffsetT) / sizeof(uint32_t)];
+};
+
+typedef section_template<boost::uint32_t> section_32_;
+typedef section_template<boost::uint64_t> section_64_;
+
+struct symtab_command_ {
+ boost::uint32_t cmd; /* LC_SYMTAB_ */
+ boost::uint32_t cmdsize; /* sizeof(struct symtab_command) */
+ boost::uint32_t symoff; /* symbol table offset */
+ boost::uint32_t nsyms; /* number of symbol table entries */
+ boost::uint32_t stroff; /* string table offset */
+ boost::uint32_t strsize; /* string table size in bytes */
+};
+
+template <class AddressOffsetT>
+struct nlist_template {
+ boost::uint32_t n_strx;
+ boost::uint8_t n_type;
+ boost::uint8_t n_sect;
+ boost::uint16_t n_desc;
+ AddressOffsetT n_value;
+};
+
+typedef nlist_template<boost::uint32_t> nlist_32_;
+typedef nlist_template<boost::uint64_t> nlist_64_;
+
+template <class AddressOffsetT>
+class macho_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef boost::dll::detail::mach_header_template<AddressOffsetT> header_t;
+ typedef boost::dll::detail::load_command_ load_command_t;
+ typedef boost::dll::detail::segment_command_template<AddressOffsetT> segment_t;
+ typedef boost::dll::detail::section_template<AddressOffsetT> section_t;
+ typedef boost::dll::detail::symtab_command_ symbol_header_t;
+ typedef boost::dll::detail::nlist_template<AddressOffsetT> nlist_t;
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SEGMENT_CMD_NUMBER = (sizeof(AddressOffsetT) > 4 ? load_command_types::LC_SEGMENT_64_ : load_command_types::LC_SEGMENT_));
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf);
+
+ uint32_t magic;
+ f.seekg(0);
+ f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
+ return (magic_bytes == magic);
+ }
+
+ explicit macho_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+private:
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+ template <class F>
+ void command_finder(uint32_t cmd_num, F callback_f) {
+ const header_t h = header();
+ load_command_t command;
+ f_.seekg(sizeof(header_t));
+ for (std::size_t i = 0; i < h.ncmds; ++i) {
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ read_raw(command);
+ if (command.cmd != cmd_num) {
+ f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
+ continue;
+ }
+
+ f_.seekg(pos);
+ callback_f(*this);
+ f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
+ }
+ }
+
+ struct section_names_gather {
+ std::vector<std::string>& ret;
+
+ void operator()(const macho_info& f) const {
+ segment_t segment;
+ f.read_raw(segment);
+
+ section_t section;
+ ret.reserve(ret.size() + segment.nsects);
+ for (std::size_t j = 0; j < segment.nsects; ++j) {
+ f.read_raw(section);
+ // `segname` goes right after the `sectname`.
+ // Forcing `sectname` to end on '\0'
+ section.segname[0] = '\0';
+ ret.push_back(section.sectname);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+ };
+
+ struct symbol_names_gather {
+ std::vector<std::string>& ret;
+ std::size_t section_index;
+
+ void operator()(const macho_info& f) const {
+ symbol_header_t symbh;
+ f.read_raw(symbh);
+ ret.reserve(ret.size() + symbh.nsyms);
+
+ nlist_t symbol;
+ std::string symbol_name;
+ for (std::size_t j = 0; j < symbh.nsyms; ++j) {
+ f.f_.seekg(symbh.symoff + j * sizeof(nlist_t));
+ f.read_raw(symbol);
+ if (!symbol.n_strx) {
+ continue; // Symbol has no name
+ }
+
+ if ((symbol.n_type & 0x0e) != 0xe || !symbol.n_sect) {
+ continue; // Symbol has no section
+ }
+
+ if (section_index && section_index != symbol.n_sect) {
+ continue; // Not in the required section
+ }
+
+ f.f_.seekg(symbh.stroff + symbol.n_strx);
+ getline(f.f_, symbol_name, '\0');
+ if (symbol_name.empty()) {
+ continue;
+ }
+
+ if (symbol_name[0] == '_') {
+ // Linker adds additional '_' symbol. Could not find official docs for that case.
+ ret.push_back(symbol_name.c_str() + 1);
+ } else {
+ ret.push_back(symbol_name);
+ }
+ }
+ }
+ };
+
+public:
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+ section_names_gather f = { ret };
+ command_finder(SEGMENT_CMD_NUMBER, f);
+ return ret;
+ }
+
+private:
+ inline header_t header() {
+ header_t h;
+
+ f_.seekg(0);
+ read_raw(h);
+
+ return h;
+ }
+
+public:
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+ symbol_names_gather f = { ret, 0 };
+ command_finder(load_command_types::LC_SYMTAB_, f);
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ // Not very optimal solution
+ std::vector<std::string> ret = sections();
+ std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name);
+ if (it == ret.end()) {
+ // No section with such name
+ ret.clear();
+ return ret;
+ }
+
+ // section indexes start from 1
+ symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) };
+ ret.clear();
+ command_finder(load_command_types::LC_SYMTAB_, f);
+ return ret;
+ }
+};
+
+typedef macho_info<boost::uint32_t> macho_info32;
+typedef macho_info<boost::uint64_t> macho_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_MACHO_INFO_HPP
diff --git a/boost/dll/detail/pe_info.hpp b/boost/dll/detail/pe_info.hpp
new file mode 100644
index 0000000000..7f1584a656
--- /dev/null
+++ b/boost/dll/detail/pe_info.hpp
@@ -0,0 +1,427 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_WINDOWS_PE_INFO_HPP
+#define BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+// reference:
+// http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/
+// http://msdn.microsoft.com/en-us/magazine/ms809762.aspx
+// http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
+//
+
+// Basic Windows typedefs. We can not use <boost/detail/winapi/basic_types.hpp> header
+// because that header must be included only on Windows platform
+typedef unsigned char BYTE_;
+typedef unsigned short WORD_;
+typedef unsigned long DWORD_;
+typedef long LONG_;
+typedef unsigned long ULONG_;
+typedef boost::int64_t LONGLONG_;
+typedef boost::uint64_t ULONGLONG_;
+
+struct IMAGE_DOS_HEADER_ { // 32/64 independent header
+ boost::dll::detail::WORD_ e_magic; // Magic number
+ boost::dll::detail::WORD_ e_cblp; // Bytes on last page of file
+ boost::dll::detail::WORD_ e_cp; // Pages in file
+ boost::dll::detail::WORD_ e_crlc; // Relocations
+ boost::dll::detail::WORD_ e_cparhdr; // Size of header in paragraphs
+ boost::dll::detail::WORD_ e_minalloc; // Minimum extra paragraphs needed
+ boost::dll::detail::WORD_ e_maxalloc; // Maximum extra paragraphs needed
+ boost::dll::detail::WORD_ e_ss; // Initial (relative) SS value
+ boost::dll::detail::WORD_ e_sp; // Initial SP value
+ boost::dll::detail::WORD_ e_csum; // Checksum
+ boost::dll::detail::WORD_ e_ip; // Initial IP value
+ boost::dll::detail::WORD_ e_cs; // Initial (relative) CS value
+ boost::dll::detail::WORD_ e_lfarlc; // File address of relocation table
+ boost::dll::detail::WORD_ e_ovno; // Overlay number
+ boost::dll::detail::WORD_ e_res[4]; // Reserved words
+ boost::dll::detail::WORD_ e_oemid; // OEM identifier (for e_oeminfo)
+ boost::dll::detail::WORD_ e_oeminfo; // OEM information; e_oemid specific
+ boost::dll::detail::WORD_ e_res2[10]; // Reserved words
+ boost::dll::detail::LONG_ e_lfanew; // File address of new exe header
+};
+
+struct IMAGE_FILE_HEADER_ { // 32/64 independent header
+ boost::dll::detail::WORD_ Machine;
+ boost::dll::detail::WORD_ NumberOfSections;
+ boost::dll::detail::DWORD_ TimeDateStamp;
+ boost::dll::detail::DWORD_ PointerToSymbolTable;
+ boost::dll::detail::DWORD_ NumberOfSymbols;
+ boost::dll::detail::WORD_ SizeOfOptionalHeader;
+ boost::dll::detail::WORD_ Characteristics;
+};
+
+struct IMAGE_DATA_DIRECTORY_ { // 32/64 independent header
+ boost::dll::detail::DWORD_ VirtualAddress;
+ boost::dll::detail::DWORD_ Size;
+};
+
+struct IMAGE_EXPORT_DIRECTORY_ { // 32/64 independent header
+ boost::dll::detail::DWORD_ Characteristics;
+ boost::dll::detail::DWORD_ TimeDateStamp;
+ boost::dll::detail::WORD_ MajorVersion;
+ boost::dll::detail::WORD_ MinorVersion;
+ boost::dll::detail::DWORD_ Name;
+ boost::dll::detail::DWORD_ Base;
+ boost::dll::detail::DWORD_ NumberOfFunctions;
+ boost::dll::detail::DWORD_ NumberOfNames;
+ boost::dll::detail::DWORD_ AddressOfFunctions;
+ boost::dll::detail::DWORD_ AddressOfNames;
+ boost::dll::detail::DWORD_ AddressOfNameOrdinals;
+};
+
+struct IMAGE_SECTION_HEADER_ { // 32/64 independent header
+ static const std::size_t IMAGE_SIZEOF_SHORT_NAME_ = 8;
+
+ boost::dll::detail::BYTE_ Name[IMAGE_SIZEOF_SHORT_NAME_];
+ union {
+ boost::dll::detail::DWORD_ PhysicalAddress;
+ boost::dll::detail::DWORD_ VirtualSize;
+ } Misc;
+ boost::dll::detail::DWORD_ VirtualAddress;
+ boost::dll::detail::DWORD_ SizeOfRawData;
+ boost::dll::detail::DWORD_ PointerToRawData;
+ boost::dll::detail::DWORD_ PointerToRelocations;
+ boost::dll::detail::DWORD_ PointerToLinenumbers;
+ boost::dll::detail::WORD_ NumberOfRelocations;
+ boost::dll::detail::WORD_ NumberOfLinenumbers;
+ boost::dll::detail::DWORD_ Characteristics;
+};
+
+
+template <class AddressOffsetT>
+struct IMAGE_OPTIONAL_HEADER_template {
+ static const std::size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES_ = 16;
+
+ boost::dll::detail::WORD_ Magic;
+ boost::dll::detail::BYTE_ MajorLinkerVersion;
+ boost::dll::detail::BYTE_ MinorLinkerVersion;
+ boost::dll::detail::DWORD_ SizeOfCode;
+ boost::dll::detail::DWORD_ SizeOfInitializedData;
+ boost::dll::detail::DWORD_ SizeOfUninitializedData;
+ boost::dll::detail::DWORD_ AddressOfEntryPoint;
+ union {
+ boost::dll::detail::DWORD_ BaseOfCode;
+ unsigned char padding_[sizeof(AddressOffsetT) == 8 ? 4 : 8]; // in x64 version BaseOfData does not exist
+ } BaseOfCode_and_BaseOfData;
+
+ AddressOffsetT ImageBase;
+ boost::dll::detail::DWORD_ SectionAlignment;
+ boost::dll::detail::DWORD_ FileAlignment;
+ boost::dll::detail::WORD_ MajorOperatingSystemVersion;
+ boost::dll::detail::WORD_ MinorOperatingSystemVersion;
+ boost::dll::detail::WORD_ MajorImageVersion;
+ boost::dll::detail::WORD_ MinorImageVersion;
+ boost::dll::detail::WORD_ MajorSubsystemVersion;
+ boost::dll::detail::WORD_ MinorSubsystemVersion;
+ boost::dll::detail::DWORD_ Win32VersionValue;
+ boost::dll::detail::DWORD_ SizeOfImage;
+ boost::dll::detail::DWORD_ SizeOfHeaders;
+ boost::dll::detail::DWORD_ CheckSum;
+ boost::dll::detail::WORD_ Subsystem;
+ boost::dll::detail::WORD_ DllCharacteristics;
+ AddressOffsetT SizeOfStackReserve;
+ AddressOffsetT SizeOfStackCommit;
+ AddressOffsetT SizeOfHeapReserve;
+ AddressOffsetT SizeOfHeapCommit;
+ boost::dll::detail::DWORD_ LoaderFlags;
+ boost::dll::detail::DWORD_ NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY_ DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES_];
+};
+
+typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::DWORD_> IMAGE_OPTIONAL_HEADER32_;
+typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::ULONGLONG_> IMAGE_OPTIONAL_HEADER64_;
+
+template <class AddressOffsetT>
+struct IMAGE_NT_HEADERS_template {
+ boost::dll::detail::DWORD_ Signature;
+ IMAGE_FILE_HEADER_ FileHeader;
+ IMAGE_OPTIONAL_HEADER_template<AddressOffsetT> OptionalHeader;
+};
+
+typedef IMAGE_NT_HEADERS_template<boost::dll::detail::DWORD_> IMAGE_NT_HEADERS32_;
+typedef IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_> IMAGE_NT_HEADERS64_;
+
+
+template <class AddressOffsetT>
+class pe_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef IMAGE_NT_HEADERS_template<AddressOffsetT> header_t;
+ typedef IMAGE_EXPORT_DIRECTORY_ exports_t;
+ typedef IMAGE_SECTION_HEADER_ section_t;
+ typedef IMAGE_DOS_HEADER_ dos_t;
+
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ dos_t dos;
+ f.seekg(0);
+ f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
+
+ // 'MZ' and 'ZM' according to Wikipedia
+ if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) {
+ return false;
+ }
+
+ header_t h;
+ f.seekg(dos.e_lfanew);
+ f.read(reinterpret_cast<char*>(&h), sizeof(h));
+
+ return h.Signature == 0x00004550 // 'PE00'
+ && h.OptionalHeader.Magic == (sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B);
+ }
+
+
+ explicit pe_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+private:
+ inline header_t header() {
+ header_t h;
+
+ dos_t dos;
+ f_.seekg(0);
+ read_raw(dos);
+
+ f_.seekg(dos.e_lfanew);
+ read_raw(h);
+
+ return h;
+ }
+
+ inline exports_t exports(const header_t& h) {
+ exports_t exports;
+
+ static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0;
+ const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress;
+
+ const std::size_t real_offset = get_file_offset(exp_virtual_address, h);
+ BOOST_ASSERT(real_offset);
+
+ f_.seekg(real_offset);
+ read_raw(exports);
+
+ return exports;
+ }
+
+ std::size_t get_file_offset(std::size_t virtual_address, const header_t& h) {
+ section_t image_section_header;
+
+ { // f_.seekg to the beginning on section headers
+ dos_t dos;
+ f_.seekg(0);
+ read_raw(dos);
+ f_.seekg(dos.e_lfanew + sizeof(header_t));
+ }
+
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ read_raw(image_section_header);
+ if (virtual_address >= image_section_header.VirtualAddress
+ && virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData)
+ {
+ return image_section_header.PointerToRawData + virtual_address - image_section_header.VirtualAddress;
+ }
+ }
+
+ return 0;
+ }
+
+public:
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+ ret.reserve(h.FileHeader.NumberOfSections);
+
+ // get names, e.g: .text .rdata .data .rsrc .reloc
+ section_t image_section_header;
+ char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
+ std::memset(name_helper, 0, sizeof(name_helper));
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ // There is no terminating null character if the string is exactly eight characters long
+ read_raw(image_section_header);
+ std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
+
+ if (name_helper[0] != '/') {
+ ret.push_back(name_helper);
+ } else {
+ // For longer names, image_section_header.Name contains a slash (/) followed by ASCII representation of a decimal number.
+ // this number is an offset into the string table.
+ // TODO: fixme
+ ret.push_back(name_helper);
+ }
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+ const exports_t exprt = exports(h);
+ const std::size_t exported_symbols = exprt.NumberOfNames;
+ const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
+
+ ret.reserve(exported_symbols);
+ boost::dll::detail::DWORD_ name_offset;
+ std::string symbol_name;
+ for (std::size_t i = 0;i < exported_symbols;++i) {
+ f_.seekg(fixed_names_addr + i * sizeof(name_offset));
+ read_raw(name_offset);
+ f_.seekg(get_file_offset(name_offset, h));
+ getline(f_, symbol_name, '\0');
+ ret.push_back(symbol_name);
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+
+ std::size_t section_begin_addr = 0;
+ std::size_t section_end_addr = 0;
+
+ { // getting address range for the section
+ section_t image_section_header;
+ char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
+ std::memset(name_helper, 0, sizeof(name_helper));
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ // There is no terminating null character if the string is exactly eight characters long
+ read_raw(image_section_header);
+ std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
+ if (!std::strcmp(section_name, name_helper)) {
+ section_begin_addr = image_section_header.PointerToRawData;
+ section_end_addr = section_begin_addr + image_section_header.SizeOfRawData;
+ }
+ }
+ BOOST_ASSERT(section_begin_addr);
+ BOOST_ASSERT(section_end_addr);
+ }
+
+ const exports_t exprt = exports(h);
+ const std::size_t exported_symbols = exprt.NumberOfFunctions;
+ const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
+ const std::size_t fixed_ordinals_addr = get_file_offset(exprt.AddressOfNameOrdinals, h);
+ const std::size_t fixed_functions_addr = get_file_offset(exprt.AddressOfFunctions, h);
+
+ ret.reserve(exported_symbols);
+ boost::dll::detail::DWORD_ ptr;
+ boost::dll::detail::WORD_ ordinal;
+ std::string symbol_name;
+ for (std::size_t i = 0;i < exported_symbols;++i) {
+ // getting ordinal
+ f_.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
+ read_raw(ordinal);
+
+ // getting function addr
+ f_.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
+ read_raw(ptr);
+ ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(ptr, h) );
+
+ if (ptr >= section_end_addr || ptr < section_begin_addr) {
+ continue;
+ }
+
+ f_.seekg(fixed_names_addr + i * sizeof(ptr));
+ read_raw(ptr);
+ f_.seekg(get_file_offset(ptr, h));
+ getline(f_, symbol_name, '\0');
+ ret.push_back(symbol_name);
+ }
+
+ return ret;
+ }
+
+ // a test method to get dependents modules,
+ // who my plugin imports (1st level only)
+ /*
+ e.g. for myself I get:
+ KERNEL32.dll
+ MSVCP110D.dll
+ boost_system-vc-mt-gd-1_56.dll
+ MSVCR110D.dll
+ */
+ /*
+ std::vector<std::string> depend_of(boost::system::error_code &ec) BOOST_NOEXCEPT {
+ std::vector<std::string> ret;
+
+ IMAGE_DOS_HEADER* image_dos_header = (IMAGE_DOS_HEADER*)native();
+ if(!image_dos_header) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ IMAGE_OPTIONAL_HEADER* image_optional_header = (IMAGE_OPTIONAL_HEADER*)((boost::dll::detail::BYTE_*)native() + image_dos_header->e_lfanew + 24);
+ if(!image_optional_header) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ IMAGE_IMPORT_DESCRIPTOR* image_import_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)((boost::dll::detail::BYTE_*)native() + image_optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ if(!image_import_descriptor) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ while(image_import_descriptor->FirstThunk) {
+ std::string module_name = reinterpret_cast<char*>((boost::dll::detail::BYTE_*)native() + image_import_descriptor->Name);
+
+ if(module_name.size()) {
+ ret.push_back(module_name);
+ }
+
+ image_import_descriptor++;
+ }
+
+ return ret;
+ }
+*/
+};
+
+typedef pe_info<boost::dll::detail::DWORD_> pe_info32;
+typedef pe_info<boost::dll::detail::ULONGLONG_> pe_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
diff --git a/boost/dll/detail/posix/path_from_handle.hpp b/boost/dll/detail/posix/path_from_handle.hpp
new file mode 100644
index 0000000000..a2787623d6
--- /dev/null
+++ b/boost/dll/detail/posix/path_from_handle.hpp
@@ -0,0 +1,169 @@
+// Copyright 2014-2015 Renato Tegon Forti, Antony Polukhin.
+//
+// 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_POSIX_PATH_FROM_HANDLE_HPP
+#define BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/dll/detail/posix/program_location_impl.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/predef/os.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+
+# include <mach-o/dyld.h>
+# include <mach-o/nlist.h>
+# include <cstddef> // for std::ptrdiff_t
+
+namespace boost { namespace dll { namespace detail {
+ inline void* strip_handle(void* handle) BOOST_NOEXCEPT {
+ return reinterpret_cast<void*>(
+ (reinterpret_cast<std::ptrdiff_t>(handle) >> 2) << 2
+ );
+ }
+
+ inline boost::filesystem::path path_from_handle(void* handle, boost::system::error_code &ec) {
+ handle = strip_handle(handle);
+
+ // Iterate through all images currently in memory
+ // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html
+ const std::size_t count = _dyld_image_count(); // not thread safe: other thread my [un]load images
+ for (std::size_t i = 0; i <= count; ++i) {
+ // on last iteration `i` is equal to `count` which is out of range, so `_dyld_get_image_name`
+ // will return NULL. `dlopen(NULL, RTLD_LAZY)` call will open the current executable.
+ const char* image_name = _dyld_get_image_name(i);
+
+ // dlopen/dlclose must not affect `_dyld_image_count()`, because libraries are already loaded and only the internal counter is affected
+ void* probe_handle = dlopen(image_name, RTLD_LAZY);
+ dlclose(probe_handle);
+
+ // If the handle is the same as what was passed in (modulo mode bits), return this image name
+ if (handle == strip_handle(probe_handle)) {
+ boost::dll::detail::reset_dlerror();
+ return image_name;
+ }
+ }
+
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return boost::filesystem::path();
+ }
+
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_ANDROID
+
+#include <boost/dll/runtime_symbol_info.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+ struct soinfo {
+ // if defined(__work_around_b_24465209__), then an array of char[128] goes here.
+ // Unfortunately, __work_around_b_24465209__ is visible only during compilation of Android's linker
+ const void* phdr;
+ size_t phnum;
+ void* entry;
+ void* base;
+ // ... // Ignoring remaning parts of the structure
+ };
+
+ inline boost::filesystem::path path_from_handle(const void* handle, boost::system::error_code &ec) {
+ static const std::size_t work_around_b_24465209__offset = 128;
+ const struct soinfo* si = reinterpret_cast<const struct soinfo*>(
+ static_cast<const char*>(handle) + work_around_b_24465209__offset
+ );
+ boost::filesystem::path ret = boost::dll::detail::symbol_location_impl(si->base, ec);
+
+ if (ec) {
+ ec.clear();
+ si = static_cast<const struct soinfo*>(handle);
+ return boost::dll::detail::symbol_location_impl(si->base, ec);
+ }
+
+ return ret;
+ }
+
+}}} // namespace boost::dll::detail
+
+#else // #if BOOST_OS_MACOS || BOOST_OS_IOS || BOOST_OS_ANDROID
+
+// for dlinfo
+#include <dlfcn.h>
+
+#if BOOST_OS_QNX
+// QNX's copy of <elf.h> and <link.h> reside in sys folder
+# include <sys/link.h>
+#else
+# include <link.h> // struct link_map
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+#if BOOST_OS_QNX
+ // Android and QNX miss struct link_map. QNX misses ElfW macro, so avoiding it.
+ struct link_map {
+ void *l_addr; // Base address shared object is loaded at
+ char *l_name; // Absolute file name object was found in
+ // ... // Ignoring remaning parts of the structure
+ };
+#endif // #if BOOST_OS_QNX
+
+ inline boost::filesystem::path path_from_handle(void* handle, boost::system::error_code &ec) {
+ // RTLD_DI_LINKMAP (RTLD_DI_ORIGIN returns only folder and is not suitable for this case)
+ // Obtain the Link_map for the handle that is specified.
+ // The p argument points to a Link_map pointer (Link_map
+ // **p). The actual storage for the Link_map structure is
+ // maintained by ld.so.1.
+ //
+ // Unfortunately we can not use `dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0`
+ // because it is not supported on MacOS X 10.3, NetBSD 3.0, OpenBSD 3.8, AIX 5.1,
+ // HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin, mingw, Interix 3.5, BeOS.
+ // Fortunately investigating the sources of open source projects brought the understanding, that
+ // `handle` is just a `struct link_map*` that contains full library name.
+
+ const struct link_map* link_map = 0;
+#if BOOST_OS_BSD_FREE
+ // FreeBSD has it's own logic http://code.metager.de/source/xref/freebsd/libexec/rtld-elf/rtld.c
+ // Fortunately it has the dlinfo call.
+ if (dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0) {
+ link_map = 0;
+ }
+#else
+ link_map = static_cast<const struct link_map*>(handle);
+#endif
+ if (!link_map) {
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return boost::filesystem::path();
+ }
+
+ if (!link_map->l_name || *link_map->l_name == '\0') {
+ return program_location_impl(ec);
+ }
+
+ return boost::filesystem::path(link_map->l_name);
+ }
+
+}}} // namespace boost::dll::detail
+
+#endif // #if BOOST_OS_MACOS || BOOST_OS_IOS
+
+#endif // BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP
+
+
diff --git a/boost/dll/detail/posix/program_location_impl.hpp b/boost/dll/detail/posix/program_location_impl.hpp
new file mode 100644
index 0000000000..bca9b8caef
--- /dev/null
+++ b/boost/dll/detail/posix/program_location_impl.hpp
@@ -0,0 +1,140 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_POSIX_PROGRAM_LOCATION_IMPL_HPP
+#define BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/predef/os.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+
+#include <mach-o/dyld.h>
+
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ ec.clear();
+
+ char path[1024];
+ uint32_t size = sizeof(path);
+ if (_NSGetExecutablePath(path, &size) == 0)
+ return boost::filesystem::path(path);
+
+ char *p = new char[size];
+ if (_NSGetExecutablePath(p, &size) != 0) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+
+ boost::filesystem::path ret(p);
+ delete[] p;
+ return ret;
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_SOLARIS
+
+#include <stdlib.h>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ ec.clear();
+
+ return boost::filesystem::path(getexecname());
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_BSD_FREE
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ ec.clear();
+
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ char buf[10240];
+ size_t cb = sizeof(buf);
+ sysctl(mib, 4, buf, &cb, NULL, 0);
+
+ return boost::filesystem::path(buf);
+ }
+}}} // namespace boost::dll::detail
+
+
+
+#elif BOOST_OS_BSD_NET
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ return boost::filesystem::read_symlink("/proc/curproc/exe", ec);
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_BSD_DRAGONFLY
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ return boost::filesystem::read_symlink("/proc/curproc/file", ec);
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_QNX
+
+#include <fstream>
+#include <string> // for std::getline
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ ec.clear();
+
+ std::string s;
+ std::ifstream ifs("/proc/self/exefile");
+ std::getline(ifs, s);
+
+ if (ifs.fail() || s.empty()) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+
+ return boost::filesystem::path(s);
+ }
+}}} // namespace boost::dll::detail
+
+#else // BOOST_OS_LINUX || BOOST_OS_UNIX || BOOST_OS_HPUX || BOOST_OS_ANDROID
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ // We can not use
+ // boost::dll::detail::path_from_handle(dlopen(NULL, RTLD_LAZY | RTLD_LOCAL), ignore);
+ // because such code returns empty path.
+
+ return boost::filesystem::read_symlink("/proc/self/exe", ec); // Linux specific
+ }
+}}} // namespace boost::dll::detail
+
+#endif
+
+#endif // BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
+
diff --git a/boost/dll/detail/posix/shared_library_impl.hpp b/boost/dll/detail/posix/shared_library_impl.hpp
new file mode 100644
index 0000000000..509e6c7487
--- /dev/null
+++ b/boost/dll/detail/posix/shared_library_impl.hpp
@@ -0,0 +1,215 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 Antony Polukhin.
+//
+// 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_SHARED_LIBRARY_IMPL_HPP
+#define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/shared_library_load_mode.hpp>
+#include <boost/dll/detail/posix/path_from_handle.hpp>
+#include <boost/dll/detail/posix/program_location_impl.hpp>
+
+#include <boost/move/utility.hpp>
+#include <boost/swap.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/predef/os.h>
+
+#include <dlfcn.h>
+#include <cstring> // strncmp
+#if !BOOST_OS_MACOS && !BOOST_OS_IOS && !BOOST_OS_QNX
+# include <link.h>
+#elif BOOST_OS_QNX
+// QNX's copy of <elf.h> and <link.h> reside in sys folder
+# include <sys/link.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+class shared_library_impl {
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
+
+public:
+ typedef void* native_handle_t;
+
+ shared_library_impl() BOOST_NOEXCEPT
+ : handle_(NULL)
+ {}
+
+ ~shared_library_impl() BOOST_NOEXCEPT {
+ unload();
+ }
+
+ shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
+ : handle_(sl.handle_)
+ {
+ sl.handle_ = NULL;
+ }
+
+ shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
+ swap(sl);
+ return *this;
+ }
+
+ void load(boost::filesystem::path sl, load_mode::type mode, boost::system::error_code &ec) {
+ typedef int native_mode_t;
+ unload();
+
+ // Do not allow opening NULL paths. User must use program_location() instead
+ if (sl.empty()) {
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return;
+ }
+
+ // Fixing modes
+ if (!(mode & load_mode::rtld_now)) {
+ mode |= load_mode::rtld_lazy;
+ }
+
+ if (!(mode & load_mode::rtld_global)) {
+ mode |= load_mode::rtld_local;
+ }
+
+#if BOOST_OS_LINUX || BOOST_OS_ANDROID
+ if (!sl.has_parent_path() && !(mode & load_mode::search_system_folders)) {
+ sl = "." / sl;
+ }
+#else
+ if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
+ boost::system::error_code current_path_ec;
+ boost::filesystem::path prog_loc = boost::filesystem::current_path(current_path_ec);
+ if (!current_path_ec) {
+ prog_loc /= sl;
+ sl.swap(prog_loc);
+ }
+ }
+#endif
+
+ mode &= ~load_mode::search_system_folders;
+
+ // Trying to open with appended decorations
+ if (!!(mode & load_mode::append_decorations)) {
+ mode &= ~load_mode::append_decorations;
+
+ boost::filesystem::path actual_path = (
+ std::strncmp(sl.filename().string().c_str(), "lib", 3)
+ ? (sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native()
+ : sl
+ );
+ actual_path += suffix();
+
+ handle_ = dlopen(actual_path.c_str(), static_cast<native_mode_t>(mode));
+ if (handle_) {
+ boost::dll::detail::reset_dlerror();
+ return;
+ }
+ }
+
+ // Opening by exactly specified path
+ handle_ = dlopen(sl.c_str(), static_cast<native_mode_t>(mode));
+ if (handle_) {
+ boost::dll::detail::reset_dlerror();
+ return;
+ }
+
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ // Maybe user wanted to load the executable itself? Checking...
+ // We assume that usually user wants to load a dynamic library not the executable itself, that's why
+ // we try this only after traditional load fails.
+ boost::system::error_code prog_loc_err;
+ boost::filesystem::path loc = boost::dll::detail::program_location_impl(prog_loc_err);
+ if (!prog_loc_err && boost::filesystem::equivalent(sl, loc, prog_loc_err) && !prog_loc_err) {
+ // As is known the function dlopen() loads the dynamic library file
+ // named by the null-terminated string filename and returns an opaque
+ // "handle" for the dynamic library. If filename is NULL, then the
+ // returned handle is for the main program.
+ ec.clear();
+ boost::dll::detail::reset_dlerror();
+ handle_ = dlopen(NULL, static_cast<native_mode_t>(mode));
+ if (!handle_) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+ }
+ }
+
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return (handle_ != 0);
+ }
+
+ void unload() BOOST_NOEXCEPT {
+ if (!is_loaded()) {
+ return;
+ }
+
+ dlclose(handle_);
+ handle_ = 0;
+ }
+
+ void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
+ boost::swap(handle_, rhs.handle_);
+ }
+
+ boost::filesystem::path full_module_path(boost::system::error_code &ec) const {
+ return boost::dll::detail::path_from_handle(handle_, ec);
+ }
+
+ static boost::filesystem::path suffix() {
+ // https://sourceforge.net/p/predef/wiki/OperatingSystems/
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+ return ".dylib";
+#else
+ return ".so";
+#endif
+ }
+
+ void* symbol_addr(const char* sb, boost::system::error_code &ec) const BOOST_NOEXCEPT {
+ // dlsym - obtain the address of a symbol from a dlopen object
+ void* const symbol = dlsym(handle_, sb);
+ if (symbol == NULL) {
+ ec = boost::system::error_code(
+ boost::system::errc::invalid_seek,
+ boost::system::generic_category()
+ );
+ }
+
+ // If handle does not refer to a valid object opened by dlopen(),
+ // or if the named symbol cannot be found within any of the objects
+ // associated with handle, dlsym() shall return NULL.
+ // More detailed diagnostic information shall be available through dlerror().
+
+ return symbol;
+ }
+
+ native_handle_t native() const BOOST_NOEXCEPT {
+ return handle_;
+ }
+
+private:
+ native_handle_t handle_;
+};
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
diff --git a/boost/dll/detail/system_error.hpp b/boost/dll/detail/system_error.hpp
new file mode 100644
index 0000000000..c032633a0b
--- /dev/null
+++ b/boost/dll/detail/system_error.hpp
@@ -0,0 +1,56 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+//
+// 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_SYSTEM_ERROR_HPP
+#define BOOST_DLL_SYSTEM_ERROR_HPP
+
+#include <boost/config.hpp>
+#include <boost/predef/os.h>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/throw_exception.hpp>
+
+#if !BOOST_OS_WINDOWS
+# include <dlfcn.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+ inline void reset_dlerror() BOOST_NOEXCEPT {
+#if !BOOST_OS_WINDOWS
+ const char* const error_txt = dlerror();
+ (void)error_txt;
+#endif
+ }
+
+ inline void report_error(const boost::system::error_code& ec, const char* message) {
+#if !BOOST_OS_WINDOWS
+ const char* const error_txt = dlerror();
+ if (error_txt) {
+ boost::throw_exception(
+ boost::system::system_error(
+ ec,
+ message + std::string(" (dlerror system message: ") + error_txt + std::string(")")
+ )
+ );
+ }
+#endif
+
+ boost::throw_exception(
+ boost::system::system_error(
+ ec, message
+ )
+ );
+ }
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SYSTEM_ERROR_HPP
+
diff --git a/boost/dll/detail/windows/path_from_handle.hpp b/boost/dll/detail/windows/path_from_handle.hpp
new file mode 100644
index 0000000000..37eee86428
--- /dev/null
+++ b/boost/dll/detail/windows/path_from_handle.hpp
@@ -0,0 +1,62 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_WINDOWS_PATH_FROM_HANDLE_HPP
+#define BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/detail/winapi/dll.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
+#include <boost/filesystem/path.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+ static inline boost::system::error_code last_error_code() BOOST_NOEXCEPT {
+ boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ return boost::system::error_code(
+ err,
+ boost::system::system_category()
+ );
+ }
+
+ inline boost::filesystem::path path_from_handle(boost::detail::winapi::HMODULE_ handle, boost::system::error_code &ec) {
+ BOOST_STATIC_CONSTANT(boost::detail::winapi::DWORD_, ERROR_INSUFFICIENT_BUFFER_ = 0x7A);
+ BOOST_STATIC_CONSTANT(boost::detail::winapi::DWORD_, DEFAULT_PATH_SIZE_ = 260);
+
+ // If `handle` parameter is NULL, GetModuleFileName retrieves the path of the
+ // executable file of the current process.
+ boost::detail::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_];
+ boost::detail::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
+ ec = last_error_code();
+ if (!ec) {
+ return boost::filesystem::path(path_hldr);
+ }
+
+ for (unsigned i = 2; i < 1025 && static_cast<boost::detail::winapi::DWORD_>(ec.value()) == ERROR_INSUFFICIENT_BUFFER_; i *= 2) {
+ std::wstring p(DEFAULT_PATH_SIZE_ * i, L'\0');
+ const std::size_t size = boost::detail::winapi::GetModuleFileNameW(handle, &p[0], DEFAULT_PATH_SIZE_ * i);
+ ec = last_error_code();
+
+ if (!ec) {
+ p.resize(size);
+ return boost::filesystem::path(p);
+ }
+ }
+
+ // Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough
+ return boost::filesystem::path();
+ }
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
+
diff --git a/boost/dll/detail/windows/shared_library_impl.hpp b/boost/dll/detail/windows/shared_library_impl.hpp
new file mode 100644
index 0000000000..48156505f4
--- /dev/null
+++ b/boost/dll/detail/windows/shared_library_impl.hpp
@@ -0,0 +1,177 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 Antony Polukhin.
+//
+// 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_SHARED_LIBRARY_IMPL_HPP
+#define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/shared_library_load_mode.hpp>
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/dll/detail/windows/path_from_handle.hpp>
+
+#include <boost/move/utility.hpp>
+#include <boost/swap.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+
+#include <boost/detail/winapi/dll.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+class shared_library_impl {
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
+
+public:
+ typedef boost::detail::winapi::HMODULE_ native_handle_t;
+
+ shared_library_impl() BOOST_NOEXCEPT
+ : handle_(NULL)
+ {}
+
+ ~shared_library_impl() BOOST_NOEXCEPT {
+ unload();
+ }
+
+ shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
+ : handle_(sl.handle_)
+ {
+ sl.handle_ = NULL;
+ }
+
+ shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
+ swap(sl);
+ return *this;
+ }
+
+ void load(boost::filesystem::path sl, load_mode::type mode, boost::system::error_code &ec) {
+ typedef boost::detail::winapi::DWORD_ native_mode_t;
+ unload();
+
+ if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
+
+ boost::system::error_code current_path_ec;
+ boost::filesystem::path prog_loc = boost::filesystem::current_path(current_path_ec);
+ if (!current_path_ec) {
+ prog_loc /= sl;
+ sl.swap(prog_loc);
+ }
+ }
+ mode &= ~load_mode::search_system_folders;
+
+ // Trying to open with appended decorations
+ if (!!(mode & load_mode::append_decorations)) {
+ mode &= ~load_mode::append_decorations;
+
+ handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".dll").c_str(), 0, static_cast<native_mode_t>(mode));
+ if (!handle_) {
+ // MinGW loves 'lib' prefix and puts it even on Windows platform
+ const boost::filesystem::path load_path = (sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native() + L".dll";
+ handle_ = boost::detail::winapi::LoadLibraryExW(
+ load_path.c_str(),
+ 0,
+ static_cast<native_mode_t>(mode)
+ );
+ }
+
+ if (handle_) {
+ return;
+ }
+ }
+
+ // From MSDN: If the string specifies a module name without a path and the
+ // file name extension is omitted, the function appends the default library
+ // extension .dll to the module name.
+ //
+ // From experiments: Default library extension appended to the module name even if
+ // we have some path. So we do not check for path, only for extension. We can not be sure that
+ // such behavior remain across all platforms, so we add L"." by hand.
+ if (sl.has_extension()) {
+ handle_ = boost::detail::winapi::LoadLibraryExW(sl.c_str(), 0, static_cast<native_mode_t>(mode));
+ } else {
+ handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast<native_mode_t>(mode));
+ }
+
+ // LoadLibraryExW method is capable of self loading from program_location() path. No special actions
+ // must be taken to allow self loading.
+
+ if (!handle_) {
+ ec = boost::dll::detail::last_error_code();
+ }
+ }
+
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return (handle_ != 0);
+ }
+
+ void unload() BOOST_NOEXCEPT {
+ if (handle_) {
+ boost::detail::winapi::FreeLibrary(handle_);
+ handle_ = 0;
+ }
+ }
+
+ void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
+ boost::swap(handle_, rhs.handle_);
+ }
+
+ boost::filesystem::path full_module_path(boost::system::error_code &ec) const {
+ return boost::dll::detail::path_from_handle(handle_, ec);
+ }
+
+ static boost::filesystem::path suffix() {
+ return L".dll";
+ }
+
+ void* symbol_addr(const char* sb, boost::system::error_code &ec) const BOOST_NOEXCEPT {
+ if (is_resource()) {
+ // `GetProcAddress` could not be called for libraries loaded with
+ // `LOAD_LIBRARY_AS_DATAFILE`, `LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`
+ // or `LOAD_LIBRARY_AS_IMAGE_RESOURCE`.
+ ec = boost::system::error_code(
+ boost::system::errc::operation_not_supported,
+ boost::system::generic_category()
+ );
+
+ return NULL;
+ }
+
+ // Judging by the documentation of GetProcAddress
+ // there is no version for UNICODE on desktop/server Windows, because
+ // names of functions are stored in narrow characters.
+ void* const symbol = boost::dll::detail::aggressive_ptr_cast<void*>(
+ boost::detail::winapi::get_proc_address(handle_, sb)
+ );
+ if (symbol == NULL) {
+ ec = boost::dll::detail::last_error_code();
+ }
+
+ return symbol;
+ }
+
+ native_handle_t native() const BOOST_NOEXCEPT {
+ return handle_;
+ }
+
+private:
+ bool is_resource() const BOOST_NOEXCEPT {
+ return false; /*!!(
+ reinterpret_cast<boost::detail::winapi::ULONG_PTR_>(handle_) & static_cast<boost::detail::winapi::ULONG_PTR_>(3)
+ );*/
+ }
+
+ native_handle_t handle_;
+};
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
diff --git a/boost/dll/detail/x_info_interface.hpp b/boost/dll/detail/x_info_interface.hpp
new file mode 100644
index 0000000000..e53214e1cd
--- /dev/null
+++ b/boost/dll/detail/x_info_interface.hpp
@@ -0,0 +1,32 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 Antony Polukhin.
+//
+// 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_X_INFO_INTERFACE_HPP
+#define BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <string>
+#include <vector>
+
+namespace boost { namespace dll { namespace detail {
+
+class x_info_interface {
+public:
+ virtual std::vector<std::string> sections() = 0;
+ virtual std::vector<std::string> symbols() = 0;
+ virtual std::vector<std::string> symbols(const char* section_name) = 0;
+
+ virtual ~x_info_interface() BOOST_NOEXCEPT {}
+};
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP