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 std::string Path = 27 fs::getMainExecutable("DynamicLibraryTests", (void *)&TestA); 28 llvm::SmallString<256> Buf(path::parent_path(Path)); 29 path::append(Buf, "PipSqueak.so"); 30 return Buf.str(); 31 } 32 33 #if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)) 34 35 typedef void (*SetStrings)(std::string &GStr, std::string &LStr); 36 typedef const char *(*GetString)(); 37 38 template <class T> static T FuncPtr(void *Ptr) { 39 union { 40 T F; 41 void *P; 42 } Tmp; 43 Tmp.P = Ptr; 44 return Tmp.F; 45 } 46 template <class T> static void* PtrFunc(T *Func) { 47 union { 48 T *F; 49 void *P; 50 } Tmp; 51 Tmp.F = Func; 52 return Tmp.P; 53 } 54 55 static const char *OverloadTestA() { return "OverloadCall"; } 56 57 std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; } 58 59 TEST(DynamicLibrary, Overload) { 60 { 61 std::string Err; 62 llvm_shutdown_obj Shutdown; 63 DynamicLibrary DL = 64 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 65 EXPECT_TRUE(DL.isValid()); 66 EXPECT_TRUE(Err.empty()); 67 68 GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 69 EXPECT_TRUE(GS != nullptr && GS != &TestA); 70 EXPECT_EQ(StdString(GS()), "LibCall"); 71 72 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 73 EXPECT_TRUE(GS != nullptr && GS != &TestA); 74 EXPECT_EQ(StdString(GS()), "LibCall"); 75 76 DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err); 77 EXPECT_TRUE(DL.isValid()); 78 EXPECT_TRUE(Err.empty()); 79 80 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 81 EXPECT_TRUE(GS != nullptr && GS == &TestA); 82 EXPECT_EQ(StdString(GS()), "ProcessCall"); 83 84 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 85 EXPECT_TRUE(GS != nullptr && GS == &TestA); 86 EXPECT_EQ(StdString(GS()), "ProcessCall"); 87 88 DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA)); 89 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); 90 EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA); 91 92 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); 93 EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA); 94 EXPECT_EQ(StdString(GS()), "OverloadCall"); 95 } 96 EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol( 97 "TestA")) == nullptr); 98 } 99 100 TEST(DynamicLibrary, Shutdown) { 101 std::string A, B; 102 { 103 std::string Err; 104 llvm_shutdown_obj Shutdown; 105 DynamicLibrary DL = 106 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 107 EXPECT_TRUE(DL.isValid()); 108 EXPECT_TRUE(Err.empty()); 109 110 SetStrings SS = FuncPtr<SetStrings>( 111 DynamicLibrary::SearchForAddressOfSymbol("SetStrings")); 112 EXPECT_TRUE(SS != nullptr); 113 114 SS(A, B); 115 EXPECT_EQ(B, "Local::Local"); 116 } 117 EXPECT_EQ(A, "Global::~Global"); 118 EXPECT_EQ(B, "Local::~Local"); 119 EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol( 120 "SetStrings")) == nullptr); 121 } 122 123 #else 124 125 TEST(DynamicLibrary, Unsupported) { 126 std::string Err; 127 DynamicLibrary DL = 128 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); 129 EXPECT_FALSE(DL.isValid()); 130 EXPECT_EQ(Err, "dlopen() not supported on this platform"); 131 } 132 133 #endif 134