Skip to content

Conversation

@asavonic
Copy link
Collaborator

@asavonic asavonic commented Sep 2, 2025

DynamicLoaderWindowsDYLD uses pointers to mModules 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.

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 the 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.
@asavonic
Copy link
Collaborator Author

asavonic commented Sep 2, 2025

@jimingham, @JDevlieghere, thanks to your suggestions in #147289, I was able to use existing LLDB API to completely release some modules from the cache, but keep other modules intact. However, this approach did not work completely, because DynamicLoaderWindowsDYLD kept modules from being released. The patch is supposed to address this problem. I think it is a corner case, because normally modules should be released when they are unloaded. In any case, I think using weak pointers here makes sense.

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@asavonic asavonic merged commit 371d1a8 into llvm:main Sep 4, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants