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