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