diff --git a/include/boost/dll/runtime_symbol_info.hpp b/include/boost/dll/runtime_symbol_info.hpp index 9dc2ba06..3f94e2ee 100644 --- a/include/boost/dll/runtime_symbol_info.hpp +++ b/include/boost/dll/runtime_symbol_info.hpp @@ -1,5 +1,5 @@ // Copyright 2014 Renato Tegon Forti, Antony Polukhin. -// Copyright 2015-2016 Antony Polukhin. +// Copyright 2015-2017 Antony Polukhin. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt @@ -47,19 +47,30 @@ namespace detail { * \b Examples: * \code * int main() { - * dll::symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)); // returns "/some/path/libmy_signal_handler.so" - * dll::symbol_location_ptr(&std::cerr); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" - * dll::symbol_location_ptr(&std::puts); // returns location of libc: "/lib/x86_64-linux-gnu/libc.so.6" + * dll::symbol_location_ptr(std::set_terminate(0)); // returns "/some/path/libmy_terminate_handler.so" + * dll::symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)); // returns "/some/path/libmy_symbol_handler.so" * } * \endcode */ - inline boost::filesystem::path symbol_location_ptr(const void* ptr_to_symbol, boost::system::error_code& ec) { + template + inline boost::filesystem::path symbol_location_ptr(T ptr_to_symbol, boost::system::error_code& ec) { + BOOST_STATIC_ASSERT_MSG(boost::is_pointer::value, "boost::dll::symbol_location_ptr works only with pointers! `ptr_to_symbol` must be a pointer"); boost::filesystem::path ret; + if (!ptr_to_symbol) { + ec = boost::system::error_code( + boost::system::errc::bad_address, + boost::system::generic_category() + ); + + return ret; + } ec.clear(); + const void* ptr = boost::dll::detail::aggressive_ptr_cast(ptr_to_symbol); + #if BOOST_OS_WINDOWS boost::detail::winapi::MEMORY_BASIC_INFORMATION_ mbi; - if (!boost::detail::winapi::VirtualQuery(ptr_to_symbol, &mbi, sizeof(mbi))) { + if (!boost::detail::winapi::VirtualQuery(ptr, &mbi, sizeof(mbi))) { ec = boost::dll::detail::last_error_code(); return ret; } @@ -69,7 +80,7 @@ namespace detail { Dl_info info; // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)` - const int res = dladdr(const_cast(ptr_to_symbol), &info); + const int res = dladdr(const_cast(ptr), &info); if (res) { ret = info.dli_fname; @@ -86,13 +97,14 @@ namespace detail { } //! \overload symbol_location_ptr(const void* ptr_to_symbol, boost::system::error_code& ec) - inline boost::filesystem::path symbol_location_ptr(const void* ptr_to_symbol) { + template + inline boost::filesystem::path symbol_location_ptr(T ptr_to_symbol) { boost::filesystem::path ret; boost::system::error_code ec; ret = boost::dll::symbol_location_ptr(ptr_to_symbol, ec); if (ec) { - boost::dll::detail::report_error(ec, "boost::dll::symbol_location_ptr(const T& symbol) failed"); + boost::dll::detail::report_error(ec, "boost::dll::symbol_location_ptr(T ptr_to_symbol) failed"); } return ret; diff --git a/test/symbol_runtime_info_test.cpp b/test/symbol_runtime_info_test.cpp index fe4d6664..a8384ee2 100644 --- a/test/symbol_runtime_info_test.cpp +++ b/test/symbol_runtime_info_test.cpp @@ -1,5 +1,5 @@ // Copyright 2014 Renato Tegon Forti, Antony Polukhin. -// Copyright 2015 Antony Polukhin. +// Copyright 2015-2017 Antony Polukhin. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt @@ -14,6 +14,9 @@ #include +#include // std::set_terminate +#include // ::signal + // lib functions typedef float (lib_version_func)(); @@ -25,6 +28,15 @@ extern "C" int BOOST_SYMBOL_EXPORT exef() { return 15; } + +extern "C" void BOOST_SYMBOL_EXPORT my_terminate_handler() { + std::abort(); +} + +extern "C" void BOOST_SYMBOL_EXPORT my_signal_handler(int) { + std::abort(); +} + void internal_function() {} int internal_variable = 1; @@ -131,6 +143,46 @@ int main(int argc, char* argv[]) { // Checking docs content std::cout << "\nsymbol_location(std::cerr); // " << symbol_location(std::cerr); std::cout << "\nsymbol_location(std::puts); // " << symbol_location(std::puts); + + std::set_terminate(&my_terminate_handler); + BOOST_TEST((boost::filesystem::equivalent( + symbol_location_ptr(std::set_terminate(0)), + argv[0] + ))); + + { + boost::system::error_code ec; + symbol_location_ptr(std::set_terminate(0), ec), + BOOST_TEST(ec); + } + + { + boost::system::error_code ec; + symbol_location(std::set_terminate(0), ec), + BOOST_TEST(ec); + } + + { + std::set_terminate(&my_terminate_handler); + boost::system::error_code ec; + symbol_location(std::set_terminate(0), ec), + BOOST_TEST(ec); + } + + ::signal(SIGSEGV, &my_signal_handler); + BOOST_TEST((boost::filesystem::equivalent( + symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)), + argv[0] + ))); + + { + ::signal(SIGSEGV, &my_signal_handler); + boost::system::error_code ec; + symbol_location(::signal(SIGSEGV, SIG_DFL), ec); + BOOST_TEST(ec); + } + + return boost::report_errors(); }