Index: lldb/include/lldb/Host/LibraryLoader.h =================================================================== --- /dev/null +++ lldb/include/lldb/Host/LibraryLoader.h @@ -0,0 +1,36 @@ +//===-- LibraryLoader.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_LibraryLoader_h +#define liblldb_Host_LibraryLoader_h + +#include "llvm/ADT/StringRef.h" + +namespace lldb_private { +class LibraryLoader { +public: + LibraryLoader(llvm::StringRef library) + : LibraryLoader(library.str().c_str()) {} + ~LibraryLoader(); + + operator bool() const { return m_handle != nullptr; } + + template T *GetSymbol(llvm::StringRef symbol) { + return reinterpret_cast(GetSymbolImpl(symbol)); + } + +protected: + LibraryLoader(const char *library); + +private: + void *GetSymbolImpl(llvm::StringRef symbol); + void *m_handle; +}; +} // namespace lldb_private + +#endif Index: lldb/source/Host/CMakeLists.txt =================================================================== --- lldb/source/Host/CMakeLists.txt +++ lldb/source/Host/CMakeLists.txt @@ -70,6 +70,7 @@ windows/HostInfoWindows.cpp windows/HostProcessWindows.cpp windows/HostThreadWindows.cpp + windows/LibraryLoader.cpp windows/LockFileWindows.cpp windows/PipeWindows.cpp windows/ProcessLauncherWindows.cpp @@ -83,6 +84,7 @@ posix/HostInfoPosix.cpp posix/HostProcessPosix.cpp posix/HostThreadPosix.cpp + posix/LibraryLoader.cpp posix/LockFilePosix.cpp posix/PipePosix.cpp posix/ProcessLauncherPosixFork.cpp @@ -101,7 +103,7 @@ macosx/cfcpp/CFCString.cpp ) if(IOS) - set_property(SOURCE macosx/Host.mm APPEND PROPERTY + set_property(SOURCE macosx/Host.mm APPEND PROPERTY COMPILE_DEFINITIONS "NO_XPC_SERVICES=1") endif() Index: lldb/source/Host/posix/LibraryLoader.cpp =================================================================== --- /dev/null +++ lldb/source/Host/posix/LibraryLoader.cpp @@ -0,0 +1,30 @@ +//===-- LibraryLoader.cpp ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/LibraryLoader.h" +#include + +using namespace lldb_private; +using namespace llvm; + +LibraryLoader::LibraryLoader(const char *library) : m_handle(nullptr) { + m_handle = dlopen(library, RTLD_LAZY); +} + +LibraryLoader::~LibraryLoader() { + if (m_handle) { + dlclose(m_handle); + m_handle = nullptr; + } +} + +void *LibraryLoader::GetSymbolImpl(llvm::StringRef symbol) { + if (!m_handle) + return nullptr; + return dlsym(m_handle, symbol.str().c_str()); +} Index: lldb/source/Host/windows/LibraryLoader.cpp =================================================================== --- /dev/null +++ lldb/source/Host/windows/LibraryLoader.cpp @@ -0,0 +1,31 @@ +//===-- LibraryLoader.cpp ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/LibraryLoader.h" +#include + +using namespace lldb_private; +using namespace llvm; + +LibraryLoader::LibraryLoader(const char *library) : m_handle(nullptr) { + m_handle = reinterpret_cast(LoadLibraryA(library)); +} + +LibraryLoader::~LibraryLoader() { + if (m_handle) { + FreeLibrary(m_handle); + m_handle = nullptr; + } +} + +void *LibraryLoader::GetSymbolImpl(llvm::StringRef symbol) { + if (!m_handle) + return nullptr; + return GetProcAddress(reinterpret_cast(m_handle), + symbol.str().c_str()); +} Index: lldb/unittests/Host/CMakeLists.txt =================================================================== --- lldb/unittests/Host/CMakeLists.txt +++ lldb/unittests/Host/CMakeLists.txt @@ -3,6 +3,7 @@ FileSystemTest.cpp HostInfoTest.cpp HostTest.cpp + LibraryLoaderTest.cpp MainLoopTest.cpp NativeProcessProtocolTest.cpp ProcessLaunchInfoTest.cpp Index: lldb/unittests/Host/LibraryLoaderTest.cpp =================================================================== --- /dev/null +++ lldb/unittests/Host/LibraryLoaderTest.cpp @@ -0,0 +1,42 @@ +//===-- LibraryLoaderTest.cpp -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/LibraryLoader.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +typedef size_t strlen_t(const char *str); + +class TestLibraryLoader : public LibraryLoader { +public: + TestLibraryLoader(const char *library) : LibraryLoader(library) {} +}; + +TEST(LibraryLoaderTest, OperatorBool) { + // Loading a bogus library fails. + TestLibraryLoader bogus("bogus"); + EXPECT_FALSE(static_cast(bogus)); + + // Loading ourselves succeeds. + TestLibraryLoader self(nullptr); + EXPECT_TRUE(static_cast(self)); +} + +TEST(LibraryLoaderTest, GetSymbol) { + TestLibraryLoader loader(nullptr); + EXPECT_TRUE(static_cast(loader)); + + strlen_t *test = loader.GetSymbol("strlen"); + + ASSERT_NE(nullptr, test); + EXPECT_EQ((size_t)4, test("test")); + + strlen_t *bogus = loader.GetSymbol("bogus"); + EXPECT_EQ(nullptr, bogus); +}