Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lldb/include/lldb/Expression/IRMemoryMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ class IRMemoryMap {
///only in the process.
};

// If 'policy' is 'eAllocationPolicyMirror' but it is impossible to allocate
// memory in the process, 'eAllocationPolicyHostOnly' will be used instead.
// The actual policy is returned via 'used_policy'.
llvm::Expected<lldb::addr_t> Malloc(size_t size, uint8_t alignment,
uint32_t permissions,
AllocationPolicy policy,
bool zero_memory);
AllocationPolicy policy, bool zero_memory,
AllocationPolicy *used_policy = nullptr);
void Leak(lldb::addr_t process_address, Status &error);
void Free(lldb::addr_t process_address, Status &error);

Expand Down
11 changes: 7 additions & 4 deletions lldb/source/Expression/IRMemoryMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,10 @@ IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
}
}

llvm::Expected<lldb::addr_t> IRMemoryMap::Malloc(size_t size, uint8_t alignment,
uint32_t permissions,
AllocationPolicy policy,
bool zero_memory) {
llvm::Expected<lldb::addr_t>
IRMemoryMap::Malloc(size_t size, uint8_t alignment, uint32_t permissions,
AllocationPolicy policy, bool zero_memory,
AllocationPolicy *used_policy) {
lldb_private::Log *log(GetLog(LLDBLog::Expressions));

lldb::ProcessSP process_sp;
Expand Down Expand Up @@ -454,6 +454,9 @@ llvm::Expected<lldb::addr_t> IRMemoryMap::Malloc(size_t size, uint8_t alignment,
(uint64_t)permissions, policy_string, aligned_address);
}

if (used_policy)
*used_policy = policy;

return aligned_address;
}

Expand Down
52 changes: 25 additions & 27 deletions lldb/source/Expression/Materializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ class EntityPersistentVariable : public Materializer::Entity {
// 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",
Expand All @@ -101,14 +102,22 @@ class EntityPersistentVariable : public Materializer::Entity {
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.
Expand Down Expand Up @@ -327,22 +336,10 @@ class EntityPersistentVariable : public Materializer::Entity {
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;
Expand Down Expand Up @@ -1082,9 +1079,8 @@ class EntityResultVariable : public Materializer::Entity {
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,
Expand Down Expand Up @@ -1114,7 +1110,9 @@ class EntityResultVariable : public Materializer::Entity {
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
Test evaluating expressions when debugging core file.
"""

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


@skipIfLLVMTargetMissing("X86")
class CoreExprTestCase(TestBase):
def setUp(self):
TestBase.setUp(self)
self.target = self.dbg.CreateTarget("linux-x86_64.out")
self.process = self.target.LoadCore("linux-x86_64.core")
self.assertTrue(self.process, PROCESS_IS_VALID)

def test_result_var(self):
"""Test that the result variable can be used in subsequent expressions."""

self.expect_expr(
"outer",
result_type="Outer",
result_children=[ValueCheck(name="inner", type="Inner")],
)
self.expect_expr(
"$0.inner",
result_type="Inner",
result_children=[ValueCheck(name="val", type="int", value="5")],
)
self.expect_expr("$1.val", result_type="int", result_value="5")

def test_persist_var(self):
"""Test that user-defined variables can be used in subsequent expressions."""

self.target.EvaluateExpression("int $my_int = 5")
self.expect_expr("$my_int * 2", result_type="int", result_value="10")

def test_context_object(self):
"""Test expression evaluation in context of an object."""

val_outer = self.expect_expr("outer", result_type="Outer")

val_inner = val_outer.EvaluateExpression("inner")
self.assertTrue(val_inner.IsValid())
self.assertEqual("Inner", val_inner.GetDisplayTypeName())

val_val = val_inner.EvaluateExpression("this->val")
self.assertTrue(val_val.IsValid())
self.assertEqual("int", val_val.GetDisplayTypeName())
self.assertEqual(val_val.GetValueAsSigned(), 5)
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions lldb/test/API/functionalities/postmortem/elf-core/expr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
struct Inner {
Inner(int val) : val(val) {}
int val;
};

struct Outer {
Outer(int val) : inner(val) {}
Inner inner;
};

extern "C" void _start(void) {
Outer outer(5);
char *boom = (char *)0;
*boom = 47;
}
4 changes: 1 addition & 3 deletions lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ def test_without_process(self):

self.expect_expr("a", result_type="char8_t", result_summary="0x61 u8'a'")
self.expect_expr("ab", result_type="const char8_t *", result_summary='u8"你好"')

# FIXME: This should work too.
self.expect("expr abc", substrs=['u8"你好"'], matching=False)
self.expect_expr("abc", result_type="char8_t[9]", result_summary='u8"你好"')

@skipIf(compiler="clang", compiler_version=["<", "7.0"])
def test_with_process(self):
Expand Down
Loading