180814287SRaphael Isemann //===-- Materializer.cpp --------------------------------------------------===//
296d2730aSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
696d2730aSSean Callanan //
796d2730aSSean Callanan //===----------------------------------------------------------------------===//
896d2730aSSean Callanan
9b9c1b51eSKate Stone #include "lldb/Expression/Materializer.h"
1029cb868aSZachary Turner #include "lldb/Core/DumpDataExtractor.h"
1135005f76SSean Callanan #include "lldb/Core/ValueObjectConstResult.h"
12f8043fa5SSean Callanan #include "lldb/Core/ValueObjectVariable.h"
138f1f9a1bSSean Callanan #include "lldb/Expression/ExpressionVariable.h"
1496d2730aSSean Callanan #include "lldb/Symbol/Symbol.h"
1596d2730aSSean Callanan #include "lldb/Symbol/Type.h"
1696d2730aSSean Callanan #include "lldb/Symbol/Variable.h"
1796d2730aSSean Callanan #include "lldb/Target/ExecutionContext.h"
18b5717e00SSean Callanan #include "lldb/Target/RegisterContext.h"
19b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
201582ee68SSean Callanan #include "lldb/Target/Target.h"
21a4e8105bSSean Callanan #include "lldb/Target/Thread.h"
22c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
236f9e6901SZachary Turner #include "lldb/Utility/Log.h"
24d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
25*317c8bf8SMichael Buch #include "lldb/lldb-forward.h"
2696d2730aSSean Callanan
27796ac80bSJonas Devlieghere #include <memory>
28796ac80bSJonas Devlieghere
2996d2730aSSean Callanan using namespace lldb_private;
3096d2730aSSean Callanan
31fcf4e252SMichael Buch // FIXME: these should be retrieved from the target
32fcf4e252SMichael Buch // instead of being hard-coded. Currently we
33fcf4e252SMichael Buch // assume that persistent vars are materialized
34fcf4e252SMichael Buch // as references, and thus pick the size of a
35fcf4e252SMichael Buch // 64-bit pointer.
36fcf4e252SMichael Buch static constexpr uint32_t g_default_var_alignment = 8;
37fcf4e252SMichael Buch static constexpr uint32_t g_default_var_byte_size = 8;
38fcf4e252SMichael Buch
AddStructMember(Entity & entity)39b9c1b51eSKate Stone uint32_t Materializer::AddStructMember(Entity &entity) {
4096d2730aSSean Callanan uint32_t size = entity.GetSize();
4196d2730aSSean Callanan uint32_t alignment = entity.GetAlignment();
4296d2730aSSean Callanan
4396d2730aSSean Callanan uint32_t ret;
4496d2730aSSean Callanan
453dd6a423SSean Callanan if (m_current_offset == 0)
4696d2730aSSean Callanan m_struct_alignment = alignment;
4796d2730aSSean Callanan
4896d2730aSSean Callanan if (m_current_offset % alignment)
4996d2730aSSean Callanan m_current_offset += (alignment - (m_current_offset % alignment));
5096d2730aSSean Callanan
5196d2730aSSean Callanan ret = m_current_offset;
5296d2730aSSean Callanan
5396d2730aSSean Callanan m_current_offset += size;
5496d2730aSSean Callanan
5596d2730aSSean Callanan return ret;
5696d2730aSSean Callanan }
5796d2730aSSean Callanan
58b9c1b51eSKate Stone class EntityPersistentVariable : public Materializer::Entity {
5996d2730aSSean Callanan public:
EntityPersistentVariable(lldb::ExpressionVariableSP & persistent_variable_sp,Materializer::PersistentVariableDelegate * delegate)609fda9d21SSean Callanan EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
61b9c1b51eSKate Stone Materializer::PersistentVariableDelegate *delegate)
62b9c1b51eSKate Stone : Entity(), m_persistent_variable_sp(persistent_variable_sp),
63b9c1b51eSKate Stone m_delegate(delegate) {
64b9c1b51eSKate Stone // Hard-coding to maximum size of a pointer since persistent variables are
65b9c1b51eSKate Stone // materialized by reference
66fcf4e252SMichael Buch m_size = g_default_var_byte_size;
67fcf4e252SMichael Buch m_alignment = g_default_var_alignment;
6896d2730aSSean Callanan }
6996d2730aSSean Callanan
MakeAllocation(IRMemoryMap & map,Status & err)7097206d57SZachary Turner void MakeAllocation(IRMemoryMap &map, Status &err) {
71a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
7235005f76SSean Callanan
7305097246SAdrian Prantl // Allocate a spare memory area to store the persistent variable's
7405097246SAdrian Prantl // contents.
7535005f76SSean Callanan
7697206d57SZachary Turner Status allocate_error;
772c381414SJim Ingham const bool zero_memory = false;
7835005f76SSean Callanan
79b9c1b51eSKate Stone lldb::addr_t mem = map.Malloc(
80aa88161bSKazu Hirata m_persistent_variable_sp->GetByteSize().value_or(0), 8,
8135005f76SSean Callanan lldb::ePermissionsReadable | lldb::ePermissionsWritable,
82b9c1b51eSKate Stone IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
8335005f76SSean Callanan
84b9c1b51eSKate Stone if (!allocate_error.Success()) {
85b9c1b51eSKate Stone err.SetErrorStringWithFormat(
86b9c1b51eSKate Stone "couldn't allocate a memory area to store %s: %s",
87b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString(),
88b9c1b51eSKate Stone allocate_error.AsCString());
8935005f76SSean Callanan return;
9096d2730aSSean Callanan }
9196d2730aSSean Callanan
9263e5fb76SJonas Devlieghere LLDB_LOGF(log, "Allocated %s (0x%" PRIx64 ") successfully",
93b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString(), mem);
9435005f76SSean Callanan
95b9c1b51eSKate Stone // Put the location of the spare memory into the live data of the
96b9c1b51eSKate Stone // ValueObject.
9735005f76SSean Callanan
98b9c1b51eSKate Stone m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
99b9c1b51eSKate Stone map.GetBestExecutionContextScope(),
100c608d206SSean Callanan m_persistent_variable_sp->GetCompilerType(),
101b9c1b51eSKate Stone m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
102edd508b3SSean Callanan map.GetAddressByteSize());
10335005f76SSean Callanan
10435005f76SSean Callanan // Clear the flag if the variable will never be deallocated.
10535005f76SSean Callanan
106b9c1b51eSKate Stone if (m_persistent_variable_sp->m_flags &
107b9c1b51eSKate Stone ExpressionVariable::EVKeepInTarget) {
10897206d57SZachary Turner Status leak_error;
109fbf5c682SSean Callanan map.Leak(mem, leak_error);
110b9c1b51eSKate Stone m_persistent_variable_sp->m_flags &=
111b9c1b51eSKate Stone ~ExpressionVariable::EVNeedsAllocation;
112fbf5c682SSean Callanan }
11335005f76SSean Callanan
11435005f76SSean Callanan // Write the contents of the variable to the area.
11535005f76SSean Callanan
11697206d57SZachary Turner Status write_error;
11735005f76SSean Callanan
118b9c1b51eSKate Stone map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
119aa88161bSKazu Hirata m_persistent_variable_sp->GetByteSize().value_or(0),
120113f56fbSAdrian Prantl write_error);
12135005f76SSean Callanan
122b9c1b51eSKate Stone if (!write_error.Success()) {
123b9c1b51eSKate Stone err.SetErrorStringWithFormat(
124b9c1b51eSKate Stone "couldn't write %s to the target: %s",
125b9c1b51eSKate Stone m_persistent_variable_sp->GetName().AsCString(),
12635005f76SSean Callanan write_error.AsCString());
12735005f76SSean Callanan return;
12835005f76SSean Callanan }
12935005f76SSean Callanan }
13035005f76SSean Callanan
DestroyAllocation(IRMemoryMap & map,Status & err)13197206d57SZachary Turner void DestroyAllocation(IRMemoryMap &map, Status &err) {
13297206d57SZachary Turner Status deallocate_error;
13335005f76SSean Callanan
134b9c1b51eSKate Stone map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
135b9c1b51eSKate Stone .GetScalar()
136b9c1b51eSKate Stone .ULongLong(),
137b9c1b51eSKate Stone deallocate_error);
13835005f76SSean Callanan
1392afbf444SSean Callanan m_persistent_variable_sp->m_live_sp.reset();
1402afbf444SSean Callanan
141b9c1b51eSKate Stone if (!deallocate_error.Success()) {
142b9c1b51eSKate Stone err.SetErrorStringWithFormat(
143b9c1b51eSKate Stone "couldn't deallocate memory for %s: %s",
144b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString(),
145b9c1b51eSKate Stone deallocate_error.AsCString());
14635005f76SSean Callanan }
14735005f76SSean Callanan }
14835005f76SSean Callanan
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)149b9c1b51eSKate Stone void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
15097206d57SZachary Turner lldb::addr_t process_address, Status &err) override {
151a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
15235005f76SSean Callanan
15357ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
15457ee3067SGreg Clayton
155b9c1b51eSKate Stone if (log) {
15663e5fb76SJonas Devlieghere LLDB_LOGF(log,
15763e5fb76SJonas Devlieghere "EntityPersistentVariable::Materialize [address = 0x%" PRIx64
158b9c1b51eSKate Stone ", m_name = %s, m_flags = 0x%hx]",
15957ee3067SGreg Clayton (uint64_t)load_addr,
16035005f76SSean Callanan m_persistent_variable_sp->GetName().AsCString(),
16135005f76SSean Callanan m_persistent_variable_sp->m_flags);
16235005f76SSean Callanan }
16335005f76SSean Callanan
164b9c1b51eSKate Stone if (m_persistent_variable_sp->m_flags &
165b9c1b51eSKate Stone ExpressionVariable::EVNeedsAllocation) {
16635005f76SSean Callanan MakeAllocation(map, err);
167b9c1b51eSKate Stone m_persistent_variable_sp->m_flags |=
168b9c1b51eSKate Stone ExpressionVariable::EVIsLLDBAllocated;
1692afbf444SSean Callanan
17035005f76SSean Callanan if (!err.Success())
17135005f76SSean Callanan return;
17235005f76SSean Callanan }
17335005f76SSean Callanan
174b9c1b51eSKate Stone if ((m_persistent_variable_sp->m_flags &
175b9c1b51eSKate Stone ExpressionVariable::EVIsProgramReference &&
176b9c1b51eSKate Stone m_persistent_variable_sp->m_live_sp) ||
177b9c1b51eSKate Stone m_persistent_variable_sp->m_flags &
178b9c1b51eSKate Stone ExpressionVariable::EVIsLLDBAllocated) {
17997206d57SZachary Turner Status write_error;
18035005f76SSean Callanan
181b9c1b51eSKate Stone map.WriteScalarToMemory(
182b9c1b51eSKate Stone load_addr,
18335005f76SSean Callanan m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
184b9c1b51eSKate Stone map.GetAddressByteSize(), write_error);
18535005f76SSean Callanan
186b9c1b51eSKate Stone if (!write_error.Success()) {
187b9c1b51eSKate Stone err.SetErrorStringWithFormat(
188b9c1b51eSKate Stone "couldn't write the location of %s to memory: %s",
189b9c1b51eSKate Stone m_persistent_variable_sp->GetName().AsCString(),
190b9c1b51eSKate Stone write_error.AsCString());
19135005f76SSean Callanan }
192b9c1b51eSKate Stone } else {
193b9c1b51eSKate Stone err.SetErrorStringWithFormat(
194b9c1b51eSKate Stone "no materialization happened for persistent variable %s",
195b9c1b51eSKate Stone m_persistent_variable_sp->GetName().AsCString());
19635005f76SSean Callanan return;
19735005f76SSean Callanan }
19835005f76SSean Callanan }
19935005f76SSean Callanan
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)200b9c1b51eSKate Stone void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
201b9c1b51eSKate Stone lldb::addr_t process_address, lldb::addr_t frame_top,
20297206d57SZachary Turner lldb::addr_t frame_bottom, Status &err) override {
203a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
20435005f76SSean Callanan
20557ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
20657ee3067SGreg Clayton
207b9c1b51eSKate Stone if (log) {
20863e5fb76SJonas Devlieghere LLDB_LOGF(log,
209b9c1b51eSKate Stone "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
210b9c1b51eSKate Stone ", m_name = %s, m_flags = 0x%hx]",
21157ee3067SGreg Clayton (uint64_t)process_address + m_offset,
21235005f76SSean Callanan m_persistent_variable_sp->GetName().AsCString(),
21335005f76SSean Callanan m_persistent_variable_sp->m_flags);
21435005f76SSean Callanan }
21535005f76SSean Callanan
216b9c1b51eSKate Stone if (m_delegate) {
2179fda9d21SSean Callanan m_delegate->DidDematerialize(m_persistent_variable_sp);
2189fda9d21SSean Callanan }
2199fda9d21SSean Callanan
220b9c1b51eSKate Stone if ((m_persistent_variable_sp->m_flags &
221b9c1b51eSKate Stone ExpressionVariable::EVIsLLDBAllocated) ||
222b9c1b51eSKate Stone (m_persistent_variable_sp->m_flags &
223b9c1b51eSKate Stone ExpressionVariable::EVIsProgramReference)) {
224b9c1b51eSKate Stone if (m_persistent_variable_sp->m_flags &
225b9c1b51eSKate Stone ExpressionVariable::EVIsProgramReference &&
226b9c1b51eSKate Stone !m_persistent_variable_sp->m_live_sp) {
227b9c1b51eSKate Stone // If the reference comes from the program, then the
22805097246SAdrian Prantl // ClangExpressionVariable's live variable data hasn't been set up yet.
22905097246SAdrian Prantl // Do this now.
23035005f76SSean Callanan
23114b1bae5SSean Callanan lldb::addr_t location;
23297206d57SZachary Turner Status read_error;
23335005f76SSean Callanan
23457ee3067SGreg Clayton map.ReadPointerFromMemory(&location, load_addr, read_error);
23535005f76SSean Callanan
236b9c1b51eSKate Stone if (!read_error.Success()) {
237b9c1b51eSKate Stone err.SetErrorStringWithFormat(
238b9c1b51eSKate Stone "couldn't read the address of program-allocated variable %s: %s",
239b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString(),
240b9c1b51eSKate Stone read_error.AsCString());
24135005f76SSean Callanan return;
24235005f76SSean Callanan }
24335005f76SSean Callanan
244b9c1b51eSKate Stone m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
245b9c1b51eSKate Stone map.GetBestExecutionContextScope(),
246e6f4a826SSean Callanan m_persistent_variable_sp.get()->GetCompilerType(),
247b9c1b51eSKate Stone m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
248aa88161bSKazu Hirata m_persistent_variable_sp->GetByteSize().value_or(0));
24935005f76SSean Callanan
25035005f76SSean Callanan if (frame_top != LLDB_INVALID_ADDRESS &&
251b9c1b51eSKate Stone frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
252b9c1b51eSKate Stone location <= frame_top) {
253b9c1b51eSKate Stone // If the variable is resident in the stack frame created by the
25405097246SAdrian Prantl // expression, then it cannot be relied upon to stay around. We
25505097246SAdrian Prantl // treat it as needing reallocation.
256b9c1b51eSKate Stone m_persistent_variable_sp->m_flags |=
257b9c1b51eSKate Stone ExpressionVariable::EVIsLLDBAllocated;
258b9c1b51eSKate Stone m_persistent_variable_sp->m_flags |=
259b9c1b51eSKate Stone ExpressionVariable::EVNeedsAllocation;
260b9c1b51eSKate Stone m_persistent_variable_sp->m_flags |=
261b9c1b51eSKate Stone ExpressionVariable::EVNeedsFreezeDry;
262b9c1b51eSKate Stone m_persistent_variable_sp->m_flags &=
263b9c1b51eSKate Stone ~ExpressionVariable::EVIsProgramReference;
26435005f76SSean Callanan }
26535005f76SSean Callanan }
26635005f76SSean Callanan
267b9c1b51eSKate Stone lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
268b9c1b51eSKate Stone .GetScalar()
269b9c1b51eSKate Stone .ULongLong();
27035005f76SSean Callanan
271b9c1b51eSKate Stone if (!m_persistent_variable_sp->m_live_sp) {
272b9c1b51eSKate Stone err.SetErrorStringWithFormat(
273b9c1b51eSKate Stone "couldn't find the memory area used to store %s",
274b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString());
27535005f76SSean Callanan return;
27635005f76SSean Callanan }
27735005f76SSean Callanan
278b9c1b51eSKate Stone if (m_persistent_variable_sp->m_live_sp->GetValue()
279b9c1b51eSKate Stone .GetValueAddressType() != eAddressTypeLoad) {
280b9c1b51eSKate Stone err.SetErrorStringWithFormat(
281b9c1b51eSKate Stone "the address of the memory area for %s is in an incorrect format",
282b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString());
28335005f76SSean Callanan return;
28435005f76SSean Callanan }
28535005f76SSean Callanan
286b9c1b51eSKate Stone if (m_persistent_variable_sp->m_flags &
287b9c1b51eSKate Stone ExpressionVariable::EVNeedsFreezeDry ||
288b9c1b51eSKate Stone m_persistent_variable_sp->m_flags &
289b9c1b51eSKate Stone ExpressionVariable::EVKeepInTarget) {
29063e5fb76SJonas Devlieghere LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
29163e5fb76SJonas Devlieghere m_persistent_variable_sp->GetName().GetCString(),
29263e5fb76SJonas Devlieghere (uint64_t)mem,
293113f56fbSAdrian Prantl (unsigned long long)m_persistent_variable_sp->GetByteSize()
294aa88161bSKazu Hirata .value_or(0));
29535005f76SSean Callanan
29635005f76SSean Callanan // Read the contents of the spare memory area
29735005f76SSean Callanan
29835005f76SSean Callanan m_persistent_variable_sp->ValueUpdated();
29935005f76SSean Callanan
30097206d57SZachary Turner Status read_error;
30135005f76SSean Callanan
302b9c1b51eSKate Stone map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
303aa88161bSKazu Hirata m_persistent_variable_sp->GetByteSize().value_or(0),
304aa88161bSKazu Hirata read_error);
30535005f76SSean Callanan
306b9c1b51eSKate Stone if (!read_error.Success()) {
307b9c1b51eSKate Stone err.SetErrorStringWithFormat(
308b9c1b51eSKate Stone "couldn't read the contents of %s from memory: %s",
309b9c1b51eSKate Stone m_persistent_variable_sp->GetName().GetCString(),
310b9c1b51eSKate Stone read_error.AsCString());
31135005f76SSean Callanan return;
31235005f76SSean Callanan }
31335005f76SSean Callanan
314b9c1b51eSKate Stone m_persistent_variable_sp->m_flags &=
315b9c1b51eSKate Stone ~ExpressionVariable::EVNeedsFreezeDry;
31635005f76SSean Callanan }
317b9c1b51eSKate Stone } else {
318b9c1b51eSKate Stone err.SetErrorStringWithFormat(
319b9c1b51eSKate Stone "no dematerialization happened for persistent variable %s",
320b9c1b51eSKate Stone m_persistent_variable_sp->GetName().AsCString());
32135005f76SSean Callanan return;
32235005f76SSean Callanan }
32335005f76SSean Callanan
324b9c1b51eSKate Stone lldb::ProcessSP process_sp =
325b9c1b51eSKate Stone map.GetBestExecutionContextScope()->CalculateProcess();
326b9c1b51eSKate Stone if (!process_sp || !process_sp->CanJIT()) {
327b9c1b51eSKate Stone // Allocations are not persistent so persistent variables cannot stay
328b9c1b51eSKate Stone // materialized.
3292afbf444SSean Callanan
330b9c1b51eSKate Stone m_persistent_variable_sp->m_flags |=
331b9c1b51eSKate Stone ExpressionVariable::EVNeedsAllocation;
3322afbf444SSean Callanan
3332afbf444SSean Callanan DestroyAllocation(map, err);
3342afbf444SSean Callanan if (!err.Success())
3352afbf444SSean Callanan return;
336b9c1b51eSKate Stone } else if (m_persistent_variable_sp->m_flags &
337b9c1b51eSKate Stone ExpressionVariable::EVNeedsAllocation &&
338b9c1b51eSKate Stone !(m_persistent_variable_sp->m_flags &
339b9c1b51eSKate Stone ExpressionVariable::EVKeepInTarget)) {
34035005f76SSean Callanan DestroyAllocation(map, err);
34135005f76SSean Callanan if (!err.Success())
34235005f76SSean Callanan return;
34335005f76SSean Callanan }
34496d2730aSSean Callanan }
3452d37e5a5SSean Callanan
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)346b9c1b51eSKate Stone void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
347b9c1b51eSKate Stone Log *log) override {
3482d37e5a5SSean Callanan StreamString dump_stream;
3492d37e5a5SSean Callanan
35097206d57SZachary Turner Status err;
3512d37e5a5SSean Callanan
35257ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
35357ee3067SGreg Clayton
354b9c1b51eSKate Stone dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
355b9c1b51eSKate Stone load_addr,
356b9c1b51eSKate Stone m_persistent_variable_sp->GetName().AsCString());
3572d37e5a5SSean Callanan
3582d37e5a5SSean Callanan {
3592d37e5a5SSean Callanan dump_stream.Printf("Pointer:\n");
3602d37e5a5SSean Callanan
3612d37e5a5SSean Callanan DataBufferHeap data(m_size, 0);
3622d37e5a5SSean Callanan
36357ee3067SGreg Clayton map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
3642d37e5a5SSean Callanan
365b9c1b51eSKate Stone if (!err.Success()) {
3662d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
367b9c1b51eSKate Stone } else {
36829cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
36929cb868aSZachary Turner load_addr);
37014b1bae5SSean Callanan
37114b1bae5SSean Callanan dump_stream.PutChar('\n');
3722d37e5a5SSean Callanan }
3732d37e5a5SSean Callanan }
3742d37e5a5SSean Callanan
3752d37e5a5SSean Callanan {
3762d37e5a5SSean Callanan dump_stream.Printf("Target:\n");
3772d37e5a5SSean Callanan
3782d37e5a5SSean Callanan lldb::addr_t target_address;
3792d37e5a5SSean Callanan
38057ee3067SGreg Clayton map.ReadPointerFromMemory(&target_address, load_addr, err);
3812d37e5a5SSean Callanan
382b9c1b51eSKate Stone if (!err.Success()) {
3832d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
384b9c1b51eSKate Stone } else {
385aa88161bSKazu Hirata DataBufferHeap data(m_persistent_variable_sp->GetByteSize().value_or(0),
386aa88161bSKazu Hirata 0);
3872d37e5a5SSean Callanan
388b9c1b51eSKate Stone map.ReadMemory(data.GetBytes(), target_address,
389aa88161bSKazu Hirata m_persistent_variable_sp->GetByteSize().value_or(0),
390aa88161bSKazu Hirata err);
3912d37e5a5SSean Callanan
392b9c1b51eSKate Stone if (!err.Success()) {
3932d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
394b9c1b51eSKate Stone } else {
39529cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
39629cb868aSZachary Turner target_address);
39714b1bae5SSean Callanan
39814b1bae5SSean Callanan dump_stream.PutChar('\n');
3992d37e5a5SSean Callanan }
4002d37e5a5SSean Callanan }
4012d37e5a5SSean Callanan }
4022d37e5a5SSean Callanan
403c156427dSZachary Turner log->PutString(dump_stream.GetString());
4042d37e5a5SSean Callanan }
4052d37e5a5SSean Callanan
Wipe(IRMemoryMap & map,lldb::addr_t process_address)406b9c1b51eSKate Stone void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
407315b6884SEugene Zelenko
40896d2730aSSean Callanan private:
409bc8ac34eSSean Callanan lldb::ExpressionVariableSP m_persistent_variable_sp;
4109fda9d21SSean Callanan Materializer::PersistentVariableDelegate *m_delegate;
41196d2730aSSean Callanan };
41296d2730aSSean Callanan
AddPersistentVariable(lldb::ExpressionVariableSP & persistent_variable_sp,PersistentVariableDelegate * delegate,Status & err)413b9c1b51eSKate Stone uint32_t Materializer::AddPersistentVariable(
414b9c1b51eSKate Stone lldb::ExpressionVariableSP &persistent_variable_sp,
41597206d57SZachary Turner PersistentVariableDelegate *delegate, Status &err) {
41696d2730aSSean Callanan EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
41706412daeSJonas Devlieghere *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
41806412daeSJonas Devlieghere delegate);
41996d2730aSSean Callanan uint32_t ret = AddStructMember(**iter);
42096d2730aSSean Callanan (*iter)->SetOffset(ret);
42196d2730aSSean Callanan return ret;
42296d2730aSSean Callanan }
42396d2730aSSean Callanan
424*317c8bf8SMichael Buch /// Base class for materialization of Variables and ValueObjects.
425*317c8bf8SMichael Buch ///
426*317c8bf8SMichael Buch /// Subclasses specify how to obtain the Value which is to be
427*317c8bf8SMichael Buch /// materialized.
428*317c8bf8SMichael Buch class EntityVariableBase : public Materializer::Entity {
42996d2730aSSean Callanan public:
430*317c8bf8SMichael Buch virtual ~EntityVariableBase() = default;
431*317c8bf8SMichael Buch
EntityVariableBase()432*317c8bf8SMichael Buch EntityVariableBase() {
433b9c1b51eSKate Stone // Hard-coding to maximum size of a pointer since all variables are
434b9c1b51eSKate Stone // materialized by reference
435fcf4e252SMichael Buch m_size = g_default_var_byte_size;
436fcf4e252SMichael Buch m_alignment = g_default_var_alignment;
43796d2730aSSean Callanan }
43896d2730aSSean Callanan
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)439b9c1b51eSKate Stone void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
44097206d57SZachary Turner lldb::addr_t process_address, Status &err) override {
441a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
442f8043fa5SSean Callanan
44357ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
444b9c1b51eSKate Stone if (log) {
44563e5fb76SJonas Devlieghere LLDB_LOGF(log,
44663e5fb76SJonas Devlieghere "EntityVariable::Materialize [address = 0x%" PRIx64
447b9c1b51eSKate Stone ", m_variable_sp = %s]",
448*317c8bf8SMichael Buch (uint64_t)load_addr, GetName().GetCString());
449f8043fa5SSean Callanan }
450f8043fa5SSean Callanan
451b024d878SSean Callanan ExecutionContextScope *scope = frame_sp.get();
452b024d878SSean Callanan
453b024d878SSean Callanan if (!scope)
454b024d878SSean Callanan scope = map.GetBestExecutionContextScope();
455b024d878SSean Callanan
456*317c8bf8SMichael Buch lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
457f8043fa5SSean Callanan
458b9c1b51eSKate Stone if (!valobj_sp) {
459b9c1b51eSKate Stone err.SetErrorStringWithFormat(
460*317c8bf8SMichael Buch "couldn't get a value object for variable %s", GetName().AsCString());
461f8043fa5SSean Callanan return;
462f8043fa5SSean Callanan }
463f8043fa5SSean Callanan
46497206d57SZachary Turner Status valobj_error = valobj_sp->GetError();
465866e91c9SSean Callanan
466b9c1b51eSKate Stone if (valobj_error.Fail()) {
467b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
468*317c8bf8SMichael Buch GetName().AsCString(),
469b9c1b51eSKate Stone valobj_error.AsCString());
470866e91c9SSean Callanan return;
471866e91c9SSean Callanan }
472866e91c9SSean Callanan
473b9c1b51eSKate Stone if (m_is_reference) {
474f8043fa5SSean Callanan DataExtractor valobj_extractor;
47597206d57SZachary Turner Status extract_error;
476866e91c9SSean Callanan valobj_sp->GetData(valobj_extractor, extract_error);
477866e91c9SSean Callanan
478b9c1b51eSKate Stone if (!extract_error.Success()) {
479b9c1b51eSKate Stone err.SetErrorStringWithFormat(
480b9c1b51eSKate Stone "couldn't read contents of reference variable %s: %s",
481*317c8bf8SMichael Buch GetName().AsCString(), extract_error.AsCString());
482866e91c9SSean Callanan return;
483866e91c9SSean Callanan }
484866e91c9SSean Callanan
485f8043fa5SSean Callanan lldb::offset_t offset = 0;
486f8043fa5SSean Callanan lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
487f8043fa5SSean Callanan
48897206d57SZachary Turner Status write_error;
48957ee3067SGreg Clayton map.WritePointerToMemory(load_addr, reference_addr, write_error);
490f8043fa5SSean Callanan
491b9c1b51eSKate Stone if (!write_error.Success()) {
492b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't write the contents of reference "
493b9c1b51eSKate Stone "variable %s to memory: %s",
494*317c8bf8SMichael Buch GetName().AsCString(),
495b9c1b51eSKate Stone write_error.AsCString());
496f8043fa5SSean Callanan return;
497f8043fa5SSean Callanan }
498b9c1b51eSKate Stone } else {
49965b320f7SSean Callanan AddressType address_type = eAddressTypeInvalid;
50065b320f7SSean Callanan const bool scalar_is_load_address = false;
501b9c1b51eSKate Stone lldb::addr_t addr_of_valobj =
502b9c1b51eSKate Stone valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
503b9c1b51eSKate Stone if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
50497206d57SZachary Turner Status write_error;
50513b4ef2dSSean Callanan map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
506f8043fa5SSean Callanan
507b9c1b51eSKate Stone if (!write_error.Success()) {
508b9c1b51eSKate Stone err.SetErrorStringWithFormat(
509b9c1b51eSKate Stone "couldn't write the address of variable %s to memory: %s",
510*317c8bf8SMichael Buch GetName().AsCString(), write_error.AsCString());
511f8043fa5SSean Callanan return;
512f8043fa5SSean Callanan }
513b9c1b51eSKate Stone } else {
514f8043fa5SSean Callanan DataExtractor data;
51597206d57SZachary Turner Status extract_error;
516866e91c9SSean Callanan valobj_sp->GetData(data, extract_error);
517b9c1b51eSKate Stone if (!extract_error.Success()) {
518b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
519*317c8bf8SMichael Buch GetName().AsCString(),
520b9c1b51eSKate Stone extract_error.AsCString());
521b9c1b51eSKate Stone return;
522b9c1b51eSKate Stone }
523b9c1b51eSKate Stone
524b9c1b51eSKate Stone if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
525b9c1b51eSKate Stone err.SetErrorStringWithFormat(
526b9c1b51eSKate Stone "trying to create a temporary region for %s but one exists",
527*317c8bf8SMichael Buch GetName().AsCString());
528b9c1b51eSKate Stone return;
529b9c1b51eSKate Stone }
530b9c1b51eSKate Stone
531*317c8bf8SMichael Buch if (data.GetByteSize() < GetByteSize(scope)) {
532*317c8bf8SMichael Buch if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
533b9c1b51eSKate Stone err.SetErrorStringWithFormat("the variable '%s' has no location, "
534b9c1b51eSKate Stone "it may have been optimized out",
535*317c8bf8SMichael Buch GetName().AsCString());
536b9c1b51eSKate Stone } else {
537b9c1b51eSKate Stone err.SetErrorStringWithFormat(
538b9c1b51eSKate Stone "size of variable %s (%" PRIu64
539b9c1b51eSKate Stone ") is larger than the ValueObject's size (%" PRIu64 ")",
540*317c8bf8SMichael Buch GetName().AsCString(), GetByteSize(scope).value_or(0),
541d13777aaSAdrian Prantl data.GetByteSize());
5429e9f219aSGreg Clayton }
543f8043fa5SSean Callanan return;
544f8043fa5SSean Callanan }
545f8043fa5SSean Callanan
546*317c8bf8SMichael Buch llvm::Optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
54736f13e49SDavide Italiano if (!opt_bit_align) {
54836f13e49SDavide Italiano err.SetErrorStringWithFormat("can't get the type alignment for %s",
549*317c8bf8SMichael Buch GetName().AsCString());
55036f13e49SDavide Italiano return;
55136f13e49SDavide Italiano }
552f8043fa5SSean Callanan
55336f13e49SDavide Italiano size_t byte_align = (*opt_bit_align + 7) / 8;
55422ac610cSSean Callanan
55597206d57SZachary Turner Status alloc_error;
5562c381414SJim Ingham const bool zero_memory = false;
557f8043fa5SSean Callanan
558b9c1b51eSKate Stone m_temporary_allocation = map.Malloc(
559b9c1b51eSKate Stone data.GetByteSize(), byte_align,
5602c381414SJim Ingham lldb::ePermissionsReadable | lldb::ePermissionsWritable,
561b9c1b51eSKate Stone IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
5622c381414SJim Ingham
5632d37e5a5SSean Callanan m_temporary_allocation_size = data.GetByteSize();
564f8043fa5SSean Callanan
565796ac80bSJonas Devlieghere m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
566796ac80bSJonas Devlieghere data.GetByteSize());
567c4ca2c1dSSean Callanan
568b9c1b51eSKate Stone if (!alloc_error.Success()) {
569b9c1b51eSKate Stone err.SetErrorStringWithFormat(
570b9c1b51eSKate Stone "couldn't allocate a temporary region for %s: %s",
571*317c8bf8SMichael Buch GetName().AsCString(), alloc_error.AsCString());
572f8043fa5SSean Callanan return;
573f8043fa5SSean Callanan }
574f8043fa5SSean Callanan
57597206d57SZachary Turner Status write_error;
576f8043fa5SSean Callanan
577b9c1b51eSKate Stone map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
578b9c1b51eSKate Stone data.GetByteSize(), write_error);
579f8043fa5SSean Callanan
580b9c1b51eSKate Stone if (!write_error.Success()) {
581b9c1b51eSKate Stone err.SetErrorStringWithFormat(
582b9c1b51eSKate Stone "couldn't write to the temporary region for %s: %s",
583*317c8bf8SMichael Buch GetName().AsCString(), write_error.AsCString());
584f8043fa5SSean Callanan return;
585f8043fa5SSean Callanan }
586f8043fa5SSean Callanan
58797206d57SZachary Turner Status pointer_write_error;
588f8043fa5SSean Callanan
589b9c1b51eSKate Stone map.WritePointerToMemory(load_addr, m_temporary_allocation,
590b9c1b51eSKate Stone pointer_write_error);
591f8043fa5SSean Callanan
592b9c1b51eSKate Stone if (!pointer_write_error.Success()) {
593b9c1b51eSKate Stone err.SetErrorStringWithFormat(
594b9c1b51eSKate Stone "couldn't write the address of the temporary region for %s: %s",
595*317c8bf8SMichael Buch GetName().AsCString(), pointer_write_error.AsCString());
596f8043fa5SSean Callanan }
597f8043fa5SSean Callanan }
598f8043fa5SSean Callanan }
59996d2730aSSean Callanan }
60096d2730aSSean Callanan
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)601b9c1b51eSKate Stone void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
602b9c1b51eSKate Stone lldb::addr_t process_address, lldb::addr_t frame_top,
60397206d57SZachary Turner lldb::addr_t frame_bottom, Status &err) override {
604a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
605f8043fa5SSean Callanan
60657ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
607b9c1b51eSKate Stone if (log) {
60863e5fb76SJonas Devlieghere LLDB_LOGF(log,
60963e5fb76SJonas Devlieghere "EntityVariable::Dematerialize [address = 0x%" PRIx64
610b9c1b51eSKate Stone ", m_variable_sp = %s]",
611*317c8bf8SMichael Buch (uint64_t)load_addr, GetName().AsCString());
612f8043fa5SSean Callanan }
613f8043fa5SSean Callanan
614b9c1b51eSKate Stone if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
615b024d878SSean Callanan ExecutionContextScope *scope = frame_sp.get();
616b024d878SSean Callanan
617b024d878SSean Callanan if (!scope)
618b024d878SSean Callanan scope = map.GetBestExecutionContextScope();
619b024d878SSean Callanan
620*317c8bf8SMichael Buch lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
621f8043fa5SSean Callanan
622b9c1b51eSKate Stone if (!valobj_sp) {
623b9c1b51eSKate Stone err.SetErrorStringWithFormat(
624b9c1b51eSKate Stone "couldn't get a value object for variable %s",
625*317c8bf8SMichael Buch GetName().AsCString());
626f8043fa5SSean Callanan return;
627f8043fa5SSean Callanan }
628f8043fa5SSean Callanan
629458ae1c6SSean Callanan lldb_private::DataExtractor data;
630458ae1c6SSean Callanan
63197206d57SZachary Turner Status extract_error;
632458ae1c6SSean Callanan
633113f56fbSAdrian Prantl map.GetMemoryData(data, m_temporary_allocation,
634aa88161bSKazu Hirata valobj_sp->GetByteSize().value_or(0), extract_error);
635458ae1c6SSean Callanan
636b9c1b51eSKate Stone if (!extract_error.Success()) {
637b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't get the data for variable %s",
638*317c8bf8SMichael Buch GetName().AsCString());
639458ae1c6SSean Callanan return;
640458ae1c6SSean Callanan }
641458ae1c6SSean Callanan
642c4ca2c1dSSean Callanan bool actually_write = true;
643c4ca2c1dSSean Callanan
644b9c1b51eSKate Stone if (m_original_data) {
645c4ca2c1dSSean Callanan if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
646b9c1b51eSKate Stone !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
647b9c1b51eSKate Stone data.GetByteSize())) {
648c4ca2c1dSSean Callanan actually_write = false;
649c4ca2c1dSSean Callanan }
650c4ca2c1dSSean Callanan }
651c4ca2c1dSSean Callanan
65297206d57SZachary Turner Status set_error;
653458ae1c6SSean Callanan
654b9c1b51eSKate Stone if (actually_write) {
655458ae1c6SSean Callanan valobj_sp->SetData(data, set_error);
656458ae1c6SSean Callanan
657b9c1b51eSKate Stone if (!set_error.Success()) {
658b9c1b51eSKate Stone err.SetErrorStringWithFormat(
659b9c1b51eSKate Stone "couldn't write the new contents of %s back into the variable",
660*317c8bf8SMichael Buch GetName().AsCString());
661458ae1c6SSean Callanan return;
662458ae1c6SSean Callanan }
663c4ca2c1dSSean Callanan }
664f8043fa5SSean Callanan
66597206d57SZachary Turner Status free_error;
666f8043fa5SSean Callanan
667f8043fa5SSean Callanan map.Free(m_temporary_allocation, free_error);
668f8043fa5SSean Callanan
669b9c1b51eSKate Stone if (!free_error.Success()) {
670b9c1b51eSKate Stone err.SetErrorStringWithFormat(
671b9c1b51eSKate Stone "couldn't free the temporary region for %s: %s",
672*317c8bf8SMichael Buch GetName().AsCString(), free_error.AsCString());
673f8043fa5SSean Callanan return;
674f8043fa5SSean Callanan }
675f8043fa5SSean Callanan
676c4ca2c1dSSean Callanan m_original_data.reset();
677f8043fa5SSean Callanan m_temporary_allocation = LLDB_INVALID_ADDRESS;
6782d37e5a5SSean Callanan m_temporary_allocation_size = 0;
679f8043fa5SSean Callanan }
68096d2730aSSean Callanan }
6812d37e5a5SSean Callanan
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)682b9c1b51eSKate Stone void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
683b9c1b51eSKate Stone Log *log) override {
6842d37e5a5SSean Callanan StreamString dump_stream;
6852d37e5a5SSean Callanan
68657ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
68757ee3067SGreg Clayton dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
6881582ee68SSean Callanan
68997206d57SZachary Turner Status err;
6902d37e5a5SSean Callanan
6911582ee68SSean Callanan lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
6922d37e5a5SSean Callanan
6932d37e5a5SSean Callanan {
6942d37e5a5SSean Callanan dump_stream.Printf("Pointer:\n");
6952d37e5a5SSean Callanan
6962d37e5a5SSean Callanan DataBufferHeap data(m_size, 0);
6972d37e5a5SSean Callanan
69857ee3067SGreg Clayton map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
6992d37e5a5SSean Callanan
700b9c1b51eSKate Stone if (!err.Success()) {
7012d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
702b9c1b51eSKate Stone } else {
703b9c1b51eSKate Stone DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
704b9c1b51eSKate Stone map.GetByteOrder(), map.GetAddressByteSize());
7052d37e5a5SSean Callanan
70629cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
70729cb868aSZachary Turner load_addr);
70814b1bae5SSean Callanan
709dcd0926aSPavel Labath lldb::offset_t offset = 0;
7101582ee68SSean Callanan
7110863f675SPavel Labath ptr = extractor.GetAddress(&offset);
7121582ee68SSean Callanan
71314b1bae5SSean Callanan dump_stream.PutChar('\n');
7142d37e5a5SSean Callanan }
7152d37e5a5SSean Callanan }
7162d37e5a5SSean Callanan
717b9c1b51eSKate Stone if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
7181582ee68SSean Callanan dump_stream.Printf("Points to process memory:\n");
719b9c1b51eSKate Stone } else {
7202d37e5a5SSean Callanan dump_stream.Printf("Temporary allocation:\n");
7211582ee68SSean Callanan }
7222d37e5a5SSean Callanan
723b9c1b51eSKate Stone if (ptr == LLDB_INVALID_ADDRESS) {
7241582ee68SSean Callanan dump_stream.Printf(" <could not be be found>\n");
725b9c1b51eSKate Stone } else {
7262d37e5a5SSean Callanan DataBufferHeap data(m_temporary_allocation_size, 0);
7272d37e5a5SSean Callanan
728b9c1b51eSKate Stone map.ReadMemory(data.GetBytes(), m_temporary_allocation,
729b9c1b51eSKate Stone m_temporary_allocation_size, err);
7302d37e5a5SSean Callanan
731b9c1b51eSKate Stone if (!err.Success()) {
7322d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
733b9c1b51eSKate Stone } else {
73429cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
73529cb868aSZachary Turner load_addr);
73614b1bae5SSean Callanan
73714b1bae5SSean Callanan dump_stream.PutChar('\n');
7382d37e5a5SSean Callanan }
7392d37e5a5SSean Callanan }
7402d37e5a5SSean Callanan
741c156427dSZachary Turner log->PutString(dump_stream.GetString());
7422d37e5a5SSean Callanan }
74314b1bae5SSean Callanan
Wipe(IRMemoryMap & map,lldb::addr_t process_address)744b9c1b51eSKate Stone void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
745b9c1b51eSKate Stone if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
74697206d57SZachary Turner Status free_error;
74714b1bae5SSean Callanan
74814b1bae5SSean Callanan map.Free(m_temporary_allocation, free_error);
74914b1bae5SSean Callanan
75014b1bae5SSean Callanan m_temporary_allocation = LLDB_INVALID_ADDRESS;
75114b1bae5SSean Callanan m_temporary_allocation_size = 0;
75214b1bae5SSean Callanan }
75314b1bae5SSean Callanan }
754315b6884SEugene Zelenko
75596d2730aSSean Callanan private:
756*317c8bf8SMichael Buch virtual ConstString GetName() const = 0;
757*317c8bf8SMichael Buch
758*317c8bf8SMichael Buch /// Creates and returns ValueObject tied to this variable
759*317c8bf8SMichael Buch /// and prepares Entity for materialization.
760*317c8bf8SMichael Buch ///
761*317c8bf8SMichael Buch /// Called each time the Materializer (de)materializes a
762*317c8bf8SMichael Buch /// variable. We re-create the ValueObject based on the
763*317c8bf8SMichael Buch /// current ExecutionContextScope since clients such as
764*317c8bf8SMichael Buch /// conditional breakpoints may materialize the same
765*317c8bf8SMichael Buch /// EntityVariable multiple times with different frames.
766*317c8bf8SMichael Buch ///
767*317c8bf8SMichael Buch /// Each subsequent use of the EntityVariableBase interface
768*317c8bf8SMichael Buch /// will query the newly created ValueObject until this
769*317c8bf8SMichael Buch /// function is called again.
770*317c8bf8SMichael Buch virtual lldb::ValueObjectSP
771*317c8bf8SMichael Buch SetupValueObject(ExecutionContextScope *scope) = 0;
772*317c8bf8SMichael Buch
773*317c8bf8SMichael Buch /// Returns size in bytes of the type associated with this variable
774*317c8bf8SMichael Buch ///
775*317c8bf8SMichael Buch /// \returns On success, returns byte size of the type associated
776*317c8bf8SMichael Buch /// with this variable. Returns NoneType otherwise.
777*317c8bf8SMichael Buch virtual llvm::Optional<uint64_t>
778*317c8bf8SMichael Buch GetByteSize(ExecutionContextScope *scope) const = 0;
779*317c8bf8SMichael Buch
780*317c8bf8SMichael Buch /// Returns 'true' if the location expression associated with this variable
781*317c8bf8SMichael Buch /// is valid.
782*317c8bf8SMichael Buch virtual bool LocationExpressionIsValid() const = 0;
783*317c8bf8SMichael Buch
784*317c8bf8SMichael Buch /// Returns alignment of the type associated with this variable in bits.
785*317c8bf8SMichael Buch ///
786*317c8bf8SMichael Buch /// \returns On success, returns alignment in bits for the type associated
787*317c8bf8SMichael Buch /// with this variable. Returns NoneType otherwise.
788*317c8bf8SMichael Buch virtual llvm::Optional<size_t>
789*317c8bf8SMichael Buch GetTypeBitAlign(ExecutionContextScope *scope) const = 0;
790*317c8bf8SMichael Buch
791*317c8bf8SMichael Buch protected:
79228c878aeSShafik Yaghmour bool m_is_reference = false;
79328c878aeSShafik Yaghmour lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
79428c878aeSShafik Yaghmour size_t m_temporary_allocation_size = 0;
795c4ca2c1dSSean Callanan lldb::DataBufferSP m_original_data;
79696d2730aSSean Callanan };
79796d2730aSSean Callanan
798*317c8bf8SMichael Buch /// Represents an Entity constructed from a VariableSP.
799*317c8bf8SMichael Buch ///
800*317c8bf8SMichael Buch /// This class is used for materialization of variables for which
801*317c8bf8SMichael Buch /// the user has a VariableSP on hand. The ValueObject is then
802*317c8bf8SMichael Buch /// derived from the associated DWARF location expression when needed
803*317c8bf8SMichael Buch /// by the Materializer.
804*317c8bf8SMichael Buch class EntityVariable : public EntityVariableBase {
805*317c8bf8SMichael Buch public:
EntityVariable(lldb::VariableSP & variable_sp)806*317c8bf8SMichael Buch EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
807*317c8bf8SMichael Buch m_is_reference =
808*317c8bf8SMichael Buch m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
809*317c8bf8SMichael Buch }
810*317c8bf8SMichael Buch
GetName() const811*317c8bf8SMichael Buch ConstString GetName() const override { return m_variable_sp->GetName(); }
812*317c8bf8SMichael Buch
SetupValueObject(ExecutionContextScope * scope)813*317c8bf8SMichael Buch lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
814*317c8bf8SMichael Buch assert(m_variable_sp != nullptr);
815*317c8bf8SMichael Buch return ValueObjectVariable::Create(scope, m_variable_sp);
816*317c8bf8SMichael Buch }
817*317c8bf8SMichael Buch
818*317c8bf8SMichael Buch llvm::Optional<uint64_t>
GetByteSize(ExecutionContextScope * scope) const819*317c8bf8SMichael Buch GetByteSize(ExecutionContextScope *scope) const override {
820*317c8bf8SMichael Buch return m_variable_sp->GetType()->GetByteSize(scope);
821*317c8bf8SMichael Buch }
822*317c8bf8SMichael Buch
LocationExpressionIsValid() const823*317c8bf8SMichael Buch bool LocationExpressionIsValid() const override {
824*317c8bf8SMichael Buch return m_variable_sp->LocationExpressionList().IsValid();
825*317c8bf8SMichael Buch }
826*317c8bf8SMichael Buch
827*317c8bf8SMichael Buch llvm::Optional<size_t>
GetTypeBitAlign(ExecutionContextScope * scope) const828*317c8bf8SMichael Buch GetTypeBitAlign(ExecutionContextScope *scope) const override {
829*317c8bf8SMichael Buch return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
830*317c8bf8SMichael Buch scope);
831*317c8bf8SMichael Buch }
832*317c8bf8SMichael Buch
833*317c8bf8SMichael Buch private:
834*317c8bf8SMichael Buch lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
835*317c8bf8SMichael Buch };
836*317c8bf8SMichael Buch
837*317c8bf8SMichael Buch /// Represents an Entity constructed from a VariableSP.
838*317c8bf8SMichael Buch ///
839*317c8bf8SMichael Buch /// This class is used for materialization of variables for
840*317c8bf8SMichael Buch /// which the user does not have a VariableSP available (e.g.,
841*317c8bf8SMichael Buch /// when materializing ivars).
842*317c8bf8SMichael Buch class EntityValueObject : public EntityVariableBase {
843*317c8bf8SMichael Buch public:
EntityValueObject(ConstString name,ValueObjectProviderTy provider)844*317c8bf8SMichael Buch EntityValueObject(ConstString name, ValueObjectProviderTy provider)
845*317c8bf8SMichael Buch : m_name(name), m_valobj_provider(std::move(provider)) {
846*317c8bf8SMichael Buch assert(m_valobj_provider);
847*317c8bf8SMichael Buch }
848*317c8bf8SMichael Buch
GetName() const849*317c8bf8SMichael Buch ConstString GetName() const override { return m_name; }
850*317c8bf8SMichael Buch
SetupValueObject(ExecutionContextScope * scope)851*317c8bf8SMichael Buch lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
852*317c8bf8SMichael Buch m_valobj_sp =
853*317c8bf8SMichael Buch m_valobj_provider(GetName(), scope->CalculateStackFrame().get());
854*317c8bf8SMichael Buch
855*317c8bf8SMichael Buch if (m_valobj_sp)
856*317c8bf8SMichael Buch m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();
857*317c8bf8SMichael Buch
858*317c8bf8SMichael Buch return m_valobj_sp;
859*317c8bf8SMichael Buch }
860*317c8bf8SMichael Buch
861*317c8bf8SMichael Buch llvm::Optional<uint64_t>
GetByteSize(ExecutionContextScope * scope) const862*317c8bf8SMichael Buch GetByteSize(ExecutionContextScope *scope) const override {
863*317c8bf8SMichael Buch if (m_valobj_sp)
864*317c8bf8SMichael Buch return m_valobj_sp->GetCompilerType().GetByteSize(scope);
865*317c8bf8SMichael Buch
866*317c8bf8SMichael Buch return {};
867*317c8bf8SMichael Buch }
868*317c8bf8SMichael Buch
LocationExpressionIsValid() const869*317c8bf8SMichael Buch bool LocationExpressionIsValid() const override {
870*317c8bf8SMichael Buch if (m_valobj_sp)
871*317c8bf8SMichael Buch return m_valobj_sp->GetError().Success();
872*317c8bf8SMichael Buch
873*317c8bf8SMichael Buch return false;
874*317c8bf8SMichael Buch }
875*317c8bf8SMichael Buch
876*317c8bf8SMichael Buch llvm::Optional<size_t>
GetTypeBitAlign(ExecutionContextScope * scope) const877*317c8bf8SMichael Buch GetTypeBitAlign(ExecutionContextScope *scope) const override {
878*317c8bf8SMichael Buch if (m_valobj_sp)
879*317c8bf8SMichael Buch return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);
880*317c8bf8SMichael Buch
881*317c8bf8SMichael Buch return {};
882*317c8bf8SMichael Buch }
883*317c8bf8SMichael Buch
884*317c8bf8SMichael Buch private:
885*317c8bf8SMichael Buch ConstString m_name;
886*317c8bf8SMichael Buch lldb::ValueObjectSP m_valobj_sp;
887*317c8bf8SMichael Buch ValueObjectProviderTy m_valobj_provider;
888*317c8bf8SMichael Buch };
889*317c8bf8SMichael Buch
AddVariable(lldb::VariableSP & variable_sp,Status & err)89097206d57SZachary Turner uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) {
89196d2730aSSean Callanan EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
89206412daeSJonas Devlieghere *iter = std::make_unique<EntityVariable>(variable_sp);
89396d2730aSSean Callanan uint32_t ret = AddStructMember(**iter);
89496d2730aSSean Callanan (*iter)->SetOffset(ret);
89596d2730aSSean Callanan return ret;
89696d2730aSSean Callanan }
89796d2730aSSean Callanan
AddValueObject(ConstString name,ValueObjectProviderTy valobj_provider,Status & err)898*317c8bf8SMichael Buch uint32_t Materializer::AddValueObject(ConstString name,
899*317c8bf8SMichael Buch ValueObjectProviderTy valobj_provider,
900*317c8bf8SMichael Buch Status &err) {
901*317c8bf8SMichael Buch assert(valobj_provider);
902*317c8bf8SMichael Buch EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
903*317c8bf8SMichael Buch *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
904*317c8bf8SMichael Buch uint32_t ret = AddStructMember(**iter);
905*317c8bf8SMichael Buch (*iter)->SetOffset(ret);
906*317c8bf8SMichael Buch return ret;
907*317c8bf8SMichael Buch }
908*317c8bf8SMichael Buch
909b9c1b51eSKate Stone class EntityResultVariable : public Materializer::Entity {
91096d2730aSSean Callanan public:
EntityResultVariable(const CompilerType & type,bool is_program_reference,bool keep_in_memory,Materializer::PersistentVariableDelegate * delegate)911b9c1b51eSKate Stone EntityResultVariable(const CompilerType &type, bool is_program_reference,
9129fda9d21SSean Callanan bool keep_in_memory,
913b9c1b51eSKate Stone Materializer::PersistentVariableDelegate *delegate)
914b9c1b51eSKate Stone : Entity(), m_type(type), m_is_program_reference(is_program_reference),
91528c878aeSShafik Yaghmour m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
916b9c1b51eSKate Stone // Hard-coding to maximum size of a pointer since all results are
917b9c1b51eSKate Stone // materialized by reference
918fcf4e252SMichael Buch m_size = g_default_var_byte_size;
919fcf4e252SMichael Buch m_alignment = g_default_var_alignment;
92096d2730aSSean Callanan }
92196d2730aSSean Callanan
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)922b9c1b51eSKate Stone void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
92397206d57SZachary Turner lldb::addr_t process_address, Status &err) override {
924b9c1b51eSKate Stone if (!m_is_program_reference) {
925b9c1b51eSKate Stone if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
926b9c1b51eSKate Stone err.SetErrorString("Trying to create a temporary region for the result "
927b9c1b51eSKate Stone "but one exists");
9281582ee68SSean Callanan return;
9291582ee68SSean Callanan }
9301582ee68SSean Callanan
93157ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
93257ee3067SGreg Clayton
9333728133dSAdrian Prantl ExecutionContextScope *exe_scope = frame_sp.get();
9343728133dSAdrian Prantl if (!exe_scope)
9353728133dSAdrian Prantl exe_scope = map.GetBestExecutionContextScope();
936799a3fc6SSean Callanan
937d6a9bbf6SAdrian Prantl llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
938d963a7c3SAdrian Prantl if (!byte_size) {
9398fb53dcaSAdrian Prantl err.SetErrorStringWithFormat("can't get size of type \"%s\"",
9408fb53dcaSAdrian Prantl m_type.GetTypeName().AsCString());
941d963a7c3SAdrian Prantl return;
942d963a7c3SAdrian Prantl }
9431582ee68SSean Callanan
9447f9bbe05SDavide Italiano llvm::Optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
94536f13e49SDavide Italiano if (!opt_bit_align) {
9468fb53dcaSAdrian Prantl err.SetErrorStringWithFormat("can't get the alignment of type \"%s\"",
9478fb53dcaSAdrian Prantl m_type.GetTypeName().AsCString());
94836f13e49SDavide Italiano return;
94936f13e49SDavide Italiano }
95036f13e49SDavide Italiano
95136f13e49SDavide Italiano size_t byte_align = (*opt_bit_align + 7) / 8;
95222ac610cSSean Callanan
95397206d57SZachary Turner Status alloc_error;
9542c381414SJim Ingham const bool zero_memory = true;
9551582ee68SSean Callanan
956b9c1b51eSKate Stone m_temporary_allocation = map.Malloc(
957d963a7c3SAdrian Prantl *byte_size, byte_align,
9582c381414SJim Ingham lldb::ePermissionsReadable | lldb::ePermissionsWritable,
959b9c1b51eSKate Stone IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
960d963a7c3SAdrian Prantl m_temporary_allocation_size = *byte_size;
9611582ee68SSean Callanan
962b9c1b51eSKate Stone if (!alloc_error.Success()) {
963b9c1b51eSKate Stone err.SetErrorStringWithFormat(
964b9c1b51eSKate Stone "couldn't allocate a temporary region for the result: %s",
965b9c1b51eSKate Stone alloc_error.AsCString());
9661582ee68SSean Callanan return;
9671582ee68SSean Callanan }
9681582ee68SSean Callanan
96997206d57SZachary Turner Status pointer_write_error;
9701582ee68SSean Callanan
971b9c1b51eSKate Stone map.WritePointerToMemory(load_addr, m_temporary_allocation,
972b9c1b51eSKate Stone pointer_write_error);
9731582ee68SSean Callanan
974b9c1b51eSKate Stone if (!pointer_write_error.Success()) {
975b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't write the address of the "
976b9c1b51eSKate Stone "temporary region for the result: %s",
977b9c1b51eSKate Stone pointer_write_error.AsCString());
9781582ee68SSean Callanan }
9791582ee68SSean Callanan }
98096d2730aSSean Callanan }
98196d2730aSSean Callanan
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)982b9c1b51eSKate Stone void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
983b9c1b51eSKate Stone lldb::addr_t process_address, lldb::addr_t frame_top,
98497206d57SZachary Turner lldb::addr_t frame_bottom, Status &err) override {
9851582ee68SSean Callanan err.Clear();
9861582ee68SSean Callanan
9873728133dSAdrian Prantl ExecutionContextScope *exe_scope = frame_sp.get();
9883728133dSAdrian Prantl if (!exe_scope)
9893728133dSAdrian Prantl exe_scope = map.GetBestExecutionContextScope();
9901582ee68SSean Callanan
991b9c1b51eSKate Stone if (!exe_scope) {
992b9c1b51eSKate Stone err.SetErrorString("Couldn't dematerialize a result variable: invalid "
993b9c1b51eSKate Stone "execution context scope");
9941582ee68SSean Callanan return;
9951582ee68SSean Callanan }
9961582ee68SSean Callanan
9971582ee68SSean Callanan lldb::addr_t address;
99897206d57SZachary Turner Status read_error;
99957ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
10001582ee68SSean Callanan
100157ee3067SGreg Clayton map.ReadPointerFromMemory(&address, load_addr, read_error);
10021582ee68SSean Callanan
1003b9c1b51eSKate Stone if (!read_error.Success()) {
1004b9c1b51eSKate Stone err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
1005b9c1b51eSKate Stone "read its address");
10061582ee68SSean Callanan return;
10071582ee68SSean Callanan }
10081582ee68SSean Callanan
10091582ee68SSean Callanan lldb::TargetSP target_sp = exe_scope->CalculateTarget();
10101582ee68SSean Callanan
1011b9c1b51eSKate Stone if (!target_sp) {
10121582ee68SSean Callanan err.SetErrorString("Couldn't dematerialize a result variable: no target");
10131582ee68SSean Callanan return;
10141582ee68SSean Callanan }
10151582ee68SSean Callanan
10160e252e38SAlex Langford auto type_system_or_err =
10170e252e38SAlex Langford target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());
10181582ee68SSean Callanan
10190e252e38SAlex Langford if (auto error = type_system_or_err.takeError()) {
1020b9c1b51eSKate Stone err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
1021b9c1b51eSKate Stone "couldn't get the corresponding type "
1022b9c1b51eSKate Stone "system: %s",
10230e252e38SAlex Langford llvm::toString(std::move(error)).c_str());
10248f1f9a1bSSean Callanan return;
10258f1f9a1bSSean Callanan }
1026b9c1b51eSKate Stone PersistentExpressionState *persistent_state =
10270e252e38SAlex Langford type_system_or_err->GetPersistentExpressionState();
10288f1f9a1bSSean Callanan
1029b9c1b51eSKate Stone if (!persistent_state) {
1030b9c1b51eSKate Stone err.SetErrorString("Couldn't dematerialize a result variable: "
1031b9c1b51eSKate Stone "corresponding type system doesn't handle persistent "
1032b9c1b51eSKate Stone "variables");
10338f1f9a1bSSean Callanan return;
10348f1f9a1bSSean Callanan }
10358f1f9a1bSSean Callanan
103667d67ebeSJim Ingham ConstString name = m_delegate
1037b9c1b51eSKate Stone ? m_delegate->GetName()
103867d67ebeSJim Ingham : persistent_state->GetNextPersistentVariableName();
10398f1f9a1bSSean Callanan
1040b9c1b51eSKate Stone lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
1041b9c1b51eSKate Stone exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
10421582ee68SSean Callanan
1043b9c1b51eSKate Stone if (!ret) {
1044b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
1045b9c1b51eSKate Stone "failed to make persistent variable %s",
1046b9c1b51eSKate Stone name.AsCString());
10471582ee68SSean Callanan return;
10481582ee68SSean Callanan }
10491582ee68SSean Callanan
1050b9c1b51eSKate Stone lldb::ProcessSP process_sp =
1051b9c1b51eSKate Stone map.GetBestExecutionContextScope()->CalculateProcess();
10522afbf444SSean Callanan
1053b9c1b51eSKate Stone if (m_delegate) {
10549fda9d21SSean Callanan m_delegate->DidDematerialize(ret);
10559fda9d21SSean Callanan }
10569fda9d21SSean Callanan
1057b9c1b51eSKate Stone bool can_persist =
1058b9c1b51eSKate Stone (m_is_program_reference && process_sp && process_sp->CanJIT() &&
1059b9c1b51eSKate Stone !(address >= frame_bottom && address < frame_top));
10602afbf444SSean Callanan
1061b9c1b51eSKate Stone if (can_persist && m_keep_in_memory) {
1062b9c1b51eSKate Stone ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
1063b9c1b51eSKate Stone address, eAddressTypeLoad,
10643e68903eSSean Callanan map.GetAddressByteSize());
10652afbf444SSean Callanan }
10661582ee68SSean Callanan
10671582ee68SSean Callanan ret->ValueUpdated();
10681582ee68SSean Callanan
1069aa88161bSKazu Hirata const size_t pvar_byte_size = ret->GetByteSize().value_or(0);
10701582ee68SSean Callanan uint8_t *pvar_data = ret->GetValueBytes();
10711582ee68SSean Callanan
10721582ee68SSean Callanan map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
10731582ee68SSean Callanan
1074b9c1b51eSKate Stone if (!read_error.Success()) {
1075b9c1b51eSKate Stone err.SetErrorString(
1076b9c1b51eSKate Stone "Couldn't dematerialize a result variable: couldn't read its memory");
10771582ee68SSean Callanan return;
10781582ee68SSean Callanan }
10791582ee68SSean Callanan
1080b9c1b51eSKate Stone if (!can_persist || !m_keep_in_memory) {
1081e6f4a826SSean Callanan ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
10821582ee68SSean Callanan
1083b9c1b51eSKate Stone if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
108497206d57SZachary Turner Status free_error;
10851582ee68SSean Callanan map.Free(m_temporary_allocation, free_error);
10861582ee68SSean Callanan }
1087b9c1b51eSKate Stone } else {
1088e6f4a826SSean Callanan ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
10891582ee68SSean Callanan }
10901582ee68SSean Callanan
10911582ee68SSean Callanan m_temporary_allocation = LLDB_INVALID_ADDRESS;
10921582ee68SSean Callanan m_temporary_allocation_size = 0;
109396d2730aSSean Callanan }
10942d37e5a5SSean Callanan
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)1095b9c1b51eSKate Stone void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1096b9c1b51eSKate Stone Log *log) override {
10972d37e5a5SSean Callanan StreamString dump_stream;
10982d37e5a5SSean Callanan
109957ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
110057ee3067SGreg Clayton
110157ee3067SGreg Clayton dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
11022d37e5a5SSean Callanan
110397206d57SZachary Turner Status err;
11041582ee68SSean Callanan
11051582ee68SSean Callanan lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
11061582ee68SSean Callanan
11071582ee68SSean Callanan {
11081582ee68SSean Callanan dump_stream.Printf("Pointer:\n");
11091582ee68SSean Callanan
11101582ee68SSean Callanan DataBufferHeap data(m_size, 0);
11111582ee68SSean Callanan
111257ee3067SGreg Clayton map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
11131582ee68SSean Callanan
1114b9c1b51eSKate Stone if (!err.Success()) {
11151582ee68SSean Callanan dump_stream.Printf(" <could not be read>\n");
1116b9c1b51eSKate Stone } else {
1117b9c1b51eSKate Stone DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
1118b9c1b51eSKate Stone map.GetByteOrder(), map.GetAddressByteSize());
11191582ee68SSean Callanan
112029cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
112129cb868aSZachary Turner load_addr);
11221582ee68SSean Callanan
1123dcd0926aSPavel Labath lldb::offset_t offset = 0;
11241582ee68SSean Callanan
11250863f675SPavel Labath ptr = extractor.GetAddress(&offset);
11261582ee68SSean Callanan
11271582ee68SSean Callanan dump_stream.PutChar('\n');
11281582ee68SSean Callanan }
11291582ee68SSean Callanan }
11301582ee68SSean Callanan
1131b9c1b51eSKate Stone if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
11321582ee68SSean Callanan dump_stream.Printf("Points to process memory:\n");
1133b9c1b51eSKate Stone } else {
11341582ee68SSean Callanan dump_stream.Printf("Temporary allocation:\n");
11351582ee68SSean Callanan }
11361582ee68SSean Callanan
1137b9c1b51eSKate Stone if (ptr == LLDB_INVALID_ADDRESS) {
11381582ee68SSean Callanan dump_stream.Printf(" <could not be be found>\n");
1139b9c1b51eSKate Stone } else {
11401582ee68SSean Callanan DataBufferHeap data(m_temporary_allocation_size, 0);
11411582ee68SSean Callanan
1142b9c1b51eSKate Stone map.ReadMemory(data.GetBytes(), m_temporary_allocation,
1143b9c1b51eSKate Stone m_temporary_allocation_size, err);
11441582ee68SSean Callanan
1145b9c1b51eSKate Stone if (!err.Success()) {
11461582ee68SSean Callanan dump_stream.Printf(" <could not be read>\n");
1147b9c1b51eSKate Stone } else {
114829cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
114929cb868aSZachary Turner load_addr);
11501582ee68SSean Callanan
11511582ee68SSean Callanan dump_stream.PutChar('\n');
11521582ee68SSean Callanan }
11531582ee68SSean Callanan }
11541582ee68SSean Callanan
1155c156427dSZachary Turner log->PutString(dump_stream.GetString());
11562d37e5a5SSean Callanan }
115714b1bae5SSean Callanan
Wipe(IRMemoryMap & map,lldb::addr_t process_address)1158b9c1b51eSKate Stone void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1159b9c1b51eSKate Stone if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
116097206d57SZachary Turner Status free_error;
11611582ee68SSean Callanan
11621582ee68SSean Callanan map.Free(m_temporary_allocation, free_error);
11631582ee68SSean Callanan }
11641582ee68SSean Callanan
11651582ee68SSean Callanan m_temporary_allocation = LLDB_INVALID_ADDRESS;
11661582ee68SSean Callanan m_temporary_allocation_size = 0;
116714b1bae5SSean Callanan }
1168315b6884SEugene Zelenko
116996d2730aSSean Callanan private:
1170e6f4a826SSean Callanan CompilerType m_type;
11711582ee68SSean Callanan bool m_is_program_reference;
117235005f76SSean Callanan bool m_keep_in_memory;
11731582ee68SSean Callanan
117428c878aeSShafik Yaghmour lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
117528c878aeSShafik Yaghmour size_t m_temporary_allocation_size = 0;
11769fda9d21SSean Callanan Materializer::PersistentVariableDelegate *m_delegate;
117796d2730aSSean Callanan };
117896d2730aSSean Callanan
AddResultVariable(const CompilerType & type,bool is_program_reference,bool keep_in_memory,PersistentVariableDelegate * delegate,Status & err)1179b9c1b51eSKate Stone uint32_t Materializer::AddResultVariable(const CompilerType &type,
11809fda9d21SSean Callanan bool is_program_reference,
11819fda9d21SSean Callanan bool keep_in_memory,
11829fda9d21SSean Callanan PersistentVariableDelegate *delegate,
118397206d57SZachary Turner Status &err) {
118496d2730aSSean Callanan EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
118506412daeSJonas Devlieghere *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
118606412daeSJonas Devlieghere keep_in_memory, delegate);
118796d2730aSSean Callanan uint32_t ret = AddStructMember(**iter);
118896d2730aSSean Callanan (*iter)->SetOffset(ret);
118996d2730aSSean Callanan return ret;
119096d2730aSSean Callanan }
119196d2730aSSean Callanan
1192b9c1b51eSKate Stone class EntitySymbol : public Materializer::Entity {
119396d2730aSSean Callanan public:
EntitySymbol(const Symbol & symbol)1194b9c1b51eSKate Stone EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
119596d2730aSSean Callanan // Hard-coding to maximum size of a symbol
1196fcf4e252SMichael Buch m_size = g_default_var_byte_size;
1197fcf4e252SMichael Buch m_alignment = g_default_var_alignment;
119896d2730aSSean Callanan }
119996d2730aSSean Callanan
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)1200b9c1b51eSKate Stone void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
120197206d57SZachary Turner lldb::addr_t process_address, Status &err) override {
1202a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
1203b5717e00SSean Callanan
120457ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
120557ee3067SGreg Clayton
1206b9c1b51eSKate Stone if (log) {
120763e5fb76SJonas Devlieghere LLDB_LOGF(log,
120863e5fb76SJonas Devlieghere "EntitySymbol::Materialize [address = 0x%" PRIx64
1209b9c1b51eSKate Stone ", m_symbol = %s]",
1210b9c1b51eSKate Stone (uint64_t)load_addr, m_symbol.GetName().AsCString());
1211b5717e00SSean Callanan }
1212b5717e00SSean Callanan
1213358cf1eaSGreg Clayton const Address sym_address = m_symbol.GetAddress();
12142f1edcd7SSean Callanan
12153728133dSAdrian Prantl ExecutionContextScope *exe_scope = frame_sp.get();
12163728133dSAdrian Prantl if (!exe_scope)
12173728133dSAdrian Prantl exe_scope = map.GetBestExecutionContextScope();
12182f1edcd7SSean Callanan
12192f1edcd7SSean Callanan lldb::TargetSP target_sp;
12202f1edcd7SSean Callanan
12212f1edcd7SSean Callanan if (exe_scope)
12222f1edcd7SSean Callanan target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
12232f1edcd7SSean Callanan
1224b9c1b51eSKate Stone if (!target_sp) {
1225b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1226b9c1b51eSKate Stone "couldn't resolve symbol %s because there is no target",
1227b9c1b51eSKate Stone m_symbol.GetName().AsCString());
12282f1edcd7SSean Callanan return;
12292f1edcd7SSean Callanan }
12302f1edcd7SSean Callanan
12312f1edcd7SSean Callanan lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
12322f1edcd7SSean Callanan
12332f1edcd7SSean Callanan if (resolved_address == LLDB_INVALID_ADDRESS)
12342f1edcd7SSean Callanan resolved_address = sym_address.GetFileAddress();
12352f1edcd7SSean Callanan
123697206d57SZachary Turner Status pointer_write_error;
12372f1edcd7SSean Callanan
123857ee3067SGreg Clayton map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
12392f1edcd7SSean Callanan
1240b9c1b51eSKate Stone if (!pointer_write_error.Success()) {
1241b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1242b9c1b51eSKate Stone "couldn't write the address of symbol %s: %s",
1243b9c1b51eSKate Stone m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1244b5717e00SSean Callanan return;
12452f1edcd7SSean Callanan }
124696d2730aSSean Callanan }
124796d2730aSSean Callanan
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)1248b9c1b51eSKate Stone void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1249b9c1b51eSKate Stone lldb::addr_t process_address, lldb::addr_t frame_top,
125097206d57SZachary Turner lldb::addr_t frame_bottom, Status &err) override {
1251a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
1252b5717e00SSean Callanan
125357ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
125457ee3067SGreg Clayton
1255b9c1b51eSKate Stone if (log) {
125663e5fb76SJonas Devlieghere LLDB_LOGF(log,
125763e5fb76SJonas Devlieghere "EntitySymbol::Dematerialize [address = 0x%" PRIx64
1258b9c1b51eSKate Stone ", m_symbol = %s]",
1259b9c1b51eSKate Stone (uint64_t)load_addr, m_symbol.GetName().AsCString());
1260b5717e00SSean Callanan }
1261b5717e00SSean Callanan
12622f1edcd7SSean Callanan // no work needs to be done
126396d2730aSSean Callanan }
12642d37e5a5SSean Callanan
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)1265b9c1b51eSKate Stone void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1266b9c1b51eSKate Stone Log *log) override {
12672d37e5a5SSean Callanan StreamString dump_stream;
12682d37e5a5SSean Callanan
126997206d57SZachary Turner Status err;
12702d37e5a5SSean Callanan
127157ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
127257ee3067SGreg Clayton
1273b9c1b51eSKate Stone dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
1274b9c1b51eSKate Stone m_symbol.GetName().AsCString());
12752d37e5a5SSean Callanan
12762d37e5a5SSean Callanan {
12772d37e5a5SSean Callanan dump_stream.Printf("Pointer:\n");
12782d37e5a5SSean Callanan
12792d37e5a5SSean Callanan DataBufferHeap data(m_size, 0);
12802d37e5a5SSean Callanan
128157ee3067SGreg Clayton map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
12822d37e5a5SSean Callanan
1283b9c1b51eSKate Stone if (!err.Success()) {
12842d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
1285b9c1b51eSKate Stone } else {
128629cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
128729cb868aSZachary Turner load_addr);
128814b1bae5SSean Callanan
128914b1bae5SSean Callanan dump_stream.PutChar('\n');
12902d37e5a5SSean Callanan }
12912d37e5a5SSean Callanan }
12922d37e5a5SSean Callanan
1293c156427dSZachary Turner log->PutString(dump_stream.GetString());
12942d37e5a5SSean Callanan }
129514b1bae5SSean Callanan
Wipe(IRMemoryMap & map,lldb::addr_t process_address)1296b9c1b51eSKate Stone void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1297315b6884SEugene Zelenko
129896d2730aSSean Callanan private:
129996d2730aSSean Callanan Symbol m_symbol;
130096d2730aSSean Callanan };
130196d2730aSSean Callanan
AddSymbol(const Symbol & symbol_sp,Status & err)130297206d57SZachary Turner uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
130396d2730aSSean Callanan EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
130406412daeSJonas Devlieghere *iter = std::make_unique<EntitySymbol>(symbol_sp);
130596d2730aSSean Callanan uint32_t ret = AddStructMember(**iter);
130696d2730aSSean Callanan (*iter)->SetOffset(ret);
130796d2730aSSean Callanan return ret;
130896d2730aSSean Callanan }
130996d2730aSSean Callanan
1310b9c1b51eSKate Stone class EntityRegister : public Materializer::Entity {
131196d2730aSSean Callanan public:
EntityRegister(const RegisterInfo & register_info)1312b9c1b51eSKate Stone EntityRegister(const RegisterInfo ®ister_info)
1313b9c1b51eSKate Stone : Entity(), m_register_info(register_info) {
131496d2730aSSean Callanan // Hard-coding alignment conservatively
131596d2730aSSean Callanan m_size = m_register_info.byte_size;
131696d2730aSSean Callanan m_alignment = m_register_info.byte_size;
131796d2730aSSean Callanan }
131896d2730aSSean Callanan
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)1319b9c1b51eSKate Stone void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
132097206d57SZachary Turner lldb::addr_t process_address, Status &err) override {
1321a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
1322b5717e00SSean Callanan
132357ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
132457ee3067SGreg Clayton
1325b9c1b51eSKate Stone if (log) {
132663e5fb76SJonas Devlieghere LLDB_LOGF(log,
132763e5fb76SJonas Devlieghere "EntityRegister::Materialize [address = 0x%" PRIx64
1328b9c1b51eSKate Stone ", m_register_info = %s]",
1329b9c1b51eSKate Stone (uint64_t)load_addr, m_register_info.name);
1330b5717e00SSean Callanan }
1331b5717e00SSean Callanan
1332b5717e00SSean Callanan RegisterValue reg_value;
1333b5717e00SSean Callanan
1334b9c1b51eSKate Stone if (!frame_sp.get()) {
1335b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1336b9c1b51eSKate Stone "couldn't materialize register %s without a stack frame",
1337b9c1b51eSKate Stone m_register_info.name);
1338b5717e00SSean Callanan return;
1339b5717e00SSean Callanan }
1340b5717e00SSean Callanan
1341b5717e00SSean Callanan lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1342b5717e00SSean Callanan
1343b9c1b51eSKate Stone if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1344b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't read the value of register %s",
1345b9c1b51eSKate Stone m_register_info.name);
1346b5717e00SSean Callanan return;
1347b5717e00SSean Callanan }
1348b5717e00SSean Callanan
1349b5717e00SSean Callanan DataExtractor register_data;
1350b5717e00SSean Callanan
1351b9c1b51eSKate Stone if (!reg_value.GetData(register_data)) {
1352b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't get the data for register %s",
1353b9c1b51eSKate Stone m_register_info.name);
1354b5717e00SSean Callanan return;
1355b5717e00SSean Callanan }
1356b5717e00SSean Callanan
1357b9c1b51eSKate Stone if (register_data.GetByteSize() != m_register_info.byte_size) {
1358b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1359b9c1b51eSKate Stone "data for register %s had size %llu but we expected %llu",
1360b9c1b51eSKate Stone m_register_info.name, (unsigned long long)register_data.GetByteSize(),
1361b9c1b51eSKate Stone (unsigned long long)m_register_info.byte_size);
1362b5717e00SSean Callanan return;
1363b5717e00SSean Callanan }
1364b5717e00SSean Callanan
1365796ac80bSJonas Devlieghere m_register_contents = std::make_shared<DataBufferHeap>(
1366796ac80bSJonas Devlieghere register_data.GetDataStart(), register_data.GetByteSize());
1367d2a507a6SSean Callanan
136897206d57SZachary Turner Status write_error;
1369b5717e00SSean Callanan
1370b9c1b51eSKate Stone map.WriteMemory(load_addr, register_data.GetDataStart(),
1371b9c1b51eSKate Stone register_data.GetByteSize(), write_error);
1372b5717e00SSean Callanan
1373b9c1b51eSKate Stone if (!write_error.Success()) {
1374b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1375b9c1b51eSKate Stone "couldn't write the contents of register %s: %s",
1376b9c1b51eSKate Stone m_register_info.name, write_error.AsCString());
1377b5717e00SSean Callanan return;
1378b5717e00SSean Callanan }
137996d2730aSSean Callanan }
138096d2730aSSean Callanan
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)1381b9c1b51eSKate Stone void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1382b9c1b51eSKate Stone lldb::addr_t process_address, lldb::addr_t frame_top,
138397206d57SZachary Turner lldb::addr_t frame_bottom, Status &err) override {
1384a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
1385b5717e00SSean Callanan
138657ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
138757ee3067SGreg Clayton
1388b9c1b51eSKate Stone if (log) {
138963e5fb76SJonas Devlieghere LLDB_LOGF(log,
139063e5fb76SJonas Devlieghere "EntityRegister::Dematerialize [address = 0x%" PRIx64
1391b9c1b51eSKate Stone ", m_register_info = %s]",
1392b9c1b51eSKate Stone (uint64_t)load_addr, m_register_info.name);
1393b5717e00SSean Callanan }
1394b5717e00SSean Callanan
139597206d57SZachary Turner Status extract_error;
1396b5717e00SSean Callanan
1397b5717e00SSean Callanan DataExtractor register_data;
1398b5717e00SSean Callanan
1399b9c1b51eSKate Stone if (!frame_sp.get()) {
1400b9c1b51eSKate Stone err.SetErrorStringWithFormat(
1401b9c1b51eSKate Stone "couldn't dematerialize register %s without a stack frame",
1402b9c1b51eSKate Stone m_register_info.name);
1403b5717e00SSean Callanan return;
1404b5717e00SSean Callanan }
1405b5717e00SSean Callanan
1406b5717e00SSean Callanan lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1407b5717e00SSean Callanan
1408b9c1b51eSKate Stone map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1409b9c1b51eSKate Stone extract_error);
1410b5717e00SSean Callanan
1411b9c1b51eSKate Stone if (!extract_error.Success()) {
1412b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
1413b9c1b51eSKate Stone m_register_info.name,
1414b9c1b51eSKate Stone extract_error.AsCString());
1415b5717e00SSean Callanan return;
1416b5717e00SSean Callanan }
1417b5717e00SSean Callanan
1418b9c1b51eSKate Stone if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1419b9c1b51eSKate Stone register_data.GetByteSize())) {
1420b9c1b51eSKate Stone // No write required, and in particular we avoid errors if the register
1421b9c1b51eSKate Stone // wasn't writable
1422d2a507a6SSean Callanan
1423d2a507a6SSean Callanan m_register_contents.reset();
1424d2a507a6SSean Callanan return;
1425d2a507a6SSean Callanan }
1426d2a507a6SSean Callanan
1427d2a507a6SSean Callanan m_register_contents.reset();
1428d2a507a6SSean Callanan
1429d2700b78SPavel Labath RegisterValue register_value(register_data.GetData(),
1430d2700b78SPavel Labath register_data.GetByteOrder());
1431b5717e00SSean Callanan
1432b9c1b51eSKate Stone if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1433b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't write the value of register %s",
1434b9c1b51eSKate Stone m_register_info.name);
1435b5717e00SSean Callanan return;
1436b5717e00SSean Callanan }
143796d2730aSSean Callanan }
14382d37e5a5SSean Callanan
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)1439b9c1b51eSKate Stone void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1440b9c1b51eSKate Stone Log *log) override {
14412d37e5a5SSean Callanan StreamString dump_stream;
14422d37e5a5SSean Callanan
144397206d57SZachary Turner Status err;
14442d37e5a5SSean Callanan
144557ee3067SGreg Clayton const lldb::addr_t load_addr = process_address + m_offset;
144657ee3067SGreg Clayton
1447b9c1b51eSKate Stone dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1448b9c1b51eSKate Stone m_register_info.name);
14492d37e5a5SSean Callanan
14502d37e5a5SSean Callanan {
14512d37e5a5SSean Callanan dump_stream.Printf("Value:\n");
14522d37e5a5SSean Callanan
14532d37e5a5SSean Callanan DataBufferHeap data(m_size, 0);
14542d37e5a5SSean Callanan
145557ee3067SGreg Clayton map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
14562d37e5a5SSean Callanan
1457b9c1b51eSKate Stone if (!err.Success()) {
14582d37e5a5SSean Callanan dump_stream.Printf(" <could not be read>\n");
1459b9c1b51eSKate Stone } else {
146029cb868aSZachary Turner DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
146129cb868aSZachary Turner load_addr);
146214b1bae5SSean Callanan
146314b1bae5SSean Callanan dump_stream.PutChar('\n');
14642d37e5a5SSean Callanan }
14652d37e5a5SSean Callanan }
14662d37e5a5SSean Callanan
1467c156427dSZachary Turner log->PutString(dump_stream.GetString());
14682d37e5a5SSean Callanan }
146914b1bae5SSean Callanan
Wipe(IRMemoryMap & map,lldb::addr_t process_address)1470b9c1b51eSKate Stone void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1471315b6884SEugene Zelenko
147296d2730aSSean Callanan private:
147396d2730aSSean Callanan RegisterInfo m_register_info;
1474d2a507a6SSean Callanan lldb::DataBufferSP m_register_contents;
147596d2730aSSean Callanan };
147696d2730aSSean Callanan
AddRegister(const RegisterInfo & register_info,Status & err)1477b9c1b51eSKate Stone uint32_t Materializer::AddRegister(const RegisterInfo ®ister_info,
147897206d57SZachary Turner Status &err) {
147996d2730aSSean Callanan EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
148006412daeSJonas Devlieghere *iter = std::make_unique<EntityRegister>(register_info);
148196d2730aSSean Callanan uint32_t ret = AddStructMember(**iter);
148296d2730aSSean Callanan (*iter)->SetOffset(ret);
148396d2730aSSean Callanan return ret;
148496d2730aSSean Callanan }
148596d2730aSSean Callanan
~Materializer()1486b9c1b51eSKate Stone Materializer::~Materializer() {
148714b1bae5SSean Callanan DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
148896d2730aSSean Callanan
148914b1bae5SSean Callanan if (dematerializer_sp)
149014b1bae5SSean Callanan dematerializer_sp->Wipe();
149114b1bae5SSean Callanan }
149214b1bae5SSean Callanan
149314b1bae5SSean Callanan Materializer::DematerializerSP
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & error)1494b9c1b51eSKate Stone Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
149597206d57SZachary Turner lldb::addr_t process_address, Status &error) {
1496b024d878SSean Callanan ExecutionContextScope *exe_scope = frame_sp.get();
1497b024d878SSean Callanan if (!exe_scope)
1498b024d878SSean Callanan exe_scope = map.GetBestExecutionContextScope();
1499b024d878SSean Callanan
150014b1bae5SSean Callanan DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
150114b1bae5SSean Callanan
1502b9c1b51eSKate Stone if (dematerializer_sp) {
150314b1bae5SSean Callanan error.SetErrorToGenericError();
150414b1bae5SSean Callanan error.SetErrorString("Couldn't materialize: already materialized");
150514b1bae5SSean Callanan }
150614b1bae5SSean Callanan
1507b9c1b51eSKate Stone DematerializerSP ret(
1508b9c1b51eSKate Stone new Dematerializer(*this, frame_sp, map, process_address));
150914b1bae5SSean Callanan
1510b9c1b51eSKate Stone if (!exe_scope) {
1511b024d878SSean Callanan error.SetErrorToGenericError();
151214b1bae5SSean Callanan error.SetErrorString("Couldn't materialize: target doesn't exist");
1513b024d878SSean Callanan }
1514b024d878SSean Callanan
1515b9c1b51eSKate Stone for (EntityUP &entity_up : m_entities) {
151696d2730aSSean Callanan entity_up->Materialize(frame_sp, map, process_address, error);
151796d2730aSSean Callanan
151896d2730aSSean Callanan if (!error.Success())
151914b1bae5SSean Callanan return DematerializerSP();
152096d2730aSSean Callanan }
152196d2730aSSean Callanan
1522a007a6d8SPavel Labath if (Log *log = GetLog(LLDBLog::Expressions)) {
152363e5fb76SJonas Devlieghere LLDB_LOGF(
152463e5fb76SJonas Devlieghere log,
1525b9c1b51eSKate Stone "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1526b9c1b51eSKate Stone ") materialized:",
1527324a1036SSaleem Abdulrasool static_cast<void *>(frame_sp.get()), process_address);
15282d37e5a5SSean Callanan for (EntityUP &entity_up : m_entities)
15292d37e5a5SSean Callanan entity_up->DumpToLog(map, process_address, log);
15302d37e5a5SSean Callanan }
15312d37e5a5SSean Callanan
153214b1bae5SSean Callanan m_dematerializer_wp = ret;
153396d2730aSSean Callanan
153414b1bae5SSean Callanan return ret;
153596d2730aSSean Callanan }
153696d2730aSSean Callanan
Dematerialize(Status & error,lldb::addr_t frame_bottom,lldb::addr_t frame_top)153797206d57SZachary Turner void Materializer::Dematerializer::Dematerialize(Status &error,
15389fda9d21SSean Callanan lldb::addr_t frame_bottom,
1539b9c1b51eSKate Stone lldb::addr_t frame_top) {
1540b57e4a1bSJason Molenda lldb::StackFrameSP frame_sp;
1541a4e8105bSSean Callanan
1542a4e8105bSSean Callanan lldb::ThreadSP thread_sp = m_thread_wp.lock();
1543a4e8105bSSean Callanan if (thread_sp)
1544a4e8105bSSean Callanan frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
154596d2730aSSean Callanan
15463728133dSAdrian Prantl ExecutionContextScope *exe_scope = frame_sp.get();
15473728133dSAdrian Prantl if (!exe_scope)
15483728133dSAdrian Prantl exe_scope = m_map->GetBestExecutionContextScope();
154914b1bae5SSean Callanan
1550b9c1b51eSKate Stone if (!IsValid()) {
155114b1bae5SSean Callanan error.SetErrorToGenericError();
155214b1bae5SSean Callanan error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
155314b1bae5SSean Callanan }
1554b024d878SSean Callanan
1555b9c1b51eSKate Stone if (!exe_scope) {
155696d2730aSSean Callanan error.SetErrorToGenericError();
1557b024d878SSean Callanan error.SetErrorString("Couldn't dematerialize: target is gone");
1558b9c1b51eSKate Stone } else {
1559a007a6d8SPavel Labath if (Log *log = GetLog(LLDBLog::Expressions)) {
156063e5fb76SJonas Devlieghere LLDB_LOGF(log,
156163e5fb76SJonas Devlieghere "Materializer::Dematerialize (frame_sp = %p, process_address "
1562b9c1b51eSKate Stone "= 0x%" PRIx64 ") about to dematerialize:",
1563324a1036SSaleem Abdulrasool static_cast<void *>(frame_sp.get()), m_process_address);
156414b1bae5SSean Callanan for (EntityUP &entity_up : m_materializer->m_entities)
156514b1bae5SSean Callanan entity_up->DumpToLog(*m_map, m_process_address, log);
15662d37e5a5SSean Callanan }
15672d37e5a5SSean Callanan
1568b9c1b51eSKate Stone for (EntityUP &entity_up : m_materializer->m_entities) {
1569b9c1b51eSKate Stone entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1570b9c1b51eSKate Stone frame_bottom, error);
157196d2730aSSean Callanan
157296d2730aSSean Callanan if (!error.Success())
157396d2730aSSean Callanan break;
157496d2730aSSean Callanan }
157596d2730aSSean Callanan }
157696d2730aSSean Callanan
157714b1bae5SSean Callanan Wipe();
157814b1bae5SSean Callanan }
157914b1bae5SSean Callanan
Wipe()1580b9c1b51eSKate Stone void Materializer::Dematerializer::Wipe() {
158114b1bae5SSean Callanan if (!IsValid())
158214b1bae5SSean Callanan return;
158314b1bae5SSean Callanan
1584b9c1b51eSKate Stone for (EntityUP &entity_up : m_materializer->m_entities) {
158514b1bae5SSean Callanan entity_up->Wipe(*m_map, m_process_address);
158614b1bae5SSean Callanan }
158714b1bae5SSean Callanan
1588315b6884SEugene Zelenko m_materializer = nullptr;
1589315b6884SEugene Zelenko m_map = nullptr;
159014b1bae5SSean Callanan m_process_address = LLDB_INVALID_ADDRESS;
159196d2730aSSean Callanan }
15929fda9d21SSean Callanan
1593b9c1b51eSKate Stone Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
1594b9c1b51eSKate Stone default;
1595