diff options
author | Igor Kudrin <ikudrin@accesssoftek.com> | 2025-06-27 14:30:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-27 14:30:24 -0700 |
commit | 442f99d7698a4ca87ebb16cb22df610c45d4698a (patch) | |
tree | 6cd1bf747cd0a88ab49167103bbcb44c4f544ace /lldb/source/Expression/Materializer.cpp | |
parent | 9f5061d4f00456d882db9eb606f4a82b2c40e7a8 (diff) | |
download | llvm-442f99d7698a4ca87ebb16cb22df610c45d4698a.zip llvm-442f99d7698a4ca87ebb16cb22df610c45d4698a.tar.gz llvm-442f99d7698a4ca87ebb16cb22df610c45d4698a.tar.bz2 |
[lldb] Fix evaluating expressions without JIT in an object context (#145599)
If a server does not support allocating memory in an inferior process or
when debugging a core file, evaluating an expression in the context of a
value object results in an error:
```
error: <lldb wrapper prefix>:43:1: use of undeclared identifier '$__lldb_class'
43 | $__lldb_class::$__lldb_expr(void *$__lldb_arg)
| ^
```
Such expressions require a live address to be stored in the value
object. However, `EntityResultVariable::Dematerialize()` only sets
`ret->m_live_sp` if JIT is available, even if the address points to the
process memory and no custom allocations were made. Similarly,
`EntityPersistentVariable::Dematerialize()` tries to deallocate memory
based on the same check, resulting in an error if the memory was not
previously allocated in `EntityPersistentVariable::Materialize()`.
As an unintended bonus, the patch also fixes a FIXME case in
`TestCxxChar8_t.py`.
Diffstat (limited to 'lldb/source/Expression/Materializer.cpp')
-rw-r--r-- | lldb/source/Expression/Materializer.cpp | 52 |
1 files changed, 25 insertions, 27 deletions
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 96add56..17ea159 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -75,11 +75,12 @@ public: // contents. const bool zero_memory = false; + IRMemoryMap::AllocationPolicy used_policy; auto address_or_error = map.Malloc( llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize()) .value_or(0), 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyMirror, zero_memory); + IRMemoryMap::eAllocationPolicyMirror, zero_memory, &used_policy); if (!address_or_error) { err = Status::FromErrorStringWithFormat( "couldn't allocate a memory area to store %s: %s", @@ -101,14 +102,22 @@ public: m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, map.GetAddressByteSize()); - // Clear the flag if the variable will never be deallocated. - if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) { - Status leak_error; - map.Leak(mem, leak_error); - m_persistent_variable_sp->m_flags &= - ~ExpressionVariable::EVNeedsAllocation; + if (used_policy == IRMemoryMap::eAllocationPolicyMirror) { + // Clear the flag if the variable will never be deallocated. + Status leak_error; + map.Leak(mem, leak_error); + m_persistent_variable_sp->m_flags &= + ~ExpressionVariable::EVNeedsAllocation; + } else { + // If the variable cannot be kept in target, clear this flag... + m_persistent_variable_sp->m_flags &= + ~ExpressionVariable::EVKeepInTarget; + // ...and set the flag to copy the value during dematerialization. + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVNeedsFreezeDry; + } } // Write the contents of the variable to the area. @@ -327,22 +336,10 @@ public: return; } - lldb::ProcessSP process_sp = - map.GetBestExecutionContextScope()->CalculateProcess(); - if (!process_sp || !process_sp->CanJIT()) { - // Allocations are not persistent so persistent variables cannot stay - // materialized. - - m_persistent_variable_sp->m_flags |= - ExpressionVariable::EVNeedsAllocation; - - DestroyAllocation(map, err); - if (!err.Success()) - return; - } else if (m_persistent_variable_sp->m_flags & - ExpressionVariable::EVNeedsAllocation && - !(m_persistent_variable_sp->m_flags & - ExpressionVariable::EVKeepInTarget)) { + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVNeedsAllocation && + !(m_persistent_variable_sp->m_flags & + ExpressionVariable::EVKeepInTarget)) { DestroyAllocation(map, err); if (!err.Success()) return; @@ -1082,9 +1079,8 @@ public: m_delegate->DidDematerialize(ret); } - bool can_persist = - (m_is_program_reference && process_sp && process_sp->CanJIT() && - !(address >= frame_bottom && address < frame_top)); + bool can_persist = m_is_program_reference && + !(address >= frame_bottom && address < frame_top); if (can_persist && m_keep_in_memory) { ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name, @@ -1114,7 +1110,9 @@ public: map.Free(m_temporary_allocation, free_error); } } else { - ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; + ret->m_flags |= m_is_program_reference + ? ExpressionVariable::EVIsProgramReference + : ExpressionVariable::EVIsLLDBAllocated; } m_temporary_allocation = LLDB_INVALID_ADDRESS; |