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