ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine *diags) { registerBuiltinCheckers(*this); for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); i != e; ++i) { // Get access to the plugin. DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); // See if it's compatible with this build of clang. const char *pluginAPIVersion = (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); if (!isCompatibleAPIVersion(pluginAPIVersion)) { warnIncompatible(diags, *i, pluginAPIVersion); continue; } // Register its checkers. RegisterCheckersFn registerPluginCheckers = (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( "clang_registerCheckers"); if (registerPluginCheckers) registerPluginCheckers(*this); } }
TEST(DynamicLibrary, Overload) { { std::string Err; llvm_shutdown_obj Shutdown; DynamicLibrary DL = DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); EXPECT_TRUE(DL.isValid()); EXPECT_TRUE(Err.empty()); GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &TestA); EXPECT_EQ(StdString(GS()), "LibCall"); GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &TestA); EXPECT_EQ(StdString(GS()), "LibCall"); DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err); EXPECT_TRUE(DL.isValid()); EXPECT_TRUE(Err.empty()); // Test overloading local symbols does not occur by default GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &TestA); EXPECT_EQ(StdString(GS()), "ProcessCall"); GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &TestA); EXPECT_EQ(StdString(GS()), "ProcessCall"); // Test overloading by forcing library priority when searching for a symbol DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst; GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &TestA); EXPECT_EQ(StdString(GS()), "LibCall"); DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA)); GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA); GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA); EXPECT_EQ(StdString(GS()), "OverloadCall"); } EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol( "TestA")) == nullptr); // Check serach ordering is reset to default after call to llvm_shutdown EXPECT_TRUE(DynamicLibrary::SearchOrder == DynamicLibrary::SO_Linker); }
TEST(DynamicLibrary, Overload) { { std::string Err; llvm_shutdown_obj Shutdown; DynamicLibrary DL = DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); EXPECT_TRUE(DL.isValid()); EXPECT_TRUE(Err.empty()); GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &TestA); EXPECT_EQ(StdString(GS()), "LibCall"); GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &TestA); EXPECT_EQ(StdString(GS()), "LibCall"); DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err); EXPECT_TRUE(DL.isValid()); EXPECT_TRUE(Err.empty()); GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &TestA); EXPECT_EQ(StdString(GS()), "ProcessCall"); GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &TestA); EXPECT_EQ(StdString(GS()), "ProcessCall"); DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA)); GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA); GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA")); EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA); EXPECT_EQ(StdString(GS()), "OverloadCall"); } EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol( "TestA")) == nullptr); }