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