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