]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Expression / Materializer.cpp
1 //===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Expression/Materializer.h"
15 #include "lldb/Core/DumpDataExtractor.h"
16 #include "lldb/Core/RegisterValue.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectVariable.h"
19 #include "lldb/Expression/ExpressionVariable.h"
20 #include "lldb/Symbol/ClangASTContext.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Symbol/Type.h"
23 #include "lldb/Symbol/Variable.h"
24 #include "lldb/Target/ExecutionContext.h"
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Thread.h"
29 #include "lldb/Utility/Log.h"
30
31 using namespace lldb_private;
32
33 uint32_t Materializer::AddStructMember(Entity &entity) {
34   uint32_t size = entity.GetSize();
35   uint32_t alignment = entity.GetAlignment();
36
37   uint32_t ret;
38
39   if (m_current_offset == 0)
40     m_struct_alignment = alignment;
41
42   if (m_current_offset % alignment)
43     m_current_offset += (alignment - (m_current_offset % alignment));
44
45   ret = m_current_offset;
46
47   m_current_offset += size;
48
49   return ret;
50 }
51
52 void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) {
53   m_size = type.GetByteSize(nullptr);
54
55   uint32_t bit_alignment = type.GetTypeBitAlign();
56
57   if (bit_alignment % 8) {
58     bit_alignment += 8;
59     bit_alignment &= ~((uint32_t)0x111u);
60   }
61
62   m_alignment = bit_alignment / 8;
63 }
64
65 class EntityPersistentVariable : public Materializer::Entity {
66 public:
67   EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
68                            Materializer::PersistentVariableDelegate *delegate)
69       : Entity(), m_persistent_variable_sp(persistent_variable_sp),
70         m_delegate(delegate) {
71     // Hard-coding to maximum size of a pointer since persistent variables are
72     // materialized by reference
73     m_size = 8;
74     m_alignment = 8;
75   }
76
77   void MakeAllocation(IRMemoryMap &map, Status &err) {
78     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
79
80     // Allocate a spare memory area to store the persistent variable's
81     // contents.
82
83     Status allocate_error;
84     const bool zero_memory = false;
85
86     lldb::addr_t mem = map.Malloc(
87         m_persistent_variable_sp->GetByteSize(), 8,
88         lldb::ePermissionsReadable | lldb::ePermissionsWritable,
89         IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
90
91     if (!allocate_error.Success()) {
92       err.SetErrorStringWithFormat(
93           "couldn't allocate a memory area to store %s: %s",
94           m_persistent_variable_sp->GetName().GetCString(),
95           allocate_error.AsCString());
96       return;
97     }
98
99     if (log)
100       log->Printf("Allocated %s (0x%" PRIx64 ") successfully",
101                   m_persistent_variable_sp->GetName().GetCString(), mem);
102
103     // Put the location of the spare memory into the live data of the
104     // ValueObject.
105
106     m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
107         map.GetBestExecutionContextScope(),
108         m_persistent_variable_sp->GetCompilerType(),
109         m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
110         map.GetAddressByteSize());
111
112     // Clear the flag if the variable will never be deallocated.
113
114     if (m_persistent_variable_sp->m_flags &
115         ExpressionVariable::EVKeepInTarget) {
116       Status leak_error;
117       map.Leak(mem, leak_error);
118       m_persistent_variable_sp->m_flags &=
119           ~ExpressionVariable::EVNeedsAllocation;
120     }
121
122     // Write the contents of the variable to the area.
123
124     Status write_error;
125
126     map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
127                     m_persistent_variable_sp->GetByteSize(), write_error);
128
129     if (!write_error.Success()) {
130       err.SetErrorStringWithFormat(
131           "couldn't write %s to the target: %s",
132           m_persistent_variable_sp->GetName().AsCString(),
133           write_error.AsCString());
134       return;
135     }
136   }
137
138   void DestroyAllocation(IRMemoryMap &map, Status &err) {
139     Status deallocate_error;
140
141     map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
142                  .GetScalar()
143                  .ULongLong(),
144              deallocate_error);
145
146     m_persistent_variable_sp->m_live_sp.reset();
147
148     if (!deallocate_error.Success()) {
149       err.SetErrorStringWithFormat(
150           "couldn't deallocate memory for %s: %s",
151           m_persistent_variable_sp->GetName().GetCString(),
152           deallocate_error.AsCString());
153     }
154   }
155
156   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
157                    lldb::addr_t process_address, Status &err) override {
158     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
159
160     const lldb::addr_t load_addr = process_address + m_offset;
161
162     if (log) {
163       log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64
164                   ", m_name = %s, m_flags = 0x%hx]",
165                   (uint64_t)load_addr,
166                   m_persistent_variable_sp->GetName().AsCString(),
167                   m_persistent_variable_sp->m_flags);
168     }
169
170     if (m_persistent_variable_sp->m_flags &
171         ExpressionVariable::EVNeedsAllocation) {
172       MakeAllocation(map, err);
173       m_persistent_variable_sp->m_flags |=
174           ExpressionVariable::EVIsLLDBAllocated;
175
176       if (!err.Success())
177         return;
178     }
179
180     if ((m_persistent_variable_sp->m_flags &
181              ExpressionVariable::EVIsProgramReference &&
182          m_persistent_variable_sp->m_live_sp) ||
183         m_persistent_variable_sp->m_flags &
184             ExpressionVariable::EVIsLLDBAllocated) {
185       Status write_error;
186
187       map.WriteScalarToMemory(
188           load_addr,
189           m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
190           map.GetAddressByteSize(), write_error);
191
192       if (!write_error.Success()) {
193         err.SetErrorStringWithFormat(
194             "couldn't write the location of %s to memory: %s",
195             m_persistent_variable_sp->GetName().AsCString(),
196             write_error.AsCString());
197       }
198     } else {
199       err.SetErrorStringWithFormat(
200           "no materialization happened for persistent variable %s",
201           m_persistent_variable_sp->GetName().AsCString());
202       return;
203     }
204   }
205
206   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
207                      lldb::addr_t process_address, lldb::addr_t frame_top,
208                      lldb::addr_t frame_bottom, Status &err) override {
209     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
210
211     const lldb::addr_t load_addr = process_address + m_offset;
212
213     if (log) {
214       log->Printf(
215           "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
216           ", m_name = %s, m_flags = 0x%hx]",
217           (uint64_t)process_address + m_offset,
218           m_persistent_variable_sp->GetName().AsCString(),
219           m_persistent_variable_sp->m_flags);
220     }
221
222     if (m_delegate) {
223       m_delegate->DidDematerialize(m_persistent_variable_sp);
224     }
225
226     if ((m_persistent_variable_sp->m_flags &
227          ExpressionVariable::EVIsLLDBAllocated) ||
228         (m_persistent_variable_sp->m_flags &
229          ExpressionVariable::EVIsProgramReference)) {
230       if (m_persistent_variable_sp->m_flags &
231               ExpressionVariable::EVIsProgramReference &&
232           !m_persistent_variable_sp->m_live_sp) {
233         // If the reference comes from the program, then the
234         // ClangExpressionVariable's live variable data hasn't been set up yet.
235         // Do this now.
236
237         lldb::addr_t location;
238         Status read_error;
239
240         map.ReadPointerFromMemory(&location, load_addr, read_error);
241
242         if (!read_error.Success()) {
243           err.SetErrorStringWithFormat(
244               "couldn't read the address of program-allocated variable %s: %s",
245               m_persistent_variable_sp->GetName().GetCString(),
246               read_error.AsCString());
247           return;
248         }
249
250         m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
251             map.GetBestExecutionContextScope(),
252             m_persistent_variable_sp.get()->GetCompilerType(),
253             m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
254             m_persistent_variable_sp->GetByteSize());
255
256         if (frame_top != LLDB_INVALID_ADDRESS &&
257             frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
258             location <= frame_top) {
259           // If the variable is resident in the stack frame created by the
260           // expression, then it cannot be relied upon to stay around.  We
261           // treat it as needing reallocation.
262           m_persistent_variable_sp->m_flags |=
263               ExpressionVariable::EVIsLLDBAllocated;
264           m_persistent_variable_sp->m_flags |=
265               ExpressionVariable::EVNeedsAllocation;
266           m_persistent_variable_sp->m_flags |=
267               ExpressionVariable::EVNeedsFreezeDry;
268           m_persistent_variable_sp->m_flags &=
269               ~ExpressionVariable::EVIsProgramReference;
270         }
271       }
272
273       lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
274                              .GetScalar()
275                              .ULongLong();
276
277       if (!m_persistent_variable_sp->m_live_sp) {
278         err.SetErrorStringWithFormat(
279             "couldn't find the memory area used to store %s",
280             m_persistent_variable_sp->GetName().GetCString());
281         return;
282       }
283
284       if (m_persistent_variable_sp->m_live_sp->GetValue()
285               .GetValueAddressType() != eAddressTypeLoad) {
286         err.SetErrorStringWithFormat(
287             "the address of the memory area for %s is in an incorrect format",
288             m_persistent_variable_sp->GetName().GetCString());
289         return;
290       }
291
292       if (m_persistent_variable_sp->m_flags &
293               ExpressionVariable::EVNeedsFreezeDry ||
294           m_persistent_variable_sp->m_flags &
295               ExpressionVariable::EVKeepInTarget) {
296         if (log)
297           log->Printf(
298               "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
299               m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem,
300               (unsigned long long)m_persistent_variable_sp->GetByteSize());
301
302         // Read the contents of the spare memory area
303
304         m_persistent_variable_sp->ValueUpdated();
305
306         Status read_error;
307
308         map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
309                        m_persistent_variable_sp->GetByteSize(), read_error);
310
311         if (!read_error.Success()) {
312           err.SetErrorStringWithFormat(
313               "couldn't read the contents of %s from memory: %s",
314               m_persistent_variable_sp->GetName().GetCString(),
315               read_error.AsCString());
316           return;
317         }
318
319         m_persistent_variable_sp->m_flags &=
320             ~ExpressionVariable::EVNeedsFreezeDry;
321       }
322     } else {
323       err.SetErrorStringWithFormat(
324           "no dematerialization happened for persistent variable %s",
325           m_persistent_variable_sp->GetName().AsCString());
326       return;
327     }
328
329     lldb::ProcessSP process_sp =
330         map.GetBestExecutionContextScope()->CalculateProcess();
331     if (!process_sp || !process_sp->CanJIT()) {
332       // Allocations are not persistent so persistent variables cannot stay
333       // materialized.
334
335       m_persistent_variable_sp->m_flags |=
336           ExpressionVariable::EVNeedsAllocation;
337
338       DestroyAllocation(map, err);
339       if (!err.Success())
340         return;
341     } else if (m_persistent_variable_sp->m_flags &
342                    ExpressionVariable::EVNeedsAllocation &&
343                !(m_persistent_variable_sp->m_flags &
344                  ExpressionVariable::EVKeepInTarget)) {
345       DestroyAllocation(map, err);
346       if (!err.Success())
347         return;
348     }
349   }
350
351   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
352                  Log *log) override {
353     StreamString dump_stream;
354
355     Status err;
356
357     const lldb::addr_t load_addr = process_address + m_offset;
358
359     dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
360                        load_addr,
361                        m_persistent_variable_sp->GetName().AsCString());
362
363     {
364       dump_stream.Printf("Pointer:\n");
365
366       DataBufferHeap data(m_size, 0);
367
368       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
369
370       if (!err.Success()) {
371         dump_stream.Printf("  <could not be read>\n");
372       } else {
373         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
374                      load_addr);
375
376         dump_stream.PutChar('\n');
377       }
378     }
379
380     {
381       dump_stream.Printf("Target:\n");
382
383       lldb::addr_t target_address;
384
385       map.ReadPointerFromMemory(&target_address, load_addr, err);
386
387       if (!err.Success()) {
388         dump_stream.Printf("  <could not be read>\n");
389       } else {
390         DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0);
391
392         map.ReadMemory(data.GetBytes(), target_address,
393                        m_persistent_variable_sp->GetByteSize(), err);
394
395         if (!err.Success()) {
396           dump_stream.Printf("  <could not be read>\n");
397         } else {
398           DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
399                        target_address);
400
401           dump_stream.PutChar('\n');
402         }
403       }
404     }
405
406     log->PutString(dump_stream.GetString());
407   }
408
409   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
410
411 private:
412   lldb::ExpressionVariableSP m_persistent_variable_sp;
413   Materializer::PersistentVariableDelegate *m_delegate;
414 };
415
416 uint32_t Materializer::AddPersistentVariable(
417     lldb::ExpressionVariableSP &persistent_variable_sp,
418     PersistentVariableDelegate *delegate, Status &err) {
419   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
420   iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate));
421   uint32_t ret = AddStructMember(**iter);
422   (*iter)->SetOffset(ret);
423   return ret;
424 }
425
426 class EntityVariable : public Materializer::Entity {
427 public:
428   EntityVariable(lldb::VariableSP &variable_sp)
429       : Entity(), m_variable_sp(variable_sp), m_is_reference(false),
430         m_temporary_allocation(LLDB_INVALID_ADDRESS),
431         m_temporary_allocation_size(0) {
432     // Hard-coding to maximum size of a pointer since all variables are
433     // materialized by reference
434     m_size = 8;
435     m_alignment = 8;
436     m_is_reference =
437         m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
438   }
439
440   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
441                    lldb::addr_t process_address, Status &err) override {
442     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
443
444     const lldb::addr_t load_addr = process_address + m_offset;
445     if (log) {
446       log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64
447                   ", m_variable_sp = %s]",
448                   (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
449     }
450
451     ExecutionContextScope *scope = frame_sp.get();
452
453     if (!scope)
454       scope = map.GetBestExecutionContextScope();
455
456     lldb::ValueObjectSP valobj_sp =
457         ValueObjectVariable::Create(scope, m_variable_sp);
458
459     if (!valobj_sp) {
460       err.SetErrorStringWithFormat(
461           "couldn't get a value object for variable %s",
462           m_variable_sp->GetName().AsCString());
463       return;
464     }
465
466     Status valobj_error = valobj_sp->GetError();
467
468     if (valobj_error.Fail()) {
469       err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
470                                    m_variable_sp->GetName().AsCString(),
471                                    valobj_error.AsCString());
472       return;
473     }
474
475     if (m_is_reference) {
476       DataExtractor valobj_extractor;
477       Status extract_error;
478       valobj_sp->GetData(valobj_extractor, extract_error);
479
480       if (!extract_error.Success()) {
481         err.SetErrorStringWithFormat(
482             "couldn't read contents of reference variable %s: %s",
483             m_variable_sp->GetName().AsCString(), extract_error.AsCString());
484         return;
485       }
486
487       lldb::offset_t offset = 0;
488       lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
489
490       Status write_error;
491       map.WritePointerToMemory(load_addr, reference_addr, write_error);
492
493       if (!write_error.Success()) {
494         err.SetErrorStringWithFormat("couldn't write the contents of reference "
495                                      "variable %s to memory: %s",
496                                      m_variable_sp->GetName().AsCString(),
497                                      write_error.AsCString());
498         return;
499       }
500     } else {
501       AddressType address_type = eAddressTypeInvalid;
502       const bool scalar_is_load_address = false;
503       lldb::addr_t addr_of_valobj =
504           valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
505       if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
506         Status write_error;
507         map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
508
509         if (!write_error.Success()) {
510           err.SetErrorStringWithFormat(
511               "couldn't write the address of variable %s to memory: %s",
512               m_variable_sp->GetName().AsCString(), write_error.AsCString());
513           return;
514         }
515       } else {
516         DataExtractor data;
517         Status extract_error;
518         valobj_sp->GetData(data, extract_error);
519         if (!extract_error.Success()) {
520           err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
521                                        m_variable_sp->GetName().AsCString(),
522                                        extract_error.AsCString());
523           return;
524         }
525
526         if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
527           err.SetErrorStringWithFormat(
528               "trying to create a temporary region for %s but one exists",
529               m_variable_sp->GetName().AsCString());
530           return;
531         }
532
533         if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) {
534           if (data.GetByteSize() == 0 &&
535               m_variable_sp->LocationExpression().IsValid() == false) {
536             err.SetErrorStringWithFormat("the variable '%s' has no location, "
537                                          "it may have been optimized out",
538                                          m_variable_sp->GetName().AsCString());
539           } else {
540             err.SetErrorStringWithFormat(
541                 "size of variable %s (%" PRIu64
542                 ") is larger than the ValueObject's size (%" PRIu64 ")",
543                 m_variable_sp->GetName().AsCString(),
544                 m_variable_sp->GetType()->GetByteSize(), data.GetByteSize());
545           }
546           return;
547         }
548
549         size_t bit_align =
550             m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign();
551         size_t byte_align = (bit_align + 7) / 8;
552
553         if (!byte_align)
554           byte_align = 1;
555
556         Status alloc_error;
557         const bool zero_memory = false;
558
559         m_temporary_allocation = map.Malloc(
560             data.GetByteSize(), byte_align,
561             lldb::ePermissionsReadable | lldb::ePermissionsWritable,
562             IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
563
564         m_temporary_allocation_size = data.GetByteSize();
565
566         m_original_data.reset(
567             new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
568
569         if (!alloc_error.Success()) {
570           err.SetErrorStringWithFormat(
571               "couldn't allocate a temporary region for %s: %s",
572               m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
573           return;
574         }
575
576         Status write_error;
577
578         map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
579                         data.GetByteSize(), write_error);
580
581         if (!write_error.Success()) {
582           err.SetErrorStringWithFormat(
583               "couldn't write to the temporary region for %s: %s",
584               m_variable_sp->GetName().AsCString(), write_error.AsCString());
585           return;
586         }
587
588         Status pointer_write_error;
589
590         map.WritePointerToMemory(load_addr, m_temporary_allocation,
591                                  pointer_write_error);
592
593         if (!pointer_write_error.Success()) {
594           err.SetErrorStringWithFormat(
595               "couldn't write the address of the temporary region for %s: %s",
596               m_variable_sp->GetName().AsCString(),
597               pointer_write_error.AsCString());
598         }
599       }
600     }
601   }
602
603   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
604                      lldb::addr_t process_address, lldb::addr_t frame_top,
605                      lldb::addr_t frame_bottom, Status &err) override {
606     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
607
608     const lldb::addr_t load_addr = process_address + m_offset;
609     if (log) {
610       log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64
611                   ", m_variable_sp = %s]",
612                   (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
613     }
614
615     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
616       ExecutionContextScope *scope = frame_sp.get();
617
618       if (!scope)
619         scope = map.GetBestExecutionContextScope();
620
621       lldb::ValueObjectSP valobj_sp =
622           ValueObjectVariable::Create(scope, m_variable_sp);
623
624       if (!valobj_sp) {
625         err.SetErrorStringWithFormat(
626             "couldn't get a value object for variable %s",
627             m_variable_sp->GetName().AsCString());
628         return;
629       }
630
631       lldb_private::DataExtractor data;
632
633       Status extract_error;
634
635       map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(),
636                         extract_error);
637
638       if (!extract_error.Success()) {
639         err.SetErrorStringWithFormat("couldn't get the data for variable %s",
640                                      m_variable_sp->GetName().AsCString());
641         return;
642       }
643
644       bool actually_write = true;
645
646       if (m_original_data) {
647         if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
648             !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
649                     data.GetByteSize())) {
650           actually_write = false;
651         }
652       }
653
654       Status set_error;
655
656       if (actually_write) {
657         valobj_sp->SetData(data, set_error);
658
659         if (!set_error.Success()) {
660           err.SetErrorStringWithFormat(
661               "couldn't write the new contents of %s back into the variable",
662               m_variable_sp->GetName().AsCString());
663           return;
664         }
665       }
666
667       Status free_error;
668
669       map.Free(m_temporary_allocation, free_error);
670
671       if (!free_error.Success()) {
672         err.SetErrorStringWithFormat(
673             "couldn't free the temporary region for %s: %s",
674             m_variable_sp->GetName().AsCString(), free_error.AsCString());
675         return;
676       }
677
678       m_original_data.reset();
679       m_temporary_allocation = LLDB_INVALID_ADDRESS;
680       m_temporary_allocation_size = 0;
681     }
682   }
683
684   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
685                  Log *log) override {
686     StreamString dump_stream;
687
688     const lldb::addr_t load_addr = process_address + m_offset;
689     dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
690
691     Status err;
692
693     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
694
695     {
696       dump_stream.Printf("Pointer:\n");
697
698       DataBufferHeap data(m_size, 0);
699
700       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
701
702       if (!err.Success()) {
703         dump_stream.Printf("  <could not be read>\n");
704       } else {
705         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
706                                 map.GetByteOrder(), map.GetAddressByteSize());
707
708         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
709                      load_addr);
710
711         lldb::offset_t offset;
712
713         ptr = extractor.GetPointer(&offset);
714
715         dump_stream.PutChar('\n');
716       }
717     }
718
719     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
720       dump_stream.Printf("Points to process memory:\n");
721     } else {
722       dump_stream.Printf("Temporary allocation:\n");
723     }
724
725     if (ptr == LLDB_INVALID_ADDRESS) {
726       dump_stream.Printf("  <could not be be found>\n");
727     } else {
728       DataBufferHeap data(m_temporary_allocation_size, 0);
729
730       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
731                      m_temporary_allocation_size, err);
732
733       if (!err.Success()) {
734         dump_stream.Printf("  <could not be read>\n");
735       } else {
736         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
737                      load_addr);
738
739         dump_stream.PutChar('\n');
740       }
741     }
742
743     log->PutString(dump_stream.GetString());
744   }
745
746   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
747     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
748       Status free_error;
749
750       map.Free(m_temporary_allocation, free_error);
751
752       m_temporary_allocation = LLDB_INVALID_ADDRESS;
753       m_temporary_allocation_size = 0;
754     }
755   }
756
757 private:
758   lldb::VariableSP m_variable_sp;
759   bool m_is_reference;
760   lldb::addr_t m_temporary_allocation;
761   size_t m_temporary_allocation_size;
762   lldb::DataBufferSP m_original_data;
763 };
764
765 uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) {
766   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
767   iter->reset(new EntityVariable(variable_sp));
768   uint32_t ret = AddStructMember(**iter);
769   (*iter)->SetOffset(ret);
770   return ret;
771 }
772
773 class EntityResultVariable : public Materializer::Entity {
774 public:
775   EntityResultVariable(const CompilerType &type, bool is_program_reference,
776                        bool keep_in_memory,
777                        Materializer::PersistentVariableDelegate *delegate)
778       : Entity(), m_type(type), m_is_program_reference(is_program_reference),
779         m_keep_in_memory(keep_in_memory),
780         m_temporary_allocation(LLDB_INVALID_ADDRESS),
781         m_temporary_allocation_size(0), m_delegate(delegate) {
782     // Hard-coding to maximum size of a pointer since all results are
783     // materialized by reference
784     m_size = 8;
785     m_alignment = 8;
786   }
787
788   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
789                    lldb::addr_t process_address, Status &err) override {
790     if (!m_is_program_reference) {
791       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
792         err.SetErrorString("Trying to create a temporary region for the result "
793                            "but one exists");
794         return;
795       }
796
797       const lldb::addr_t load_addr = process_address + m_offset;
798
799       ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
800
801       size_t byte_size = m_type.GetByteSize(exe_scope);
802       size_t bit_align = m_type.GetTypeBitAlign();
803       size_t byte_align = (bit_align + 7) / 8;
804
805       if (!byte_align)
806         byte_align = 1;
807
808       Status alloc_error;
809       const bool zero_memory = true;
810
811       m_temporary_allocation = map.Malloc(
812           byte_size, byte_align,
813           lldb::ePermissionsReadable | lldb::ePermissionsWritable,
814           IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
815       m_temporary_allocation_size = byte_size;
816
817       if (!alloc_error.Success()) {
818         err.SetErrorStringWithFormat(
819             "couldn't allocate a temporary region for the result: %s",
820             alloc_error.AsCString());
821         return;
822       }
823
824       Status pointer_write_error;
825
826       map.WritePointerToMemory(load_addr, m_temporary_allocation,
827                                pointer_write_error);
828
829       if (!pointer_write_error.Success()) {
830         err.SetErrorStringWithFormat("couldn't write the address of the "
831                                      "temporary region for the result: %s",
832                                      pointer_write_error.AsCString());
833       }
834     }
835   }
836
837   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
838                      lldb::addr_t process_address, lldb::addr_t frame_top,
839                      lldb::addr_t frame_bottom, Status &err) override {
840     err.Clear();
841
842     ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
843
844     if (!exe_scope) {
845       err.SetErrorString("Couldn't dematerialize a result variable: invalid "
846                          "execution context scope");
847       return;
848     }
849
850     lldb::addr_t address;
851     Status read_error;
852     const lldb::addr_t load_addr = process_address + m_offset;
853
854     map.ReadPointerFromMemory(&address, load_addr, read_error);
855
856     if (!read_error.Success()) {
857       err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
858                          "read its address");
859       return;
860     }
861
862     lldb::TargetSP target_sp = exe_scope->CalculateTarget();
863
864     if (!target_sp) {
865       err.SetErrorString("Couldn't dematerialize a result variable: no target");
866       return;
867     }
868
869     Status type_system_error;
870     TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(
871         &type_system_error, m_type.GetMinimumLanguage());
872
873     if (!type_system) {
874       err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
875                                    "couldn't get the corresponding type "
876                                    "system: %s",
877                                    type_system_error.AsCString());
878       return;
879     }
880
881     PersistentExpressionState *persistent_state =
882         type_system->GetPersistentExpressionState();
883
884     if (!persistent_state) {
885       err.SetErrorString("Couldn't dematerialize a result variable: "
886                          "corresponding type system doesn't handle persistent "
887                          "variables");
888       return;
889     }
890
891     ConstString name =
892         m_delegate
893             ? m_delegate->GetName()
894             : persistent_state->GetNextPersistentVariableName(
895                   *target_sp, persistent_state->GetPersistentVariablePrefix());
896
897     lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
898         exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
899
900     if (!ret) {
901       err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
902                                    "failed to make persistent variable %s",
903                                    name.AsCString());
904       return;
905     }
906
907     lldb::ProcessSP process_sp =
908         map.GetBestExecutionContextScope()->CalculateProcess();
909
910     if (m_delegate) {
911       m_delegate->DidDematerialize(ret);
912     }
913
914     bool can_persist =
915         (m_is_program_reference && process_sp && process_sp->CanJIT() &&
916          !(address >= frame_bottom && address < frame_top));
917
918     if (can_persist && m_keep_in_memory) {
919       ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
920                                                       address, eAddressTypeLoad,
921                                                       map.GetAddressByteSize());
922     }
923
924     ret->ValueUpdated();
925
926     const size_t pvar_byte_size = ret->GetByteSize();
927     uint8_t *pvar_data = ret->GetValueBytes();
928
929     map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
930
931     if (!read_error.Success()) {
932       err.SetErrorString(
933           "Couldn't dematerialize a result variable: couldn't read its memory");
934       return;
935     }
936
937     if (!can_persist || !m_keep_in_memory) {
938       ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
939
940       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
941         Status free_error;
942         map.Free(m_temporary_allocation, free_error);
943       }
944     } else {
945       ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
946     }
947
948     m_temporary_allocation = LLDB_INVALID_ADDRESS;
949     m_temporary_allocation_size = 0;
950   }
951
952   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
953                  Log *log) override {
954     StreamString dump_stream;
955
956     const lldb::addr_t load_addr = process_address + m_offset;
957
958     dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
959
960     Status err;
961
962     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
963
964     {
965       dump_stream.Printf("Pointer:\n");
966
967       DataBufferHeap data(m_size, 0);
968
969       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
970
971       if (!err.Success()) {
972         dump_stream.Printf("  <could not be read>\n");
973       } else {
974         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
975                                 map.GetByteOrder(), map.GetAddressByteSize());
976
977         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
978                      load_addr);
979
980         lldb::offset_t offset;
981
982         ptr = extractor.GetPointer(&offset);
983
984         dump_stream.PutChar('\n');
985       }
986     }
987
988     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
989       dump_stream.Printf("Points to process memory:\n");
990     } else {
991       dump_stream.Printf("Temporary allocation:\n");
992     }
993
994     if (ptr == LLDB_INVALID_ADDRESS) {
995       dump_stream.Printf("  <could not be be found>\n");
996     } else {
997       DataBufferHeap data(m_temporary_allocation_size, 0);
998
999       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
1000                      m_temporary_allocation_size, err);
1001
1002       if (!err.Success()) {
1003         dump_stream.Printf("  <could not be read>\n");
1004       } else {
1005         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1006                      load_addr);
1007
1008         dump_stream.PutChar('\n');
1009       }
1010     }
1011
1012     log->PutString(dump_stream.GetString());
1013   }
1014
1015   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1016     if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1017       Status free_error;
1018
1019       map.Free(m_temporary_allocation, free_error);
1020     }
1021
1022     m_temporary_allocation = LLDB_INVALID_ADDRESS;
1023     m_temporary_allocation_size = 0;
1024   }
1025
1026 private:
1027   CompilerType m_type;
1028   bool m_is_program_reference;
1029   bool m_keep_in_memory;
1030
1031   lldb::addr_t m_temporary_allocation;
1032   size_t m_temporary_allocation_size;
1033   Materializer::PersistentVariableDelegate *m_delegate;
1034 };
1035
1036 uint32_t Materializer::AddResultVariable(const CompilerType &type,
1037                                          bool is_program_reference,
1038                                          bool keep_in_memory,
1039                                          PersistentVariableDelegate *delegate,
1040                                          Status &err) {
1041   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1042   iter->reset(new EntityResultVariable(type, is_program_reference,
1043                                        keep_in_memory, delegate));
1044   uint32_t ret = AddStructMember(**iter);
1045   (*iter)->SetOffset(ret);
1046   return ret;
1047 }
1048
1049 class EntitySymbol : public Materializer::Entity {
1050 public:
1051   EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1052     // Hard-coding to maximum size of a symbol
1053     m_size = 8;
1054     m_alignment = 8;
1055   }
1056
1057   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1058                    lldb::addr_t process_address, Status &err) override {
1059     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1060
1061     const lldb::addr_t load_addr = process_address + m_offset;
1062
1063     if (log) {
1064       log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64
1065                   ", m_symbol = %s]",
1066                   (uint64_t)load_addr, m_symbol.GetName().AsCString());
1067     }
1068
1069     const Address sym_address = m_symbol.GetAddress();
1070
1071     ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1072
1073     lldb::TargetSP target_sp;
1074
1075     if (exe_scope)
1076       target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1077
1078     if (!target_sp) {
1079       err.SetErrorStringWithFormat(
1080           "couldn't resolve symbol %s because there is no target",
1081           m_symbol.GetName().AsCString());
1082       return;
1083     }
1084
1085     lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1086
1087     if (resolved_address == LLDB_INVALID_ADDRESS)
1088       resolved_address = sym_address.GetFileAddress();
1089
1090     Status pointer_write_error;
1091
1092     map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1093
1094     if (!pointer_write_error.Success()) {
1095       err.SetErrorStringWithFormat(
1096           "couldn't write the address of symbol %s: %s",
1097           m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1098       return;
1099     }
1100   }
1101
1102   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1103                      lldb::addr_t process_address, lldb::addr_t frame_top,
1104                      lldb::addr_t frame_bottom, Status &err) override {
1105     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1106
1107     const lldb::addr_t load_addr = process_address + m_offset;
1108
1109     if (log) {
1110       log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64
1111                   ", m_symbol = %s]",
1112                   (uint64_t)load_addr, m_symbol.GetName().AsCString());
1113     }
1114
1115     // no work needs to be done
1116   }
1117
1118   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1119                  Log *log) override {
1120     StreamString dump_stream;
1121
1122     Status err;
1123
1124     const lldb::addr_t load_addr = process_address + m_offset;
1125
1126     dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
1127                        m_symbol.GetName().AsCString());
1128
1129     {
1130       dump_stream.Printf("Pointer:\n");
1131
1132       DataBufferHeap data(m_size, 0);
1133
1134       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1135
1136       if (!err.Success()) {
1137         dump_stream.Printf("  <could not be read>\n");
1138       } else {
1139         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1140                      load_addr);
1141
1142         dump_stream.PutChar('\n');
1143       }
1144     }
1145
1146     log->PutString(dump_stream.GetString());
1147   }
1148
1149   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1150
1151 private:
1152   Symbol m_symbol;
1153 };
1154
1155 uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1156   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1157   iter->reset(new EntitySymbol(symbol_sp));
1158   uint32_t ret = AddStructMember(**iter);
1159   (*iter)->SetOffset(ret);
1160   return ret;
1161 }
1162
1163 class EntityRegister : public Materializer::Entity {
1164 public:
1165   EntityRegister(const RegisterInfo &register_info)
1166       : Entity(), m_register_info(register_info) {
1167     // Hard-coding alignment conservatively
1168     m_size = m_register_info.byte_size;
1169     m_alignment = m_register_info.byte_size;
1170   }
1171
1172   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1173                    lldb::addr_t process_address, Status &err) override {
1174     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1175
1176     const lldb::addr_t load_addr = process_address + m_offset;
1177
1178     if (log) {
1179       log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64
1180                   ", m_register_info = %s]",
1181                   (uint64_t)load_addr, m_register_info.name);
1182     }
1183
1184     RegisterValue reg_value;
1185
1186     if (!frame_sp.get()) {
1187       err.SetErrorStringWithFormat(
1188           "couldn't materialize register %s without a stack frame",
1189           m_register_info.name);
1190       return;
1191     }
1192
1193     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1194
1195     if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1196       err.SetErrorStringWithFormat("couldn't read the value of register %s",
1197                                    m_register_info.name);
1198       return;
1199     }
1200
1201     DataExtractor register_data;
1202
1203     if (!reg_value.GetData(register_data)) {
1204       err.SetErrorStringWithFormat("couldn't get the data for register %s",
1205                                    m_register_info.name);
1206       return;
1207     }
1208
1209     if (register_data.GetByteSize() != m_register_info.byte_size) {
1210       err.SetErrorStringWithFormat(
1211           "data for register %s had size %llu but we expected %llu",
1212           m_register_info.name, (unsigned long long)register_data.GetByteSize(),
1213           (unsigned long long)m_register_info.byte_size);
1214       return;
1215     }
1216
1217     m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(),
1218                                                  register_data.GetByteSize()));
1219
1220     Status write_error;
1221
1222     map.WriteMemory(load_addr, register_data.GetDataStart(),
1223                     register_data.GetByteSize(), write_error);
1224
1225     if (!write_error.Success()) {
1226       err.SetErrorStringWithFormat(
1227           "couldn't write the contents of register %s: %s",
1228           m_register_info.name, write_error.AsCString());
1229       return;
1230     }
1231   }
1232
1233   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1234                      lldb::addr_t process_address, lldb::addr_t frame_top,
1235                      lldb::addr_t frame_bottom, Status &err) override {
1236     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1237
1238     const lldb::addr_t load_addr = process_address + m_offset;
1239
1240     if (log) {
1241       log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64
1242                   ", m_register_info = %s]",
1243                   (uint64_t)load_addr, m_register_info.name);
1244     }
1245
1246     Status extract_error;
1247
1248     DataExtractor register_data;
1249
1250     if (!frame_sp.get()) {
1251       err.SetErrorStringWithFormat(
1252           "couldn't dematerialize register %s without a stack frame",
1253           m_register_info.name);
1254       return;
1255     }
1256
1257     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1258
1259     map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1260                       extract_error);
1261
1262     if (!extract_error.Success()) {
1263       err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
1264                                    m_register_info.name,
1265                                    extract_error.AsCString());
1266       return;
1267     }
1268
1269     if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1270                 register_data.GetByteSize())) {
1271       // No write required, and in particular we avoid errors if the register
1272       // wasn't writable
1273
1274       m_register_contents.reset();
1275       return;
1276     }
1277
1278     m_register_contents.reset();
1279
1280     RegisterValue register_value(
1281         const_cast<uint8_t *>(register_data.GetDataStart()),
1282         register_data.GetByteSize(), register_data.GetByteOrder());
1283
1284     if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1285       err.SetErrorStringWithFormat("couldn't write the value of register %s",
1286                                    m_register_info.name);
1287       return;
1288     }
1289   }
1290
1291   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1292                  Log *log) override {
1293     StreamString dump_stream;
1294
1295     Status err;
1296
1297     const lldb::addr_t load_addr = process_address + m_offset;
1298
1299     dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1300                        m_register_info.name);
1301
1302     {
1303       dump_stream.Printf("Value:\n");
1304
1305       DataBufferHeap data(m_size, 0);
1306
1307       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1308
1309       if (!err.Success()) {
1310         dump_stream.Printf("  <could not be read>\n");
1311       } else {
1312         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1313                      load_addr);
1314
1315         dump_stream.PutChar('\n');
1316       }
1317     }
1318
1319     log->PutString(dump_stream.GetString());
1320   }
1321
1322   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1323
1324 private:
1325   RegisterInfo m_register_info;
1326   lldb::DataBufferSP m_register_contents;
1327 };
1328
1329 uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1330                                    Status &err) {
1331   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1332   iter->reset(new EntityRegister(register_info));
1333   uint32_t ret = AddStructMember(**iter);
1334   (*iter)->SetOffset(ret);
1335   return ret;
1336 }
1337
1338 Materializer::Materializer()
1339     : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {}
1340
1341 Materializer::~Materializer() {
1342   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1343
1344   if (dematerializer_sp)
1345     dematerializer_sp->Wipe();
1346 }
1347
1348 Materializer::DematerializerSP
1349 Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1350                           lldb::addr_t process_address, Status &error) {
1351   ExecutionContextScope *exe_scope = frame_sp.get();
1352
1353   if (!exe_scope)
1354     exe_scope = map.GetBestExecutionContextScope();
1355
1356   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1357
1358   if (dematerializer_sp) {
1359     error.SetErrorToGenericError();
1360     error.SetErrorString("Couldn't materialize: already materialized");
1361   }
1362
1363   DematerializerSP ret(
1364       new Dematerializer(*this, frame_sp, map, process_address));
1365
1366   if (!exe_scope) {
1367     error.SetErrorToGenericError();
1368     error.SetErrorString("Couldn't materialize: target doesn't exist");
1369   }
1370
1371   for (EntityUP &entity_up : m_entities) {
1372     entity_up->Materialize(frame_sp, map, process_address, error);
1373
1374     if (!error.Success())
1375       return DematerializerSP();
1376   }
1377
1378   if (Log *log =
1379           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
1380     log->Printf(
1381         "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1382         ") materialized:",
1383         static_cast<void *>(frame_sp.get()), process_address);
1384     for (EntityUP &entity_up : m_entities)
1385       entity_up->DumpToLog(map, process_address, log);
1386   }
1387
1388   m_dematerializer_wp = ret;
1389
1390   return ret;
1391 }
1392
1393 void Materializer::Dematerializer::Dematerialize(Status &error,
1394                                                  lldb::addr_t frame_bottom,
1395                                                  lldb::addr_t frame_top) {
1396   lldb::StackFrameSP frame_sp;
1397
1398   lldb::ThreadSP thread_sp = m_thread_wp.lock();
1399   if (thread_sp)
1400     frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1401
1402   ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1403
1404   if (!IsValid()) {
1405     error.SetErrorToGenericError();
1406     error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1407   }
1408
1409   if (!exe_scope) {
1410     error.SetErrorToGenericError();
1411     error.SetErrorString("Couldn't dematerialize: target is gone");
1412   } else {
1413     if (Log *log =
1414             lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
1415       log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address "
1416                   "= 0x%" PRIx64 ") about to dematerialize:",
1417                   static_cast<void *>(frame_sp.get()), m_process_address);
1418       for (EntityUP &entity_up : m_materializer->m_entities)
1419         entity_up->DumpToLog(*m_map, m_process_address, log);
1420     }
1421
1422     for (EntityUP &entity_up : m_materializer->m_entities) {
1423       entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1424                                frame_bottom, error);
1425
1426       if (!error.Success())
1427         break;
1428     }
1429   }
1430
1431   Wipe();
1432 }
1433
1434 void Materializer::Dematerializer::Wipe() {
1435   if (!IsValid())
1436     return;
1437
1438   for (EntityUP &entity_up : m_materializer->m_entities) {
1439     entity_up->Wipe(*m_map, m_process_address);
1440   }
1441
1442   m_materializer = nullptr;
1443   m_map = nullptr;
1444   m_process_address = LLDB_INVALID_ADDRESS;
1445 }
1446
1447 Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
1448     default;