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