| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
[lldb] Enable locate module callback for all module loading (#160199) Main executables were bypassing the locate module callback that shared libraries use, preventing custom symbol file location logic from working consistently. This PR fix this by * Adding target context to ModuleSpec * Leveraging that context to use target search path and platform's locate module callback in ModuleList::GetSharedModule This ensures both main executables and shared libraries get the same callback treatment for symbol file resolution. --------- Co-authored-by: George Hu <hyubo@meta.com> Co-authored-by: George Hu <georgehuyubo@gmail.com> | 10 个月前 | |
[lldb] Store StreamAsynchronousIO in a unique_ptr (NFC) (#127961) Make StreamAsynchronousIO an unique_ptr instead of a shared_ptr. I tried passing the class by value, but the llvm::raw_ostream forwarder stored in the Stream parent class isn't movable and I don't think it's worth changing that. Additionally, there's a few places that expect a StreamSP, which are easily created from a StreamUP. | 1 年前 | |
[LLDB] [NFC] - Remove duplicate #include headers from the files of lldb dir & few other files (#141478) A few files of lldb dir & few other files had duplicate headers included. This patch removes those redundancies. --------- Co-authored-by: Akash Agrawal <akashag@qti.qualcomm.com> | 1 年前 | |
[lldb-dap] persistent assembly breakpoints (#148061) Resolves #141955 - Adds data to breakpoints Source object, in order for assembly breakpoints, which rely on a temporary sourceReference value, to be able to resolve in future sessions like normal path+line breakpoints - Adds optional instructions_offset parameter to BreakpointResolver | 1 年前 | |
[lldb] fix parallel module loading deadlock for Linux DYLD (#166480) Another attempt at resolving the deadlock issue @GeorgeHuyubo discovered (his previous [attempt](https://github.com/llvm/llvm-project/pull/160225)). This change can be summarized as the following: * Plumb through a boolean flag to force no preload in GetOrCreateModules all the way through to LoadModuleAtAddress. * Parallelize Module::PreloadSymbols separately from Target::GetOrCreateModule and its caller LoadModuleAtAddress (this is what avoids the deadlock). These changes roughly maintain the performance characteristics of the previous implementation of parallel module loading. Testing on targets with between 5000 and 14000 modules, I saw similar numbers as before, often more than 10% faster in the new implementation across multiple trials for these massive targets. I think it's because we have less lock contention with this approach. # The deadlock See [bt.txt](https://github.com/user-attachments/files/22524471/bt.txt) for a sample backtrace of LLDB when the deadlock occurs. As @GeorgeHuyubo explains in his [PR](https://github.com/llvm/llvm-project/pull/160225), the deadlock occurs from an ABBA deadlock that happens when a thread context-switches out of Module::PreloadSymbols, goes into Target::GetOrCreateModule for another module, possibly entering this block: if (!module_sp) { // The platform is responsible for finding and caching an appropriate // module in the shared module cache. if (m_platform_sp) { error = m_platform_sp->GetSharedModule( module_spec, m_process_sp.get(), module_sp, &search_paths, &old_modules, &did_create_module); } else { error = Status::FromErrorString("no platform is currently set"); } } Module::PreloadSymbols holds a module-level mutex, and then GetSharedModule *attempts* to hold the mutex of the global shared ModuleList. So, this thread holds the module mutex, and waits on the global shared ModuleList mutex. A competing thread may execute Target::GetOrCreateModule, enter the same block as above, grabbing the global shared ModuleList mutex. Then, in ModuleList::GetSharedModule, we eventually call ModuleList::FindModules which eventually waits for the Module mutex held by the first thread (via Module::GetUUID). Thus, we deadlock. ## Reproducing the deadlock It might be worth noting that I've never been able to observe this deadlock issue during live debugging (e.g. launching or attaching to processes), however we were able to consistently reproduce this issue with coredumps when using the following settings: (lldb) settings set target.parallel-module-load true (lldb) settings set target.preload-symbols true (lldb) settings set symbols.load-on-demand false (lldb) target create --core /some/core/file/here # deadlock happens ## How this change avoids this deadlock This change avoids concurrent executions of Module::PreloadSymbols with Target::GetOrCreateModule by waiting until after the Target::GetOrCreateModule executions to run Module::PreloadSymbols in parallel. This avoids the ordering of holding a Module lock *then* the ModuleList lock, as Target::GetOrCreateModule executions maintain the ordering of the shared ModuleList lock first (from what I've read and tested). ## Why not read-write lock? Some feedback in https://github.com/llvm/llvm-project/pull/160225 was to modify mutexes used in these components with read-write locks. This might be a good idea overall, but I don't think it would *easily* resolve this specific deadlock. Module::PreloadSymbols would probably need a write lock to Module, so even if we had a read lock in Module::GetUUID we would still contend. Maybe the ModuleList lock could be a read lock that converts to a write lock if it chooses to update the module, but it seems likely that some thread would try to update the shared module list and then the write lock would contend again. Perhaps with deeper architectural changes, we could fix this issue? # Other attempts One downside of this approach (and the former approach of parallel module loading) is that each DYLD would need to implement this pattern themselves. With @clayborg's help, I looked at a few other approaches: * In Target::GetOrCreateModule, backgrounding the Module::PreloadSymbols call by adding it directly to the thread pool via Debugger::GetThreadPool().async(). This required adding a lock to Module::SetLoadAddress (probably should be one there already) since ObjectFileELF::SetLoadAddress is not thread-safe (updates sections). Unfortunately, during execution, this causes the preload symbols to run synchronously with Target::GetOrCreateModule, preventing us from truly parallelizing the execution. * In Module::PreloadSymbols, backgrounding the symtab and sym_file PreloadSymbols calls individually, but similar issues as the above. * Passing a callback function like https://github.com/swiftlang/llvm-project/pull/10746 instead of the boolean I use in this change. It's functionally the same change IMO, with some design tradeoffs: * Pro: the caller doesn't need to explicitly call Module::PreloadSymbols itself, and can instead call whatever function is passed into the callback. * Con: the caller needs to delay the execution of the callback such that it occurs after the GetOrCreateModule logic, otherwise we run into the same issue. I thought this would be trickier for the caller, requiring some kinda condition variable or otherwise storing the calls to execute afterwards. # Test Plan: ninja check-lldb --------- Co-authored-by: Tom Yang <toyang@fb.com> | 9 个月前 | |
[lldb][NFC] Make the target's SectionLoadList private. (#113278) Lots of code around LLDB was directly accessing the target's section load list. This NFC patch makes the section load list private so the Target class can access it, but everyone else now uses accessor functions. This allows us to control the resolving of addresses and will allow for functionality in LLDB which can lazily resolve addresses in JIT plug-ins with a future patch. | 1 年前 | |
[lldb] Use weak pointers instead of shared pointers in DynamicLoader (#156446) 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. | 1 年前 | |
[lldb/cmake] Implicitly pass arguments to llvm_add_library (#142583) If we're not touching them, we don't need to do anything special to pass them along -- with one important caveat: due to how cmake arguments work, the implicitly passed arguments need to be specified before arguments that we handle. This isn't particularly nice, but the alternative is enumerating all arguments that can be used by llvm_add_library and the macros it calls (it also relies on implicit passing of some arguments to llvm_process_sources). | 1 年前 | |
| 1 年前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 10 个月前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 9 个月前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 1 年前 |