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