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