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