Materializer.cpp revision 269024
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
26using namespace lldb_private;
27
28uint32_t
29Materializer::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
49void
50Materializer::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
65class EntityPersistentVariable : public Materializer::Entity
66{
67public:
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    }
391private:
392    lldb::ClangExpressionVariableSP m_persistent_variable_sp;
393};
394
395uint32_t
396Materializer::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
405class EntityVariable : public Materializer::Entity
406{
407public:
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    }
698private:
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
705uint32_t
706Materializer::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
715class EntityResultVariable : public Materializer::Entity
716{
717public:
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    }
969private:
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
978uint32_t
979Materializer::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
989class EntitySymbol : public Materializer::Entity
990{
991public:
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    }
1103private:
1104    Symbol m_symbol;
1105};
1106
1107uint32_t
1108Materializer::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
1117class EntityRegister : public Materializer::Entity
1118{
1119public:
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    }
1280private:
1281    RegisterInfo m_register_info;
1282    lldb::DataBufferSP m_register_contents;
1283};
1284
1285uint32_t
1286Materializer::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
1295Materializer::Materializer () :
1296    m_dematerializer_wp(),
1297    m_result_entity(NULL),
1298    m_current_offset(0),
1299    m_struct_alignment(8)
1300{
1301}
1302
1303Materializer::~Materializer ()
1304{
1305    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1306
1307    if (dematerializer_sp)
1308        dematerializer_sp->Wipe();
1309}
1310
1311Materializer::DematerializerSP
1312Materializer::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
1355void
1356Materializer::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
1405void
1406Materializer::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}
1420