127 lines · cpp
1//===- llvm/unittest/Support/DynamicLibrary/DynamicLibraryTest.cpp --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/DynamicLibrary.h"10#include "llvm/Config/config.h"11#include "llvm/Support/Compiler.h"12#include "llvm/Support/FileSystem.h"13#include "llvm/Support/Path.h"14#include "gtest/gtest.h"15 16#include "PipSqueak.h"17 18// FIXME: Missing globals/DSO https://github.com/llvm/llvm-project/issues/57206.19#if !LLVM_HWADDRESS_SANITIZER_BUILD20 21using namespace llvm;22using namespace llvm::sys;23 24std::string LibPath(const std::string Name = "PipSqueak") {25 const auto &Argvs = testing::internal::GetArgvs();26 const char *Argv0 =27 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, (Name + LLVM_PLUGIN_EXT).c_str());32 return std::string(Buf.str());33}34 35#if defined(_WIN32) || defined(HAVE_DLOPEN)36 37typedef void (*SetStrings)(std::string &GStr, std::string &LStr);38typedef void (*TestOrder)(std::vector<std::string> &V);39typedef const char *(*GetString)();40 41template <class T> static T FuncPtr(void *Ptr) {42 union {43 T F;44 void *P;45 } Tmp;46 Tmp.P = Ptr;47 return Tmp.F;48}49template <class T> static void* PtrFunc(T *Func) {50 union {51 T *F;52 void *P;53 } Tmp;54 Tmp.F = Func;55 return Tmp.P;56}57 58static const char *OverloadTestA() { return "OverloadCall"; }59 60std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; }61 62TEST(DynamicLibrary, Overload) {63 {64 std::string Err;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_NE(GS, nullptr);72 EXPECT_NE(GS, &TestA);73 EXPECT_EQ(StdString(GS()), "LibCall");74 75 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));76 EXPECT_NE(GS, nullptr);77 EXPECT_NE(GS, &TestA);78 EXPECT_EQ(StdString(GS()), "LibCall");79 80 DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err);81 EXPECT_TRUE(DL.isValid());82 EXPECT_TRUE(Err.empty());83 84 // Test overloading local symbols does not occur by default85 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));86 EXPECT_NE(GS, nullptr);87 EXPECT_EQ(GS, &TestA);88 EXPECT_EQ(StdString(GS()), "ProcessCall");89 90 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));91 EXPECT_NE(GS, nullptr);92 EXPECT_EQ(GS, &TestA);93 EXPECT_EQ(StdString(GS()), "ProcessCall");94 95 // Test overloading by forcing library priority when searching for a symbol96 DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst;97 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));98 EXPECT_NE(GS, nullptr);99 EXPECT_NE(GS, &TestA);100 EXPECT_EQ(StdString(GS()), "LibCall");101 102 DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));103 GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));104 EXPECT_NE(GS, nullptr);105 EXPECT_NE(GS, &OverloadTestA);106 107 GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));108 EXPECT_NE(GS, nullptr);109 EXPECT_EQ(GS, &OverloadTestA);110 EXPECT_EQ(StdString(GS()), "OverloadCall");111 }112}113 114#else115 116TEST(DynamicLibrary, Unsupported) {117 std::string Err;118 DynamicLibrary DL =119 DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);120 EXPECT_FALSE(DL.isValid());121 EXPECT_EQ(Err, "dlopen() not supported on this platform");122}123 124#endif125 126#endif127