diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h --- a/lldb/include/lldb/Host/HostInfoBase.h +++ b/lldb/include/lldb/Host/HostInfoBase.h @@ -37,7 +37,13 @@ ~HostInfoBase() {} public: - static void Initialize(); + /// A helper function for determining the liblldb location. It receives a + /// FileSpec with the location of file containing _this_ code. It can + /// (optionally) replace it with a file spec pointing to a more canonical + /// copy. + using SharedLibraryDirectoryHelper = void(FileSpec &this_file); + + static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); static void Terminate(); /// Gets the host target triple. diff --git a/lldb/include/lldb/Host/linux/HostInfoLinux.h b/lldb/include/lldb/Host/linux/HostInfoLinux.h --- a/lldb/include/lldb/Host/linux/HostInfoLinux.h +++ b/lldb/include/lldb/Host/linux/HostInfoLinux.h @@ -27,7 +27,7 @@ ~HostInfoLinux(); public: - static void Initialize(); + static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); diff --git a/lldb/include/lldb/Host/windows/HostInfoWindows.h b/lldb/include/lldb/Host/windows/HostInfoWindows.h --- a/lldb/include/lldb/Host/windows/HostInfoWindows.h +++ b/lldb/include/lldb/Host/windows/HostInfoWindows.h @@ -25,7 +25,7 @@ ~HostInfoWindows(); public: - static void Initialize(); + static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); static void Terminate(); static size_t GetPageSize(); diff --git a/lldb/include/lldb/Initialization/SystemInitializerCommon.h b/lldb/include/lldb/Initialization/SystemInitializerCommon.h --- a/lldb/include/lldb/Initialization/SystemInitializerCommon.h +++ b/lldb/include/lldb/Initialization/SystemInitializerCommon.h @@ -10,6 +10,7 @@ #define LLDB_INITIALIZATION_SYSTEMINITIALIZERCOMMON_H #include "SystemInitializer.h" +#include "lldb/Host/HostInfo.h" namespace lldb_private { /// Initializes common lldb functionality. @@ -22,11 +23,14 @@ /// the constructor. class SystemInitializerCommon : public SystemInitializer { public: - SystemInitializerCommon(); + SystemInitializerCommon(HostInfo::SharedLibraryDirectoryHelper *helper); ~SystemInitializerCommon() override; llvm::Error Initialize() override; void Terminate() override; + +private: + HostInfo::SharedLibraryDirectoryHelper *m_shlib_dir_helper; }; } // namespace lldb_private diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -29,9 +29,22 @@ #define LLDB_PLUGIN(p) LLDB_PLUGIN_DECLARE(p) #include "Plugins/Plugins.def" +#if LLDB_ENABLE_PYTHON +#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h" + +constexpr lldb_private::HostInfo::SharedLibraryDirectoryHelper + *g_shlib_dir_helper = + lldb_private::ScriptInterpreterPython::SharedLibraryDirectoryHelper; + +#else +constexpr lldb_private::HostInfo::SharedLibraryDirectoryHelper + *g_shlib_dir_helper = 0; +#endif + using namespace lldb_private; -SystemInitializerFull::SystemInitializerFull() = default; +SystemInitializerFull::SystemInitializerFull() + : SystemInitializerCommon(g_shlib_dir_helper) {} SystemInitializerFull::~SystemInitializerFull() = default; llvm::Error SystemInitializerFull::Initialize() { diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -71,13 +71,18 @@ llvm::once_flag m_lldb_global_tmp_dir_once; FileSpec m_lldb_global_tmp_dir; }; +} // namespace -HostInfoBaseFields *g_fields = nullptr; -} +static HostInfoBaseFields *g_fields = nullptr; +static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr; -void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } +void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) { + g_shlib_dir_helper = helper; + g_fields = new HostInfoBaseFields(); +} void HostInfoBase::Terminate() { + g_shlib_dir_helper = nullptr; delete g_fields; g_fields = nullptr; } @@ -249,9 +254,8 @@ reinterpret_cast( HostInfoBase::ComputeSharedLibraryDirectory))); - // This is necessary because when running the testsuite the shlib might be a - // symbolic link inside the Python resource dir. - FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); + if (g_shlib_dir_helper) + g_shlib_dir_helper(lldb_file_spec); // Remove the filename so that this FileSpec only represents the directory. file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); diff --git a/lldb/source/Host/linux/HostInfoLinux.cpp b/lldb/source/Host/linux/HostInfoLinux.cpp --- a/lldb/source/Host/linux/HostInfoLinux.cpp +++ b/lldb/source/Host/linux/HostInfoLinux.cpp @@ -33,8 +33,8 @@ HostInfoLinuxFields *g_fields = nullptr; } -void HostInfoLinux::Initialize() { - HostInfoPosix::Initialize(); +void HostInfoLinux::Initialize(SharedLibraryDirectoryHelper *helper) { + HostInfoPosix::Initialize(helper); g_fields = new HostInfoLinuxFields(); } diff --git a/lldb/source/Host/windows/HostInfoWindows.cpp b/lldb/source/Host/windows/HostInfoWindows.cpp --- a/lldb/source/Host/windows/HostInfoWindows.cpp +++ b/lldb/source/Host/windows/HostInfoWindows.cpp @@ -39,9 +39,9 @@ FileSpec HostInfoWindows::m_program_filespec; -void HostInfoWindows::Initialize() { +void HostInfoWindows::Initialize(SharedLibraryDirectoryHelper *helper) { ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); - HostInfoBase::Initialize(); + HostInfoBase::Initialize(helper); } void HostInfoWindows::Terminate() { diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -11,7 +11,6 @@ #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Host/Socket.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/ReproducerProvider.h" @@ -35,7 +34,9 @@ using namespace lldb_private; using namespace lldb_private::repro; -SystemInitializerCommon::SystemInitializerCommon() {} +SystemInitializerCommon::SystemInitializerCommon( + HostInfo::SharedLibraryDirectoryHelper *helper) + : m_shlib_dir_helper(helper) {} SystemInitializerCommon::~SystemInitializerCommon() {} @@ -125,7 +126,7 @@ return e; Log::Initialize(); - HostInfo::Initialize(); + HostInfo::Initialize(m_shlib_dir_helper); llvm::Error error = Socket::Initialize(); if (error) diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -51,6 +51,7 @@ static lldb_private::ConstString GetPluginNameStatic(); static const char *GetPluginDescriptionStatic(); static FileSpec GetPythonDir(); + static void SharedLibraryDirectoryHelper(FileSpec &this_file); protected: static void ComputePythonDirForApple(llvm::SmallVectorImpl &path); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -410,6 +410,31 @@ return g_spec; } +void ScriptInterpreterPython::SharedLibraryDirectoryHelper( + FileSpec &this_file) { + // When we're loaded from python, this_file will point to the file inside the + // python package directory. Replace it with the one in the lib directory. +#ifdef _WIN32 + // On windows, we need to manually back out of the python tree, and go into + // the bin directory. This is pretty much the inverse of what ComputePythonDir + // does. + if (this_file.GetFileNameExtension() == ConstString(".pyd")) { + this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd + this_file.RemoveLastPathComponent(); // lldb + for (auto it = llvm::sys::path::begin(LLDB_PYTHON_RELATIVE_LIBDIR), + end = llvm::sys::path::end(LLDB_PYTHON_RELATIVE_LIBDIR); + it != end; ++it) + this_file.RemoveLastPathComponent(); + this_file.AppendPathComponent("bin"); + this_file.AppendPathComponent("liblldb.dll"); + } +#else + // The python file is a symlink, so we can find the real library by resolving + // it. We can do this unconditionally. + FileSystem::Instance().ResolveSymbolicLink(this_file, this_file); +#endif +} + lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() { static ConstString g_name("script-python"); return g_name; diff --git a/lldb/test/API/functionalities/paths/TestPaths.py b/lldb/test/API/functionalities/paths/TestPaths.py --- a/lldb/test/API/functionalities/paths/TestPaths.py +++ b/lldb/test/API/functionalities/paths/TestPaths.py @@ -8,6 +8,7 @@ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil class TestPaths(TestBase): @@ -29,7 +30,18 @@ for path_type in dir_path_types: f = lldb.SBHostOS.GetLLDBPath(path_type) # No directory path types should have the filename set - self.assertTrue(f.GetFilename() is None) + self.assertIsNone(f.GetFilename()) + + shlib_dir = lldb.SBHostOS.GetLLDBPath(lldb.ePathTypeLLDBShlibDir).GetDirectory() + if lldbplatformutil.getHostPlatform() == 'windows': + filenames = ['liblldb.dll'] + elif lldbplatformutil.getHostPlatform() == 'darwin': + filenames = ['LLDB', 'liblldb.dylib'] + else: + filenames = ['liblldb.so'] + self.assertTrue(any([os.path.exists(os.path.join(shlib_dir, f)) for f in + filenames]), "shlib_dir = " + shlib_dir) + @no_debug_info_test def test_directory_doesnt_end_with_slash(self): diff --git a/lldb/tools/lldb-server/SystemInitializerLLGS.h b/lldb/tools/lldb-server/SystemInitializerLLGS.h --- a/lldb/tools/lldb-server/SystemInitializerLLGS.h +++ b/lldb/tools/lldb-server/SystemInitializerLLGS.h @@ -14,6 +14,8 @@ class SystemInitializerLLGS : public lldb_private::SystemInitializerCommon { public: + SystemInitializerLLGS() : SystemInitializerCommon(nullptr) {} + llvm::Error Initialize() override; void Terminate() override; }; diff --git a/lldb/tools/lldb-test/SystemInitializerTest.cpp b/lldb/tools/lldb-test/SystemInitializerTest.cpp --- a/lldb/tools/lldb-test/SystemInitializerTest.cpp +++ b/lldb/tools/lldb-test/SystemInitializerTest.cpp @@ -22,7 +22,8 @@ using namespace lldb_private; -SystemInitializerTest::SystemInitializerTest() = default; +SystemInitializerTest::SystemInitializerTest() + : SystemInitializerCommon(nullptr) {} SystemInitializerTest::~SystemInitializerTest() = default; llvm::Error SystemInitializerTest::Initialize() {