DynamicLoaderWindowsDYLD uses pointers to Modules to maintain a map from modules to their addresses, but it does not need to keep "strong" references to them. Weak pointers should be enough, and would allow modules to be released elsewhere. Other DynamicLoader classes do not use shared pointers as well. For example, DynamicLoaderPOSIXDYLD has a similar map with weak pointers. Actually testing for modules being completely released can be tricky. The test here is just to illustrate the case where shared pointers kept modules in DynamicLoaderWindowsDYLD and prevented them from being released. The test executes the following sequence: 1. Create a target, load an executable and run it. 2. Remove one module from the target. The target should be the last actual use of the module, but we have another reference to it in the shared module cache. 3. Call MemoryPressureDetected to remove this last reference from the cache. 4. Replace the corresponding DLL file. LLDB memory maps DLLs, and this makes files read-only on Windows. Unless the modules are completely released (and therefore unmapped), (4) is going to fail with "access denied". However, the test does not trigger the bug completely - it passes with and without the change.
55 lines
1.8 KiB
C++
55 lines
1.8 KiB
C++
//===-- DynamicLoaderWindowsDYLD.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 LLDB_SOURCE_PLUGINS_DYNAMICLOADER_WINDOWS_DYLD_DYNAMICLOADERWINDOWSDYLD_H
|
|
#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_WINDOWS_DYLD_DYNAMICLOADERWINDOWSDYLD_H
|
|
|
|
#include "lldb/Target/DynamicLoader.h"
|
|
#include "lldb/lldb-forward.h"
|
|
|
|
#include <map>
|
|
|
|
namespace lldb_private {
|
|
|
|
class DynamicLoaderWindowsDYLD : public DynamicLoader {
|
|
public:
|
|
DynamicLoaderWindowsDYLD(Process *process);
|
|
|
|
~DynamicLoaderWindowsDYLD() override;
|
|
|
|
static void Initialize();
|
|
static void Terminate();
|
|
static llvm::StringRef GetPluginNameStatic() { return "windows-dyld"; }
|
|
static llvm::StringRef GetPluginDescriptionStatic();
|
|
|
|
static DynamicLoader *CreateInstance(Process *process, bool force);
|
|
|
|
void OnLoadModule(lldb::ModuleSP module_sp, const ModuleSpec module_spec,
|
|
lldb::addr_t module_addr);
|
|
void OnUnloadModule(lldb::addr_t module_addr);
|
|
|
|
void DidAttach() override;
|
|
void DidLaunch() override;
|
|
Status CanLoadImage() override;
|
|
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
|
|
bool stop) override;
|
|
|
|
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
|
|
|
|
protected:
|
|
lldb::addr_t GetLoadAddress(lldb::ModuleSP executable);
|
|
|
|
private:
|
|
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>>
|
|
m_loaded_modules;
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_WINDOWS_DYLD_DYNAMICLOADERWINDOWSDYLD_H
|