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