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