Materializer.cpp revision 263367
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            lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf();
465            if (addr_of_valobj != LLDB_INVALID_ADDRESS)
466            {
467                Error write_error;
468                map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
469
470                if (!write_error.Success())
471                {
472                    err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
473                    return;
474                }
475            }
476            else
477            {
478                DataExtractor data;
479                valobj_sp->GetData(data);
480
481                if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
482                {
483                    err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
484                    return;
485                }
486
487                if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize())
488                {
489                    if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
490                    {
491                        err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
492                    }
493                    else
494                    {
495                        err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")",
496                                                     m_variable_sp->GetName().AsCString(),
497                                                     m_variable_sp->GetType()->GetByteSize(),
498                                                     data.GetByteSize());
499                    }
500                    return;
501                }
502
503                size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign();
504                size_t byte_align = (bit_align + 7) / 8;
505
506                Error alloc_error;
507
508                m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
509                m_temporary_allocation_size = data.GetByteSize();
510
511                if (!alloc_error.Success())
512                {
513                    err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
514                    return;
515                }
516
517                Error write_error;
518
519                map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error);
520
521                if (!write_error.Success())
522                {
523                    err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
524                    return;
525                }
526
527                Error pointer_write_error;
528
529                map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
530
531                if (!pointer_write_error.Success())
532                {
533                    err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
534                }
535            }
536        }
537    }
538
539    void Dematerialize (lldb::StackFrameSP &frame_sp,
540                        IRMemoryMap &map,
541                        lldb::addr_t process_address,
542                        lldb::addr_t frame_top,
543                        lldb::addr_t frame_bottom,
544                        Error &err)
545    {
546        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
547
548        const lldb::addr_t load_addr = process_address + m_offset;
549        if (log)
550        {
551            log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
552                        (uint64_t)load_addr,
553                        m_variable_sp->GetName().AsCString());
554        }
555
556        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
557        {
558            ExecutionContextScope *scope = frame_sp.get();
559
560            if (!scope)
561                scope = map.GetBestExecutionContextScope();
562
563            lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
564
565            if (!valobj_sp)
566            {
567                err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
568                return;
569            }
570
571            lldb_private::DataExtractor data;
572
573            Error extract_error;
574
575            map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error);
576
577            if (!extract_error.Success())
578            {
579                err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
580                return;
581            }
582
583            Error set_error;
584
585            valobj_sp->SetData(data, set_error);
586
587            if (!set_error.Success())
588            {
589                err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
590                return;
591            }
592
593            Error free_error;
594
595            map.Free(m_temporary_allocation, free_error);
596
597            if (!free_error.Success())
598            {
599                err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
600                return;
601            }
602
603            m_temporary_allocation = LLDB_INVALID_ADDRESS;
604            m_temporary_allocation_size = 0;
605        }
606    }
607
608    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
609    {
610        StreamString dump_stream;
611
612        const lldb::addr_t load_addr = process_address + m_offset;
613        dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
614
615        Error err;
616
617        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
618
619        {
620            dump_stream.Printf("Pointer:\n");
621
622            DataBufferHeap data (m_size, 0);
623
624            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
625
626            if (!err.Success())
627            {
628                dump_stream.Printf("  <could not be read>\n");
629            }
630            else
631            {
632                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
633
634                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
635
636                lldb::offset_t offset;
637
638                ptr = extractor.GetPointer(&offset);
639
640                dump_stream.PutChar('\n');
641            }
642        }
643
644        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
645        {
646            dump_stream.Printf("Points to process memory:\n");
647        }
648        else
649        {
650            dump_stream.Printf("Temporary allocation:\n");
651        }
652
653        if (ptr == LLDB_INVALID_ADDRESS)
654        {
655            dump_stream.Printf("  <could not be be found>\n");
656        }
657        else
658        {
659            DataBufferHeap data (m_temporary_allocation_size, 0);
660
661            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
662
663            if (!err.Success())
664            {
665                dump_stream.Printf("  <could not be read>\n");
666            }
667            else
668            {
669                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
670
671                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
672
673                dump_stream.PutChar('\n');
674            }
675        }
676
677        log->PutCString(dump_stream.GetData());
678    }
679
680    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
681    {
682        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
683        {
684            Error free_error;
685
686            map.Free(m_temporary_allocation, free_error);
687
688            m_temporary_allocation = LLDB_INVALID_ADDRESS;
689            m_temporary_allocation_size = 0;
690        }
691
692    }
693private:
694    lldb::VariableSP    m_variable_sp;
695    bool                m_is_reference;
696    lldb::addr_t        m_temporary_allocation;
697    size_t              m_temporary_allocation_size;
698};
699
700uint32_t
701Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
702{
703    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
704    iter->reset (new EntityVariable (variable_sp));
705    uint32_t ret = AddStructMember(**iter);
706    (*iter)->SetOffset(ret);
707    return ret;
708}
709
710class EntityResultVariable : public Materializer::Entity
711{
712public:
713    EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
714        Entity(),
715        m_type(type),
716        m_is_program_reference(is_program_reference),
717        m_keep_in_memory(keep_in_memory),
718        m_temporary_allocation(LLDB_INVALID_ADDRESS),
719        m_temporary_allocation_size(0)
720    {
721        // Hard-coding to maximum size of a pointer since all results are materialized by reference
722        m_size = 8;
723        m_alignment = 8;
724    }
725
726    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
727    {
728        if (!m_is_program_reference)
729        {
730            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
731            {
732                err.SetErrorString("Trying to create a temporary region for the result but one exists");
733                return;
734            }
735
736            const lldb::addr_t load_addr = process_address + m_offset;
737
738            size_t byte_size = m_type.GetByteSize();
739            size_t bit_align = m_type.GetTypeBitAlign();
740            size_t byte_align = (bit_align + 7) / 8;
741
742            Error alloc_error;
743
744            m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
745            m_temporary_allocation_size = byte_size;
746
747            if (!alloc_error.Success())
748            {
749                err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
750                return;
751            }
752
753            Error pointer_write_error;
754
755            map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
756
757            if (!pointer_write_error.Success())
758            {
759                err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
760            }
761        }
762    }
763
764    void Dematerialize (lldb::StackFrameSP &frame_sp,
765                        IRMemoryMap &map,
766                        lldb::addr_t process_address,
767                        lldb::addr_t frame_top,
768                        lldb::addr_t frame_bottom,
769                        Error &err)
770    {
771        err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
772    }
773
774    void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
775                        lldb::StackFrameSP &frame_sp,
776                        IRMemoryMap &map,
777                        lldb::addr_t process_address,
778                        lldb::addr_t frame_top,
779                        lldb::addr_t frame_bottom,
780                        Error &err)
781    {
782        err.Clear();
783
784        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
785
786        if (!exe_scope)
787        {
788            err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
789            return;
790        }
791
792        lldb::addr_t address;
793        Error read_error;
794        const lldb::addr_t load_addr = process_address + m_offset;
795
796        map.ReadPointerFromMemory (&address, load_addr, read_error);
797
798        if (!read_error.Success())
799        {
800            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
801            return;
802        }
803
804        lldb::TargetSP target_sp = exe_scope->CalculateTarget();
805
806        if (!target_sp)
807        {
808            err.SetErrorString("Couldn't dematerialize a result variable: no target");
809            return;
810        }
811
812        ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
813
814        lldb::ClangExpressionVariableSP ret;
815
816        ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
817                                                                 name,
818                                                                 m_type,
819                                                                 map.GetByteOrder(),
820                                                                 map.GetAddressByteSize());
821
822        if (!ret)
823        {
824            err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
825            return;
826        }
827
828        lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
829
830        bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
831
832        if (can_persist && m_keep_in_memory)
833        {
834            ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
835                                                            m_type,
836                                                            name,
837                                                            address,
838                                                            eAddressTypeLoad,
839                                                            map.GetAddressByteSize());
840        }
841
842        ret->ValueUpdated();
843
844        const size_t pvar_byte_size = ret->GetByteSize();
845        uint8_t *pvar_data = ret->GetValueBytes();
846
847        map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
848
849        if (!read_error.Success())
850        {
851            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
852            return;
853        }
854
855        result_variable_sp = ret;
856
857        if (!can_persist || !m_keep_in_memory)
858        {
859            ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
860
861            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
862            {
863                Error free_error;
864                map.Free(m_temporary_allocation, free_error);
865            }
866        }
867        else
868        {
869            ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
870        }
871
872        m_temporary_allocation = LLDB_INVALID_ADDRESS;
873        m_temporary_allocation_size = 0;
874    }
875
876    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
877    {
878        StreamString dump_stream;
879
880        const lldb::addr_t load_addr = process_address + m_offset;
881
882        dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
883
884        Error err;
885
886        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
887
888        {
889            dump_stream.Printf("Pointer:\n");
890
891            DataBufferHeap data (m_size, 0);
892
893            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
894
895            if (!err.Success())
896            {
897                dump_stream.Printf("  <could not be read>\n");
898            }
899            else
900            {
901                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
902
903                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
904
905                lldb::offset_t offset;
906
907                ptr = extractor.GetPointer(&offset);
908
909                dump_stream.PutChar('\n');
910            }
911        }
912
913        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
914        {
915            dump_stream.Printf("Points to process memory:\n");
916        }
917        else
918        {
919            dump_stream.Printf("Temporary allocation:\n");
920        }
921
922        if (ptr == LLDB_INVALID_ADDRESS)
923        {
924            dump_stream.Printf("  <could not be be found>\n");
925        }
926        else
927        {
928            DataBufferHeap data (m_temporary_allocation_size, 0);
929
930            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
931
932            if (!err.Success())
933            {
934                dump_stream.Printf("  <could not be read>\n");
935            }
936            else
937            {
938                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
939
940                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
941
942                dump_stream.PutChar('\n');
943            }
944        }
945
946        log->PutCString(dump_stream.GetData());
947    }
948
949    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
950    {
951        if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
952        {
953            Error free_error;
954
955            map.Free(m_temporary_allocation, free_error);
956        }
957
958        m_temporary_allocation = LLDB_INVALID_ADDRESS;
959        m_temporary_allocation_size = 0;
960    }
961private:
962    TypeFromUser    m_type;
963    bool            m_is_program_reference;
964    bool            m_keep_in_memory;
965
966    lldb::addr_t    m_temporary_allocation;
967    size_t          m_temporary_allocation_size;
968};
969
970uint32_t
971Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
972{
973    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
974    iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
975    uint32_t ret = AddStructMember(**iter);
976    (*iter)->SetOffset(ret);
977    m_result_entity = iter->get();
978    return ret;
979}
980
981class EntitySymbol : public Materializer::Entity
982{
983public:
984    EntitySymbol (const Symbol &symbol) :
985        Entity(),
986        m_symbol(symbol)
987    {
988        // Hard-coding to maximum size of a symbol
989        m_size = 8;
990        m_alignment = 8;
991    }
992
993    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
994    {
995        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
996
997        const lldb::addr_t load_addr = process_address + m_offset;
998
999        if (log)
1000        {
1001            log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1002                        (uint64_t)load_addr,
1003                        m_symbol.GetName().AsCString());
1004        }
1005
1006        Address &sym_address = m_symbol.GetAddress();
1007
1008        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1009
1010        lldb::TargetSP target_sp;
1011
1012        if (exe_scope)
1013            target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1014
1015        if (!target_sp)
1016        {
1017            err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
1018            return;
1019        }
1020
1021        lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1022
1023        if (resolved_address == LLDB_INVALID_ADDRESS)
1024            resolved_address = sym_address.GetFileAddress();
1025
1026        Error pointer_write_error;
1027
1028        map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1029
1030        if (!pointer_write_error.Success())
1031        {
1032            err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1033            return;
1034        }
1035    }
1036
1037    void Dematerialize (lldb::StackFrameSP &frame_sp,
1038                        IRMemoryMap &map,
1039                        lldb::addr_t process_address,
1040                        lldb::addr_t frame_top,
1041                        lldb::addr_t frame_bottom,
1042                        Error &err)
1043    {
1044        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1045
1046        const lldb::addr_t load_addr = process_address + m_offset;
1047
1048        if (log)
1049        {
1050            log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1051                        (uint64_t)load_addr,
1052                        m_symbol.GetName().AsCString());
1053        }
1054
1055        // no work needs to be done
1056    }
1057
1058    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1059    {
1060        StreamString dump_stream;
1061
1062        Error err;
1063
1064        const lldb::addr_t load_addr = process_address + m_offset;
1065
1066        dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString());
1067
1068        {
1069            dump_stream.Printf("Pointer:\n");
1070
1071            DataBufferHeap data (m_size, 0);
1072
1073            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1074
1075            if (!err.Success())
1076            {
1077                dump_stream.Printf("  <could not be read>\n");
1078            }
1079            else
1080            {
1081                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1082
1083                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1084
1085                dump_stream.PutChar('\n');
1086            }
1087        }
1088
1089        log->PutCString(dump_stream.GetData());
1090    }
1091
1092    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1093    {
1094    }
1095private:
1096    Symbol m_symbol;
1097};
1098
1099uint32_t
1100Materializer::AddSymbol (const Symbol &symbol_sp, Error &err)
1101{
1102    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1103    iter->reset (new EntitySymbol (symbol_sp));
1104    uint32_t ret = AddStructMember(**iter);
1105    (*iter)->SetOffset(ret);
1106    return ret;
1107}
1108
1109class EntityRegister : public Materializer::Entity
1110{
1111public:
1112    EntityRegister (const RegisterInfo &register_info) :
1113        Entity(),
1114        m_register_info(register_info)
1115    {
1116        // Hard-coding alignment conservatively
1117        m_size = m_register_info.byte_size;
1118        m_alignment = m_register_info.byte_size;
1119    }
1120
1121    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
1122    {
1123        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1124
1125        const lldb::addr_t load_addr = process_address + m_offset;
1126
1127        if (log)
1128        {
1129            log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1130                        (uint64_t)load_addr,
1131                        m_register_info.name);
1132        }
1133
1134        RegisterValue reg_value;
1135
1136        if (!frame_sp.get())
1137        {
1138            err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
1139            return;
1140        }
1141
1142        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1143
1144        if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
1145        {
1146            err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
1147            return;
1148        }
1149
1150        DataExtractor register_data;
1151
1152        if (!reg_value.GetData(register_data))
1153        {
1154            err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
1155            return;
1156        }
1157
1158        if (register_data.GetByteSize() != m_register_info.byte_size)
1159        {
1160            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);
1161            return;
1162        }
1163
1164        m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
1165
1166        Error write_error;
1167
1168        map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
1169
1170        if (!write_error.Success())
1171        {
1172            err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
1173            return;
1174        }
1175    }
1176
1177    void Dematerialize (lldb::StackFrameSP &frame_sp,
1178                        IRMemoryMap &map,
1179                        lldb::addr_t process_address,
1180                        lldb::addr_t frame_top,
1181                        lldb::addr_t frame_bottom,
1182                        Error &err)
1183    {
1184        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1185
1186        const lldb::addr_t load_addr = process_address + m_offset;
1187
1188        if (log)
1189        {
1190            log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1191                        (uint64_t)load_addr,
1192                        m_register_info.name);
1193        }
1194
1195        Error extract_error;
1196
1197        DataExtractor register_data;
1198
1199        if (!frame_sp.get())
1200        {
1201            err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
1202            return;
1203        }
1204
1205        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1206
1207        map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error);
1208
1209        if (!extract_error.Success())
1210        {
1211            err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
1212            return;
1213        }
1214
1215        if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize()))
1216        {
1217            // No write required, and in particular we avoid errors if the register wasn't writable
1218
1219            m_register_contents.reset();
1220            return;
1221        }
1222
1223        m_register_contents.reset();
1224
1225        RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
1226
1227        if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
1228        {
1229            err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
1230            return;
1231        }
1232    }
1233
1234    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1235    {
1236        StreamString dump_stream;
1237
1238        Error err;
1239
1240        const lldb::addr_t load_addr = process_address + m_offset;
1241
1242
1243        dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name);
1244
1245        {
1246            dump_stream.Printf("Value:\n");
1247
1248            DataBufferHeap data (m_size, 0);
1249
1250            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1251
1252            if (!err.Success())
1253            {
1254                dump_stream.Printf("  <could not be read>\n");
1255            }
1256            else
1257            {
1258                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1259
1260                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1261
1262                dump_stream.PutChar('\n');
1263            }
1264        }
1265
1266        log->PutCString(dump_stream.GetData());
1267    }
1268
1269    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1270    {
1271    }
1272private:
1273    RegisterInfo m_register_info;
1274    lldb::DataBufferSP m_register_contents;
1275};
1276
1277uint32_t
1278Materializer::AddRegister (const RegisterInfo &register_info, Error &err)
1279{
1280    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1281    iter->reset (new EntityRegister (register_info));
1282    uint32_t ret = AddStructMember(**iter);
1283    (*iter)->SetOffset(ret);
1284    return ret;
1285}
1286
1287Materializer::Materializer () :
1288    m_dematerializer_wp(),
1289    m_result_entity(NULL),
1290    m_current_offset(0),
1291    m_struct_alignment(8)
1292{
1293}
1294
1295Materializer::~Materializer ()
1296{
1297    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1298
1299    if (dematerializer_sp)
1300        dematerializer_sp->Wipe();
1301}
1302
1303Materializer::DematerializerSP
1304Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
1305{
1306    ExecutionContextScope *exe_scope = frame_sp.get();
1307
1308    if (!exe_scope)
1309        exe_scope = map.GetBestExecutionContextScope();
1310
1311    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1312
1313    if (dematerializer_sp)
1314    {
1315        error.SetErrorToGenericError();
1316        error.SetErrorString("Couldn't materialize: already materialized");
1317    }
1318
1319    DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
1320
1321    if (!exe_scope)
1322    {
1323        error.SetErrorToGenericError();
1324        error.SetErrorString("Couldn't materialize: target doesn't exist");
1325    }
1326
1327    for (EntityUP &entity_up : m_entities)
1328    {
1329        entity_up->Materialize(frame_sp, map, process_address, error);
1330
1331        if (!error.Success())
1332            return DematerializerSP();
1333    }
1334
1335    if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1336    {
1337        log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
1338        for (EntityUP &entity_up : m_entities)
1339            entity_up->DumpToLog(map, process_address, log);
1340    }
1341
1342    m_dematerializer_wp = ret;
1343
1344    return ret;
1345}
1346
1347void
1348Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
1349{
1350    lldb::StackFrameSP frame_sp;
1351
1352    lldb::ThreadSP thread_sp = m_thread_wp.lock();
1353    if (thread_sp)
1354        frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1355
1356    ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1357
1358    if (!IsValid())
1359    {
1360        error.SetErrorToGenericError();
1361        error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1362    }
1363
1364    if (!exe_scope)
1365    {
1366        error.SetErrorToGenericError();
1367        error.SetErrorString("Couldn't dematerialize: target is gone");
1368    }
1369    else
1370    {
1371        if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1372        {
1373            log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
1374            for (EntityUP &entity_up : m_materializer->m_entities)
1375                entity_up->DumpToLog(*m_map, m_process_address, log);
1376        }
1377
1378        for (EntityUP &entity_up : m_materializer->m_entities)
1379        {
1380            if (entity_up.get() == m_materializer->m_result_entity)
1381            {
1382                static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1383            }
1384            else
1385            {
1386                entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1387            }
1388
1389            if (!error.Success())
1390                break;
1391        }
1392    }
1393
1394    Wipe();
1395}
1396
1397void
1398Materializer::Dematerializer::Wipe ()
1399{
1400    if (!IsValid())
1401        return;
1402
1403    for (EntityUP &entity_up : m_materializer->m_entities)
1404    {
1405        entity_up->Wipe (*m_map, m_process_address);
1406    }
1407
1408    m_materializer = NULL;
1409    m_map = NULL;
1410    m_process_address = LLDB_INVALID_ADDRESS;
1411}
1412