]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Expression/Materializer.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Expression / Materializer.cpp
1 //===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/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             size_t byte_size = m_type.GetByteSize(nullptr);
822             size_t bit_align = m_type.GetTypeBitAlign();
823             size_t byte_align = (bit_align + 7) / 8;
824
825             if (!byte_align)
826                 byte_align = 1;
827
828             Error alloc_error;
829             const bool zero_memory = true;
830
831             m_temporary_allocation = map.Malloc(byte_size,
832                                                 byte_align,
833                                                 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
834                                                 IRMemoryMap::eAllocationPolicyMirror,
835                                                 zero_memory,
836                                                 alloc_error);
837             m_temporary_allocation_size = byte_size;
838
839             if (!alloc_error.Success())
840             {
841                 err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
842                 return;
843             }
844
845             Error pointer_write_error;
846
847             map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
848
849             if (!pointer_write_error.Success())
850             {
851                 err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
852             }
853         }
854     }
855
856     void Dematerialize(lldb::StackFrameSP &frame_sp,
857                        IRMemoryMap &map,
858                        lldb::addr_t process_address,
859                        lldb::addr_t frame_top,
860                        lldb::addr_t frame_bottom,
861                        Error &err) override
862     {
863         err.Clear();
864
865         ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
866
867         if (!exe_scope)
868         {
869             err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
870             return;
871         }
872
873         lldb::addr_t address;
874         Error read_error;
875         const lldb::addr_t load_addr = process_address + m_offset;
876
877         map.ReadPointerFromMemory (&address, load_addr, read_error);
878
879         if (!read_error.Success())
880         {
881             err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
882             return;
883         }
884
885         lldb::TargetSP target_sp = exe_scope->CalculateTarget();
886
887         if (!target_sp)
888         {
889             err.SetErrorString("Couldn't dematerialize a result variable: no target");
890             return;
891         }
892
893         Error type_system_error;
894         TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage());
895
896         if (!type_system)
897         {
898             err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString());
899             return;
900         }
901
902         PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState();
903
904         if (!persistent_state)
905         {
906             err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables");
907             return;
908         }
909
910         ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName();
911
912         lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope,
913                                                                                     name,
914                                                                                     m_type,
915                                                                                     map.GetByteOrder(),
916                                                                                     map.GetAddressByteSize());
917
918         if (!ret)
919         {
920             err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
921             return;
922         }
923
924         lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
925
926         if (m_delegate)
927         {
928             m_delegate->DidDematerialize(ret);
929         }
930
931         bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
932
933         if (can_persist && m_keep_in_memory)
934         {
935             ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
936                                                             m_type,
937                                                             name,
938                                                             address,
939                                                             eAddressTypeLoad,
940                                                             map.GetAddressByteSize());
941         }
942
943         ret->ValueUpdated();
944
945         const size_t pvar_byte_size = ret->GetByteSize();
946         uint8_t *pvar_data = ret->GetValueBytes();
947
948         map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
949
950         if (!read_error.Success())
951         {
952             err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
953             return;
954         }
955
956         if (!can_persist || !m_keep_in_memory)
957         {
958             ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
959
960             if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
961             {
962                 Error free_error;
963                 map.Free(m_temporary_allocation, free_error);
964             }
965         }
966         else
967         {
968             ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
969         }
970
971         m_temporary_allocation = LLDB_INVALID_ADDRESS;
972         m_temporary_allocation_size = 0;
973     }
974
975     void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
976     {
977         StreamString dump_stream;
978
979         const lldb::addr_t load_addr = process_address + m_offset;
980
981         dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
982
983         Error err;
984
985         lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
986
987         {
988             dump_stream.Printf("Pointer:\n");
989
990             DataBufferHeap data (m_size, 0);
991
992             map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
993
994             if (!err.Success())
995             {
996                 dump_stream.Printf("  <could not be read>\n");
997             }
998             else
999             {
1000                 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1001
1002                 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1003
1004                 lldb::offset_t offset;
1005
1006                 ptr = extractor.GetPointer(&offset);
1007
1008                 dump_stream.PutChar('\n');
1009             }
1010         }
1011
1012         if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
1013         {
1014             dump_stream.Printf("Points to process memory:\n");
1015         }
1016         else
1017         {
1018             dump_stream.Printf("Temporary allocation:\n");
1019         }
1020
1021         if (ptr == LLDB_INVALID_ADDRESS)
1022         {
1023             dump_stream.Printf("  <could not be be found>\n");
1024         }
1025         else
1026         {
1027             DataBufferHeap data (m_temporary_allocation_size, 0);
1028
1029             map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
1030
1031             if (!err.Success())
1032             {
1033                 dump_stream.Printf("  <could not be read>\n");
1034             }
1035             else
1036             {
1037                 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1038
1039                 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1040
1041                 dump_stream.PutChar('\n');
1042             }
1043         }
1044
1045         log->PutCString(dump_stream.GetData());
1046     }
1047
1048     void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
1049     {
1050         if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
1051         {
1052             Error free_error;
1053
1054             map.Free(m_temporary_allocation, free_error);
1055         }
1056
1057         m_temporary_allocation = LLDB_INVALID_ADDRESS;
1058         m_temporary_allocation_size = 0;
1059     }
1060
1061 private:
1062     CompilerType    m_type;
1063     bool            m_is_program_reference;
1064     bool            m_keep_in_memory;
1065
1066     lldb::addr_t    m_temporary_allocation;
1067     size_t          m_temporary_allocation_size;
1068     Materializer::PersistentVariableDelegate *m_delegate;
1069 };
1070
1071 uint32_t
1072 Materializer::AddResultVariable (const CompilerType &type,
1073                                  bool is_program_reference,
1074                                  bool keep_in_memory,
1075                                  PersistentVariableDelegate *delegate,
1076                                  Error &err)
1077 {
1078     EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1079     iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate));
1080     uint32_t ret = AddStructMember(**iter);
1081     (*iter)->SetOffset(ret);
1082     return ret;
1083 }
1084
1085 class EntitySymbol : public Materializer::Entity
1086 {
1087 public:
1088     EntitySymbol (const Symbol &symbol) :
1089         Entity(),
1090         m_symbol(symbol)
1091     {
1092         // Hard-coding to maximum size of a symbol
1093         m_size = 8;
1094         m_alignment = 8;
1095     }
1096
1097     void Materialize(lldb::StackFrameSP &frame_sp,
1098                      IRMemoryMap &map,
1099                      lldb::addr_t process_address,
1100                      Error &err) override
1101     {
1102         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1103
1104         const lldb::addr_t load_addr = process_address + m_offset;
1105
1106         if (log)
1107         {
1108             log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1109                         (uint64_t)load_addr,
1110                         m_symbol.GetName().AsCString());
1111         }
1112
1113         const Address sym_address = m_symbol.GetAddress();
1114
1115         ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1116
1117         lldb::TargetSP target_sp;
1118
1119         if (exe_scope)
1120             target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1121
1122         if (!target_sp)
1123         {
1124             err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
1125             return;
1126         }
1127
1128         lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1129
1130         if (resolved_address == LLDB_INVALID_ADDRESS)
1131             resolved_address = sym_address.GetFileAddress();
1132
1133         Error pointer_write_error;
1134
1135         map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1136
1137         if (!pointer_write_error.Success())
1138         {
1139             err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1140             return;
1141         }
1142     }
1143
1144     void Dematerialize(lldb::StackFrameSP &frame_sp,
1145                        IRMemoryMap &map,
1146                        lldb::addr_t process_address,
1147                        lldb::addr_t frame_top,
1148                        lldb::addr_t frame_bottom,
1149                        Error &err) override
1150     {
1151         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1152
1153         const lldb::addr_t load_addr = process_address + m_offset;
1154
1155         if (log)
1156         {
1157             log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1158                         (uint64_t)load_addr,
1159                         m_symbol.GetName().AsCString());
1160         }
1161
1162         // no work needs to be done
1163     }
1164
1165     void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
1166     {
1167         StreamString dump_stream;
1168
1169         Error err;
1170
1171         const lldb::addr_t load_addr = process_address + m_offset;
1172
1173         dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString());
1174
1175         {
1176             dump_stream.Printf("Pointer:\n");
1177
1178             DataBufferHeap data (m_size, 0);
1179
1180             map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1181
1182             if (!err.Success())
1183             {
1184                 dump_stream.Printf("  <could not be read>\n");
1185             }
1186             else
1187             {
1188                 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1189
1190                 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1191
1192                 dump_stream.PutChar('\n');
1193             }
1194         }
1195
1196         log->PutCString(dump_stream.GetData());
1197     }
1198
1199     void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
1200     {
1201     }
1202
1203 private:
1204     Symbol m_symbol;
1205 };
1206
1207 uint32_t
1208 Materializer::AddSymbol (const Symbol &symbol_sp, Error &err)
1209 {
1210     EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1211     iter->reset (new EntitySymbol (symbol_sp));
1212     uint32_t ret = AddStructMember(**iter);
1213     (*iter)->SetOffset(ret);
1214     return ret;
1215 }
1216
1217 class EntityRegister : public Materializer::Entity
1218 {
1219 public:
1220     EntityRegister (const RegisterInfo &register_info) :
1221         Entity(),
1222         m_register_info(register_info)
1223     {
1224         // Hard-coding alignment conservatively
1225         m_size = m_register_info.byte_size;
1226         m_alignment = m_register_info.byte_size;
1227     }
1228
1229     void Materialize(lldb::StackFrameSP &frame_sp,
1230                      IRMemoryMap &map,
1231                      lldb::addr_t process_address,
1232                      Error &err) override
1233     {
1234         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1235
1236         const lldb::addr_t load_addr = process_address + m_offset;
1237
1238         if (log)
1239         {
1240             log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1241                         (uint64_t)load_addr,
1242                         m_register_info.name);
1243         }
1244
1245         RegisterValue reg_value;
1246
1247         if (!frame_sp.get())
1248         {
1249             err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
1250             return;
1251         }
1252
1253         lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1254
1255         if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
1256         {
1257             err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
1258             return;
1259         }
1260
1261         DataExtractor register_data;
1262
1263         if (!reg_value.GetData(register_data))
1264         {
1265             err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
1266             return;
1267         }
1268
1269         if (register_data.GetByteSize() != m_register_info.byte_size)
1270         {
1271             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);
1272             return;
1273         }
1274
1275         m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
1276
1277         Error write_error;
1278         
1279         map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
1280         
1281         if (!write_error.Success())
1282         {
1283             err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
1284             return;
1285         }
1286     }
1287
1288     void Dematerialize(lldb::StackFrameSP &frame_sp,
1289                        IRMemoryMap &map,
1290                        lldb::addr_t process_address,
1291                        lldb::addr_t frame_top,
1292                        lldb::addr_t frame_bottom,
1293                        Error &err) override
1294     {
1295         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1296
1297         const lldb::addr_t load_addr = process_address + m_offset;
1298
1299         if (log)
1300         {
1301             log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1302                         (uint64_t)load_addr,
1303                         m_register_info.name);
1304         }
1305
1306         Error extract_error;
1307
1308         DataExtractor register_data;
1309
1310         if (!frame_sp.get())
1311         {
1312             err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
1313             return;
1314         }
1315
1316         lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1317
1318         map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error);
1319
1320         if (!extract_error.Success())
1321         {
1322             err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
1323             return;
1324         }
1325
1326         if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize()))
1327         {
1328             // No write required, and in particular we avoid errors if the register wasn't writable
1329
1330             m_register_contents.reset();
1331             return;
1332         }
1333
1334         m_register_contents.reset();
1335
1336         RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
1337
1338         if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
1339         {
1340             err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
1341             return;
1342         }
1343     }
1344
1345     void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
1346     {
1347         StreamString dump_stream;
1348
1349         Error err;
1350
1351         const lldb::addr_t load_addr = process_address + m_offset;
1352
1353
1354         dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name);
1355
1356         {
1357             dump_stream.Printf("Value:\n");
1358
1359             DataBufferHeap data (m_size, 0);
1360
1361             map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1362
1363             if (!err.Success())
1364             {
1365                 dump_stream.Printf("  <could not be read>\n");
1366             }
1367             else
1368             {
1369                 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1370
1371                 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1372
1373                 dump_stream.PutChar('\n');
1374             }
1375         }
1376
1377         log->PutCString(dump_stream.GetData());
1378     }
1379
1380     void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
1381     {
1382     }
1383
1384 private:
1385     RegisterInfo m_register_info;
1386     lldb::DataBufferSP m_register_contents;
1387 };
1388
1389 uint32_t
1390 Materializer::AddRegister (const RegisterInfo &register_info, Error &err)
1391 {
1392     EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1393     iter->reset (new EntityRegister (register_info));
1394     uint32_t ret = AddStructMember(**iter);
1395     (*iter)->SetOffset(ret);
1396     return ret;
1397 }
1398
1399 Materializer::Materializer () :
1400     m_dematerializer_wp(),
1401     m_current_offset(0),
1402     m_struct_alignment(8)
1403 {
1404 }
1405
1406 Materializer::~Materializer ()
1407 {
1408     DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1409
1410     if (dematerializer_sp)
1411         dematerializer_sp->Wipe();
1412 }
1413
1414 Materializer::DematerializerSP
1415 Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
1416 {
1417     ExecutionContextScope *exe_scope = frame_sp.get();
1418
1419     if (!exe_scope)
1420         exe_scope = map.GetBestExecutionContextScope();
1421
1422     DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1423
1424     if (dematerializer_sp)
1425     {
1426         error.SetErrorToGenericError();
1427         error.SetErrorString("Couldn't materialize: already materialized");
1428     }
1429
1430     DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
1431
1432     if (!exe_scope)
1433     {
1434         error.SetErrorToGenericError();
1435         error.SetErrorString("Couldn't materialize: target doesn't exist");
1436     }
1437
1438     for (EntityUP &entity_up : m_entities)
1439     {
1440         entity_up->Materialize(frame_sp, map, process_address, error);
1441
1442         if (!error.Success())
1443             return DematerializerSP();
1444     }
1445
1446     if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1447     {
1448         log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:",
1449                     static_cast<void*>(frame_sp.get()), process_address);
1450         for (EntityUP &entity_up : m_entities)
1451             entity_up->DumpToLog(map, process_address, log);
1452     }
1453
1454     m_dematerializer_wp = ret;
1455
1456     return ret;
1457 }
1458
1459 void
1460 Materializer::Dematerializer::Dematerialize (Error &error,
1461                                              lldb::addr_t frame_bottom,
1462                                              lldb::addr_t frame_top)
1463 {
1464     lldb::StackFrameSP frame_sp;
1465
1466     lldb::ThreadSP thread_sp = m_thread_wp.lock();
1467     if (thread_sp)
1468         frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1469
1470     ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1471
1472     if (!IsValid())
1473     {
1474         error.SetErrorToGenericError();
1475         error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1476     }
1477
1478     if (!exe_scope)
1479     {
1480         error.SetErrorToGenericError();
1481         error.SetErrorString("Couldn't dematerialize: target is gone");
1482     }
1483     else
1484     {
1485         if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1486         {
1487             log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:",
1488                         static_cast<void*>(frame_sp.get()), m_process_address);
1489             for (EntityUP &entity_up : m_materializer->m_entities)
1490                 entity_up->DumpToLog(*m_map, m_process_address, log);
1491         }
1492
1493         for (EntityUP &entity_up : m_materializer->m_entities)
1494         {
1495             entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1496
1497             if (!error.Success())
1498                 break;
1499         }
1500     }
1501
1502     Wipe();
1503 }
1504
1505 void
1506 Materializer::Dematerializer::Wipe ()
1507 {
1508     if (!IsValid())
1509         return;
1510
1511     for (EntityUP &entity_up : m_materializer->m_entities)
1512     {
1513         entity_up->Wipe (*m_map, m_process_address);
1514     }
1515
1516     m_materializer = nullptr;
1517     m_map = nullptr;
1518     m_process_address = LLDB_INVALID_ADDRESS;
1519 }
1520
1521 Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default;