1 //===- llvm/unittest/Support/DynamicLibrary/DynamicLibraryTest.cpp --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Config/config.h" 11 #include "llvm/Support/DynamicLibrary.h" 12 #include "llvm/Support/FileSystem.h" 13 #include "llvm/Support/ManagedStatic.h" 14 #include "llvm/Support/Path.h" 15 #include "gtest/gtest.h" 16 17 #include "PipSqueak.h" 18 #include <string> 19 20 using namespace llvm; 21 using namespace llvm::sys; 22 23 extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; } 24 25 std::string LibPath() { 26 const std::vector<testing::internal::string>& Argvs = testing::internal::GetArgvs(); 27 const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests"; 28 void *Ptr = (void*)(intptr_t)TestA; 29 std::string Path = fs::getMainExecutable(Argv0, Ptr); 30 llvm::SmallString<256> Buf(path::parent_path(Path)); 31 path::append(Buf, "PipSqueak.so"); 32 return Buf.str(); 33 } 34 35 #if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)) 36 37 typedef void (*SetStrings)(std::string &GStr, std::string &LStr); 38 typedef const char *(*GetString)(); 39 40 template <class T> static T FuncPtr(void *Ptr) { 41 union { 42 T F; 43 void *P; 44 } Tmp; 45 Tmp.P = Ptr; 46 return Tmp.F; 47 } 48 template <class T> static void* PtrFunc(T *Func) { 49 union { 50 T *F; 51 void *P; 52 } Tmp; 53 Tmp.F = Func; 54 return Tmp.P; 55 } 56 57 static const char *OverloadTestA() { return "OverloadCall"; } 58 59 std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; } 60 61 TEST(DynamicLibrary, Overload) { 62 { 63 std::string Err; 64 llvm_shutdown_obj Shutdown; 65 DynamicLibrary DL = 66 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 67 EXPECT_TRUE(DL.isValid()); 68 EXPECT_TRUE(Err.empty()); 69 70 GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 71 EXPECT_TRUE(GS != nullptr && GS != &TestA); 72 EXPECT_EQ(StdString(GS()), "LibCall"); 73 74 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 75 EXPECT_TRUE(GS != nullptr && GS != &TestA); 76 EXPECT_EQ(StdString(GS()), "LibCall"); 77 78 DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err); 79 EXPECT_TRUE(DL.isValid()); 80 EXPECT_TRUE(Err.empty()); 81 82 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 83 EXPECT_TRUE(GS != nullptr && GS == &TestA); 84 EXPECT_EQ(StdString(GS()), "ProcessCall"); 85 86 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 87 EXPECT_TRUE(GS != nullptr && GS == &TestA); 88 EXPECT_EQ(StdString(GS()), "ProcessCall"); 89 90 DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA)); 91 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 92 EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA); 93 94 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 95 EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA); 96 EXPECT_EQ(StdString(GS()), "OverloadCall"); 97 } 98 EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol( 99 "TestA")) == nullptr); 100 } 101 102 TEST(DynamicLibrary, Shutdown) { 103 std::string A, B; 104 { 105 std::string Err; 106 llvm_shutdown_obj Shutdown; 107 DynamicLibrary DL = 108 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 109 EXPECT_TRUE(DL.isValid()); 110 EXPECT_TRUE(Err.empty()); 111 112 SetStrings SS = FuncPtr<SetStrings>( 113 DynamicLibrary::SearchForAddressOfSymbol("SetStrings")); 114 EXPECT_TRUE(SS != nullptr); 115 116 SS(A, B); 117 EXPECT_EQ(B, "Local::Local"); 118 } 119 EXPECT_EQ(A, "Global::~Global"); 120 EXPECT_EQ(B, "Local::~Local"); 121 EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol( 122 "SetStrings")) == nullptr); 123 } 124 125 #else 126 127 TEST(DynamicLibrary, Unsupported) { 128 std::string Err; 129 DynamicLibrary DL = 130 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 131 EXPECT_FALSE(DL.isValid()); 132 EXPECT_EQ(Err, "dlopen() not supported on this platform"); 133 } 134 135 #endif 136