symbol_runtime_info_test.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright 2015-2019 Antony Polukhin.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // For more information, see http://www.boost.org
  8. #include "../example/b2_workarounds.hpp"
  9. #include <boost/dll.hpp>
  10. #include <boost/dll/runtime_symbol_info.hpp>
  11. #include <boost/filesystem/operations.hpp>
  12. #include <boost/core/lightweight_test.hpp>
  13. #include <boost/predef/os.h>
  14. #include <cmath>
  15. #include <exception> // std::set_terminate
  16. #include <signal.h> // ::signal
  17. // Makes global error variables dirty. Useful for preventing issues like https://github.com/boostorg/dll/issues/16
  18. void make_error_code_dirty() {
  19. using namespace std;
  20. (void)log(-1.0);
  21. #if BOOST_OS_WINDOWS
  22. boost::winapi::WCHAR_ path_hldr[10];
  23. int some_invalid_value_for_handle = 0xFF004242;
  24. boost::winapi::HMODULE_ some_invalid_handle;
  25. memcpy(&some_invalid_handle, &some_invalid_value_for_handle, sizeof(some_invalid_value_for_handle));
  26. boost::winapi::GetModuleFileNameW(some_invalid_handle, path_hldr, 10);
  27. #endif
  28. }
  29. // lib functions
  30. typedef float (lib_version_func)();
  31. typedef void (say_hello_func) ();
  32. typedef int (increment) (int);
  33. // exe function
  34. extern "C" int BOOST_SYMBOL_EXPORT exef() {
  35. return 15;
  36. }
  37. extern "C" void BOOST_SYMBOL_EXPORT my_terminate_handler() {
  38. std::abort();
  39. }
  40. extern "C" void BOOST_SYMBOL_EXPORT my_signal_handler(int) {
  41. std::abort();
  42. }
  43. void internal_function() {}
  44. int internal_variable = 1;
  45. // Unit Tests
  46. int main(int argc, char* argv[]) {
  47. using namespace boost::dll;
  48. boost::dll::fs::path shared_library_path = b2_workarounds::first_lib_from_argv(argc, argv);
  49. BOOST_TEST(shared_library_path.string().find("test_library") != std::string::npos);
  50. make_error_code_dirty();
  51. shared_library lib(shared_library_path);
  52. std::cout << std::endl;
  53. std::cout << "shared_library: " << shared_library_path << std::endl;
  54. std::cout << "symbol_location: " << symbol_location(lib.get<int>("integer_g")) << std::endl;
  55. std::cout << "lib.location(): " << lib.location() << std::endl;
  56. BOOST_TEST(
  57. symbol_location(lib.get<int>("integer_g")) == lib.location()
  58. );
  59. make_error_code_dirty();
  60. BOOST_TEST(
  61. symbol_location(lib.get<say_hello_func>("say_hello")) == lib.location()
  62. );
  63. BOOST_TEST(
  64. symbol_location(lib.get<lib_version_func>("lib_version")) == lib.location()
  65. );
  66. make_error_code_dirty();
  67. BOOST_TEST(
  68. symbol_location(lib.get<const int>("const_integer_g")) == lib.location()
  69. );
  70. // Checking that symbols are still available, after another load+unload of the library
  71. { shared_library sl2(shared_library_path); }
  72. BOOST_TEST(
  73. symbol_location(lib.get<int>("integer_g")) == lib.location()
  74. );
  75. make_error_code_dirty();
  76. // Checking aliases
  77. BOOST_TEST(
  78. symbol_location(lib.get<std::size_t(*)(const std::vector<int>&)>("foo_bar")) == lib.location()
  79. );
  80. BOOST_TEST(
  81. symbol_location(lib.get_alias<std::size_t(const std::vector<int>&)>("foo_bar")) == lib.location()
  82. );
  83. BOOST_TEST(
  84. symbol_location(lib.get<std::size_t*>("foo_variable")) == lib.location()
  85. );
  86. BOOST_TEST(
  87. symbol_location(lib.get_alias<std::size_t>("foo_variable")) == lib.location()
  88. );
  89. { // self
  90. make_error_code_dirty();
  91. shared_library sl(program_location());
  92. make_error_code_dirty();
  93. BOOST_TEST(
  94. (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef")), argv[0]))
  95. );
  96. }
  97. { // self with error_code
  98. boost::dll::fs::error_code ec;
  99. shared_library sl(program_location(ec));
  100. BOOST_TEST(!ec);
  101. BOOST_TEST(
  102. (boost::dll::fs::equivalent(symbol_location(sl.get<int(void)>("exef"), ec), argv[0]))
  103. );
  104. BOOST_TEST(!ec);
  105. symbol_location(&sl.get<int(void)>("exef"), ec);
  106. BOOST_TEST(ec);
  107. }
  108. std::cout << "\ninternal_function: " << symbol_location(internal_function);
  109. std::cout << "\nargv[0] : " << boost::filesystem::absolute(argv[0]);
  110. BOOST_TEST(
  111. (boost::dll::fs::equivalent(symbol_location(internal_function), argv[0]))
  112. );
  113. BOOST_TEST(
  114. (boost::dll::fs::equivalent(symbol_location(internal_variable), argv[0]))
  115. );
  116. make_error_code_dirty();
  117. BOOST_TEST(
  118. (boost::dll::fs::equivalent(this_line_location(), argv[0]))
  119. );
  120. { // this_line_location with error_code
  121. boost::dll::fs::error_code ec;
  122. make_error_code_dirty();
  123. BOOST_TEST(
  124. (boost::dll::fs::equivalent(this_line_location(ec), argv[0]))
  125. );
  126. BOOST_TEST(!ec);
  127. }
  128. BOOST_TEST(
  129. lib.get_alias<boost::dll::fs::path()>("module_location_from_itself")() == lib.location()
  130. );
  131. // Checking docs content
  132. std::cout << "\nsymbol_location(std::cerr); // " << symbol_location(std::cerr);
  133. std::cout << "\nsymbol_location(std::puts); // " << symbol_location(std::puts);
  134. std::set_terminate(&my_terminate_handler);
  135. BOOST_TEST((boost::dll::fs::equivalent(
  136. symbol_location_ptr(std::set_terminate(0)),
  137. argv[0]
  138. )));
  139. {
  140. boost::dll::fs::error_code ec;
  141. boost::dll::fs::path p = symbol_location_ptr(std::set_terminate(0), ec);
  142. BOOST_TEST(ec || !p.empty());
  143. }
  144. {
  145. boost::dll::fs::error_code ec;
  146. symbol_location(std::set_terminate(0), ec),
  147. BOOST_TEST(ec);
  148. }
  149. {
  150. std::set_terminate(&my_terminate_handler);
  151. boost::dll::fs::error_code ec;
  152. make_error_code_dirty();
  153. symbol_location(std::set_terminate(0), ec),
  154. BOOST_TEST(ec);
  155. }
  156. {
  157. boost::dll::fs::error_code ec;
  158. ::signal(SIGSEGV, &my_signal_handler);
  159. boost::dll::fs::path p = symbol_location_ptr(::signal(SIGSEGV, SIG_DFL), ec);
  160. BOOST_TEST((boost::dll::fs::equivalent(
  161. p,
  162. argv[0]
  163. )) || ec);
  164. }
  165. {
  166. ::signal(SIGSEGV, &my_signal_handler);
  167. boost::dll::fs::error_code ec;
  168. make_error_code_dirty();
  169. symbol_location(::signal(SIGSEGV, SIG_DFL), ec);
  170. BOOST_TEST(ec);
  171. }
  172. return boost::report_errors();
  173. }