testDynamicLoader.cxx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
  3. #include "kwsysPrivate.h"
  4. #include KWSYS_HEADER(DynamicLoader.hxx)
  5. #if defined(__BEOS__) || defined(__HAIKU__)
  6. # include <be/kernel/OS.h> /* disable_debugger() API. */
  7. #endif
  8. // Needed for __GLIBC__ test macro.
  9. #ifdef __linux__
  10. # include <features.h>
  11. // Will define LIBDL_SO macro on systems with glibc.
  12. # ifdef __GLIBC__
  13. # include <gnu/lib-names.h>
  14. // Define to LIBC_SO, if not defined by above header.
  15. # ifndef LIBDL_SO
  16. # define LIBDL_SO LIBC_SO
  17. # endif
  18. # endif
  19. // Define the LIBDL_SO macro, if not defined above.
  20. # ifndef LIBDL_SO
  21. # define LIBDL_SO "libdl.so"
  22. # endif
  23. #endif
  24. // Work-around CMake dependency scanning limitation. This must
  25. // duplicate the above list of headers.
  26. #if 0
  27. # include "DynamicLoader.hxx.in"
  28. #endif
  29. #include <iostream>
  30. #include <string>
  31. // Include with <> instead of "" to avoid getting any in-source copy
  32. // left on disk.
  33. #include <testSystemTools.h>
  34. // For TestDynamicLoaderData, which, though not referenced literally,
  35. // is referenced semantically.
  36. #include "testDynload.h"
  37. static std::string GetLibName(const char* lname, const char* subdir = nullptr)
  38. {
  39. // Construct proper name of lib
  40. std::string slname;
  41. slname = RUNTIME_OUTPUT_DIRECTORY;
  42. if (subdir) {
  43. slname += "/";
  44. slname += subdir;
  45. }
  46. #ifdef CMAKE_INTDIR
  47. slname += "/";
  48. slname += CMAKE_INTDIR;
  49. #endif
  50. slname += "/";
  51. slname += kwsys::DynamicLoader::LibPrefix();
  52. slname += lname;
  53. slname += kwsys::DynamicLoader::LibExtension();
  54. return slname;
  55. }
  56. /* libname = Library name (proper prefix, proper extension)
  57. * System = symbol to lookup in libname
  58. * r1: should OpenLibrary succeed ?
  59. * r2: should GetSymbolAddress succeed ?
  60. * r3: should CloseLibrary succeed ?
  61. */
  62. static int TestDynamicLoader(const char* libname, const char* symbol, int r1,
  63. int r2, int r3, int flags = 0)
  64. {
  65. std::cerr << "Testing: " << libname << std::endl;
  66. kwsys::DynamicLoader::LibraryHandle l =
  67. kwsys::DynamicLoader::OpenLibrary(libname, flags);
  68. // If result is incompatible with expectation just fails (xor):
  69. if ((r1 && !l) || (!r1 && l)) {
  70. std::cerr << "OpenLibrary: " << kwsys::DynamicLoader::LastError()
  71. << std::endl;
  72. return 1;
  73. }
  74. kwsys::DynamicLoader::SymbolPointer f =
  75. kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
  76. if ((r2 && !f) || (!r2 && f)) {
  77. std::cerr << "GetSymbolAddress: " << kwsys::DynamicLoader::LastError()
  78. << std::endl;
  79. return 1;
  80. }
  81. #ifndef __APPLE__
  82. int s = kwsys::DynamicLoader::CloseLibrary(l);
  83. if ((r3 && !s) || (!r3 && s)) {
  84. std::cerr << "CloseLibrary: " << kwsys::DynamicLoader::LastError()
  85. << std::endl;
  86. return 1;
  87. }
  88. #else
  89. (void)r3;
  90. #endif
  91. return 0;
  92. }
  93. int testDynamicLoader(int argc, char* argv[])
  94. {
  95. #if defined(_WIN32)
  96. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
  97. #elif defined(__BEOS__) || defined(__HAIKU__)
  98. disable_debugger(1);
  99. #endif
  100. int res = 0;
  101. if (argc == 3) {
  102. // User specify a libname and symbol to check.
  103. res = TestDynamicLoader(argv[1], argv[2], 1, 1, 1);
  104. return res;
  105. }
  106. // dlopen() on Syllable before 11/22/2007 doesn't return 0 on error
  107. #ifndef __SYLLABLE__
  108. // Make sure that inexistent lib is giving correct result
  109. res += TestDynamicLoader("azerty_", "foo_bar", 0, 0, 0);
  110. // Make sure that random binary file cannot be assimilated as dylib
  111. res += TestDynamicLoader(TEST_SYSTEMTOOLS_SOURCE_DIR "/testSystemTools.bin",
  112. "wp", 0, 0, 0);
  113. #endif
  114. #ifdef __linux__
  115. // This one is actually fun to test, since dlopen is by default
  116. // loaded...wonder why :)
  117. res += TestDynamicLoader("foobar.lib", "dlopen", 0, 1, 0);
  118. res += TestDynamicLoader(LIBDL_SO, "dlopen", 1, 1, 1);
  119. res += TestDynamicLoader(LIBDL_SO, "TestDynamicLoader", 1, 0, 1);
  120. #endif
  121. // Now try on the generated library
  122. std::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload");
  123. res += TestDynamicLoader(libname.c_str(), "dummy", 1, 0, 1);
  124. res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderSymbolPointer",
  125. 1, 1, 1);
  126. res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderSymbolPointer",
  127. 1, 0, 1);
  128. res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData", 1, 1, 1);
  129. res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData", 1, 0, 1);
  130. #ifdef _WIN32
  131. libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynloadUse", "dynloaddir");
  132. res += TestDynamicLoader(libname.c_str(), "dummy", 0, 0, 0);
  133. res += TestDynamicLoader(libname.c_str(), "TestLoad", 1, 1, 1,
  134. kwsys::DynamicLoader::SearchBesideLibrary);
  135. res += TestDynamicLoader(libname.c_str(), "_TestLoad", 1, 0, 1,
  136. kwsys::DynamicLoader::SearchBesideLibrary);
  137. #endif
  138. return res;
  139. }